From c0116b622292886ae589e0bf72c66638494a67c9 Mon Sep 17 00:00:00 2001 From: falood Date: Wed, 26 Feb 2014 18:34:11 +0800 Subject: [PATCH] Improve notify support --- .gitignore | 3 ++ .../4d51c84f8dca_create_notify_table.py | 33 +++++++++++++++++++ june/app.py | 3 +- june/handlers/notify.py | 30 +++++++++++++++++ june/handlers/topic.py | 14 +++++++- june/models/__init__.py | 13 ++++++++ june/models/account.py | 1 + june/models/notify.py | 21 ++++++++++++ june/models/topic.py | 24 ++++++++++++++ june/templates/notify/notify.html | 20 +++++++++++ june/templates/snippet/macro.html | 27 +++++++++++++++ 11 files changed, 187 insertions(+), 2 deletions(-) create mode 100644 alembic/versions/4d51c84f8dca_create_notify_table.py create mode 100644 june/handlers/notify.py create mode 100644 june/models/notify.py create mode 100644 june/templates/notify/notify.html diff --git a/.gitignore b/.gitignore index 9aa2a11..e76d701 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,9 @@ db.sqlite *.mo *.log *.tmp.* +*.swp +*~ +\#.*\# *.iml .idea/ __pycache__ diff --git a/alembic/versions/4d51c84f8dca_create_notify_table.py b/alembic/versions/4d51c84f8dca_create_notify_table.py new file mode 100644 index 0000000..683f5a5 --- /dev/null +++ b/alembic/versions/4d51c84f8dca_create_notify_table.py @@ -0,0 +1,33 @@ +"""create notify table + +Revision ID: 4d51c84f8dca +Revises: 4ad568a7a84e +Create Date: 2014-02-26 13:26:20.556780 + +""" + +# revision identifiers, used by Alembic. +revision = '4d51c84f8dca' +down_revision = '4ad568a7a84e' + +from datetime import datetime +from alembic import op +import sqlalchemy as sa + + +def upgrade(): + op.create_table( + 'notify', + sa.Column('id', sa.Integer, primary_key=True), + sa.Column('account_id', sa.Integer, nullable=False), + sa.Column('topic_id', sa.Integer, index=True, nullable=False), + sa.Column('reason', sa.String(100), nullable=False), + sa.Column('is_viewed', sa.String(100), default=0, nullable=False), + sa.Column('created', sa.DateTime, default=datetime.utcnow), + ) + op.add_column('account', sa.Column('notify_count', sa.Integer, default=0)) + + +def downgrade(): + op.drop_table('notify') + op.drop_column('account', 'notify_count') diff --git a/june/app.py b/june/app.py index 3d23a72..9cd400d 100644 --- a/june/app.py +++ b/june/app.py @@ -68,7 +68,8 @@ def rendering_time(response): def register_routes(app): - from .handlers import front, account, node, topic, user, admin + from .handlers import front, account, node, topic, user, admin, notify + app.register_blueprint(notify.bp, url_prefix='/notify') app.register_blueprint(account.bp, url_prefix='/account') app.register_blueprint(node.bp, url_prefix='/node') app.register_blueprint(topic.bp, url_prefix='/topic') diff --git a/june/handlers/notify.py b/june/handlers/notify.py new file mode 100644 index 0000000..584ad6d --- /dev/null +++ b/june/handlers/notify.py @@ -0,0 +1,30 @@ +# coding: utf-8 + +from flask import Blueprint, g, request +from flask import render_template, abort +from ..helpers import force_int +from ..models import Notify +from ..models import fill_with_topics, fill_with_users +from ..utils.user import require_login + + +__all__ = ['bp'] + +bp = Blueprint('notify', __name__) + + +@bp.route('/') +@require_login +def notifies(): + """ + The topics list page. + """ + page = force_int(request.args.get('page', 1), 0) + if not page: + return abort(404) + paginator = Notify.query.filter_by( + account_id=g.user.id, is_viewed=0).order_by( + Notify.created.desc()).paginate(page) + paginator.items = fill_with_users(paginator.items) + paginator.items = fill_with_topics(paginator.items) + return render_template('notify/notify.html', paginator=paginator) diff --git a/june/handlers/topic.py b/june/handlers/topic.py index ee6e0fc..6589446 100644 --- a/june/handlers/topic.py +++ b/june/handlers/topic.py @@ -6,7 +6,7 @@ from flask import url_for from flask.ext.babel import gettext as _ from ..helpers import force_int, limit_request -from ..models import db, Node, Account +from ..models import db, Node, Account, Notify from ..models import Topic, Reply, LikeTopic from ..models import fill_topics, fill_with_users from ..forms import TopicForm, ReplyForm @@ -132,6 +132,18 @@ def view(uid): topic.author = author topic.node = node + if g.user.notify_count != 0: + args = {'account_id': g.user.id, + 'topic_id': topic.id, + 'is_viewed': 0} + notifies = Notify.query.filter_by(**args).all() + g.user.notify_count -= len(notifies) + db.session.add(g.user) + for i in notifies: + i.is_viewed = 1 + db.session.add(i) + db.session.commit() + if g.user: topic.like = LikeTopic.query.filter_by( account_id=g.user.id, topic_id=uid diff --git a/june/models/__init__.py b/june/models/__init__.py index aae3e97..fdc2326 100644 --- a/june/models/__init__.py +++ b/june/models/__init__.py @@ -5,6 +5,7 @@ from .account import * from .node import * from .topic import * +from .notify import * from flask.ext.sqlalchemy import models_committed @@ -34,6 +35,13 @@ def fill_with_nodes(items): return items +def fill_with_topics(items): + tids = set(map(lambda o: o.topic_id, items)) + topics = Topic.query.filter_in(Topic.id, tids) + items = map(lambda o: _attach_topic(o, topics.get(o.topic_id)), items) + return items + + def get_by_ids(model, uids): if not len(uids): return {} @@ -86,6 +94,11 @@ def _attach_node(item, node): return item +def _attach_topic(item, topic): + item.topic = topic + return item + + def _clear_cache(sender, changes): for model, operation in changes: if isinstance(model, Account) and operation != 'update': diff --git a/june/models/account.py b/june/models/account.py index 3ce3ba8..2d357bd 100644 --- a/june/models/account.py +++ b/june/models/account.py @@ -25,6 +25,7 @@ class Account(db.Model, SessionMixin): created = db.Column(db.DateTime, default=datetime.utcnow) token = db.Column(db.String(20)) + notify_count = db.Column(db.Integer, default=0) def __init__(self, **kwargs): self.token = self.create_token(16) diff --git a/june/models/notify.py b/june/models/notify.py new file mode 100644 index 0000000..41fb44e --- /dev/null +++ b/june/models/notify.py @@ -0,0 +1,21 @@ +# coding: utf-8 + +from datetime import datetime +from ._base import db, SessionMixin + +__all__ = ['Notify'] + + +class Notify(db.Model, SessionMixin): + id = db.Column(db.Integer, primary_key=True) + account_id = db.Column(db.Integer, nullable=False) + topic_id = db.Column(db.Integer, index=True, nullable=False) + reason = db.Column(db.String(100), nullable=False) + is_viewed = db.Column(db.String(100), default=0, nullable=False) + created = db.Column(db.DateTime, default=datetime.utcnow) + + def __str__(self): + return self.id + + def __repr__(self): + return '' % self.id diff --git a/june/models/topic.py b/june/models/topic.py index 814324b..c6b70a3 100644 --- a/june/models/topic.py +++ b/june/models/topic.py @@ -1,8 +1,10 @@ # coding: utf-8 +import re from datetime import datetime from ._base import db from .account import Account +from .notify import Notify from .node import Node, NodeStatus @@ -153,6 +155,28 @@ def save(self, user=None, topic=None): topic.updated = datetime.utcnow() db.session.add(topic) + if topic.account_id != user.id: + args = {'account_id': topic.account_id, + 'topic_id': topic.id, + 'reason': 'reply'} + notify = Notify(**args) + db.session.add(notify) + creator = Account.query.get(topic.account_id) + creator.notify_count += 1 + db.session.add(creator) + + for user_ated in set(re.findall('@([0-9a-z]+)', self.content)): + u = Account.query.filter_by(username=user_ated).first() + if not u or u.id in [topic.account_id, user.id]: + continue + args = {'account_id': u.id, + 'topic_id': topic.id, + 'reason': 'at'} + notify = Notify(**args) + db.session.add(notify) + u.notify_count += 1 + db.session.add(u) + db.session.add(self) db.session.commit() return self diff --git a/june/templates/notify/notify.html b/june/templates/notify/notify.html new file mode 100644 index 0000000..72a7739 --- /dev/null +++ b/june/templates/notify/notify.html @@ -0,0 +1,20 @@ +{% extends "layout.html" %} +{% from "snippet/macro.html" import notify_columns, pagination %} + +{% block subtitle %}{{ _('Notify') }}{% endblock %} + +{% block content %} +
+
+

{{ _('Unread Message') }}

+
+
+ {{ notify_columns(paginator.items) }} +
+ {% if paginator.pages > 1 %} + + {% endif %} +
+{% endblock %} diff --git a/june/templates/snippet/macro.html b/june/templates/snippet/macro.html index 854b58b..e212e08 100644 --- a/june/templates/snippet/macro.html +++ b/june/templates/snippet/macro.html @@ -83,6 +83,26 @@

{% endif %} {% endmacro %} +{% macro render_notify(item) %} +
+

user {{item.user.username}} {{item.reason}} you on topic {{item.topic.title}}

+
+{% endmacro %} + +{% macro notify_columns(notifies) %} + {% if notifies %} +
+ {% for item in notifies %} + {{ render_notify(item) }} + {% endfor %} +
+ {% else %} +
+

{{ _('There is no notify yet.') }}

+
+ {% endif %} +{% endmacro %} + {% macro pagination(paginator, url) %} {% endmacro %}