Commits

Ivan Melnikov committed 3f60402 Draft

Notify subscribers

  • Participants
  • Parent commits 8472f0a

Comments (0)

Files changed (4)

 
 builtins:
 - appstats: on
+- deferred: on
 
 
 libraries:
 from google.appengine.ext.webapp import blobstore_handlers
 from google.appengine.api import taskqueue
 from google.appengine.api import memcache
+from google.appengine.ext import deferred
+from google.appengine.api import mail
 
 from creole import Parser
 from creole.html_emitter import HtmlEmitter
 	# url = db.StringProperty()
 
 class PageIndex(db.Model):
+	''' Usefull to move page clusters and show subpages '''
 	path = db.StringListProperty(required=True)
 	# store random mark to determine 
 	# we have already moved page in case of failure
 
+class Subscribe(db.Model):
+	page = db.ListProperty(item_type=int, default=[])
+	cluster = db.ListProperty(item_type=int, default=[])
+
+	def subscribe(self, page_id, t):
+		if t == 'page':
+			self.page.append(page_id)
+		if t == 'cluster':
+			self.cluster.append(page_id)
+		if t == 'none':
+			if page_id in self.page: 
+				self.page.remove(page_id)
+			if page_id in self.cluster:
+				self.cluster.remove(page_id)
+
+
 CACHE_PAGE = 'page:'
 CACHE_FILES = 'files:'
 
 		result.append(current)
 	return result
 
+def add_page_index(page_id, path):
+	index = PageIndex(key=db.Key.from_path('PageIndex', page_id), path=index_path(path))
+	index.put()
+
+def notify(page_id, from_email):
+	page = Page.get_by_id(page_id)
+	users = Subscribe.all(keys_only=True).filter('page', page_id)
+	for user in users:
+		u = User.get_by_id(user.id())
+		log.info('Notify user %s about page %s updated', u.name, page.path)
+		mail.send_mail(sender=from_email,
+              to=u.email,
+              subject='Page "%s" updated' % page.path,
+              body='''
+              Page %s updated
+              ''' % page.path)
+
+
 ##################
 ###   Server   ###
 ##################
 
 		# add path index
 		if new:
-			index = PageIndex(key=db.Key.from_path('PageIndex', page.key().id()), path=index_path(path))
-			index.put()
+			deferred.defer(add_page_index, page.key().id(), path)
 
 		# add to search index
-		add_page(page)
+		deferred.defer(add_page, page.key().id())
+
+		# notify subscribers
+		deferred.defer(notify, page.key().id(), user.email)
 		
 		self.redirect(encode(page.path))
 
 		self.response.out.write(template.render(values))
 
 
+class SubscribePage(webapp2.RequestHandler):
+	def get(self, path):
+		if not path: path = '/'
+		page = get_page(path)
+
+		values = {'page': page, 'breadcrumbs': breadcrumbs(path)}
+		if page:
+			# TODO: lazy load
+			values['files'] = get_files(page)
+			values['upload'] = blobstore.create_upload_url(encode(page.upath()+'/.files'))
+
+			subscribers = []
+			user_ids = Subscribe.all(keys_only=True).filter('page', page.key().id())
+			for user in user_ids:
+				subscribers.append(get_user(user.id()))
+			values['subscribers'] = subscribers
+
+			user = get_user()
+			s = Subscribe.get_by_id(user.key().id())
+			if s is not None:
+				if page.key().id() in s.cluster:
+					values['type'] = 'cluster'
+				elif page.key().id() in s.page:
+					values['type'] = 'page'
+				else:
+					values['type'] = 'none'
+
+
+		template = jinja_environment.get_template('subscribe.html')
+		self.response.out.write(template.render(values))
+
+	def post(self, path):
+		if not path: path = '/'
+		page = get_page(path)
+		if not page: return
+
+		
+		user = get_user()
+		user_id = user.key().id()
+		s = Subscribe.get_by_id(user_id)
+		if not s:
+			s = Subscribe(key=db.Key.from_path('Subscribe', user_id))
+
+		page_id = page.key().id()
+		t = self.request.get('type')
+		s.subscribe(page_id, t)
+		s.put()
+
+		self.redirect(path)
+
 
 class EditPageFiles(blobstore_handlers.BlobstoreUploadHandler, blobstore_handlers.BlobstoreDownloadHandler):
 	def post(self, path):
 
 _INDEX_NAME="page"
 
-def add_page(page):
+def add_page(page_id):
+	page = Page.get_by_id(page_id)
 	# add to search index
 	doc = search.Document(doc_id=page.path, 
 						fields=[search.HtmlField(name='html', value=page.html),])
 							   ('(.*)/\.show', ShowHistoryPage),
 							   ('(.*)/\.move', MovePage),
 							   ('(.*)/\.tree', TreePage),
+							   ('(.*)/\.subscribe', SubscribePage),
 							   ('/\.preview', PreviewPage),
 
 							   ('(.*)/\.files', EditPageFiles),

File template/page/get.html

 			<a href="{{ page.upath() }}/.delete">Удалить</a>
 		</li>
 		<li class="page-files-link">
-			<a href="{{ page.upath() }}/.tree">Кластер</a>
+			<a href="{{ page.upath() }}/.tree">Подстраницы</a>
+		</li>
+		<li class="page-files-link">
+			<a href="{{ page.upath() }}/.subscribe">Подписка</a>
 		</li>
 	</ul>
 </div>

File template/page/subscribe.html

+{% extends "get.html" %}
+
+{% block get_content %}
+
+<h1>Подписка</h1>
+Получайте уведомления об изменениях.
+
+<form method="post">
+Отслеживать изменения: <br/>
+<label>
+	<input type="radio" name="type" value="page" {% if type == 'page' %}checked{% endif %}/>
+	только страницы
+</label><br/>
+<label>
+	<input type="radio" name="type" value="cluster" {% if type == 'cluster' %}checked{% endif %}/>
+	кластера целиком
+</label><br/>
+<label>
+	<input type="radio" name="type" value="none" {% if type == 'none' %}checked{% endif %}/>
+	отписаться
+</label><br/>
+
+<input type="submit" value="Сохранить"/>
+</form>
+
+<h2>Наблюдатели</h2>
+
+{% for user in subscribers %}
+<div>
+{{ user.name }}
+</div>
+{% endfor %}
+
+{% endblock %}