Skip to content

Commit 00fc383

Browse files
committed
Add sorting option for comments
Add sorting and pagination support for comments, including new API query parameters for sort order and offset. Adjust comment fetching logic accordingly. Closes #4
1 parent 4694f21 commit 00fc383

10 files changed

Lines changed: 229 additions & 54 deletions

File tree

CHANGES.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,14 @@ New Features
1212
- Add search for comments by URL in the admin interface (`#1000`_, pkvach)
1313
- Add CSS variables for better organization and flexibility (`#1001`_, pkvach)
1414
- Add support for comment search by Thread URL in admin interface (`#1020`_, pkvach)
15+
- Add sorting option for comments (`#1005`_, pkvach)
1516

1617
.. _#966: https://github.com/posativ/isso/pull/966
1718
.. _#998: https://github.com/isso-comments/isso/pull/998
1819
.. _#1000: https://github.com/isso-comments/isso/pull/1000
1920
.. _#1001: https://github.com/isso-comments/isso/pull/1001
2021
.. _#1020: https://github.com/isso-comments/isso/pull/1020
22+
.. _#1005: https://github.com/isso-comments/isso/pull/1005
2123

2224
Breaking Changes
2325
^^^^^^^^^^^^^^^^

docs/docs/reference/client-config.rst

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ preferably in the script tag which embeds the JS:
1313
data-isso-max-comments-top="10"
1414
data-isso-max-comments-nested="5"
1515
data-isso-reveal-on-click="5"
16+
data-isso-sorting="newest"
1617
data-isso-avatar="true"
1718
data-isso-avatar-bg="#f0f0f0"
1819
data-isso-avatar-fg="#9abf88 #5698c4 #e279a3 #9163b6 ..."
@@ -255,6 +256,21 @@ data-isso-reply-notifications-default-enabled
255256
.. versionadded:: 0.13
256257

257258

259+
.. _data-isso-sorting:
260+
261+
data-isso-sorting
262+
Sort thread comments by specified sorting method.
263+
264+
Possible sorting methods:
265+
266+
- ``newest``: Bring newest comments to the top
267+
- ``oldest``: Bring oldest comments to the top
268+
- ``upvotes``: Bring most liked comments to the top
269+
270+
Default sorting is ``oldest``.
271+
272+
.. versionadded:: 0.13.1
273+
258274
Deprecated Client Settings
259275
--------------------------
260276

isso/db/comments.py

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -238,11 +238,11 @@ def fetchall(self, mode=5, after=0, parent='any', order_by='id',
238238
yield dict(zip(fields_comments + fields_threads, item))
239239

240240
def fetch(self, uri, mode=5, after=0, parent='any',
241-
order_by='id', asc=1, limit=None):
241+
order_by='id', asc=1, limit=None, offset=0):
242242
"""
243243
Return comments for :param:`uri` with :param:`mode`.
244244
"""
245-
sql = ['SELECT comments.* FROM comments INNER JOIN threads ON',
245+
sql = ['SELECT comments.*, likes - dislikes AS karma FROM comments INNER JOIN threads ON',
246246
' threads.uri=? AND comments.tid=threads.id AND (? | comments.mode) = ?',
247247
' AND comments.created>?']
248248

@@ -256,14 +256,18 @@ def fetch(self, uri, mode=5, after=0, parent='any',
256256
sql_args.append(parent)
257257

258258
# custom sanitization
259-
if order_by not in ['id', 'created', 'modified', 'likes', 'dislikes']:
259+
if order_by not in ['id', 'created', 'modified', 'likes', 'dislikes', 'karma']:
260260
order_by = 'id'
261261
sql.append('ORDER BY ')
262262
sql.append(order_by)
263263
if not asc:
264264
sql.append(' DESC')
265265

266-
if limit:
266+
if offset and limit:
267+
sql.append('LIMIT ?,?')
268+
sql_args.append(offset)
269+
sql_args.append(limit)
270+
elif limit:
267271
sql.append('LIMIT ?')
268272
sql_args.append(limit)
269273

@@ -350,19 +354,18 @@ def vote(self, upvote, id, remote_addr):
350354
return {'likes': likes + 1, 'dislikes': dislikes}
351355
return {'likes': likes, 'dislikes': dislikes + 1}
352356

353-
def reply_count(self, url, mode=5, after=0):
357+
def reply_count(self, url, mode=5):
354358
"""
355359
Return comment count for main thread and all reply threads for one url.
356360
"""
357361

358362
sql = ['SELECT comments.parent,count(*)',
359363
'FROM comments INNER JOIN threads ON',
360364
' threads.uri=? AND comments.tid=threads.id AND',
361-
' (? | comments.mode = ?) AND',
362-
' comments.created > ?',
365+
' (? | comments.mode = ?)',
363366
'GROUP BY comments.parent']
364367

365-
return dict(self.db.execute(sql, [url, mode, mode, after]).fetchall())
368+
return dict(self.db.execute(sql, [url, mode, mode]).fetchall())
366369

367370
def count(self, *urls):
368371
"""

isso/js/app/api.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -138,17 +138,13 @@ var view = function(id, plain) {
138138
return deferred.promise;
139139
};
140140

141-
var fetch = function(tid, limit, nested_limit, parent, lastcreated) {
142-
if (typeof(limit) === 'undefined') { limit = "inf"; }
143-
if (typeof(nested_limit) === 'undefined') { nested_limit = "inf"; }
144-
if (typeof(parent) === 'undefined') { parent = null; }
141+
var fetch = function({ tid, limit = "inf", nested_limit = "inf", parent = null, sort = "", offset = 0 }) {
142+
var query_dict = { uri: tid || location(), sort, parent, offset };
145143

146-
var query_dict = {uri: tid || location(), after: lastcreated, parent: parent};
147-
148-
if(limit !== "inf") {
144+
if (limit !== "inf") {
149145
query_dict['limit'] = limit;
150146
}
151-
if(nested_limit !== "inf"){
147+
if (nested_limit !== "inf") {
152148
query_dict['nested_limit'] = nested_limit;
153149
}
154150

isso/js/app/default_config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ var default_config = {
1313
"max-comments-top": "inf",
1414
"max-comments-nested": 5,
1515
"reveal-on-click": 5,
16+
"sorting": "oldest",
1617
"gravatar": false,
1718
"avatar": true,
1819
"avatar-bg": "#f0f0f0",

isso/js/app/isso.js

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ var Postbox = function(parent) {
114114
notification: $("[name=notification]", el).checked() ? 1 : 0,
115115
}).then(function(comment) {
116116
$(".isso-textarea", el).value = "";
117-
insert(comment, true);
117+
insert({ comment, scrollIntoView: true, offset: 0 });
118118

119119
if (parent !== null) {
120120
el.onsuccess();
@@ -125,7 +125,7 @@ var Postbox = function(parent) {
125125
return el;
126126
};
127127

128-
var insert_loader = function(comment, lastcreated) {
128+
var insert_loader = function(comment, offset) {
129129
var entrypoint;
130130
if (comment.id === null) {
131131
entrypoint = $("#isso-root");
@@ -140,34 +140,37 @@ var insert_loader = function(comment, lastcreated) {
140140

141141
$("a.isso-load-hidden", el).on("click", function() {
142142
el.remove();
143-
api.fetch($("#isso-thread").getAttribute("data-isso-id"),
144-
config["reveal-on-click"], config["max-comments-nested"],
145-
comment.id,
146-
lastcreated).then(
143+
144+
api.fetch({
145+
tid: $("#isso-thread").getAttribute("data-isso-id"),
146+
limit: config["reveal-on-click"],
147+
nested_limit: config["max-comments-nested"],
148+
parent: comment.id,
149+
sort: config["sorting"],
150+
offset: offset
151+
}).then(
147152
function(rv) {
148153
if (rv.total_replies === 0) {
149154
return;
150155
}
151156

152-
var lastcreated = 0;
153157
rv.replies.forEach(function(commentObject) {
154-
insert(commentObject, false);
155-
if(commentObject.created > lastcreated) {
156-
lastcreated = commentObject.created;
157-
}
158+
insert({ comment: commentObject, scrollIntoView: false, offset: 0 });
159+
158160
});
159161

160162
if(rv.hidden_replies > 0) {
161-
insert_loader(rv, lastcreated);
163+
insert_loader(rv, offset + rv.replies.length);
162164
}
163165
},
164166
function(err) {
165167
console.log(err);
166-
});
168+
}
169+
);
167170
});
168171
};
169172

170-
var insert = function(comment, scrollIntoView) {
173+
var insert = function({ comment, scrollIntoView, offset }) {
171174
var el = $.htmlify(template.render("comment", {"comment": comment}));
172175

173176
// update datetime every 60 seconds
@@ -381,19 +384,13 @@ var insert = function(comment, scrollIntoView) {
381384
show($("a.isso-reply", footer).detach());
382385
}
383386

384-
if(comment.hasOwnProperty('replies')) {
385-
var lastcreated = 0;
386-
comment.replies.forEach(function(replyObject) {
387-
insert(replyObject, false);
388-
if(replyObject.created > lastcreated) {
389-
lastcreated = replyObject.created;
390-
}
391-
387+
if (comment.hasOwnProperty('replies')) {
388+
comment.replies.forEach(function (replyObject) {
389+
insert({ comment: replyObject, scrollIntoView: false, offset: offset + 1 });
392390
});
393-
if(comment.hidden_replies > 0) {
394-
insert_loader(comment, lastcreated);
391+
if (comment.hidden_replies > 0) {
392+
insert_loader(comment, offset + comment.replies.length);
395393
}
396-
397394
}
398395

399396
};

isso/js/embed.js

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -122,28 +122,30 @@ function fetchComments() {
122122
}
123123
isso_root.textContent = '';
124124

125-
api.fetch(isso_thread.getAttribute("data-isso-id") || location.pathname,
126-
config["max-comments-top"],
127-
config["max-comments-nested"]).then(
125+
126+
api.fetch({
127+
tid: isso_thread.getAttribute("data-isso-id") || location.pathname,
128+
limit: config["max-comments-top"],
129+
nested_limit: config["max-comments-nested"],
130+
parent: null,
131+
sort: config["sorting"],
132+
offset: 0
133+
}).then(
128134
function (rv) {
129135

130136
if (rv.total_replies === 0) {
131137
heading.textContent = i18n.translate("no-comments");
132138
return;
133139
}
134140

135-
var lastcreated = 0;
136141
var count = rv.total_replies;
137142
rv.replies.forEach(function(comment) {
138-
isso.insert(comment, false);
139-
if (comment.created > lastcreated) {
140-
lastcreated = comment.created;
141-
}
143+
isso.insert({ comment: comment, scrollIntoView: false, offset: 0 });
142144
});
143145
heading.textContent = i18n.pluralize("num-comments", count);
144146

145147
if (rv.hidden_replies > 0) {
146-
isso.insert_loader(rv, lastcreated);
148+
isso.insert_loader(rv, rv.replies.length);
147149
}
148150

149151
if (window.location.hash.length > 0 &&

isso/js/tests/unit/comment.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ test('Rendered comment should match snapshot', () => {
5858
var isso_thread = $('#isso-thread');
5959
isso_thread.append('<div id="isso-root"></div>');
6060

61-
isso.insert(comment, false);
61+
isso.insert({ comment, scrollIntoView: false, offset: 0 });
6262

6363
// Will create a `.snap` file in `./__snapshots__/`.
6464
// Don't forget to check in those files when changing anything!

0 commit comments

Comments
 (0)