Skip to content

Commit

Permalink
Enable importance checkbox for admin and participant (#1682)
Browse files Browse the repository at this point in the history
* incorporate changes from https://github.com/chena11356/polis/tree/implement-comment-prioritization-checkbox

credit to https://github.com/chena11356
addresses #217

* include high_priority in vote posts to server

* rename "priority_type" to "importance_enabled"

* use actual quotes since HTML escapes are not being respected

* Editing the importance/significance label and help text, moving it up above the vote buttons

* lint fix

* update migration filename

---------

Co-authored-by: Hadjar Homaei <[email protected]>
  • Loading branch information
ballPointPenguin and xeeg authored Dec 4, 2024
1 parent 0094417 commit 2ea31da
Show file tree
Hide file tree
Showing 14 changed files with 119 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,10 @@ class ConversationConfig extends React.Component {
Customize the user interface
</Heading>

<CheckboxField field="importance_enabled" label="Importance Enabled">
[EXPERIMENTAL FEATURE] Participants can see the &quot;This comment is important&quot; checkbox
</CheckboxField>

<CheckboxField field="vis_type" label="Visualization" isIntegerBool>
Participants can see the visualization
</CheckboxField>
Expand Down
2 changes: 2 additions & 0 deletions client-participation/js/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ var IconFaAngleRight = require("./templates/icon_fa_angle_right.handlebars");
var IconFaAsterisk = require("./templates/icon_fa_asterisk.handlebars");
var IconFaBan = require("./templates/icon_fa_ban.handlebars");
var IconFaCircleCheckPartial = require("./templates/icon_fa_check_circle.handlebars");
var IconFaCircleQuestion = require("./templates/icon_fa_question_circle.handlebars");
var iconFaFacebookSquare16 = require("./templates/icon_fa_facebook_square_16.handlebars");
var iconFaFacebookSquare25 = require("./templates/icon_fa_facebook_square_25.handlebars");
var IconFaLightBulb = require("./templates/icon_fa_lightbulb_o.handlebars");
Expand Down Expand Up @@ -320,6 +321,7 @@ Handlebars.registerPartial("linkTos", LinkTosPartial);
Handlebars.registerPartial("linkPrivacy", LinkPrivacyPartial);
Handlebars.registerPartial("linkAddPolis", LinkAddPolisPartial);
Handlebars.registerPartial("iconFaCircleCheck", IconFaCircleCheckPartial);
Handlebars.registerPartial("iconFaCircleQuestion", IconFaCircleQuestion);
Handlebars.registerPartial("iconFaBan", IconFaBan);
Handlebars.registerPartial("iconFaLightBulb", IconFaLightBulb);
Handlebars.registerPartial("iconFaAsterisk", IconFaAsterisk);
Expand Down
3 changes: 2 additions & 1 deletion client-participation/js/models/vote.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module.exports = Model.extend({
pid: undefined, // PPPParticipant id -- this is a unique id every participant has in every convo that starts at 0
conversation_id: undefined, // converSation id
votes: undefined, // agree = -1, pass = 0, disagree = 1
participantStarred: false
participantStarred: false,
high_priority: false,
}
});
12 changes: 6 additions & 6 deletions client-participation/js/stores/polis.js
Original file line number Diff line number Diff line change
Expand Up @@ -349,10 +349,10 @@ module.exports = function(params) {
}
}

function disagree(commentId, starred, weight) {
function disagree(commentId, starred, high_priority) {
clearComment(commentId, "push");
var o = {
weight: weight,
high_priority: high_priority,
vote: polisTypes.reactions.push,
tid: commentId
};
Expand Down Expand Up @@ -415,10 +415,10 @@ module.exports = function(params) {
return promise;
}

function agree(commentId, starred, weight) {
function agree(commentId, starred, high_priority) {
clearComment(commentId);
var o = {
weight: weight,
high_priority: high_priority,
vote: polisTypes.reactions.pull,
tid: commentId
};
Expand All @@ -428,10 +428,10 @@ module.exports = function(params) {
return react(o);
}

function pass(tid, starred, weight) {
function pass(tid, starred, high_priority) {
clearComment(tid);
var o = {
weight: weight,
high_priority: high_priority,
vote: polisTypes.reactions.pass,
tid: tid
};
Expand Down
14 changes: 14 additions & 0 deletions client-participation/js/strings/en_us.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ s.pass = "Pass / Unsure";

s.writePrompt = "Share your perspective...";
s.anonPerson = "Anonymous";
s.importantCheckbox = "Important/Significant";
s.importantCheckboxDesc =
"Check this box if you believe this statement is especially important to you or is highly relevant to the conversation, irrespective of your vote. It will give this statement higher priority compared to your other votes in the conversation analysis."
s.howImportantPrompt = "How important is this statement?";
s.howImportantLow = "Low";
s.howImportantMedium = "Medium";
s.howImportantHigh = "High";

s.modSpam = "Spam";
s.modOffTopic = "Off Topic";
s.modImportant = "Important";
s.modSubmitInitialState = "Skip (none of the above), next statement";
s.modSubmit = "Done, next statement";

s.x_wrote = "wrote:";
s.x_tweeted = "tweeted:";
s.comments_remaining = "{{num_comments}} remaining";
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{{! Copyright (C) 2012-present, The Authors. This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License, version 3, as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. You should have received a copy of the GNU Affero General Public License along with this program. If not, see <http://www.gnu.org/licenses/>. }}

<svg
viewBox="0 0 512 512"
xmlns="http://www.w3.org/2000/svg"
height="17px"
width="17px"
><path
d="M256 0C114.6 0 0 114.6 0 256s114.6 256 256 256s256-114.6 256-256S397.4 0 256 0zM256 464c-114.7 0-208-93.31-208-208S141.3 48 256 48s208 93.31 208 208S370.7 464 256 464zM256 336c-18 0-32 14-32 32s13.1 32 32 32c17.1 0 32-14 32-32S273.1 336 256 336zM289.1 128h-51.1C199 128 168 159 168 198c0 13 11 24 24 24s24-11 24-24C216 186 225.1 176 237.1 176h51.1C301.1 176 312 186 312 198c0 8-4 14.1-11 18.1L244 251C236 256 232 264 232 272V288c0 13 11 24 24 24S280 301 280 288V286l45.1-28c21-13 34-36 34-60C360 159 329 128 289.1 128z"
></path></svg>
33 changes: 24 additions & 9 deletions client-participation/js/templates/vote-view.handlebars
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,29 @@
</div>
</div>
{{else}} {{!-- !shouldMod --}}
{{#if showImportantCheckbox}}
<div style="text-align: center; margin-bottom: 20px">
<label class="weight-label">
<span class="weight-radio"></span>
<input type="checkbox" name="checkbox" id="weight_high" aria-describedby="importantCheckboxDesc">
{{s.importantCheckbox}}
<span id="importantCheckboxDesc" class="is-visually-hidden">
{{s.importantCheckboxDesc}}
</span>
</label>
<i class="svgIcon" style="
display: inline-block;
position: relative;
top: 2px;
width: 17px;
fill: #8a8a8a;
"
data-text="{{s.importantCheckboxDesc}}"
onclick="alert(this.dataset.text)"
aria-hidden="true"
>{{> iconFaCircleQuestion}}</i>
</div>
{{/if}}
<div
class="
reactionButtons
Expand Down Expand Up @@ -291,15 +314,7 @@
</button>
</div>

{{#if showImportantCheckbox}}
<div style="text-align: center; margin-bottom: 20px">
<label class="weight-label">
<span class="weight-radio"></span>
<input type="checkbox" name="checkbox" id="weight_high">
{{s.importantCheckbox}}
</label>
</div>
{{/if}}


{{/if}} {{!-- /shouldMod --}}

Expand Down
33 changes: 17 additions & 16 deletions client-participation/js/views/vote-view.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ module.exports = Handlebones.ModelView.extend({
}

}
ctx.showImportantCheckbox = preload.conversation.importance_enabled;
ctx.social = socialCtx;
ctx.noModSet = !ctx.spamOn && !ctx.otOn && !ctx.importantOn;
ctx.canSubscribe = !!preload.firstPtpt || this.votesByMe.size() > 0;
Expand Down Expand Up @@ -486,13 +487,13 @@ module.exports = Handlebones.ModelView.extend({
});
return false;
};
this.getWeight = function() {
if ($("#weight_low").prop("checked")) {
return -1;
} else if ($("#weight_high").prop("checked")) {
return 1;

// note: instead of -1/1/0, weight is now the boolean high_priority
this.highPriority = function () {
if ($("#weight_high").prop("checked")) {
return true;
}
return 0;
return false;
};
this.participantAgreed = function(e) {
this.mostRecentVoteType = "agree";
Expand All @@ -504,12 +505,12 @@ module.exports = Handlebones.ModelView.extend({
this.wipVote = {
vote: -1,
conversation_id: conversation_id,
weight: this.getWeight(),
high_priority: this.highPriority(),
tid: tid
};
serverClient.addToVotesByMe(this.wipVote);
this.onButtonClicked();
serverClient.agree(tid, starred, this.wipVote.weight)
serverClient.agree(tid, starred, this.wipVote.high_priority)
.then(onVote.bind(this), onFail.bind(this));
};
this.participantDisagreed = function() {
Expand All @@ -519,12 +520,12 @@ module.exports = Handlebones.ModelView.extend({
this.wipVote = {
vote: 1,
conversation_id: conversation_id,
weight: this.getWeight(),
high_priority: this.highPriority(),
tid: tid
};
serverClient.addToVotesByMe(this.wipVote);
this.onButtonClicked();
serverClient.disagree(tid, starred, this.wipVote.weight)
serverClient.disagree(tid, starred, this.wipVote.high_priority)
.then(onVote.bind(this), onFail.bind(this));
};
this.participantPassed = function() {
Expand All @@ -534,12 +535,12 @@ module.exports = Handlebones.ModelView.extend({
this.wipVote = {
vote: 0,
conversation_id: conversation_id,
weight: this.getWeight(),
high_priority: this.highPriority(), // TODO: specify in help text that this is for "important but unsure"
tid: tid
};
serverClient.addToVotesByMe(this.wipVote);
this.onButtonClicked();
serverClient.pass(tid, starred, this.wipVote.weight)
serverClient.pass(tid, starred, this.wipVote.high_priority)
.then(onVote.bind(this), onFail.bind(this));
};

Expand Down Expand Up @@ -579,7 +580,7 @@ module.exports = Handlebones.ModelView.extend({
return;
}
var starred = this.model.get("starred");
var weight = 0;
var high_priority = this.wipVote.high_priority;

var tid = this.wipVote.tid;

Expand All @@ -591,13 +592,13 @@ module.exports = Handlebones.ModelView.extend({
}

if (this.wipVote.vote === -1) {
serverClient.agree(tid, starred, weight)
serverClient.agree(tid, starred, high_priority)
.then(reloadPage, onFailAfterAuth);
} else if (this.wipVote.vote === 0) {
serverClient.pass(tid, starred, weight)
serverClient.pass(tid, starred, high_priority)
.then(reloadPage, onFailAfterAuth);
} else if (this.wipVote.vote === 1) {
serverClient.disagree(tid, starred, weight)
serverClient.disagree(tid, starred, high_priority)
.then(reloadPage, onFailAfterAuth);
} else {
alert(3);
Expand Down
3 changes: 3 additions & 0 deletions server/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ flavors of node.
\i postgres/migrations/000003_add_origin_permanent_cookie_columns.sql
\i postgres/migrations/000004_drop_waitinglist_table.sql
\i postgres/migrations/000005_drop_slack_stripe_canvas.sql
\i postgres/migrations/000006_update_votes_rule.sql
\i postgres/migrations/000007_drop_geolocation_fields.sql
\i postgres/migrations/000008_add_comment_priority.sql
```

You can also separately run `psql -d polis -f postgres/migrations/000000_initial.sql` and
Expand Down
3 changes: 2 additions & 1 deletion server/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -847,7 +847,7 @@ helpersInitialized.then(
),
need("vote", getIntInRange(-1, 1), assignToP),
want("starred", getBool, assignToP),
want("weight", getNumberInRange(-1, 1), assignToP, 0),
want("high_priority", getBool, assignToP, false),
resolve_pidThing("pid", assignToP, "post:votes"),
want("xid", getStringLimitLength(1, 999), assignToP),
want("lang", getStringLimitLength(1, 10), assignToP), // language of the next comment to be returned
Expand Down Expand Up @@ -1004,6 +1004,7 @@ helpersInitialized.then(
want("strict_moderation", getBool, assignToP),
want("topic", getOptionalStringLimitLength(1000), assignToP),
want("description", getOptionalStringLimitLength(50000), assignToP),
want("importance_enabled", getBool, assignToP),
want("vis_type", getInt, assignToP),
want("help_type", getInt, assignToP),
want("write_type", getInt, assignToP),
Expand Down
7 changes: 7 additions & 0 deletions server/postgres/migrations/000008_add_comment_priority.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
ALTER TABLE conversations
ADD importance_enabled BOOLEAN NOT NULL
DEFAULT (false);

ALTER TABLE votes
ADD high_priority BOOLEAN NOT NULL
DEFAULT (false);
2 changes: 2 additions & 0 deletions server/src/d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export type ConversationType = {
help_bgcolor?: any;
style_btn?: any;
write_type?: any;
importance_enabled?: any;
owner_sees_participation_stats?: any;
link_url?: any;
course_invite?: any;
Expand Down Expand Up @@ -208,4 +209,5 @@ export type Vote = {
weight: any;
starred: any;
parent_url: any;
high_priority: any;
};
3 changes: 2 additions & 1 deletion server/src/db/sql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const sql_conversations: any = sql.define({
"parent_url",
"vis_type",
"write_type",
"importance_enabled",
"help_type",
"socialbtn_type",
"subscribe_type",
Expand Down Expand Up @@ -75,7 +76,7 @@ const sql_comments = sql.define({

const sql_votes_latest_unique: any = sql.define({
name: "votes_latest_unique",
columns: ["zid", "tid", "pid", "modified", "vote"],
columns: ["zid", "tid", "pid", "modified", "vote", "weight", "high_priority"],
});

const sql_participant_metadata_answers: any = sql.define({
Expand Down
Loading

0 comments on commit 2ea31da

Please sign in to comment.