git.fiddlerwoaroof.com
Browse code

Adding resharing

fiddlerwoaroof authored on 20/10/2015 01:28:21
Showing 8 changed files
... ...
@@ -14,6 +14,24 @@ END
14 14
 $$ LANGUAGE plpgsql;
15 15
 
16 16
 
17
+DROP FUNCTION IF EXISTS subscribe_link(text,int);
18
+CREATE OR REPLACE FUNCTION subscribe_link(username text, linkid int)
19
+  RETURNS bool AS $$
20
+DECLARE
21
+  uid int;
22
+  result bool;
23
+  n_title text;
24
+  n_url text;
25
+BEGIN
26
+  SELECT INTO result NOT exists(SELECT * FROM user_links WHERE user_id=uid AND link_id=linkid);
27
+  IF result THEN
28
+    SELECT title,url INTO n_title,n_url FROM links WHERE links.id=linkid;
29
+    PERFORM put_link(username, n_url, n_title);
30
+  END IF;
31
+  RETURN result;
32
+END
33
+$$ LANGUAGE plpgsql;
34
+
17 35
 DROP FUNCTION IF EXISTS delete_link(text,int);
18 36
 CREATE OR REPLACE FUNCTION delete_link(username text, linkid int)
19 37
   RETURNS bool AS $$
... ...
@@ -30,10 +48,25 @@ BEGIN
30 48
 END
31 49
 $$ LANGUAGE plpgsql;
32 50
 
51
+DROP FUNCTION IF EXIST has_user_shared(text, text);
52
+CREATE OR REPLACE FUNCTION has_user_shared(username text, linkurl text) RETURNS bool AS $$
53
+DECLARE
54
+  result bool;
55
+BEGIN
56
+  SELECT INTO result EXISTS(
57
+    SELECT 1 FROM user_links ul
58
+    LEFT JOIN users u ON user_id=u.id
59
+    LEFT JOIN links l ON link_id=l.id
60
+    WHERE linkurl=l.url AND username=u.name
61
+  );
62
+  RETURN result;
63
+END
64
+$$ LANGUAGE plpgsql;
65
+
33 66
 DROP FUNCTION IF EXISTS get_bones(text, timestamp, int);
34 67
 DROP FUNCTION IF EXISTS get_bones(text, int, timestamp);
35 68
 CREATE OR REPLACE FUNCTION get_bones(username text, lim int, before timestamp)
36
-  RETURNS TABLE(url text, title text, posted timestamp, poster text, total_votes bigint, subscriber_vote int) AS $$
69
+  RETURNS TABLE(linkid int, url text, title text, posted timestamp, poster text, total_votes bigint, subscriber_vote int, shared bool) AS $$
37 70
 DECLARE
38 71
   subscriber_id int;
39 72
 BEGIN
... ...
@@ -43,7 +76,9 @@ BEGIN
43 76
     AS
44 77
       SELECT
45 78
         DISTINCT ON (links.url)
46
-        links.url,links.title,links.posted,users1.name,total_votes(links.id),user_vote(subscriber_id,links.id)
79
+        links.id,links.url,links.title,links.posted,users1.name,
80
+        total_votes(links.id),user_vote(subscriber_id,links.id),
81
+        has_user_shared(username, links.url)
47 82
         FROM user_subscriptions
48 83
         RIGHT JOIN user_links ON user_subscriptions.to_id=user_links.user_id
49 84
         INNER JOIN links ON link_id=links.id
... ...
@@ -58,7 +93,8 @@ $$ LANGUAGE plpgsql;
58 93
 
59 94
 DROP FUNCTION IF EXISTS get_bones(text, int);
60 95
 CREATE OR REPLACE FUNCTION get_bones(username text, lim int)
61
-  RETURNS TABLE(url text, title text, posted timestamp, poster text, total_votes bigint, subscriber_vote int) AS $$
96
+  RETURNS TABLE(linkid int, url text, title text, posted timestamp, poster text, total_votes bigint,
97
+                subscriber_vote int, shared bool) AS $$
62 98
 DECLARE
63 99
   subscriber_id int;
64 100
 BEGIN
... ...
@@ -68,7 +104,9 @@ BEGIN
68 104
     AS
69 105
       SELECT
70 106
         DISTINCT ON (links.url)
71
-        links.url,links.title,links.posted,users1.name,total_votes(links.id),user_vote(subscriber_id,links.id)
107
+        links.id,links.url,links.title,links.posted,users1.name,
108
+        total_votes(links.id),user_vote(subscriber_id,links.id),
109
+        has_user_shared(username, links.url)
72 110
         FROM user_subscriptions
73 111
         RIGHT JOIN user_links ON user_subscriptions.to_id=user_links.user_id
74 112
         INNER JOIN links ON link_id=links.id
... ...
@@ -81,7 +119,8 @@ $$ LANGUAGE plpgsql;
81 119
 
82 120
 DROP FUNCTION IF EXISTS get_bones(text);
83 121
 CREATE OR REPLACE FUNCTION get_bones(username text)
84
-  RETURNS TABLE(url text, title text, posted timestamp, poster text, total_votes bigint, subscriber_vote int) AS $$
122
+  RETURNS TABLE(linkid int, url text, title text, posted timestamp, poster text, total_votes bigint,
123
+                subscriber_vote int, shared bool) AS $$
85 124
 DECLARE
86 125
   subscriber_id int;
87 126
 BEGIN
... ...
@@ -91,7 +130,9 @@ BEGIN
91 130
     AS
92 131
       SELECT
93 132
         DISTINCT ON (links.url)
94
-        links.url,links.title,links.posted,users1.name,total_votes(links.id),user_vote(subscriber_id,links.id)
133
+        links.id,links.url,links.title,links.posted,users1.name,
134
+        total_votes(links.id),user_vote(subscriber_id,links.id),
135
+        has_user_shared(username, links.url)
95 136
         FROM user_subscriptions
96 137
         RIGHT JOIN user_links ON user_subscriptions.to_id=user_links.user_id
97 138
         INNER JOIN links ON link_id=links.id
... ...
@@ -104,7 +145,7 @@ $$ LANGUAGE plpgsql;
104 145
 
105 146
 DROP FUNCTION IF EXISTS get_bone(text);
106 147
 CREATE OR REPLACE FUNCTION get_bone(username text)
107
-  RETURNS TABLE(name text, url text, title text, posted timestamp, linkid int, votes bigint) AS $$
148
+  RETURNS TABLE(name text, url text, title text, posted timestamp, linkid int, votes bigint, shared bool) AS $$
108 149
 BEGIN
109 150
   RETURN QUERY SELECT users.name, links.url, links.title, links.posted, links.id, total_votes(links.id)
110 151
       FROM users
... ...
@@ -66,4 +66,4 @@ WITH recent_users AS (
66 66
   RIGHT JOIN users ON user_id=users.id
67 67
   WHERE posted > now() - interval '1 week'
68 68
   ORDER BY posted desc, user_id)
69
-SELECT DISTINCT ON (name) user_id,name,posted FROM recent_users;
69
+SELECT DISTINCT ON (user_id) user_id,name,posted FROM recent_users;
... ...
@@ -1,5 +1,6 @@
1 1
 import flask
2 2
 from flask import Blueprint, session, redirect, url_for, escape, request, abort, g
3
+import flask_login;
3 4
 from flask.ext.cors import cross_origin
4 5
 from flask.ext.login import login_required, current_user
5 6
 import urllib2
... ...
@@ -31,7 +32,7 @@ def as_json(f):
31 32
         return res
32 33
     return _inner
33 34
         
34
-@bone_blueprint.route('/link/<linkid>', methods=['GET','DELETE'])
35
+@bone_blueprint.route('/link/<linkid>', methods=['GET','POST','DELETE'])
35 36
 @login_required
36 37
 def delete_link(linkid):
37 38
     db = database.get_db()
... ...
@@ -42,6 +43,11 @@ def delete_link(linkid):
42 43
             cur.execute('SELECT id,url,title,posted FROM links WHERE id=%s', (linkid,))
43 44
             nid,url,title,posted = cur.fetchone()
44 45
             result = dict(id=nid,url=url,title=title,posted=posted.isoformat())
46
+        elif request.method == 'POST':
47
+            result = False
48
+            if 'username' in session:
49
+                cur.execute('SELECT subscribe_link(%s,%s)', (current_user.id,linkid))
50
+                result = cur.fetchone()[0]
45 51
         elif request.method == 'DELETE':
46 52
             result = False
47 53
             if 'username' in session:
... ...
@@ -163,10 +169,14 @@ def data(username):
163 169
 
164 170
     result = {'marrow':[], 'sectionTitle': sectionTitle}
165 171
     with database.get_db().cursor() as cur:
166
-        cur.execute("SELECT url, title, posted, linkid, votes from get_bone(%s);", (username,))
172
+        cur_username = 'anonymous'
173
+        if current_user.is_authenticated:
174
+            cur_username = current_user.id
175
+        cur.execute("SELECT url, title, posted, linkid, votes, has_user_shared(%s, url) from get_bone(%s);",
176
+                    (cur_username, username,))
167 177
         result['marrow'] = [
168
-                dict(id=linkid, url=url,title=title,posted=posted.isoformat(),votes=votes)
169
-                     for url,title,posted,linkid,votes
178
+                dict(id=linkid, url=url,title=title,posted=posted.isoformat(),votes=votes,shared=shared)
179
+                     for url,title,posted,linkid,votes,shared
170 180
                      in cur.fetchall()
171 181
         ]
172 182
     return json.dumps(result)
... ...
@@ -230,8 +240,9 @@ def subscriptions(before, count):
230 240
                 args = args + (before,)
231 241
             cur.callproc("get_bones", args)
232 242
             result['marrow'] = [
233
-                dict(poster=poster, url=url,title=title,posted=posted.isoformat(), votes=votes, myVote=myvote)
234
-                    for url,title,posted,poster,votes,myvote
243
+                dict(id=id,poster=poster, url=url,title=title,posted=posted.isoformat(), votes=votes,
244
+                     myVote=myvote, shared=shared)
245
+                    for id,url,title,posted,poster,votes,myvote,shared
235 246
                     in cur.fetchall()
236 247
             ]
237 248
     return (json.dumps(result), 200, {'Content-Type': 'application/json'})
... ...
@@ -7,6 +7,9 @@
7 7
       data-title="{{marrow.title}}"
8 8
       data-poster="{{marrow.poster}}"
9 9
       data-votes="{{marrow.votes}}">
10
+    <a href class="add-link" ng-click="reshare({item:marrow})" title="Reshare Link"
11
+      analytics-on="click" analytics-category="link" analytics-label="reshare"
12
+      analytics-event="{{marrow.url}}">{{!marrow.shared? '(+)': '&check;'}}</a>
10 13
     <span class="vote-disp">{{marrow.votes}}</span>
11 14
     <span ng-if="marrow.title">
12 15
       <a href="{{marrow.url}}" class="list-item" >{{marrow.title}}</a>
... ...
@@ -2,7 +2,7 @@ boneMod = angular.module('marrowApp.directives.boneList', []);
2 2
 
3 3
 boneMod.directive('boneList', function () {
4 4
   return {
5
-    scope: { bone: '=' },
5
+    scope: { bone: '=', reshare: '&' },
6 6
     templateUrl: 'js/directives/bone-list/bone-list.html'
7 7
   };
8 8
 });
... ...
@@ -84,6 +84,15 @@ marrowApp.controller('RootCtrl', function ($scope,$http,$location,$route, Subscr
84 84
   $scope.url = "";
85 85
   $scope.title = "";
86 86
 
87
+  $scope.reshare = function (marrow) {
88
+    if (!marrow.shared ) {
89
+      $http.post('/api/bones/link/'+marrow.id).success(function(shared) {
90
+        marrow.shared = true;
91
+        if (shared === true) { $scope.update(); }
92
+      });
93
+    };
94
+  };
95
+
87 96
   $scope.toggleSubscribe = function (txt) {
88 97
     var postObj = {"from":$scope.bone.sectionTitle, "to":$scope.bone.sectionTitle};
89 98
     var promise = null;
... ...
@@ -13,7 +13,7 @@
13 13
       <gravatar-image class="my-image" user-name="{{bone.sectionTitle}}"></gravatar-image>
14 14
     </a>
15 15
   </h2>
16
-  <bone-list bone="bone.marrow" />
16
+  <bone-list bone="bone.marrow" reshare="reshare(item)" />
17 17
 </section>
18 18
 
19 19
 
... ...
@@ -30,12 +30,17 @@
30 30
         <span class="voting">
31 31
           <span class="score">{{marrow.votes}}</span>
32 32
           <button class="upVote vote-button fa fa-plus" ng-class="{selected: marrow.myVote===1}" ng-click="upVote(marrow)"
33
-                  analytics-on="click" analytics-event="vote" analytics-category="{{marrow.myVote===0? 'up' : 'zero'}}"></button>
33
+                  analytics-on="click" analytics-event="vote" analytics-category="{{marrow.myVote===0? 'up' : 'zero'}}">
34
+          </button>
34 35
         </span>
35 36
         <span ng-if="marrow.title">
36 37
           <a href="{{marrow.url}}" class="list-item">{{marrow.title}}</a>
37 38
           <br />
38 39
         </span>
40
+        <a class="add-link" ng-click="reshare(marrow)" title="Reshare Link"
41
+           analytics-on="click" analytics-category="link" analytics-label="reshare"
42
+           analytics-event="{{marrow.url}}">{{!marrow.shared? 'Reshare': '&check;'}}</a>
43
+        &mdash;
39 44
         <a href="{{marrow.url}}" ng-class="{'de-emphasize':marrow.title}" >{{marrow.url}}</a>
40 45
       </div>
41 46
       <user-badge poster="{{marrow.poster}}"></user-badge>