You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@allura.apache.org by br...@apache.org on 2016/12/05 16:39:34 UTC

[1/9] allura git commit: [#7981] don't allow overlapping subscriptions between Forums and its Threads

Repository: allura
Updated Branches:
  refs/heads/master 23cf3566d -> 3b8240fc2


[#7981] don't allow overlapping subscriptions between Forums and its Threads


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/dec2ab0b
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/dec2ab0b
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/dec2ab0b

Branch: refs/heads/master
Commit: dec2ab0baa2fcbf3e7137cac4c4ead385d006c8b
Parents: a02c913
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Nov 18 17:52:02 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:20 2016 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/site_admin.py         |  7 ++---
 Allura/allura/lib/search.py                     | 31 ++++++++++++++++++++
 Allura/allura/model/artifact.py                 |  2 +-
 Allura/allura/model/notification.py             |  3 +-
 .../allura/tests/functional/test_site_admin.py  | 12 ++++----
 .../forgediscussion/controllers/forum.py        | 24 ++++++++++++++-
 requirements.txt                                |  2 +-
 7 files changed, 66 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/controllers/site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/site_admin.py b/Allura/allura/controllers/site_admin.py
index 459362e..a7ece1a 100644
--- a/Allura/allura/controllers/site_admin.py
+++ b/Allura/allura/controllers/site_admin.py
@@ -272,12 +272,9 @@ class SiteAdminController(object):
             if match:
                 count = match.hits
                 objects = match.docs
-                ids = [obj['id'].split('#')[1] for obj in objects]
-                ids = [bson.ObjectId(_id) for _id in ids if _id != 'None']
-                mongo_objects = {}
-                for obj in model.query.find({'_id': {'$in': ids}}):
-                    mongo_objects[str(obj._id)] = obj
 
+                ids = [obj['id'] for obj in objects]
+                mongo_objects = search.mapped_artifacts_from_index_ids(ids, model)
                 for i in range(len(objects)):
                     obj = objects[i]
                     _id = obj['id'].split('#')[1]

http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/lib/search.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/search.py b/Allura/allura/lib/search.py
index 2ee9b82..02afa05 100644
--- a/Allura/allura/lib/search.py
+++ b/Allura/allura/lib/search.py
@@ -21,6 +21,7 @@ from logging import getLogger
 from urllib import urlencode
 from itertools import imap
 
+import bson
 import markdown
 import jinja2
 from tg import redirect, url
@@ -330,3 +331,33 @@ def find_shortlinks(text):
     md.convert(text)
     link_index = md.treeprocessors['links'].alinks
     return [link for link in link_index if link is not None]
+
+
+def artifacts_from_index_ids(index_ids, model, objectid_id=True):
+    '''
+    :param list[str] index_ids: a list of search/subscription/artifact-reference index_id values
+    :param type model: the Artifact class
+    :param bool objectid_id: whether the _id values are ObjectIds
+    :return: instances of the model, for each id given
+    :rtype: list
+    '''
+    # this could be made more flexible to not require the model passed in
+    ids = [index_id.split('#')[1] for index_id in index_ids]
+    if objectid_id:
+        ids = [bson.ObjectId(_id) for _id in ids if id != 'None']
+    return model.query.find({'_id': {'$in': ids}}).all()
+
+
+def mapped_artifacts_from_index_ids(index_ids, model, objectid_id=True):
+    '''
+    :param list[str] index_ids: a list of search/subscription/artifact-reference index_id values
+    :param type model: the Artifact class
+    :param bool objectid_id: whether the _id values are ObjectIds
+    :return: instances of the model, keyed by str(_id)
+    :rtype: dict
+    '''
+    models = artifacts_from_index_ids(index_ids, model, objectid_id=objectid_id)
+    map = {}
+    for m in models:
+        map[str(m._id)] = m
+    return map
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/model/artifact.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index 39316d2..523a7ad 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -201,7 +201,7 @@ class Artifact(MappedClass, SearchIndexable):
         from allura.model import Mailbox
         if user is None:
             user = c.user
-        Mailbox.subscribe(
+        return Mailbox.subscribe(
             user_id=user._id,
             project_id=self.app_config.project_id,
             app_config_id=self.app_config._id,

http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/model/notification.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py
index 52ef451..80ff6a6 100644
--- a/Allura/allura/model/notification.py
+++ b/Allura/allura/model/notification.py
@@ -486,8 +486,9 @@ class Mailbox(MappedClass):
             # tool
             for other_mbox in cls.query.find(dict(
                     user_id=user_id, project_id=project_id, app_config_id=app_config_id)):
-                if other_mbox is not mbox:
+                if other_mbox != mbox:
                     other_mbox.delete()
+        return mbox
 
     @classmethod
     def unsubscribe(

http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/Allura/allura/tests/functional/test_site_admin.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_site_admin.py b/Allura/allura/tests/functional/test_site_admin.py
index 7889136..c46e2b1 100644
--- a/Allura/allura/tests/functional/test_site_admin.py
+++ b/Allura/allura/tests/functional/test_site_admin.py
@@ -407,9 +407,9 @@ class TestUsersSearch(TestController):
             M.User(_id=_id, username='darth')
             ThreadLocalORMSession().flush_all()
 
-    @patch('allura.controllers.site_admin.search')
-    def test_default_fields(self, search):
-        search.site_admin_search.return_value = self.TEST_HIT
+    @patch('allura.controllers.site_admin.search.site_admin_search')
+    def test_default_fields(self, site_admin_search):
+        site_admin_search.return_value = self.TEST_HIT
         r = self.app.get('/nf/admin/search_users?q=fake&f=username')
         options = [o['value'] for o in r.html.findAll('option')]
         assert_equal(options, ['username', 'display_name', '__custom__'])
@@ -417,9 +417,9 @@ class TestUsersSearch(TestController):
         assert_equal(ths, ['Username', 'Display name', 'Email', 'Registered',
                            'Status', 'Details'])
 
-    @patch('allura.controllers.site_admin.search')
-    def test_additional_fields(self, search):
-        search.site_admin_search.return_value = self.TEST_HIT
+    @patch('allura.controllers.site_admin.search.site_admin_search')
+    def test_additional_fields(self, site_admin_search):
+        site_admin_search.return_value = self.TEST_HIT
         with h.push_config(config, **{'search.user.additional_search_fields': 'email_addresses, url',
                                       'search.user.additional_display_fields': 'url'}):
             r = self.app.get('/nf/admin/search_users?q=fake&f=username')

http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/ForgeDiscussion/forgediscussion/controllers/forum.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/forum.py b/ForgeDiscussion/forgediscussion/controllers/forum.py
index bb0fa33..52b3b7c 100644
--- a/ForgeDiscussion/forgediscussion/controllers/forum.py
+++ b/ForgeDiscussion/forgediscussion/controllers/forum.py
@@ -16,7 +16,10 @@
 #       under the License.
 
 import logging
+import re
+
 import pymongo
+from allura.lib.search import mapped_artifacts_from_index_ids
 
 from tg import expose, validate, redirect
 from tg import request
@@ -116,7 +119,6 @@ class ForumController(DiscussionController):
             limit=limit,
             page=page)
 
-
     @expose('jinja:forgediscussion:templates/discussionforums/deleted.html')
     def deleted(self):
         return dict()
@@ -127,8 +129,28 @@ class ForumController(DiscussionController):
     def subscribe_to_forum(self, subscribe=None, unsubscribe=None, shortname=None, **kw):
         if subscribe:
             self.discussion.subscribe(type='direct')
+
+            # unsubscribe from all individual threads that are part of this forum, so you don't have overlapping subscriptions
+            forumthread_index_prefix = (DM.ForumThread.__module__ + '.' + DM.ForumThread.__name__).replace('.', '/') + '#'
+            thread_mboxes = M.Mailbox.query.find(dict(
+                user_id=c.user._id,
+                project_id=c.project._id,
+                app_config_id=c.app.config._id,
+                artifact_index_id=re.compile('^' + re.escape(forumthread_index_prefix)),
+            )).all()
+            # get the ForumThread objects from the subscriptions
+            thread_index_ids = [mbox.artifact_index_id for mbox in thread_mboxes]
+            threads_by_id = mapped_artifacts_from_index_ids(thread_index_ids, DM.ForumThread, objectid_id=False)
+            for mbox in thread_mboxes:
+                thread_id = mbox.artifact_index_id.split('#')[1]
+                thread = threads_by_id[thread_id]
+                # only delete if the ForumThread is part of this forum
+                if thread.discussion_id == self.discussion._id:
+                    mbox.delete()
+
         elif unsubscribe:
             self.discussion.unsubscribe()
+
         return {
             'status': 'ok',
             'subscribed': M.Mailbox.subscribed(artifact=self.discussion),

http://git-wip-us.apache.org/repos/asf/allura/blob/dec2ab0b/requirements.txt
----------------------------------------------------------------------
diff --git a/requirements.txt b/requirements.txt
index 30f99f3..1d8dffd 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -21,7 +21,7 @@ httplib2==0.7.4
 iso8601==0.1.4
 Jinja2==2.8
 Markdown==2.2.0
-Ming==0.5.4
+Ming==0.5.5
 oauth2==1.5.170
 # tg2 dep PasteDeploy must specified before TurboGears2, to avoid a version/allow-hosts problem
 Paste==1.7.5.1


[3/9] allura git commit: [#7981] remove old thread subscription field, use modern Artifact/Mailbox approach

Posted by br...@apache.org.
[#7981] remove old thread subscription field, use modern Artifact/Mailbox approach


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/59a6a343
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/59a6a343
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/59a6a343

Branch: refs/heads/master
Commit: 59a6a343f1d5953c1c1a53244fe7d8763a71b529
Parents: e7a39fc
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Nov 18 12:19:54 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:20 2016 -0500

----------------------------------------------------------------------
 Allura/allura/controllers/discuss.py            | 13 +++++++------
 Allura/allura/model/artifact.py                 | 11 +++++++++++
 Allura/allura/model/discuss.py                  | 13 -------------
 .../allura/templates/widgets/threads_table.html |  2 +-
 Allura/allura/tests/functional/test_discuss.py  | 20 ++++++++++++--------
 Allura/allura/tests/model/test_discussion.py    |  1 +
 .../forgediscussion/controllers/root.py         |  1 +
 ForgeDiscussion/forgediscussion/forum_main.py   |  2 --
 .../tests/functional/test_forum.py              | 10 ----------
 9 files changed, 33 insertions(+), 40 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/Allura/allura/controllers/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index 9cb5f37..d6ba1ff 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -25,6 +25,7 @@ from pylons import tmpl_context as c, app_globals as g
 from webob import exc
 
 from ming.base import Object
+from ming.odm import session
 from ming.utils import LazyProperty
 
 from allura import model as M
@@ -96,13 +97,13 @@ class DiscussionController(BaseController, FeedController):
     def subscribe(self, **kw):
         threads = kw.pop('threads', [])
         for t in threads:
-            thread = self.M.Thread.query.find(dict(_id=t['_id'])).first()
-            if 'subscription' in t:
-                thread['subscription'] = True
+            thread = self.M.Thread.query.get(_id=t['_id'])
+            if t.get('subscription'):
+                thread.subscribe()
             else:
-                thread['subscription'] = False
-            M.session.artifact_orm_session._get().skip_mod_date = True
-            M.session.artifact_orm_session._get().skip_last_updated = True
+                thread.unsubscribe()
+            session(self.M.Thread)._get().skip_mod_date = True
+            session(self.M.Thread)._get().skip_last_updated = True
         redirect(request.referer)
 
     def get_feed(self, project, app, user):

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/Allura/allura/model/artifact.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index ff4bd76..39316d2 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -226,6 +226,17 @@ class Artifact(MappedClass, SearchIndexable):
             app_config_id=self.app_config._id,
             artifact_index_id=self.index_id())
 
+    def subscribed(self, user=None):
+        from allura.model import Mailbox
+        if user is None:
+            user = c.user
+        return Mailbox.subscribed(
+            user_id=user._id,
+            project_id=self.app_config.project_id,
+            app_config_id=self.app_config._id,
+            artifact=self,
+        )
+
     def primary(self):
         """If an artifact is a "secondary" artifact (discussion of a ticket, for
         instance), return the artifact that is the "primary".

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/Allura/allura/model/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index b3cf04b..19c0ea5 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -118,9 +118,6 @@ class Discussion(Artifact, ActivityObject):
             text=self.description)
         return result
 
-    def subscription(self):
-        return self.subscriptions.get(str(c.user._id))
-
     def delete(self):
         # Delete all the threads, posts, and artifacts
         self.thread_class().query.remove(dict(discussion_id=self._id))
@@ -428,16 +425,6 @@ class Thread(Artifact, ActivityObject):
             text=self.subject)
         return result
 
-    def _get_subscription(self):
-        return self.subscriptions.get(str(c.user._id))
-
-    def _set_subscription(self, value):
-        if value:
-            self.subscriptions[str(c.user._id)] = True
-        else:
-            self.subscriptions.pop(str(c.user._id), None)
-    subscription = property(_get_subscription, _set_subscription)
-
     def delete(self):
         for p in self.post_class().query.find(dict(thread_id=self._id)):
             p.delete()

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/Allura/allura/templates/widgets/threads_table.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/threads_table.html b/Allura/allura/templates/widgets/threads_table.html
index 2101606..bc20d29 100644
--- a/Allura/allura/templates/widgets/threads_table.html
+++ b/Allura/allura/templates/widgets/threads_table.html
@@ -37,7 +37,7 @@
         {% if not c.user.is_anonymous() %}
           <td>
             <input type="checkbox" name="threads-{{loop.index0}}.subscription"
-                 {% if thread.subscription %}checked="checked"{% endif %}/>
+                 {% if thread.subscribed() %}checked="checked"{% endif %}/>
             <input type="hidden" name="threads-{{loop.index0}}._id" value="{{thread._id}}"/>
           </td>
         {% endif %}

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/Allura/allura/tests/functional/test_discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/functional/test_discuss.py b/Allura/allura/tests/functional/test_discuss.py
index 836d094..56bb77d 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -24,6 +24,7 @@ from ming.odm import session
 from allura.tests import TestController
 from allura import model as M
 
+
 class TestDiscussBase(TestController):
 
     def _thread_link(self):
@@ -41,24 +42,27 @@ class TestDiscussBase(TestController):
 
 class TestDiscuss(TestDiscussBase):
 
-    def _is_subscribed(self, username, thread_id):
-        user_id = str(M.User.by_username(username)._id)
-        thread = M.Thread.query.get(_id=thread_id)
-        return thread.subscriptions.get(user_id)
+    def _is_subscribed(self, user, thread):
+        return M.Mailbox.query.get(user_id=user._id, artifact_index_id=thread.index_id())
 
     def test_subscribe_unsubscribe(self):
-        user = 'test-admin'
+        user = M.User.by_username('test-admin')
         thread_id = self._thread_id()
-        assert_false(self._is_subscribed(user, thread_id))
+        thread = M.Thread.query.get(_id=thread_id)
+
+        # remove tool-wide subscription, so it doesn't interfere
+        M.Mailbox.query.remove(dict(user_id=user._id, app_config_id=thread.app_config_id))
+
+        assert_false(self._is_subscribed(user, thread))
         link = self._thread_link()
         params = {
             'threads-0._id': thread_id,
             'threads-0.subscription': 'on'}
         r = self.app.post('/wiki/_discuss/subscribe', params=params)
-        assert_true(self._is_subscribed(user, thread_id))
+        assert_true(self._is_subscribed(user, thread))
         params = {'threads-0._id': thread_id}
         r = self.app.post('/wiki/_discuss/subscribe', params=params)
-        assert_false(self._is_subscribed(user, thread_id))
+        assert_false(self._is_subscribed(user, thread))
 
     def _make_post(self, text):
         thread_link = self._thread_link()

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/Allura/allura/tests/model/test_discussion.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_discussion.py b/Allura/allura/tests/model/test_discussion.py
index bd95bd3..b579d18 100644
--- a/Allura/allura/tests/model/test_discussion.py
+++ b/Allura/allura/tests/model/test_discussion.py
@@ -104,6 +104,7 @@ def test_thread_methods():
 
     assert 'wiki/_discuss/' in t.url()
     assert t.index()['views_i'] == 0
+    # FIXME
     assert not t.subscription
     t.subscription = True
     assert t.subscription

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/ForgeDiscussion/forgediscussion/controllers/root.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index cb4b4f8..8ade51f 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -203,6 +203,7 @@ class RootController(BaseController, DispatchIndex, FeedController):
             objs.append(dict(obj=model.Thread.query.get(_id=data['id']),
                              subscribed=bool(data.get('subscribed'))))
         for obj in objs:
+            # TODO where is this called from?
             if obj['subscribed']:
                 obj['obj'].subscriptions[str(c.user._id)] = True
             else:

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/ForgeDiscussion/forgediscussion/forum_main.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/forum_main.py b/ForgeDiscussion/forgediscussion/forum_main.py
index 524b11d..60b97d3 100644
--- a/ForgeDiscussion/forgediscussion/forum_main.py
+++ b/ForgeDiscussion/forgediscussion/forum_main.py
@@ -91,8 +91,6 @@ class ForgeDiscussionApp(Application):
         self.root = RootController()
         self.api_root = RootRestController()
         self.admin = ForumAdminController(self)
-        self.default_forum_preferences = dict(
-            subscriptions={})
 
     def has_access(self, user, topic):
         f = DM.Forum.query.get(shortname=topic.replace('.', '/'),

http://git-wip-us.apache.org/repos/asf/allura/blob/59a6a343/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
index 55da689..6606b32 100644
--- a/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
+++ b/ForgeDiscussion/forgediscussion/tests/functional/test_forum.py
@@ -374,16 +374,6 @@ class TestForum(TestController):
         r = self.app.get('/discussion/markdown_syntax')
         assert 'Markdown Syntax' in r
 
-    def test_forum_subscribe(self):
-        self.app.post('/discussion/subscribe', params={
-            'forum-0.shortname': 'testforum',
-            'forum-0.subscribed': 'on',
-        })
-        self.app.post('/discussion/subscribe', params={
-            'forum-0.shortname': 'testforum',
-            'forum-0.subscribed': '',
-        })
-
     def test_forum_index(self):
         self.app.get('/discussion/testforum/')
         self.app.get('/discussion/testforum/childforum/')


[6/9] allura git commit: [#7981] make thread moderate panel a little nicer looking

Posted by br...@apache.org.
[#7981] make thread moderate panel a little nicer looking


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/e7a39fce
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/e7a39fce
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/e7a39fce

Branch: refs/heads/master
Commit: e7a39fce90a909851507c35591ad5a4f54bb5600
Parents: c8e7076
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Nov 18 10:48:27 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:20 2016 -0500

----------------------------------------------------------------------
 Allura/allura/lib/widgets/discuss.py                           | 2 +-
 .../templates/discussion_widgets/thread_header.html            | 6 ++++--
 ForgeDiscussion/forgediscussion/widgets/forum_widgets.py       | 4 ++--
 3 files changed, 7 insertions(+), 5 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/e7a39fce/Allura/allura/lib/widgets/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/discuss.py b/Allura/allura/lib/widgets/discuss.py
index a527dd9..98f60ca 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -485,7 +485,7 @@ class Thread(HierWidget):
             if (mod_thread_link.length) {
                 if (mod_thread_form.length) {
                     mod_thread_link.click(function (e) {
-                        mod_thread_form.show();
+                        mod_thread_form.toggle();
                         return false;
                     });
                 }

http://git-wip-us.apache.org/repos/asf/allura/blob/e7a39fce/ForgeDiscussion/forgediscussion/templates/discussion_widgets/thread_header.html
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/templates/discussion_widgets/thread_header.html b/ForgeDiscussion/forgediscussion/templates/discussion_widgets/thread_header.html
index 9a988df..1c71c85 100644
--- a/ForgeDiscussion/forgediscussion/templates/discussion_widgets/thread_header.html
+++ b/ForgeDiscussion/forgediscussion/templates/discussion_widgets/thread_header.html
@@ -26,9 +26,11 @@
 <div class="grid-5"><label>Updated:</label> {{lib.abbr_date(value.mod_date)}}</div>
 
 {% if show_moderate and h.has_access(value, 'moderate')() %}
-  <div id="mod_thread_form" style="display: none;">
+  <div id="mod_thread_form" style="display: none; clear: both">
     <h2>Moderate Thread</h2>
-    {{widgets.moderate_thread.display(value=value, action=value.url()+'moderate')}}
+    <div class="grid-19 fright">
+      {{widgets.moderate_thread.display(value=value, action=value.url()+'moderate')}}
+    </div>
     <div style="clear: both;">&nbsp;</div>
   </div>
 {% endif %}

http://git-wip-us.apache.org/repos/asf/allura/blob/e7a39fce/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
index d26f330..8c0c07f 100644
--- a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
+++ b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
@@ -120,8 +120,8 @@ class ModerateThread(CsrfForm):
     submit_text = 'Save Changes'
 
     class fields(ew_core.NameList):
-        discussion = _ForumSelector(label='New Forum')
-        flags = ew.CheckboxSet(options=['Sticky', 'Announcement'])
+        discussion = _ForumSelector(label='Move to different forum:')
+        flags = ew.CheckboxSet(label='Options', options=['Sticky', 'Announcement'])
 
     class buttons(ew_core.NameList):
         delete = ew.SubmitButton(label='Delete Thread')


[5/9] allura git commit: [#7981] frontend bugfix, cleanup, and consolidation

Posted by br...@apache.org.
[#7981] frontend bugfix, cleanup, and consolidation


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a02c9137
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a02c9137
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a02c9137

Branch: refs/heads/master
Commit: a02c9137d4965eb59637b2325a44fd56c7be2f2f
Parents: a7ef457
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Nov 18 17:08:24 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:20 2016 -0500

----------------------------------------------------------------------
 Allura/allura/lib/widgets/__init__.py           |  4 +-
 Allura/allura/lib/widgets/discuss.py            | 26 ---------
 Allura/allura/model/discuss.py                  |  2 +
 Allura/allura/templates/widgets/discussion.html | 26 ---------
 .../templates/widgets/discussion_header.html    | 19 ------
 .../allura/templates/widgets/threads_table.html |  7 +--
 Allura/allura/tests/model/test_discussion.py    |  7 ---
 Allura/allura/tests/model/test_notification.py  |  2 +-
 .../forgediscussion/controllers/root.py         | 30 ----------
 .../discussion_widgets/forum_summary.html       | 28 ---------
 .../forgediscussion/widgets/__init__.py         |  4 +-
 .../forgediscussion/widgets/forum_widgets.py    | 61 +++++++-------------
 12 files changed, 30 insertions(+), 186 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/lib/widgets/__init__.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/__init__.py b/Allura/allura/lib/widgets/__init__.py
index 9d21e37..3e8e798 100644
--- a/Allura/allura/lib/widgets/__init__.py
+++ b/Allura/allura/lib/widgets/__init__.py
@@ -15,12 +15,12 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from .discuss import Post, Thread, Discussion
+from .discuss import Post, Thread
 from .subscriptions import SubscriptionForm
 from .oauth_widgets import OAuthApplicationForm, OAuthRevocationForm
 from .auth_widgets import LoginForm, ForgottenPasswordForm, DisableAccountForm
 from .vote import VoteForm
 
 __all__ = [
-    'Post', 'Thread', 'Discussion', 'SubscriptionForm', 'OAuthApplicationForm', 'OAuthRevocationForm', 'LoginForm',
+    'Post', 'Thread', 'SubscriptionForm', 'OAuthApplicationForm', 'OAuthRevocationForm', 'LoginForm',
     'ForgottenPasswordForm', 'DisableAccountForm', 'VoteForm']

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/lib/widgets/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/discuss.py b/Allura/allura/lib/widgets/discuss.py
index 98f60ca..2d1fb1d 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -254,14 +254,6 @@ class Attachment(ew_core.Widget):
     post = None
 
 
-class DiscussionHeader(HierWidget):
-    template = 'jinja:allura:templates/widgets/discussion_header.html'
-    params = ['value']
-    value = None
-    widgets = dict(
-        edit_post=EditPost(submit_text='New Thread'))
-
-
 class ThreadHeader(HierWidget):
     template = 'jinja:allura:templates/widgets/thread_header.html'
     defaults = dict(
@@ -516,21 +508,3 @@ class Thread(HierWidget):
             }
         });
         ''')
-
-
-class Discussion(HierWidget):
-    template = 'jinja:allura:templates/widgets/discussion.html'
-    defaults = dict(
-        HierWidget.defaults,
-        value=None,
-        threads=None,
-        show_subject=False,
-        allow_create_thread=False)
-    widgets = dict(
-        discussion_header=DiscussionHeader(),
-        edit_post=EditPost(submit_text='New Topic'),
-        subscription_form=SubscriptionForm())
-
-    def resources(self):
-        for r in super(Discussion, self).resources():
-            yield r

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/model/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 2af6146..257ac38 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -242,6 +242,8 @@ class Thread(Artifact, ActivityObject):
 
     @property
     def artifact(self):
+        # Threads attached to a wiki page, ticket, etc will have a .ref.artifact pointing to that WikiPage etc
+        # Threads that are part of a forum will not have that
         if self.ref is None:
             return self.discussion
         return self.ref.artifact

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/templates/widgets/discussion.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/discussion.html b/Allura/allura/templates/widgets/discussion.html
deleted file mode 100644
index 82ee24c..0000000
--- a/Allura/allura/templates/widgets/discussion.html
+++ /dev/null
@@ -1,26 +0,0 @@
-{#-
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
--#}
-{{widgets.subscription_form.display(value=value,
-                                    threads=threads,
-                                    action=value.url() + 'subscribe',
-                                    allow_create_thread=allow_create_thread,
-                                    show_subject=show_subject,
-                                    limit=limit,
-                                    page=page,
-                                    count=count)}}

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/templates/widgets/discussion_header.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/discussion_header.html b/Allura/allura/templates/widgets/discussion_header.html
deleted file mode 100644
index b464bfa..0000000
--- a/Allura/allura/templates/widgets/discussion_header.html
+++ /dev/null
@@ -1,19 +0,0 @@
-{#-
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
--#}
-<div>{{g.markdown.cached_convert(value, 'description')|safe}}</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/templates/widgets/threads_table.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/threads_table.html b/Allura/allura/templates/widgets/threads_table.html
index bc20d29..873b537 100644
--- a/Allura/allura/templates/widgets/threads_table.html
+++ b/Allura/allura/templates/widgets/threads_table.html
@@ -22,7 +22,7 @@
   <table class="forum-list clear">
     <thead>
       <tr>
-        {% if not c.user.is_anonymous() %}
+        {% if not c.user.is_anonymous() and allow_subscriptions %}
           <th>{{ g.icons['mail'].render(tag='span', title='Subscriptions') }}</th>
         {% endif %}
         <th class="topic">Topic</th>
@@ -34,10 +34,9 @@
     <tbody class="forum-list">
       {% for thread in value %}
       <tr>
-        {% if not c.user.is_anonymous() %}
+        {% if not c.user.is_anonymous() and allow_subscriptions %}
           <td>
-            <input type="checkbox" name="threads-{{loop.index0}}.subscription"
-                 {% if thread.subscribed() %}checked="checked"{% endif %}/>
+            <input type="checkbox" name="threads-{{loop.index0}}.subscription" {% if thread.subscribed() %}checked="checked"{% endif %} />
             <input type="hidden" name="threads-{{loop.index0}}._id" value="{{thread._id}}"/>
           </td>
         {% endif %}

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/tests/model/test_discussion.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_discussion.py b/Allura/allura/tests/model/test_discussion.py
index b579d18..0258f38 100644
--- a/Allura/allura/tests/model/test_discussion.py
+++ b/Allura/allura/tests/model/test_discussion.py
@@ -67,7 +67,6 @@ def test_discussion_methods():
     assert d.last_post == None
     assert d.url().endswith('wiki/_discuss/')
     assert d.index()['name_s'] == 'test'
-    assert d.subscription() == None
     assert d.find_posts().count() == 0
     jsn = d.__json__()
     assert jsn['name'] == d.name
@@ -104,12 +103,6 @@ def test_thread_methods():
 
     assert 'wiki/_discuss/' in t.url()
     assert t.index()['views_i'] == 0
-    # FIXME
-    assert not t.subscription
-    t.subscription = True
-    assert t.subscription
-    t.subscription = False
-    assert not t.subscription
     assert t.post_count == 3
     jsn = t.__json__()
     assert '_id' in jsn

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/Allura/allura/tests/model/test_notification.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/model/test_notification.py b/Allura/allura/tests/model/test_notification.py
index 820e22c..f4ba56e 100644
--- a/Allura/allura/tests/model/test_notification.py
+++ b/Allura/allura/tests/model/test_notification.py
@@ -188,7 +188,7 @@ class TestPostNotifications(unittest.TestCase):
         ThreadLocalORMSession.flush_all()
         M.MonQTask.list()
         t = M.MonQTask.get()
-        assert t.args[1] == self.pg.index_id()
+        assert_equal(t.args[1], [self.pg.index_id()])
 
     def test_post_user_notification(self):
         u = M.User.query.get(username='test-admin')

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/ForgeDiscussion/forgediscussion/controllers/root.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/root.py b/ForgeDiscussion/forgediscussion/controllers/root.py
index 8ade51f..24c2ea1 100644
--- a/ForgeDiscussion/forgediscussion/controllers/root.py
+++ b/ForgeDiscussion/forgediscussion/controllers/root.py
@@ -56,7 +56,6 @@ log = logging.getLogger(__name__)
 class RootController(BaseController, DispatchIndex, FeedController):
 
     class W(object):
-        forum_subscription_form = FW.ForumSubscriptionForm()
         new_topic = DW.NewTopicPost(submit_text='Post')
 
         announcements_table = FW.AnnouncementsTable()
@@ -186,30 +185,6 @@ class RootController(BaseController, DispatchIndex, FeedController):
         else:
             raise exc.HTTPNotFound()
 
-    @h.vardec
-    @expose()
-    @validate(W.forum_subscription_form)
-    def subscribe(self, **kw):
-        require_authenticated()
-        forum = kw.pop('forum', [])
-        thread = kw.pop('thread', [])
-        objs = []
-        for data in forum:
-            objs.append(
-                dict(obj=model.Forum.query.get(shortname=data['shortname'],
-                                               app_config_id=c.app.config._id),
-                     subscribed=bool(data.get('subscribed'))))
-        for data in thread:
-            objs.append(dict(obj=model.Thread.query.get(_id=data['id']),
-                             subscribed=bool(data.get('subscribed'))))
-        for obj in objs:
-            # TODO where is this called from?
-            if obj['subscribed']:
-                obj['obj'].subscriptions[str(c.user._id)] = True
-            else:
-                obj['obj'].subscriptions.pop(str(c.user._id), None)
-        redirect(request.referer)
-
     def get_feed(self, project, app, user):
         """Return a :class:`allura.controllers.feed.FeedArgs` object describing
         the xml feed for this controller.
@@ -252,11 +227,6 @@ class RootController(BaseController, DispatchIndex, FeedController):
         grouping['year'] = {'$year': '$timestamp'}
         grouping['month'] = {'$month': '$timestamp'}
         grouping['day'] = {'$dayOfMonth': '$timestamp'}
-        {
-            'year': {'$year': '$timestamp'},
-            'month': {'$month': '$timestamp'},
-            'day': {'$dayOfMonth': '$timestamp'},
-        }
         mongo_data = model.ForumPost.query.aggregate([
             {'$match': {
                 'discussion_id': discussion_id_q,

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/ForgeDiscussion/forgediscussion/templates/discussion_widgets/forum_summary.html
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/templates/discussion_widgets/forum_summary.html b/ForgeDiscussion/forgediscussion/templates/discussion_widgets/forum_summary.html
deleted file mode 100644
index a795858..0000000
--- a/ForgeDiscussion/forgediscussion/templates/discussion_widgets/forum_summary.html
+++ /dev/null
@@ -1,28 +0,0 @@
-{#-
-       Licensed to the Apache Software Foundation (ASF) under one
-       or more contributor license agreements.  See the NOTICE file
-       distributed with this work for additional information
-       regarding copyright ownership.  The ASF licenses this file
-       to you under the Apache License, Version 2.0 (the
-       "License"); you may not use this file except in compliance
-       with the License.  You may obtain a copy of the License at
-
-         http://www.apache.org/licenses/LICENSE-2.0
-
-       Unless required by applicable law or agreed to in writing,
-       software distributed under the License is distributed on an
-       "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-       KIND, either express or implied.  See the License for the
-       specific language governing permissions and limitations
-       under the License.
--#}
-<a href="{{value.url()}}">{{value.name}}</a>({{value.shortname}})<br/>
-{% if value.subforums %}
-  <b>Subforums:</b>
-  {% for sf in value.subforums %}
-    <span>
-      {% if loop.index0 != 0 %}, {% endif %}
-      <a href="{{sf.url()}}">{{sf.name}}</a>
-    </span>
-  {% endfor %}
-{% endif %}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/ForgeDiscussion/forgediscussion/widgets/__init__.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/widgets/__init__.py b/ForgeDiscussion/forgediscussion/widgets/__init__.py
index 53322a7..02bbb9e 100644
--- a/ForgeDiscussion/forgediscussion/widgets/__init__.py
+++ b/ForgeDiscussion/forgediscussion/widgets/__init__.py
@@ -15,10 +15,10 @@
 #       specific language governing permissions and limitations
 #       under the License.
 
-from forum_widgets import ForumSubscriptionForm, ThreadSubscriptionForm, AnnouncementsTable
+from forum_widgets import ThreadSubscriptionForm, AnnouncementsTable
 from forum_widgets import ModerateThread, ForumHeader, ThreadHeader
 from forum_widgets import Post, Thread, Forum
 
 __all__ = [
-    'ForumSubscriptionForm', 'ThreadSubscriptionForm', 'AnnouncementsTable', 'ModerateThread', 'ForumHeader',
+    'ThreadSubscriptionForm', 'AnnouncementsTable', 'ModerateThread', 'ForumHeader',
     'ThreadHeader', 'Post', 'Thread', 'Forum']

http://git-wip-us.apache.org/repos/asf/allura/blob/a02c9137/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
index 8c0c07f..fb063d9 100644
--- a/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
+++ b/ForgeDiscussion/forgediscussion/widgets/forum_widgets.py
@@ -30,35 +30,6 @@ from allura.lib.widgets.subscriptions import SubscribeForm
 from forgediscussion import model as M
 
 
-class _ForumSummary(ew_core.Widget):
-    template = 'jinja:forgediscussion:templates/discussion_widgets/forum_summary.html'
-    defaults = dict(
-        ew_core.Widget.defaults,
-        name=None,
-        value=None,
-        show_label=True,
-        label=None)
-
-
-class _ForumsTable(ew.TableField):
-
-    class fields(ew_core.NameList):
-        _id = ew.HiddenField(validator=V.Ming(M.ForumThread))
-        num_topics = ffw.DisplayOnlyField(show_label=True, label='Topics')
-        num_posts = ffw.DisplayOnlyField(show_label=True, label='Posts')
-        last_post = ffw.DisplayOnlyField(show_label=True)
-        subscribed = ew.Checkbox(suppress_label=True, show_label=True)
-    fields.insert(0, _ForumSummary())
-
-
-class ForumSubscriptionForm(CsrfForm):
-
-    class fields(ew_core.NameList):
-        forums = _ForumsTable()
-        page_list = ffw.PageList()
-    submit_text = 'Update Subscriptions'
-
-
 class _ThreadsTable(DW._ThreadsTable):
 
     class fields(ew_core.NameList):
@@ -71,7 +42,7 @@ class _ThreadsTable(DW._ThreadsTable):
         flags = ffw.DisplayOnlyField(show_label=True)
         last_post = ffw.DisplayOnlyField(show_label=True)
         subscription = ew.Checkbox(suppress_label=True, show_label=True)
-    defaults = dict(DW._ThreadsTable.defaults, div_id='forum_threads')
+    defaults = dict(DW._ThreadsTable.defaults, div_id='forum_threads', allow_subscriptions=True)
 
 
 class ThreadSubscriptionForm(DW.SubscriptionForm):
@@ -93,7 +64,7 @@ class AnnouncementsTable(DW._ThreadsTable):
         num_views = ffw.DisplayOnlyField(show_label=True)
         flags = ffw.DisplayOnlyField(show_label=True)
         last_post = ffw.DisplayOnlyField(show_label=True)
-    defaults = dict(DW._ThreadsTable.defaults, div_id='announcements')
+    defaults = dict(DW._ThreadsTable.defaults, div_id='announcements', allow_subscriptions=False)
     name = 'announcements'
 
 
@@ -127,11 +98,13 @@ class ModerateThread(CsrfForm):
         delete = ew.SubmitButton(label='Delete Thread')
 
 
-class ForumHeader(DW.DiscussionHeader):
+class ForumHeader(DW.HierWidget):
     template = 'jinja:forgediscussion:templates/discussion_widgets/forum_header.html'
-    widgets = dict(DW.DiscussionHeader.widgets,
+    params = ['value']
+    value = None
+    widgets = dict(DW.HierWidget.widgets,
                    announcements_table=AnnouncementsTable(),
-                   forum_subscription_form=ForumSubscriptionForm())
+                   )
 
 
 class ThreadHeader(DW.ThreadHeader):
@@ -157,13 +130,19 @@ class Thread(DW.Thread):
                    post=Post())
 
 
-class Forum(DW.Discussion):
+class Forum(DW.HierWidget):
     template = 'jinja:forgediscussion:templates/discussion_widgets/discussion.html'
-    allow_create_thread = True
-    show_subject = True
-    widgets = dict(DW.Discussion.widgets,
-                   discussion_header=ForumHeader(),
-                   forum_subscription_form=ForumSubscriptionForm(),
-                   whole_forum_subscription_form=SubscribeForm(),
+    defaults = dict(
+        DW.HierWidget.defaults,
+        value=None,
+        threads=None,
+        show_subject=True,
+        allow_create_thread=True
+    )
+    widgets = dict(DW.HierWidget.widgets,
                    subscription_form=ThreadSubscriptionForm()
                    )
+
+    def resources(self):
+        for r in super(Forum, self).resources():
+            yield r


[9/9] allura git commit: [#7981] add per-thread subscription icon

Posted by br...@apache.org.
[#7981] add per-thread subscription icon


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/3b8240fc
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/3b8240fc
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/3b8240fc

Branch: refs/heads/master
Commit: 3b8240fc25e58976aafcccc946a984865c8d03cb
Parents: 91837a7
Author: Dave Brondsema <da...@brondsema.net>
Authored: Wed Nov 30 16:23:31 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:21 2016 -0500

----------------------------------------------------------------------
 .../lib/widgets/resources/js/subscriptions.js   |  6 ++++--
 .../forgediscussion/controllers/forum.py        | 20 ++++++++++++++++++++
 .../templates/discussionforums/thread.html      |  1 +
 .../forgediscussion/templates/index.html        |  2 +-
 ForgeTracker/forgetracker/tracker_main.py       |  1 +
 ForgeWiki/forgewiki/wiki_main.py                |  1 +
 6 files changed, 28 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/3b8240fc/Allura/allura/lib/widgets/resources/js/subscriptions.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/subscriptions.js b/Allura/allura/lib/widgets/resources/js/subscriptions.js
index 5e61caf..14d37a7 100644
--- a/Allura/allura/lib/widgets/resources/js/subscriptions.js
+++ b/Allura/allura/lib/widgets/resources/js/subscriptions.js
@@ -69,10 +69,12 @@ SubscriptionForm = React.createClass({
         if (resp.subscribed_to_tool) {
           text = "You can't subscribe to this ";
           text += this.props.thing;
-          text += " because you are already subscribed to the entire tool";
+          text += " because you are already subscribed to the entire ";
+          text += resp.subscribed_to_entire_name ? resp.subscribed_to_entire_name : "tool";
+          text += ".";
         } else {
           var action = resp.subscribed ? 'subscribed to' : 'unsubscribed from';
-          text = 'Successfully ' + action + ' this ' + this.props.thing;
+          text = 'Successfully ' + action + ' this ' + this.props.thing + '.';
         }
         $(link).tooltipster('content', text).tooltipster('show');
         if (this.state.tooltip_timeout) {

http://git-wip-us.apache.org/repos/asf/allura/blob/3b8240fc/ForgeDiscussion/forgediscussion/controllers/forum.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/forum.py b/ForgeDiscussion/forgediscussion/controllers/forum.py
index 3b81842..ee00fe2 100644
--- a/ForgeDiscussion/forgediscussion/controllers/forum.py
+++ b/ForgeDiscussion/forgediscussion/controllers/forum.py
@@ -161,6 +161,7 @@ class ForumController(DiscussionController):
 
 
 class ForumThreadController(ThreadController):
+    W = WidgetConfig
 
     @expose('jinja:forgediscussion:templates/discussionforums/thread.html')
     @validate(dict(page=validators.Int(if_empty=0, if_invalid=0),
@@ -168,6 +169,7 @@ class ForumThreadController(ThreadController):
     def index(self, limit=25, page=0, count=0, **kw):
         if self.thread.discussion.deleted and not has_access(c.app, 'configure')():
             redirect(self.thread.discussion.url() + 'deleted')
+        c.thread_subscription_form = self.W.subscribe_form
         return super(ForumThreadController, self).index(limit=limit, page=page, count=count, show_moderate=True, **kw)
 
     @h.vardec
@@ -191,6 +193,24 @@ class ForumThreadController(ThreadController):
         self.thread.flags = args.pop('flags', [])
         redirect(self.thread.url())
 
+    @expose('json:')
+    @require_post()
+    @validate(W.subscribe_form)
+    def subscribe(self, subscribe=None, unsubscribe=None, **kw):
+        if subscribe:
+            self.thread.subscribe()
+        elif unsubscribe:
+            self.thread.unsubscribe()
+
+        sub_tool = M.Mailbox.subscribed()
+        sub_forum = M.Mailbox.subscribed(artifact=self.discussion)
+        return {
+            'status': 'ok',
+            'subscribed': M.Mailbox.subscribed(artifact=self.thread),
+            'subscribed_to_tool': sub_tool or sub_forum,
+            'subscribed_to_entire_name': 'forum' if sub_forum else 'discussion tool',
+        }
+
 
 class ForumPostController(PostController):
 

http://git-wip-us.apache.org/repos/asf/allura/blob/3b8240fc/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html b/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
index 367cd8a..d37d044 100644
--- a/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
+++ b/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
@@ -31,6 +31,7 @@
   {% endif %}
   {# {{ g.icons['tag'].render(title='Label This', extra_css='thread_tag') }}   these labels aren't used anywhere ... #}
   {{ g.icons['feed'].render(href='feed.rss', title='Follow This', extra_css='thread_feed0') }}
+  {{ c.thread_subscription_form.display(value=thread.subscribed(), action='subscribe', style='icon', thing='thread') }}
 {% endblock %}
 
 {% block edit_box %}

http://git-wip-us.apache.org/repos/asf/allura/blob/3b8240fc/ForgeDiscussion/forgediscussion/templates/index.html
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/templates/index.html b/ForgeDiscussion/forgediscussion/templates/index.html
index da2c3a9..b43fedc 100644
--- a/ForgeDiscussion/forgediscussion/templates/index.html
+++ b/ForgeDiscussion/forgediscussion/templates/index.html
@@ -21,5 +21,5 @@
 
 {% block actions %}
   {{ super() }}
-  {{c.whole_forum_subscription_form.display(value=c.subscribed, action='subscribe_to_forum', style='icon', thing='discussion')}}
+  {{c.whole_forum_subscription_form.display(value=c.subscribed, action='subscribe_to_forum', style='icon', thing='forum')}}
 {% endblock %}

http://git-wip-us.apache.org/repos/asf/allura/blob/3b8240fc/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 42dffb3..3227c4f 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -1559,6 +1559,7 @@ class TicketController(BaseController, FeedController):
             'status': 'ok',
             'subscribed': M.Mailbox.subscribed(artifact=self.ticket),
             'subscribed_to_tool': M.Mailbox.subscribed(),
+            'subscribed_to_entire_name': 'ticket tracker',
         }
 
     @expose('json:')

http://git-wip-us.apache.org/repos/asf/allura/blob/3b8240fc/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index 379914a..3fb7fb3 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -793,6 +793,7 @@ class PageController(BaseController, FeedController):
             'status': 'ok',
             'subscribed': M.Mailbox.subscribed(artifact=self.page),
             'subscribed_to_tool': M.Mailbox.subscribed(),
+            'subscribed_to_entire_name': 'wiki',
         }
 
 


[8/9] allura git commit: [#7981] SubscriptionForm gets subscribed_to_tool from response, doesn't need it passed in beforehand

Posted by br...@apache.org.
[#7981] SubscriptionForm gets subscribed_to_tool from response, doesn't need it passed in beforehand


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/91837a7c
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/91837a7c
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/91837a7c

Branch: refs/heads/master
Commit: 91837a7c637d9634233fd0d6538f5634beb7ceb3
Parents: 5a45aa3
Author: Dave Brondsema <da...@brondsema.net>
Authored: Tue Nov 29 13:43:14 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:21 2016 -0500

----------------------------------------------------------------------
 Allura/allura/lib/widgets/resources/js/subscriptions.js | 2 --
 Allura/allura/lib/widgets/subscriptions.py              | 1 -
 Allura/allura/templates/repo/tree.html                  | 2 +-
 Allura/allura/templates/widgets/subscribe.html          | 1 -
 ForgeBlog/forgeblog/main.py                             | 1 -
 ForgeTracker/forgetracker/templates/tracker/ticket.html | 2 +-
 ForgeTracker/forgetracker/tracker_main.py               | 2 --
 ForgeWiki/forgewiki/wiki_main.py                        | 1 -
 8 files changed, 2 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/Allura/allura/lib/widgets/resources/js/subscriptions.js
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/resources/js/subscriptions.js b/Allura/allura/lib/widgets/resources/js/subscriptions.js
index ceec169..5e61caf 100644
--- a/Allura/allura/lib/widgets/resources/js/subscriptions.js
+++ b/Allura/allura/lib/widgets/resources/js/subscriptions.js
@@ -23,7 +23,6 @@ var dom = React.createElement;
 var state = {
   'thing': 'tool',
   'subscribed': false,
-  'subscribed_to_tool': false,
   'url': '',
   'icon': {}
 };
@@ -64,7 +63,6 @@ SubscriptionForm = React.createClass({
       if (resp.status == 'ok') {
         set_state({
           subscribed: resp.subscribed,
-          subscribed_to_tool: resp.subscribed_to_tool
         });
         var link = this.getLinkNode();
         var text = null;

http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/Allura/allura/lib/widgets/subscriptions.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/subscriptions.py b/Allura/allura/lib/widgets/subscriptions.py
index 2595b41..2409d68 100644
--- a/Allura/allura/lib/widgets/subscriptions.py
+++ b/Allura/allura/lib/widgets/subscriptions.py
@@ -77,7 +77,6 @@ class SubscribeForm(ew.SimpleForm):
         ew.SimpleForm.defaults,
         thing='tool',
         style='icon',
-        tool_subscribed=False,
         value=None)
 
     class fields(ew_core.NameList):

http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/Allura/allura/templates/repo/tree.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/repo/tree.html b/Allura/allura/templates/repo/tree.html
index 3721225..2f0cd03 100644
--- a/Allura/allura/templates/repo/tree.html
+++ b/Allura/allura/templates/repo/tree.html
@@ -65,7 +65,7 @@ form.tarball button:hover {
 
 {{ g.icons['history'].render(href='%slog/?path=%s' % (commit.url(), path), show_title=True) }}
 {% if c.user and c.user != c.user.anonymous() %}
-  {{c.subscribe_form.display(value=tool_subscribed, tool_subscribed=tool_subscribed, action='subscribe', style='icon')}}
+  {{c.subscribe_form.display(value=tool_subscribed, action='subscribe', style='icon')}}
 {% endif %}
 {{ g.icons['feed'].render(href='{}feed/'.format(c.app.url)) }}
 {% endblock %}

http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/Allura/allura/templates/widgets/subscribe.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/subscribe.html b/Allura/allura/templates/widgets/subscribe.html
index 9f46e9c..0601d5f 100644
--- a/Allura/allura/templates/widgets/subscribe.html
+++ b/Allura/allura/templates/widgets/subscribe.html
@@ -27,7 +27,6 @@
   document.SUBSCRIPTION_OPTIONS = {
     "thing": "{{thing}}",
     "subscribed": {{"true" if value else "false"}},
-    "subscribed_to_tool": {{"true" if tool_subscribed else "false"}},
     "url": "{{action}}",
     "icon": {
       "css": "{{g.icons['mail'].css}}"

http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/ForgeBlog/forgeblog/main.py
----------------------------------------------------------------------
diff --git a/ForgeBlog/forgeblog/main.py b/ForgeBlog/forgeblog/main.py
index a200ea9..cb11239 100644
--- a/ForgeBlog/forgeblog/main.py
+++ b/ForgeBlog/forgeblog/main.py
@@ -354,7 +354,6 @@ class PostController(BaseController, FeedController):
         post = self._get_version(version)
         base_post = self.post
         subscribed = M.Mailbox.subscribed(artifact=self.post)
-        c.subscribe_form.tool_subscribed = M.Mailbox.subscribed()
         return dict(post=post, base_post=base_post,
                     page=page, limit=limit, count=post_count,
                     subscribed=subscribed)

http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/ForgeTracker/forgetracker/templates/tracker/ticket.html
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/templates/tracker/ticket.html b/ForgeTracker/forgetracker/templates/tracker/ticket.html
index afe0253..8665611 100644
--- a/ForgeTracker/forgetracker/templates/tracker/ticket.html
+++ b/ForgeTracker/forgetracker/templates/tracker/ticket.html
@@ -36,7 +36,7 @@
 {% block actions %}
   {{ g.icons['feed'].render(href='feed.rss', title='Follow this Ticket') }}
 {% if c.user and c.user != c.user.anonymous() %}
-  {{c.subscribe_form.display(value=subscribed, tool_subscribed=tool_subscribed, action='subscribe', style='icon')}}
+  {{c.subscribe_form.display(value=subscribed, action='subscribe', style='icon')}}
 {% endif %}
 {% if h.has_access(ticket.app, 'admin') %}
   {{ g.icons['move'].render(show_title=True, href='move') }}

http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/ForgeTracker/forgetracker/tracker_main.py
----------------------------------------------------------------------
diff --git a/ForgeTracker/forgetracker/tracker_main.py b/ForgeTracker/forgetracker/tracker_main.py
index 98011ef..42dffb3 100644
--- a/ForgeTracker/forgetracker/tracker_main.py
+++ b/ForgeTracker/forgetracker/tracker_main.py
@@ -1382,7 +1382,6 @@ class TicketController(BaseController, FeedController):
             c.ticket_custom_field = W.ticket_custom_field
             c.vote_form = W.vote_form
             tool_subscribed = M.Mailbox.subscribed()
-            c.subscribe_form.tool_subscribed = tool_subscribed
             if tool_subscribed:
                 subscribed = False
             else:
@@ -1393,7 +1392,6 @@ class TicketController(BaseController, FeedController):
             voting_enabled = self.ticket.app.config.options.get('EnableVoting')
             return dict(ticket=self.ticket, globals=c.app.globals,
                         allow_edit=has_access(self.ticket, 'update')(),
-                        tool_subscribed=tool_subscribed,
                         subscribed=subscribed, voting_enabled=voting_enabled,
                         page=page, limit=limit, count=post_count)
         else:

http://git-wip-us.apache.org/repos/asf/allura/blob/91837a7c/ForgeWiki/forgewiki/wiki_main.py
----------------------------------------------------------------------
diff --git a/ForgeWiki/forgewiki/wiki_main.py b/ForgeWiki/forgewiki/wiki_main.py
index ace38b6..379914a 100644
--- a/ForgeWiki/forgewiki/wiki_main.py
+++ b/ForgeWiki/forgewiki/wiki_main.py
@@ -596,7 +596,6 @@ class PageController(BaseController, FeedController):
         next = cur + 1
         hide_left_bar = not (c.app.show_left_bar)
         subscribed_to_page = M.Mailbox.subscribed(artifact=self.page)
-        c.subscribe_form.tool_subscribed = M.Mailbox.subscribed()
         return dict(
             page=page,
             cur=cur, prev=prev, next=next,


[4/9] allura git commit: [#7981] show appropriate items for anonymous users, tighten up thread list display

Posted by br...@apache.org.
[#7981] show appropriate items for anonymous users, tighten up thread list display


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/c8e70762
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/c8e70762
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/c8e70762

Branch: refs/heads/master
Commit: c8e70762c9964c4fa0e61092fdcc4def8b8368e6
Parents: 23cf356
Author: Dave Brondsema <da...@brondsema.net>
Authored: Thu Nov 17 15:28:04 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:20 2016 -0500

----------------------------------------------------------------------
 Allura/allura/lib/helpers.py                       |  2 +-
 Allura/allura/lib/security.py                      |  8 ++++++++
 Allura/allura/nf/allura/css/site_style.css         |  6 ++++++
 Allura/allura/templates/widgets/page_list.html     | 17 ++++++++++-------
 .../templates/widgets/subscription_form.html       |  9 ++++++---
 Allura/allura/templates/widgets/thread_widget.html | 10 +++++++---
 Allura/allura/templates/widgets/threads_table.html | 16 +++++++++-------
 .../templates/discussionforums/create_topic.html   |  3 +++
 .../templates/discussionforums/thread.html         |  2 +-
 9 files changed, 51 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/Allura/allura/lib/helpers.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/helpers.py b/Allura/allura/lib/helpers.py
index b90692a..181fdcd 100644
--- a/Allura/allura/lib/helpers.py
+++ b/Allura/allura/lib/helpers.py
@@ -64,7 +64,7 @@ from allura.lib import AsciiDammit
 from allura.lib import utils
 
 # import to make available to templates, don't delete:
-from .security import has_access
+from .security import has_access, is_allowed_by_role
 
 
 log = logging.getLogger(__name__)

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/Allura/allura/lib/security.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/security.py b/Allura/allura/lib/security.py
index bd98c9a..41691f4 100644
--- a/Allura/allura/lib/security.py
+++ b/Allura/allura/lib/security.py
@@ -441,6 +441,14 @@ def all_allowed(obj, user_or_role=None, project=None):
     return perms
 
 
+def is_allowed_by_role(obj, permission, role_name, project):
+    # probably more effecient ways of doing these, e.g. through a modified has_access
+    # but this is easy
+    from allura import model as M
+    role = M.ProjectRole.by_name(role_name, project)
+    return permission in all_allowed(obj, role, project)
+
+
 def require(predicate, message=None):
     '''
     Example: ``require(has_access(c.app, 'read'))``

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/Allura/allura/nf/allura/css/site_style.css
----------------------------------------------------------------------
diff --git a/Allura/allura/nf/allura/css/site_style.css b/Allura/allura/nf/allura/css/site_style.css
index c114f94..026d902 100644
--- a/Allura/allura/nf/allura/css/site_style.css
+++ b/Allura/allura/nf/allura/css/site_style.css
@@ -2593,6 +2593,12 @@ div.attachment_item{
 .forum-list th .ico {
   margin-left: 4px;
 }
+.forum-list .topic h3 {
+    padding-left: 0;
+}
+.forum-list th .icon {
+    margin-left: 3px;
+}
 
 .gravatar b {
   overflow: visible;

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/Allura/allura/templates/widgets/page_list.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/page_list.html b/Allura/allura/templates/widgets/page_list.html
index 64ff18f..2621601 100644
--- a/Allura/allura/templates/widgets/page_list.html
+++ b/Allura/allura/templates/widgets/page_list.html
@@ -16,12 +16,15 @@
        specific language governing permissions and limitations
        under the License.
 -#}
+{% set pager_output = paginator.pager(
+        format='$link_first $link_previous ~2~ $link_next $link_last' + (show_label and ' (Page $page of $page_count)' or ''),
+        show_if_single_page=show_if_single_page
+    ) %}
+{% if pager_output.strip() %}
 <div>
-  <div class="page_list">
-    {{paginator.pager(
-            format='$link_first $link_previous ~2~ $link_next $link_last' + (show_label and ' (Page $page of $page_count)' or ''),
-            show_if_single_page=show_if_single_page
-        )}}
-  </div>
-  <div class="clear"></div>
+    <div class="page_list">
+      {{ pager_output }}
+    </div>
+    <div class="clear"></div>
 </div>
+{% endif %}

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/Allura/allura/templates/widgets/subscription_form.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/subscription_form.html b/Allura/allura/templates/widgets/subscription_form.html
index 1a58efe..7b6ef2f 100644
--- a/Allura/allura/templates/widgets/subscription_form.html
+++ b/Allura/allura/templates/widgets/subscription_form.html
@@ -19,14 +19,17 @@
 {% import 'allura:templates/jinja_master/lib.html' as lib with context %}
 <div {{attrs|default({}, true)|xmlattr}} class="discussion_subscription_form">
   <div class="clear"></div>
-  <div class="pagination_size">{{widget.fields['page_list'].display(limit=limit, page=page, count=count)}}</div>
+  {% set pager_widget_output = widget.fields['page_list'].display(limit=limit, page=page, count=count) %}
+  {% if pager_widget_output.strip() %}
+    <div class="pagination_size">{{ pager_widget_output }}</div>
+  {% endif %}
   <form method="{{method}}" action="{{action}}" {% if enctype %}enctype="{{enctype}}"{% endif %} class="follow_form">
     {{widget.fields['threads'].display(value=threads)}}
+    {% if threads and not c.user.is_anonymous() %}
     <p>
-    {% if threads %}
     <input type="submit" value="Update email subscriptions"/>
-    {% endif %}
     </p>
+    {% endif %}
     {% if method.upper() == 'POST' %}{{lib.csrf_token()}}{% endif %}
   </form>
   {{widget.fields['page_list'].display(limit=limit, page=page, count=count)}}

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/Allura/allura/templates/widgets/thread_widget.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/thread_widget.html b/Allura/allura/templates/widgets/thread_widget.html
index fa26fd7..f9a6d9d 100644
--- a/Allura/allura/templates/widgets/thread_widget.html
+++ b/Allura/allura/templates/widgets/thread_widget.html
@@ -19,8 +19,8 @@
 {% import 'allura:templates/jinja_master/lib.html' as lib with context %}
 
 <div>
-                <div class="row">
-                        <div class="column grid_12">
+  <div class="row">
+     <div class="column grid_12">
       {% if limit %}
         {{widgets.page_list.display(limit=limit, page=page, count=count)}}
       {% endif %}
@@ -68,5 +68,9 @@
       </div>
     </div>
   </div>
-
+{% elif c.user.is_anonymous() and h.is_allowed_by_role(value, 'post', '*authenticated', c.project)%}
+  <hr>
+  <p>
+    <a href="{{ tg.config.get('auth.login_url', '/auth/') }}">Log in</a> to post a comment.
+  </p>
 {% endif %}

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/Allura/allura/templates/widgets/threads_table.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/threads_table.html b/Allura/allura/templates/widgets/threads_table.html
index 5a52f99..2101606 100644
--- a/Allura/allura/templates/widgets/threads_table.html
+++ b/Allura/allura/templates/widgets/threads_table.html
@@ -22,7 +22,9 @@
   <table class="forum-list clear">
     <thead>
       <tr>
-        <th>{{ g.icons['mail'].render(tag='span', title='Subscriptions') }}</th>
+        {% if not c.user.is_anonymous() %}
+          <th>{{ g.icons['mail'].render(tag='span', title='Subscriptions') }}</th>
+        {% endif %}
         <th class="topic">Topic</th>
         <th>Posts</th>
         <th>Views</th>
@@ -32,11 +34,13 @@
     <tbody class="forum-list">
       {% for thread in value %}
       <tr>
-        <td>
-          <input type="checkbox" name="threads-{{loop.index0}}.subscription"
+        {% if not c.user.is_anonymous() %}
+          <td>
+            <input type="checkbox" name="threads-{{loop.index0}}.subscription"
                  {% if thread.subscription %}checked="checked"{% endif %}/>
-          <input type="hidden" name="threads-{{loop.index0}}._id" value="{{thread._id}}"/>
-        </td>
+            <input type="hidden" name="threads-{{loop.index0}}._id" value="{{thread._id}}"/>
+          </td>
+        {% endif %}
         {% if not thread.first_post %}
         <td class="topic">
           {% if 'flags' in thread and 'Sticky' in thread.flags %}
@@ -61,9 +65,7 @@
         {% else %}
           {% set author = thread.last_post.author() %}
           <td>
-          <p class="gravatar sm">
             By {{lib.gravatar(author, size=16)}} {{lib.user_link(author)}}<br />on {{thread.last_post.timestamp.strftime('%a %b %d, %Y %I:%M %p')}}
-          </p>
           </td>
         {% endif %}
       </tr>

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/ForgeDiscussion/forgediscussion/templates/discussionforums/create_topic.html
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/templates/discussionforums/create_topic.html b/ForgeDiscussion/forgediscussion/templates/discussionforums/create_topic.html
index b5e560f..852c2d6 100644
--- a/ForgeDiscussion/forgediscussion/templates/discussionforums/create_topic.html
+++ b/ForgeDiscussion/forgediscussion/templates/discussionforums/create_topic.html
@@ -25,6 +25,9 @@
 {% block edit_box %}
 {% if forums | length == 0 %}
   <p>You do not have permission to post in any forums.</p>
+  {% if c.user.is_anonymous() %}
+    <p><a href="{{ config.get('auth.login_url', '/auth/') }}">Click here to log in.</a></p>
+  {% endif %}
 {% else %}
   <div class="editbox">
     {{c.new_topic.display(action=c.app.url + 'save_new_topic',show_subject=True,forums=forums, current_forum=current_forum)}}

http://git-wip-us.apache.org/repos/asf/allura/blob/c8e70762/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html b/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
index 076790a..367cd8a 100644
--- a/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
+++ b/ForgeDiscussion/forgediscussion/templates/discussionforums/thread.html
@@ -29,7 +29,7 @@
   {% if show_moderate and h.has_access(thread, 'moderate')() %}
     {{ g.icons['moderate'].render(id='mod_thread_link') }}
   {% endif %}
-  {{ g.icons['tag'].render(title='Label This', extra_css='thread_tag') }}
+  {# {{ g.icons['tag'].render(title='Label This', extra_css='thread_tag') }}   these labels aren't used anywhere ... #}
   {{ g.icons['feed'].render(href='feed.rss', title='Follow This', extra_css='thread_feed0') }}
 {% endblock %}
 


[7/9] allura git commit: [#7981] disable per-thread checkboxes form, when subscribed at a higher level

Posted by br...@apache.org.
[#7981] disable per-thread checkboxes form, when subscribed at a higher level


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/5a45aa3f
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/5a45aa3f
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/5a45aa3f

Branch: refs/heads/master
Commit: 5a45aa3f0227e6bfa4db5869412be63fc598edde
Parents: dec2ab0
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Nov 18 17:52:18 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:21 2016 -0500

----------------------------------------------------------------------
 Allura/allura/templates/widgets/subscription_form.html |  3 ++-
 Allura/allura/templates/widgets/threads_table.html     | 11 ++++++++++-
 ForgeDiscussion/forgediscussion/controllers/forum.py   |  4 +++-
 3 files changed, 15 insertions(+), 3 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/5a45aa3f/Allura/allura/templates/widgets/subscription_form.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/subscription_form.html b/Allura/allura/templates/widgets/subscription_form.html
index 7b6ef2f..c03f8d2 100644
--- a/Allura/allura/templates/widgets/subscription_form.html
+++ b/Allura/allura/templates/widgets/subscription_form.html
@@ -25,7 +25,8 @@
   {% endif %}
   <form method="{{method}}" action="{{action}}" {% if enctype %}enctype="{{enctype}}"{% endif %} class="follow_form">
     {{widget.fields['threads'].display(value=threads)}}
-    {% if threads and not c.user.is_anonymous() %}
+    {% if threads and not c.user.is_anonymous() and
+            not c.subscribed and not c.tool_subscribed %}
     <p>
     <input type="submit" value="Update email subscriptions"/>
     </p>

http://git-wip-us.apache.org/repos/asf/allura/blob/5a45aa3f/Allura/allura/templates/widgets/threads_table.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/threads_table.html b/Allura/allura/templates/widgets/threads_table.html
index 873b537..c4f3d0b 100644
--- a/Allura/allura/templates/widgets/threads_table.html
+++ b/Allura/allura/templates/widgets/threads_table.html
@@ -18,6 +18,9 @@
 -#}
 {% import 'allura:templates/jinja_master/lib.html' as lib with context %}
 
+{% set forum_subscribed = c.subscribed %} {# set in controller #}
+{% set tool_subscribed = c.tool_subscribed %}
+
 <div{{ {'id': div_id}|xmlattr }}>
   <table class="forum-list clear">
     <thead>
@@ -36,7 +39,13 @@
       <tr>
         {% if not c.user.is_anonymous() and allow_subscriptions %}
           <td>
-            <input type="checkbox" name="threads-{{loop.index0}}.subscription" {% if thread.subscribed() %}checked="checked"{% endif %} />
+            <input type="checkbox" name="threads-{{loop.index0}}.subscription"
+                   {%- if thread.subscribed() or forum_subscribed or tool_subscribed %} checked="checked" {% endif -%}
+                   {%- if forum_subscribed or tool_subscribed %}
+                        disabled title="You are subscribed to this entire {% if forum_subscribed %}Forum. Unsubscribe with mail icon in upper right, or on Account - Subscriptions page.
+                            {%- else %}Discussion tool.  Unsubscribe on Account - Subscriptions page.{% endif %}"
+                   {%- endif -%}
+            />
             <input type="hidden" name="threads-{{loop.index0}}._id" value="{{thread._id}}"/>
           </td>
         {% endif %}

http://git-wip-us.apache.org/repos/asf/allura/blob/5a45aa3f/ForgeDiscussion/forgediscussion/controllers/forum.py
----------------------------------------------------------------------
diff --git a/ForgeDiscussion/forgediscussion/controllers/forum.py b/ForgeDiscussion/forgediscussion/controllers/forum.py
index 52b3b7c..3b81842 100644
--- a/ForgeDiscussion/forgediscussion/controllers/forum.py
+++ b/ForgeDiscussion/forgediscussion/controllers/forum.py
@@ -106,7 +106,9 @@ class ForumController(DiscussionController):
         if self.discussion.deleted:
             redirect(self.discussion.url() + 'deleted')
         limit, page, start = g.handle_paging(limit, page)
-        c.subscribed = M.Mailbox.subscribed(artifact=self.discussion)
+        if not c.user.is_anonymous():
+            c.subscribed = M.Mailbox.subscribed(artifact=self.discussion)
+            c.tool_subscribed = M.Mailbox.subscribed()
         threads = DM.ForumThread.query.find(dict(discussion_id=self.discussion._id, num_replies={'$gt': 0})) \
                                       .sort([('flags', pymongo.DESCENDING), ('last_post_date', pymongo.DESCENDING)])
         c.discussion = self.W.discussion


[2/9] allura git commit: [#7981] allow notifications to be fired against multiple artifacts so that Thread- and Forum-level subscriptions work

Posted by br...@apache.org.
[#7981] allow notifications to be fired against multiple artifacts so that Thread- and Forum-level subscriptions work


Project: http://git-wip-us.apache.org/repos/asf/allura/repo
Commit: http://git-wip-us.apache.org/repos/asf/allura/commit/a7ef4578
Tree: http://git-wip-us.apache.org/repos/asf/allura/tree/a7ef4578
Diff: http://git-wip-us.apache.org/repos/asf/allura/diff/a7ef4578

Branch: refs/heads/master
Commit: a7ef4578ebb1671cfe272790d8e2fed87f3ae277
Parents: 59a6a34
Author: Dave Brondsema <da...@brondsema.net>
Authored: Fri Nov 18 15:26:47 2016 -0500
Committer: Dave Brondsema <da...@brondsema.net>
Committed: Mon Dec 5 11:39:20 2016 -0500

----------------------------------------------------------------------
 Allura/allura/model/discuss.py            | 10 +++++----
 Allura/allura/model/notification.py       | 29 +++++++++++++-------------
 Allura/allura/tasks/notification_tasks.py |  4 ++--
 Allura/allura/tests/test_tasks.py         |  4 ++--
 4 files changed, 25 insertions(+), 22 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/a7ef4578/Allura/allura/model/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/discuss.py b/Allura/allura/model/discuss.py
index 19c0ea5..2af6146 100644
--- a/Allura/allura/model/discuss.py
+++ b/Allura/allura/model/discuss.py
@@ -758,16 +758,18 @@ class Post(Message, VersionedArtifact, ActivityObject):
             n = Notification.query.get(_id=msg_id)
             if n:
                 # 'approved' notification also exists, re-send
-                n.fire_notification_task(artifact, 'message')
+                n.fire_notification_task([artifact, self.thread], 'message')
             else:
                 # 'approved' notification does not exist, create
                 notification_params['message_id'] = msg_id
         if not n:
-            n = Notification.post(artifact, 'message', **notification_params)
+            # artifact is Forum (or artifact like WikiPage)
+            n = Notification.post(artifact, 'message',
+                                  additional_artifacts_to_match_subscriptions=self.thread,
+                                  **notification_params)
         if not n:
             return
-        if (hasattr(artifact, "monitoring_email")
-                and artifact.monitoring_email):
+        if getattr(artifact, 'monitoring_email', None):
             if hasattr(artifact, 'notify_post'):
                 if artifact.notify_post:
                     n.send_simple(artifact.monitoring_email)

http://git-wip-us.apache.org/repos/asf/allura/blob/a7ef4578/Allura/allura/model/notification.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/notification.py b/Allura/allura/model/notification.py
index 955a75d..52ef451 100644
--- a/Allura/allura/model/notification.py
+++ b/Allura/allura/model/notification.py
@@ -43,7 +43,7 @@ from pylons import tmpl_context as c, app_globals as g
 from tg import config
 import pymongo
 import jinja2
-from paste.deploy.converters import asbool
+from paste.deploy.converters import asbool, aslist
 
 from ming import schema as S
 from ming.orm import FieldProperty, ForeignIdProperty, RelationProperty, session
@@ -108,24 +108,23 @@ class Notification(MappedClass):
     )
 
     @classmethod
-    def post(cls, artifact, topic, **kw):
-        '''Create a notification and  send the notify message'''
+    def post(cls, artifact, topic, additional_artifacts_to_match_subscriptions=None, **kw):
+        '''Create a notification and send the notify message'''
         n = cls._make_notification(artifact, topic, **kw)
         if n:
             # make sure notification is flushed in time for task to process it
             session(n).flush(n)
-            n.fire_notification_task(artifact, topic)
+            artifacts = [artifact] + aslist(additional_artifacts_to_match_subscriptions)
+            n.fire_notification_task(artifacts, topic)
         return n
 
-    def fire_notification_task(self, artifact, topic):
+    def fire_notification_task(self, artifacts, topic):
         import allura.tasks.notification_tasks
-        allura.tasks.notification_tasks.notify.post(
-            self._id, artifact.index_id(), topic)
+        allura.tasks.notification_tasks.notify.post(self._id, [a.index_id() for a in artifacts], topic)
 
     @classmethod
     def post_user(cls, user, artifact, topic, **kw):
-        '''Create a notification and deliver directly to a user's flash
-    mailbox'''
+        '''Create a notification and deliver directly to a user's flash mailbox'''
         try:
             mbox = Mailbox(user_id=user._id, is_flash=True,
                            project_id=None,
@@ -530,23 +529,25 @@ class Mailbox(MappedClass):
             artifact_index_id=artifact_index_id)).count() != 0
 
     @classmethod
-    def deliver(cls, nid, artifact_index_id, topic):
+    def deliver(cls, nid, artifact_index_ids, topic):
         '''Called in the notification message handler to deliver notification IDs
         to the appropriate mailboxes.  Atomically appends the nids
         to the appropriate mailboxes.
         '''
+
+        artifact_index_ids.append(None)  # get tool-wide ("None") and specific artifact subscriptions
         d = {
             'project_id': c.project._id,
             'app_config_id': c.app.config._id,
-            'artifact_index_id': {'$in': [None, artifact_index_id]},
+            'artifact_index_id': {'$in': artifact_index_ids},
             'topic': {'$in': [None, topic]}
         }
         mboxes = cls.query.find(d).all()
-        log.debug('Delivering notification %s to mailboxes [%s]', nid, ', '.join(
-            [str(m._id) for m in mboxes]))
+        log.debug('Delivering notification %s to mailboxes [%s]', nid, ', '.join([str(m._id) for m in mboxes]))
         for mbox in mboxes:
             try:
                 mbox.query.update(
+                    # _id is automatically specified by ming's "query", so this matches the current mbox
                     {'$push': dict(queue=nid),
                      '$set': dict(last_modified=datetime.utcnow(),
                                   queue_empty=False),
@@ -558,7 +559,7 @@ class Mailbox(MappedClass):
                 # mboxes for this notification get skipped and lost forever
                 log.exception(
                     'Error adding notification: %s for artifact %s on project %s to user %s',
-                    nid, artifact_index_id, c.project._id, mbox.user_id)
+                    nid, artifact_index_ids, c.project._id, mbox.user_id)
 
     @classmethod
     def fire_ready(cls):

http://git-wip-us.apache.org/repos/asf/allura/blob/a7ef4578/Allura/allura/tasks/notification_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tasks/notification_tasks.py b/Allura/allura/tasks/notification_tasks.py
index a6b7564..e370222 100644
--- a/Allura/allura/tasks/notification_tasks.py
+++ b/Allura/allura/tasks/notification_tasks.py
@@ -19,7 +19,7 @@ from allura.lib.decorators import task
 
 
 @task
-def notify(n_id, ref_id, topic):
+def notify(n_id, ref_ids, topic):
     from allura import model as M
-    M.Mailbox.deliver(n_id, ref_id, topic)
+    M.Mailbox.deliver(n_id, ref_ids, topic)
     M.Mailbox.fire_ready()

http://git-wip-us.apache.org/repos/asf/allura/blob/a7ef4578/Allura/allura/tests/test_tasks.py
----------------------------------------------------------------------
diff --git a/Allura/allura/tests/test_tasks.py b/Allura/allura/tests/test_tasks.py
index 7224ec0..abfa021 100644
--- a/Allura/allura/tests/test_tasks.py
+++ b/Allura/allura/tests/test_tasks.py
@@ -481,8 +481,8 @@ class TestNotificationTasks(unittest.TestCase):
     def test_delivers_messages(self):
         with mock.patch.object(M.Mailbox, 'deliver') as deliver:
             with mock.patch.object(M.Mailbox, 'fire_ready') as fire_ready:
-                notification_tasks.notify('42', '52', 'none')
-                assert deliver.called_with('42', '52', 'none')
+                notification_tasks.notify('42', ['52'], 'none')
+                assert deliver.called_with('42', ['52'], 'none')
                 assert fire_ready.called_with()