From 3e1576d494cfafde59f144cddb7ada0c278f1496 Mon Sep 17 00:00:00 2001 From: Adhityaa Chandrasekar Date: Wed, 4 Dec 2019 18:50:50 -0800 Subject: [PATCH] api, frontend, db: add comment sorting Closes https://gitlab.com/commento/commento/issues/215 --- api/comment_list.go | 1 + api/domain.go | 1 + api/domain_get.go | 6 +- api/domain_list.go | 6 +- api/domain_update.go | 6 +- db/20191204173000-sort-method.sql | 10 +++ frontend/dashboard.html | 40 ++++++++++ frontend/js/commento.js | 118 ++++++++++++++++++++++++------ frontend/sass/commento.scss | 24 ++++++ 9 files changed, 185 insertions(+), 27 deletions(-) create mode 100644 db/20191204173000-sort-method.sql diff --git a/api/comment_list.go b/api/comment_list.go index 8827417..bfdeb66 100644 --- a/api/comment_list.go +++ b/api/comment_list.go @@ -191,6 +191,7 @@ func commentListHandler(w http.ResponseWriter, r *http.Request) { "requireIdentification": d.RequireIdentification, "isFrozen": d.State == "frozen", "isModerator": isModerator, + "defaultSortPolicy": d.DefaultSortPolicy, "attributes": p, "configuredOauths": map[string]bool{ "commento": d.CommentoProvider, diff --git a/api/domain.go b/api/domain.go index 4f1ba8c..af08a73 100644 --- a/api/domain.go +++ b/api/domain.go @@ -25,4 +25,5 @@ type domain struct { SsoProvider bool `json:"ssoProvider"` SsoSecret string `json:"ssoSecret"` SsoUrl string `json:"ssoUrl"` + DefaultSortPolicy string `json:"defaultSortPolicy"` } diff --git a/api/domain_get.go b/api/domain_get.go index d856425..00c2b89 100644 --- a/api/domain_get.go +++ b/api/domain_get.go @@ -27,7 +27,8 @@ func domainGet(dmn string) (domain, error) { gitlabProvider, ssoProvider, ssoSecret, - ssoUrl + ssoUrl, + defaultSortPolicy FROM domains WHERE domain = $1; ` @@ -54,7 +55,8 @@ func domainGet(dmn string) (domain, error) { &d.GitlabProvider, &d.SsoProvider, &d.SsoSecret, - &d.SsoUrl); err != nil { + &d.SsoUrl, + &d.DefaultSortPolicy); err != nil { return d, errorNoSuchDomain } diff --git a/api/domain_list.go b/api/domain_list.go index 85c654d..d09995b 100644 --- a/api/domain_list.go +++ b/api/domain_list.go @@ -29,7 +29,8 @@ func domainList(ownerHex string) ([]domain, error) { gitlabProvider, ssoProvider, ssoSecret, - ssoUrl + ssoUrl, + defaultSortPolicy FROM domains WHERE ownerHex=$1; ` @@ -62,7 +63,8 @@ func domainList(ownerHex string) ([]domain, error) { &d.GitlabProvider, &d.SsoProvider, &d.SsoSecret, - &d.SsoUrl); err != nil { + &d.SsoUrl, + &d.DefaultSortPolicy); err != nil { logger.Errorf("cannot Scan domain: %v", err) return nil, errorInternal } diff --git a/api/domain_update.go b/api/domain_update.go index c5a808e..11aa4cc 100644 --- a/api/domain_update.go +++ b/api/domain_update.go @@ -25,7 +25,8 @@ func domainUpdate(d domain) error { githubProvider=$12, gitlabProvider=$13, ssoProvider=$14, - ssoUrl=$15 + ssoUrl=$15, + defaultSortPolicy=$16 WHERE domain=$1; ` @@ -44,7 +45,8 @@ func domainUpdate(d domain) error { d.GithubProvider, d.GitlabProvider, d.SsoProvider, - d.SsoUrl) + d.SsoUrl, + d.DefaultSortPolicy) if err != nil { logger.Errorf("cannot update non-moderators: %v", err) return errorInternal diff --git a/db/20191204173000-sort-method.sql b/db/20191204173000-sort-method.sql new file mode 100644 index 0000000..ca12a70 --- /dev/null +++ b/db/20191204173000-sort-method.sql @@ -0,0 +1,10 @@ +-- Default sort policy for each domain + +CREATE TYPE sortPolicy AS ENUM ( + 'score-desc', + 'creationdate-desc', + 'creationdate-asc' +); + +ALTER TABLE domains + ADD defaultSortPolicy sortPolicy NOT NULL DEFAULT 'score-desc'; diff --git a/frontend/dashboard.html b/frontend/dashboard.html index 783434c..23a8e30 100644 --- a/frontend/dashboard.html +++ b/frontend/dashboard.html @@ -204,6 +204,26 @@ +
+
+ Comment Sorting +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
@@ -320,6 +340,26 @@ +
+
+ Default Comment Sorting +
+
+
+ + +
+
+ + +
+
+ + +
+
+
+
diff --git a/frontend/js/commento.js b/frontend/js/commento.js index 2de12e1..9a7410c 100644 --- a/frontend/js/commento.js +++ b/frontend/js/commento.js @@ -34,11 +34,13 @@ var ID_MOD_TOOLS_LOCK_BUTTON = "commento-mod-tools-lock-button"; var ID_ERROR = "commento-error"; var ID_LOGGED_CONTAINER = "commento-logged-container"; + var ID_PRE_COMMENTS_AREA = "commento-pre-comments-area"; var ID_COMMENTS_AREA = "commento-comments-area"; var ID_SUPER_CONTAINER = "commento-textarea-super-container-"; var ID_TEXTAREA_CONTAINER = "commento-textarea-container-"; var ID_TEXTAREA = "commento-textarea-"; var ID_ANONYMOUS_CHECKBOX = "commento-anonymous-checkbox-"; + var ID_SORT_POLICY = "commento-sort-policy-"; var ID_CARD = "commento-comment-card-"; var ID_BODY = "commento-comment-body-"; var ID_TEXT = "commento-comment-text-"; @@ -85,6 +87,7 @@ var configuredOauths = {}; var popupBoxType = "login"; var oauthButtonsShown = false; + var sortPolicy = "score-desc"; var selfHex = undefined; var mobileView = null; @@ -388,6 +391,8 @@ commenters = Object.assign({}, commenters, resp.commenters) configuredOauths = resp.configuredOauths; + sortPolicy = resp.defaultSortPolicy; + call(callback); }); } @@ -564,13 +569,62 @@ } + var sortPolicyNames = { + "score-desc": "Upvotes", + "creationdate-desc": "Newest", + "creationdate-asc": "Oldest", + }; + + + function sortPolicyApply(policy) { + classRemove($(ID_SORT_POLICY + sortPolicy), "sort-policy-button-selected"); + + var commentsArea = $(ID_COMMENTS_AREA); + commentsArea.innerHTML = ""; + sortPolicy = policy; + var cards = commentsRecurse(parentMap(comments), "root"); + if (cards) { + append(commentsArea, cards); + } + + classAdd($(ID_SORT_POLICY + policy), "sort-policy-button-selected"); + } + + + function sortPolicyBox() { + var sortPolicyButtonsContainer = create("div"); + var sortPolicyButtons = create("div"); + + classAdd(sortPolicyButtonsContainer, "sort-policy-buttons-container"); + classAdd(sortPolicyButtons, "sort-policy-buttons"); + + for (var sp in sortPolicyNames) { + var sortPolicyButton = create("a"); + sortPolicyButton.id = ID_SORT_POLICY + sp; + classAdd(sortPolicyButton, "sort-policy-button"); + if (sp === sortPolicy) { + classAdd(sortPolicyButton, "sort-policy-button-selected"); + } + sortPolicyButton.innerText = sortPolicyNames[sp]; + onclick(sortPolicyButton, sortPolicyApply, sp); + append(sortPolicyButtons, sortPolicyButton) + } + + append(sortPolicyButtonsContainer, sortPolicyButtons); + + return sortPolicyButtonsContainer + } + + function rootCreate(callback) { var login = create("div"); var loginText = create("div"); var mainArea = $(ID_MAIN_AREA); + var preCommentsArea = create("div"); var commentsArea = create("div"); login.id = ID_LOGIN; + preCommentsArea.id = ID_PRE_COMMENTS_AREA; commentsArea.id = ID_COMMENTS_AREA; classAdd(login, "login"); @@ -601,6 +655,12 @@ append(mainArea, textareaCreate("root")); } + if (comments.length > 0) { + append(mainArea, sortPolicyBox()); + } + + append(mainArea, preCommentsArea); + append(mainArea, commentsArea); append(root, mainArea); @@ -696,7 +756,7 @@ onclick(replyButton, global.replyShow, id) } else { textarea.value = ""; - insertAfter(textareaSuperContainer, newCard); + insertAfter($(ID_PRE_COMMENTS_AREA), newCard); } call(callback); @@ -762,6 +822,27 @@ } + var sortPolicyFunctions = { + "score-desc": function(a, b) { + return b.score - a.score; + }, + "creationdate-desc": function(a, b) { + if (a.creationDate < b.creationDate) { + return 1; + } else { + return -1; + } + }, + "creationdate-asc": function(a, b) { + if (a.creationDate < b.creationDate) { + return -1; + } else { + return 1; + } + }, + }; + + function commentsRecurse(parentMap, parentHex) { var cur = parentMap[parentHex]; if (!cur || !cur.length) { @@ -775,15 +856,7 @@ return Infinity; } - if (a.score !== b.score) { - return b.score - a.score; - } - - if (a.creationDate < b.creationDate) { - return -1; - } else { - return 1; - } + return sortPolicyFunctions[sortPolicy](a, b); }); var curTime = (new Date()).getTime(); @@ -1325,28 +1398,31 @@ } - function commentsRender() { - var parentMap = {}; - var parentHex; - - var commentsArea = $(ID_COMMENTS_AREA); - + function parentMap(comments) { + var m = {}; comments.forEach(function(comment) { - parentHex = comment.parentHex; - if (!(parentHex in parentMap)) { - parentMap[parentHex] = []; + var parentHex = comment.parentHex; + if (!(parentHex in m)) { + m[parentHex] = []; } comment.creationDate = new Date(comment.creationDate); - parentMap[parentHex].push(comment); + console.log(m, parentHex); + m[parentHex].push(comment); commentsMap[comment.commentHex] = { "html": comment.html, "markdown": comment.markdown, }; }); - var cards = commentsRecurse(parentMap, "root"); + return m; + } + + + function commentsRender() { + var commentsArea = $(ID_COMMENTS_AREA); + var cards = commentsRecurse(parentMap(comments), "root"); if (cards) { append(commentsArea, cards); } diff --git a/frontend/sass/commento.scss b/frontend/sass/commento.scss index c8a4cb8..9285309 100644 --- a/frontend/sass/commento.scss +++ b/frontend/sass/commento.scss @@ -57,6 +57,30 @@ font-weight: 700; margin-top: 16px; } + + .commento-sort-policy-buttons-container { + padding: 12px 0px; + font-weight: 400; + + .commento-sort-policy-buttons { + float: right; + + .commento-sort-policy-button { + color: $gray-6; + font-size: 13px; + padding: 0px 7px; + } + + .commento-sort-policy-button:hover { + cursor: pointer; + } + + .commento-sort-policy-button-selected { + color: $blue-8; + font-weight: bold; + } + } + } } .commento-root-font {