allura-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From brond...@apache.org
Subject [08/10] allura git commit: [#8253] Refactor codes and customizable emojis for reactions
Date Thu, 08 Nov 2018 21:53:49 GMT
[#8253] Refactor codes and customizable emojis for reactions


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

Branch: refs/heads/master
Commit: 8d3b43b10497c02e31d7fe67c95a508421860644
Parents: de72730
Author: Shalitha <shalithasuranga@gmail.com>
Authored: Thu Nov 1 15:18:50 2018 +0530
Committer: Dave Brondsema <dbrondsema@slashdotmedia.com>
Committed: Thu Nov 8 21:53:25 2018 +0000

----------------------------------------------------------------------
 Allura/allura/controllers/discuss.py            | 16 ++---
 Allura/allura/lib/app_globals.py                |  5 ++
 Allura/allura/lib/utils.py                      | 12 ++++
 Allura/allura/lib/widgets/discuss.py            | 72 ++++++++++++++++++++
 Allura/allura/model/artifact.py                 | 57 +++++++---------
 Allura/allura/public/nf/js/allura-base.js       | 69 -------------------
 .../allura/templates/widgets/post_widget.html   | 21 +-----
 Allura/allura/tests/functional/test_discuss.py  | 32 +++++----
 8 files changed, 140 insertions(+), 144 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/Allura/allura/controllers/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/controllers/discuss.py b/Allura/allura/controllers/discuss.py
index f2ea923..1e5e30a 100644
--- a/Allura/allura/controllers/discuss.py
+++ b/Allura/allura/controllers/discuss.py
@@ -379,19 +379,15 @@ class PostController(BaseController):
                 'error' : 'no_permission'
             }
         status = 'ok'
-        if r in self.post.reaction_list:
+        if r in utils.get_reaction_emoji_list():
             self.post.post_reaction(r, c.user)
         else:
             status = 'error' 
-        return {
-            'status' : status,
-            'react_thumbs_up': self.post.react_thumbs_up,
-            'react_thumbs_down': self.post.react_thumbs_down,
-            'react_laugh': self.post.react_laugh,
-            'react_hooray': self.post.react_hooray,
-            'react_confused': self.post.react_confused,
-            'react_heart': self.post.react_heart
-        }
+        emoji_unicode = {}
+        # Need send back unicode emojis too for rendering :+1: .. etc
+        for em_code in self.post.react_counts:
+            emoji_unicode[em_code] = g.emojize(em_code)
+        return dict(status=status, counts=self.post.react_counts, emoji_unicode=emoji_unicode)
 
     def error_handler(self, *args, **kwargs):
         redirect(request.referer)

http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/Allura/allura/lib/app_globals.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/app_globals.py b/Allura/allura/lib/app_globals.py
index ddcfa14..02980c1 100644
--- a/Allura/allura/lib/app_globals.py
+++ b/Allura/allura/lib/app_globals.py
@@ -34,6 +34,7 @@ import traceback
 import activitystream
 import pkg_resources
 import markdown
+import emoji
 import pygments
 import pygments.lexers
 import pygments.formatters
@@ -608,6 +609,10 @@ class Globals(object):
             "image_height": logo['image_height']
         }
 
+    def emojize(self, text):
+        """Coverts emoji codes to unicode emojis"""
+        return emoji.emojize(text, use_aliases=True)
+
 
 class Icon(object):
 

http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/Allura/allura/lib/utils.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/utils.py b/Allura/allura/lib/utils.py
index ccc19d2..07fd2a1 100644
--- a/Allura/allura/lib/utils.py
+++ b/Allura/allura/lib/utils.py
@@ -30,6 +30,7 @@ import magic
 from itertools import groupby
 import operator as op
 import collections
+import emoji
 
 import tg
 import pylons
@@ -762,3 +763,14 @@ def umask(new_mask):
         yield
     finally:
         os.umask(cur_mask)
+
+
+def get_reaction_emoji_list():
+    """ Get reactions emoji list from .ini file. If not defined there get fixed 
+    default emoji list """
+    emo_list = tg.config.get('reactions.emoji_list')
+    if emo_list is None:
+        emo_list = [':+1:', ':-1:', ':smile:', ':tada:', ':confused:', ':heart:']
+    else:
+        emo_list = emo_list.split(',')
+    return emo_list

http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/Allura/allura/lib/widgets/discuss.py
----------------------------------------------------------------------
diff --git a/Allura/allura/lib/widgets/discuss.py b/Allura/allura/lib/widgets/discuss.py
index f7be446..9ff25f9 100644
--- a/Allura/allura/lib/widgets/discuss.py
+++ b/Allura/allura/lib/widgets/discuss.py
@@ -19,7 +19,10 @@ from formencode import validators as fev
 
 import ew as ew_core
 import ew.jinja2_ew as ew
+from pylons import app_globals as g
+from  tg import config
 
+from allura.lib import utils
 from allura.lib import validators as V
 from allura.lib.widgets import form_fields as ffw
 from allura.lib.widgets import forms as ff
@@ -300,6 +303,15 @@ class Post(HierWidget):
         attach_post=AttachPost(submit_text='Attach'),
         attachment=Attachment())
 
+    def get_reaction_tooltip_content(self):
+        """Construct html content for the reaction tooltip"""
+        html = ''
+        for em in utils.get_reaction_emoji_list():
+            emoji_u = g.emojize(em)
+            html += '<span onclick="reactComment(\'` + btnId +  `\', \'%s\')">` + twemoji.parse(\'%s\')
+ `</span>' % \
+            (em, emoji_u)
+        return html
+
     def resources(self):
         for r in super(Post, self).resources():
             yield r
@@ -427,6 +439,66 @@ class Post(HierWidget):
             });
         }());
         ''')
+        
+        yield ew.JSScript('''
+        // Reaction support
+        $(function(){
+
+        $('.reaction-button').tooltipster({
+            animation: 'fade',
+            delay: 200,
+            theme: 'tooltipster-default',
+            trigger: 'click',
+            position: 'top',
+            iconCloning: false,
+            maxWidth: 400,
+            contentAsHTML: true,
+            interactive: true
+        });
+
+        $('.reaction-button').each(function() {
+            var btnId = $(this).attr('id');
+            $(this).click(function(e) {
+                e.preventDefault();
+                var tooltiptext = `
+                <div class="post-reactions-list">
+                    %s
+                </div>
+                `;
+                $(this).tooltipster('content', tooltiptext);
+                $(this).tooltipster('show', function() {
+                    twemoji.parse($('.tooltipster-content')[0]);
+                });
+            });
+        });
+
+
+        });
+
+        function reactComment(btnId ,r) {
+        var btn = $('#' + btnId);
+        var reacts_list = btn.closest('.post-content').find('.reactions');
+        $.ajax({
+            type: 'post',
+            url: btn.data('commentlink') + 'post_reaction',
+            data: {
+                'r' : r,
+                '_session_id' : $.cookie('_session_id')
+            },
+            success: function(res) {
+                var react_html = '';
+
+                for (var i in res.counts) {
+                    react_html += '<span>' + res.emoji_unicode[i] + '</span>
' + res.counts[i];
+                }
+                
+                reacts_list.html(react_html);
+                twemoji.parse(reacts_list[0]);
+                btn.tooltipster('hide');
+            }
+        });
+        }
+        ''' % self.get_reaction_tooltip_content() ) 
 
 
 class PostThread(ew_core.Widget):

http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/Allura/allura/model/artifact.py
----------------------------------------------------------------------
diff --git a/Allura/allura/model/artifact.py b/Allura/allura/model/artifact.py
index 21aad0d..74480f5 100644
--- a/Allura/allura/model/artifact.py
+++ b/Allura/allura/model/artifact.py
@@ -1055,22 +1055,11 @@ class ReactableArtifact(MappedClass):
 
     """Reaction support for the Artifact. Use as a mixin."""
 
-    class __mongometa__:
-        session = main_orm_session
-        name = 'reaction'
-
-    react_thumbs_up = FieldProperty(int, if_missing=0)
-    react_thumbs_down = FieldProperty(int, if_missing=0)
-    react_laugh = FieldProperty(int, if_missing=0)
-    react_hooray = FieldProperty(int, if_missing=0)
-    react_confused = FieldProperty(int, if_missing=0)
-    react_heart = FieldProperty(int, if_missing=0)
-
+    react_counts = FieldProperty({str: None}, if_missing=dict())
+    # dict to store reaction counts
     react_users = FieldProperty({str: None}, if_missing=dict())
     # dict to store reactions vs usernames
 
-    reaction_list = ['thumbs_up', 'thumbs_down', 'laugh', 'hooray', 'confused', 'heart']
-
     def post_reaction(self, r, user):
         current_reaction = self.user_reacted(user)
         if current_reaction is None:
@@ -1079,11 +1068,13 @@ class ReactableArtifact(MappedClass):
                 self.react_users[r].append(user.username)
             else:
                 self.react_users[r] = [user.username]
-            self.update_react_count(r, 1)
+            self.update_react_count(r)
         elif current_reaction == r:
             # prev=current so remove
             self.react_users[r].remove(user.username)
-            self.update_react_count(r, -1)
+            self.update_react_count(r, add=False)
+            if len(self.react_users[r]) == 0:
+                self.react_users.pop(r)
         else:
             # prev!=currnet so remove prev then append
             self.react_users[current_reaction].remove(user.username)
@@ -1091,29 +1082,27 @@ class ReactableArtifact(MappedClass):
                 self.react_users[r].append(user.username)
             else:
                 self.react_users[r] = [user.username]
-            self.update_react_count(current_reaction, -1)
-            self.update_react_count(r, 1)
+            self.update_react_count(current_reaction, add=False)
+            self.update_react_count(r)
+            if len(self.react_users[current_reaction]) == 0:
+                self.react_users.pop(current_reaction)
 
     def user_reacted(self, user):
-        for i in self.reaction_list:
-            if i in self.react_users:
-                if user.username in self.react_users[i]:
-                    return i
+        for i in self.react_users:
+            if user.username in self.react_users[i]:
+                return i
         return 
     
-    def update_react_count(self, r, i):
-        if r == 'thumbs_up':
-            self.react_thumbs_up += i
-        elif r == 'thumbs_down':
-            self.react_thumbs_down += i
-        elif r == 'laugh':
-            self.react_laugh += i
-        elif r == 'hooray':
-            self.react_hooray += i
-        elif r == 'confused':
-            self.react_confused += i
-        elif r == 'heart':
-            self.react_heart += i
+    def update_react_count(self, r, add=True):
+        i = 1
+        if not add:
+            i = -1
+        if r in self.react_counts:
+            self.react_counts[r] += i
+            if self.react_counts[r] == 0:
+                self.react_counts.pop(r)
+        else:
+            self.react_counts[r] = 1
 
 class MovedArtifact(Artifact):
 

http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/Allura/allura/public/nf/js/allura-base.js
----------------------------------------------------------------------
diff --git a/Allura/allura/public/nf/js/allura-base.js b/Allura/allura/public/nf/js/allura-base.js
index 87b414f..b59fbe2 100644
--- a/Allura/allura/public/nf/js/allura-base.js
+++ b/Allura/allura/public/nf/js/allura-base.js
@@ -254,72 +254,3 @@ $(function(){
         });
     });
 });
-
-// Reaction support
-$(function(){
-
-    $('.reaction-button').tooltipster({
-        animation: 'fade',
-        delay: 200,
-        theme: 'tooltipster-default',
-        trigger: 'click',
-        position: 'top',
-        iconCloning: false,
-        maxWidth: 400,
-        contentAsHTML: true,
-        interactive: true
-    });
-
-    $('.reaction-button').each(function() {
-        var btnId = $(this).attr('id');
-        $(this).click(function(e) {
-            e.preventDefault();
-            var tooltiptext = `
-            <div class="post-reactions-list">
-                <span onclick="reactComment('` + btnId  + `', 'thumbs_up')"><img
draggable="false" class="emoji" alt="👍" src="https://twemoji.maxcdn.com/2/72x72/1f44d.png"></span>
-                <span onclick="reactComment('` + btnId  + `', 'thumbs_down')"><img
draggable="false" class="emoji" alt="👎" src="https://twemoji.maxcdn.com/2/72x72/1f44e.png"></span>
-                <span onclick="reactComment('` + btnId  + `', 'laugh')"><img draggable="false"
class="emoji" alt="😃" src="https://twemoji.maxcdn.com/2/72x72/1f603.png"></span>
-                <span onclick="reactComment('` + btnId  + `', 'hooray')"><img draggable="false"
class="emoji" alt="🎉" src="https://twemoji.maxcdn.com/2/72x72/1f389.png"></span>
-                <span onclick="reactComment('` + btnId  + `', 'confused')"><img
draggable="false" class="emoji" alt="😕" src="https://twemoji.maxcdn.com/2/72x72/1f615.png"></span>
-                <span onclick="reactComment('` + btnId  + `', 'heart')"><img draggable="false"
class="emoji" alt="❤" src="https://twemoji.maxcdn.com/2/72x72/2764.png"></span>
-            </div>
-            `;
-            $(this).tooltipster('content', tooltiptext);
-            $(this).tooltipster('show');
-        });
-    });
-
-
-});
-
-function reactComment(btnId ,r) {
-    var btn = $('#' + btnId);
-    var reacts_list = btn.closest('.post-content').find('.reactions');
-    $.ajax({
-        type: 'post',
-        url: btn.data('commentlink') + 'post_reaction',
-        data: {
-            'r' : r,
-            '_session_id' : $.cookie('_session_id')
-        },
-        success: function(res) {
-            var react_html = '';
-            if(res.react_thumbs_up > 0) 
-                react_html += '<span>👍</span> ' + res.react_thumbs_up;
-            if(res.react_thumbs_down > 0) 
-                react_html += '<span>👎</span> ' + res.react_thumbs_down;
-            if(res.react_laugh > 0) 
-                react_html += '<span>😄</span> ' + res.react_laugh;
-            if(res.react_hooray > 0) 
-                react_html += '<span>🎉</span> ' + res.react_hooray;
-            if(res.react_confused > 0) 
-                react_html += '<span>😕</span> ' + res.react_confused;
-            if(res.react_heart > 0) 
-                react_html += '<span>❤</span> ' + res.react_heart;
-            
-            reacts_list.html(react_html);
-            twemoji.parse(reacts_list[0]);
-            btn.tooltipster('hide');
-        }
-    });
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/Allura/allura/templates/widgets/post_widget.html
----------------------------------------------------------------------
diff --git a/Allura/allura/templates/widgets/post_widget.html b/Allura/allura/templates/widgets/post_widget.html
index 496d973..fc3f555 100644
--- a/Allura/allura/templates/widgets/post_widget.html
+++ b/Allura/allura/templates/widgets/post_widget.html
@@ -84,24 +84,9 @@
 
             <div{% if h.has_access(value, 'moderate') %} class="active-md" data-markdownlink="{{value.url()}}"
{% endif %}>{{g.markdown.cached_convert(value, 'text')|safe}}</div>&nbsp;
             <div class='reactions' style='user-select: none; cursor: default'>
-              {% if value.react_thumbs_up > 0 %}
-              <span>{{ '\U0001F44D' }}</span> {{ value.react_thumbs_up }}
-              {% endif %}
-              {% if value.react_thumbs_down > 0 %}
-              <span>{{ '\U0001F44E' }}</span> {{ value.react_thumbs_down }}
-              {% endif %}
-              {% if value.react_laugh > 0 %}
-              <span>{{ '\U0001F604' }}</span> {{ value.react_laugh }}
-              {% endif %}
-              {% if value.react_hooray > 0 %}
-              <span>{{ '\U0001F389' }}</span> {{ value.react_hooray }}
-              {% endif %}
-              {% if value.react_confused > 0 %}
-              <span>{{ '\U0001F615' }}</span> {{ value.react_confused }}
-              {% endif %}
-              {% if value.react_heart > 0 %}
-              <span>{{ '\U00002764' }}</span> {{ value.react_heart }}
-              {% endif %}
+              {% for reaction in value.react_counts %}
+                <span>{{ g.emojize(reaction) }}</span> {{ value.react_counts[reaction]
}}
+              {% endfor %}
             </div>
             {{lib.related_artifacts(value)}}
             {% if value.edit_count %}

http://git-wip-us.apache.org/repos/asf/allura/blob/8d3b43b1/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 5539710..15ef794 100644
--- a/Allura/allura/tests/functional/test_discuss.py
+++ b/Allura/allura/tests/functional/test_discuss.py
@@ -224,18 +224,20 @@ class TestDiscuss(TestDiscussBase):
         response = self.app.post(
             react_link,
             params={
-                'r': 'heart'})
-        assert response.json['status'] == 'ok' and response.json['react_heart'] == 1
+                'r': ':+1:'})
+        assert response.json['status'] == 'ok' and response.json['counts'][':+1:'] == 1 and
\
+        response.json['emoji_unicode'][':+1:'] == u'\U0001F44D'
         response = self.app.post(
             react_link,
             params={
                 'r': 'invalid'})
-        assert response.json['status'] == 'error' and response.json['react_heart'] == 1
+        assert response.json['status'] == 'error' and response.json['counts'][':+1:'] ==
1 and \
+        response.json['emoji_unicode'][':+1:'] == u'\U0001F44D'
         # anon users can't react comments
         response = self.app.post(
             react_link,
             params={
-                'r': 'heart'},
+                'r': ':+1:'},
             extra_environ=dict(username='*anonymous'))
         assert response.json['error'] == 'no_permission'
         # even anon can't send invalid reactions
@@ -254,14 +256,16 @@ class TestDiscuss(TestDiscussBase):
         response = self.app.post(
             react_link,
             params={
-                'r': 'thumbs_down'})
-        assert response.json['status'] == 'ok' and response.json['react_thumbs_down'] ==
1
+                'r': ':-1:'})
+        assert response.json['status'] == 'ok' and response.json['counts'][':-1:'] == 1 and
\
+        response.json['emoji_unicode'][':-1:'] == u'\U0001F44E'
         response = self.app.post(
             react_link,
             params={
-                'r': 'thumbs_up'})
-        assert response.json['status'] == 'ok' and response.json['react_thumbs_up'] == 1
-        assert response.json['status'] == 'ok' and response.json['react_thumbs_down'] ==
0
+                'r': ':+1:'})
+        assert response.json['status'] == 'ok' and response.json['counts'][':+1:'] == 1 and
\
+        ':-1:' not in response.json['counts'] and ':-1:' not in response.json['emoji_unicode']
and \
+        response.json['emoji_unicode'][':+1:'] == u'\U0001F44D'
 
     def test_comment_post_reaction_undo(self):
         r = self._make_post('This is a post')
@@ -271,13 +275,15 @@ class TestDiscuss(TestDiscussBase):
         response = self.app.post(
             react_link,
             params={
-                'r': 'hooray'})
-        assert response.json['status'] == 'ok' and response.json['react_hooray'] == 1
+                'r': ':tada:'})
+        assert response.json['status'] == 'ok' and response.json['counts'][':tada:'] == 1
and \
+        response.json['emoji_unicode'][':tada:'] == u'\U0001F389'
         response = self.app.post(
             react_link,
             params={
-                'r': 'hooray'})
-        assert response.json['status'] == 'ok' and response.json['react_hooray'] == 0
+                'r': ':tada:'})
+        assert response.json['status'] == 'ok' and ':tada:' not in response.json['counts']
and \
+        ':tada:' not in response.json['emoji_unicode']
 
     def test_user_filter(self):
         r = self._make_post('Test post')


Mime
View raw message