Merge remote-tracking branch 'refs/remotes/rodney757/notifications'
This commit is contained in:
commit
2c79dbc5ff
@ -460,3 +460,15 @@ def create_oauth1_tables(db):
|
|||||||
NonceTimestamp_v0.__table__.create(db.bind)
|
NonceTimestamp_v0.__table__.create(db.bind)
|
||||||
|
|
||||||
db.commit()
|
db.commit()
|
||||||
|
|
||||||
|
|
||||||
|
@RegisterMigration(15, MIGRATIONS)
|
||||||
|
def wants_notifications(db):
|
||||||
|
"""Add a wants_notifications field to User model"""
|
||||||
|
metadata = MetaData(bind=db.bind)
|
||||||
|
user_table = inspect_table(metadata, "core__users")
|
||||||
|
|
||||||
|
col = Column('wants_notifications', Boolean, default=True)
|
||||||
|
col.create(user_table)
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
@ -69,6 +69,7 @@ class User(Base, UserMixin):
|
|||||||
# Intented to be nullable=False, but migrations would not work for it
|
# Intented to be nullable=False, but migrations would not work for it
|
||||||
# set to nullable=True implicitly.
|
# set to nullable=True implicitly.
|
||||||
wants_comment_notification = Column(Boolean, default=True)
|
wants_comment_notification = Column(Boolean, default=True)
|
||||||
|
wants_notifications = Column(Boolean, default=True)
|
||||||
license_preference = Column(Unicode)
|
license_preference = Column(Unicode)
|
||||||
is_admin = Column(Boolean, default=False, nullable=False)
|
is_admin = Column(Boolean, default=False, nullable=False)
|
||||||
url = Column(Unicode)
|
url = Column(Unicode)
|
||||||
|
@ -67,6 +67,8 @@ class EditAccountForm(wtforms.Form):
|
|||||||
normalize_user_or_email_field(allow_user=False)])
|
normalize_user_or_email_field(allow_user=False)])
|
||||||
wants_comment_notification = wtforms.BooleanField(
|
wants_comment_notification = wtforms.BooleanField(
|
||||||
description=_("Email me when others comment on my media"))
|
description=_("Email me when others comment on my media"))
|
||||||
|
wants_notifications = wtforms.BooleanField(
|
||||||
|
description=_("Enable/Disable insite notifications"))
|
||||||
license_preference = wtforms.SelectField(
|
license_preference = wtforms.SelectField(
|
||||||
_('License preference'),
|
_('License preference'),
|
||||||
[
|
[
|
||||||
|
@ -228,10 +228,12 @@ def edit_account(request):
|
|||||||
user = request.user
|
user = request.user
|
||||||
form = forms.EditAccountForm(request.form,
|
form = forms.EditAccountForm(request.form,
|
||||||
wants_comment_notification=user.wants_comment_notification,
|
wants_comment_notification=user.wants_comment_notification,
|
||||||
license_preference=user.license_preference)
|
license_preference=user.license_preference,
|
||||||
|
wants_notifications=user.wants_notifications)
|
||||||
|
|
||||||
if request.method == 'POST' and form.validate():
|
if request.method == 'POST' and form.validate():
|
||||||
user.wants_comment_notification = form.wants_comment_notification.data
|
user.wants_comment_notification = form.wants_comment_notification.data
|
||||||
|
user.wants_notifications = form.wants_notifications.data
|
||||||
|
|
||||||
user.license_preference = form.license_preference.data
|
user.license_preference = form.license_preference.data
|
||||||
|
|
||||||
|
@ -17,7 +17,8 @@
|
|||||||
import logging
|
import logging
|
||||||
|
|
||||||
from mediagoblin.db.models import Notification, \
|
from mediagoblin.db.models import Notification, \
|
||||||
CommentNotification, CommentSubscription
|
CommentNotification, CommentSubscription, User
|
||||||
|
from mediagoblin.notifications.task import email_notification_task
|
||||||
from mediagoblin.notifications.tools import generate_comment_message
|
from mediagoblin.notifications.tools import generate_comment_message
|
||||||
|
|
||||||
_log = logging.getLogger(__name__)
|
_log = logging.getLogger(__name__)
|
||||||
@ -121,6 +122,12 @@ NOTIFICATION_FETCH_LIMIT = 100
|
|||||||
|
|
||||||
def get_notifications(user_id, only_unseen=True):
|
def get_notifications(user_id, only_unseen=True):
|
||||||
query = Notification.query.filter_by(user_id=user_id)
|
query = Notification.query.filter_by(user_id=user_id)
|
||||||
|
wants_notifications = User.query.filter_by(id=user_id).first()\
|
||||||
|
.wants_notifications
|
||||||
|
|
||||||
|
# If the user does not want notifications, don't return any
|
||||||
|
if not wants_notifications:
|
||||||
|
return None
|
||||||
|
|
||||||
if only_unseen:
|
if only_unseen:
|
||||||
query = query.filter_by(seen=False)
|
query = query.filter_by(seen=False)
|
||||||
@ -130,12 +137,19 @@ def get_notifications(user_id, only_unseen=True):
|
|||||||
|
|
||||||
return notifications
|
return notifications
|
||||||
|
|
||||||
|
|
||||||
def get_notification_count(user_id, only_unseen=True):
|
def get_notification_count(user_id, only_unseen=True):
|
||||||
query = Notification.query.filter_by(user_id=user_id)
|
query = Notification.query.filter_by(user_id=user_id)
|
||||||
|
wants_notifications = User.query.filter_by(id=user_id).first()\
|
||||||
|
.wants_notifications
|
||||||
|
|
||||||
if only_unseen:
|
if only_unseen:
|
||||||
query = query.filter_by(seen=False)
|
query = query.filter_by(seen=False)
|
||||||
|
|
||||||
count = query.count()
|
# If the user doesn't want notifications, don't show any
|
||||||
|
if not wants_notifications:
|
||||||
|
count = None
|
||||||
|
else:
|
||||||
|
count = query.count()
|
||||||
|
|
||||||
return count
|
return count
|
||||||
|
@ -23,3 +23,7 @@ add_route('mediagoblin.notifications.subscribe_comments',
|
|||||||
add_route('mediagoblin.notifications.silence_comments',
|
add_route('mediagoblin.notifications.silence_comments',
|
||||||
'/u/<string:user>/m/<string:media>/notifications/silence/',
|
'/u/<string:user>/m/<string:media>/notifications/silence/',
|
||||||
'mediagoblin.notifications.views:silence_comments')
|
'mediagoblin.notifications.views:silence_comments')
|
||||||
|
|
||||||
|
add_route('mediagoblin.notifications.mark_all_comment_notifications_seen',
|
||||||
|
'/notifications/comments/mark_all_seen/',
|
||||||
|
'mediagoblin.notifications.views:mark_all_comment_notifications_seen')
|
||||||
|
@ -14,19 +14,15 @@
|
|||||||
# You should have received a copy of the GNU Affero General Public License
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
from mediagoblin.tools.response import render_to_response, render_404, redirect
|
from mediagoblin.tools.response import redirect
|
||||||
from mediagoblin.tools.translate import pass_to_ugettext as _
|
from mediagoblin.tools.translate import pass_to_ugettext as _
|
||||||
from mediagoblin.decorators import (uses_pagination, get_user_media_entry,
|
from mediagoblin.decorators import get_user_media_entry, require_active_login
|
||||||
get_media_entry_by_id,
|
|
||||||
require_active_login, user_may_delete_media, user_may_alter_collection,
|
|
||||||
get_user_collection, get_user_collection_item, active_user_from_url)
|
|
||||||
|
|
||||||
from mediagoblin import messages
|
from mediagoblin import messages
|
||||||
|
|
||||||
from mediagoblin.notifications import add_comment_subscription, \
|
from mediagoblin.notifications import (add_comment_subscription,
|
||||||
silence_comment_subscription
|
silence_comment_subscription, mark_comment_notification_seen,
|
||||||
|
get_notifications)
|
||||||
|
|
||||||
from werkzeug.exceptions import BadRequest
|
|
||||||
|
|
||||||
@get_user_media_entry
|
@get_user_media_entry
|
||||||
@require_active_login
|
@require_active_login
|
||||||
@ -41,6 +37,7 @@ def subscribe_comments(request, media):
|
|||||||
|
|
||||||
return redirect(request, location=media.url_for_self(request.urlgen))
|
return redirect(request, location=media.url_for_self(request.urlgen))
|
||||||
|
|
||||||
|
|
||||||
@get_user_media_entry
|
@get_user_media_entry
|
||||||
@require_active_login
|
@require_active_login
|
||||||
def silence_comments(request, media):
|
def silence_comments(request, media):
|
||||||
@ -52,3 +49,17 @@ def silence_comments(request, media):
|
|||||||
' %s.') % media.title)
|
' %s.') % media.title)
|
||||||
|
|
||||||
return redirect(request, location=media.url_for_self(request.urlgen))
|
return redirect(request, location=media.url_for_self(request.urlgen))
|
||||||
|
|
||||||
|
|
||||||
|
@require_active_login
|
||||||
|
def mark_all_comment_notifications_seen(request):
|
||||||
|
"""
|
||||||
|
Marks all comment notifications seen.
|
||||||
|
"""
|
||||||
|
for comment in get_notifications(request.user.id):
|
||||||
|
mark_comment_notification_seen(comment.subject_id, request.user)
|
||||||
|
|
||||||
|
if request.GET.get('next'):
|
||||||
|
return redirect(request, location=request.GET.get('next'))
|
||||||
|
else:
|
||||||
|
return redirect(request, 'index')
|
||||||
|
@ -33,4 +33,17 @@ var notifications = {};
|
|||||||
|
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
notifications.init();
|
notifications.init();
|
||||||
|
|
||||||
|
var mark_all_comments_seen = document.getElementById('mark_all_comments_seen');
|
||||||
|
|
||||||
|
if (mark_all_comments_seen) {
|
||||||
|
mark_all_comments_seen.href = '#';
|
||||||
|
mark_all_comments_seen.onclick = function() {
|
||||||
|
$.ajax({
|
||||||
|
type: 'GET',
|
||||||
|
url: mark_all_comments_seen_url,
|
||||||
|
success: function(res, status, xhr) { window.location.reload(); },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
@ -37,6 +37,9 @@
|
|||||||
src="{{ request.staticdirect('/js/header_dropdown.js') }}"></script>
|
src="{{ request.staticdirect('/js/header_dropdown.js') }}"></script>
|
||||||
<script type="text/javascript"
|
<script type="text/javascript"
|
||||||
src="{{ request.staticdirect('/js/notifications.js') }}"></script>
|
src="{{ request.staticdirect('/js/notifications.js') }}"></script>
|
||||||
|
<script>
|
||||||
|
var mark_all_comments_seen_url = "{{ request.urlgen('mediagoblin.notifications.mark_all_comment_notifications_seen') }}"
|
||||||
|
</script>
|
||||||
|
|
||||||
{# For clarification, the difference between the extra_head.html template
|
{# For clarification, the difference between the extra_head.html template
|
||||||
# and the head template hook is that the former should be used by
|
# and the head template hook is that the former should be used by
|
||||||
|
@ -36,5 +36,9 @@
|
|||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
<a href="{{ request.urlgen('mediagoblin.notifications.mark_all_comment_notifications_seen') }}?next={{
|
||||||
|
request.base_url|urlencode }}" id="mark_all_comments_seen">
|
||||||
|
{% trans %}Mark all read{% endtrans %}
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -149,3 +149,56 @@ otherperson@example.com\n\nSGkgb3RoZXJwZXJzb24sCmNocmlzIGNvbW1lbnRlZCBvbiB5b3VyI
|
|||||||
|
|
||||||
# User should not have been notified
|
# User should not have been notified
|
||||||
assert len(notifications) == 1
|
assert len(notifications) == 1
|
||||||
|
|
||||||
|
def test_mark_all_comment_notifications_seen(self):
|
||||||
|
""" Test that mark_all_comments_seen works"""
|
||||||
|
|
||||||
|
user = fixture_add_user('otherperson', password='nosreprehto')
|
||||||
|
|
||||||
|
media_entry = fixture_media_entry(uploader=user.id, state=u'processed')
|
||||||
|
|
||||||
|
fixture_comment_subscription(media_entry)
|
||||||
|
|
||||||
|
media_uri_id = '/u/{0}/m/{1}/'.format(user.username,
|
||||||
|
media_entry.id)
|
||||||
|
|
||||||
|
# add 2 comments
|
||||||
|
self.test_app.post(
|
||||||
|
media_uri_id + 'comment/add/',
|
||||||
|
{
|
||||||
|
'comment_content': u'Test comment #43'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
self.test_app.post(
|
||||||
|
media_uri_id + 'comment/add/',
|
||||||
|
{
|
||||||
|
'comment_content': u'Test comment #44'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
notifications = Notification.query.filter_by(
|
||||||
|
user_id=user.id).all()
|
||||||
|
|
||||||
|
assert len(notifications) == 2
|
||||||
|
|
||||||
|
# both comments should not be marked seen
|
||||||
|
assert notifications[0].seen == False
|
||||||
|
assert notifications[1].seen == False
|
||||||
|
|
||||||
|
# login with other user to mark notifications seen
|
||||||
|
self.logout()
|
||||||
|
self.login('otherperson', 'nosreprehto')
|
||||||
|
|
||||||
|
# mark all comment notifications seen
|
||||||
|
res = self.test_app.get('/notifications/comments/mark_all_seen/')
|
||||||
|
res.follow()
|
||||||
|
|
||||||
|
assert urlparse.urlsplit(res.location)[2] == '/'
|
||||||
|
|
||||||
|
notifications = Notification.query.filter_by(
|
||||||
|
user_id=user.id).all()
|
||||||
|
|
||||||
|
# both notifications should be marked seen
|
||||||
|
assert notifications[0].seen == True
|
||||||
|
assert notifications[1].seen == True
|
||||||
|
Loading…
x
Reference in New Issue
Block a user