-
Notifications
You must be signed in to change notification settings - Fork 23
/
Copy pathrating.js
180 lines (165 loc) · 7.57 KB
/
rating.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle 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 General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
/**
* Implements rating functionality
*
* @module mod_moodleoverflow/rating
* @copyright 2022 Justus Dieckmann WWU
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
import Ajax from 'core/ajax';
import Prefetch from 'core/prefetch';
import {get_string as getString} from 'core/str';
const RATING_DOWNVOTE = 1;
const RATING_UPVOTE = 2;
const RATING_REMOVE_DOWNVOTE = 10;
const RATING_REMOVE_UPVOTE = 20;
const RATING_SOLVED = 3;
const RATING_HELPFUL = 4;
const root = document.getElementById('moodleoverflow-root');
/**
* Send a vote via AJAX, then updates post and user ratings.
* @param {int} postid
* @param {int} rating
* @param {int} userid
* @returns {Promise<*>}
*/
async function sendVote(postid, rating, userid) {
const response = await Ajax.call([{
methodname: 'mod_moodleoverflow_record_vote',
args: {
postid: postid,
ratingid: rating
}
}])[0];
root.querySelectorAll(`[data-moodleoverflow-userreputation="${userid}"]`).forEach((i) => {
i.textContent = response.raterreputation;
});
root.querySelectorAll(`[data-moodleoverflow-userreputation="${response.ownerid}"]`).forEach((i) => {
i.textContent = response.ownerreputation;
});
root.querySelectorAll(`[data-moodleoverflow-postreputation="${postid}"]`).forEach((i) => {
i.textContent = response.postrating;
});
return response;
}
/**
* Init function.
*
* @param {int} userid
* @param {boolean} allowmultiplemarks // true means allowed, false means not allowed.
*
*/
export function init(userid, allowmultiplemarks) {
Prefetch.prefetchStrings('mod_moodleoverflow',
['marksolved', 'marknotsolved', 'markhelpful', 'marknothelpful',
'action_remove_upvote', 'action_upvote', 'action_remove_downvote', 'action_downvote']);
root.onclick = async(event) => {
const actionElement = event.target.closest('[data-moodleoverflow-action]');
if (!actionElement) {
return;
}
const action = actionElement.getAttribute('data-moodleoverflow-action');
const postElement = actionElement.closest('[data-moodleoverflow-postid]');
const postid = postElement?.getAttribute('data-moodleoverflow-postid');
switch (action) {
case 'upvote':
case 'downvote': {
const isupvote = action === 'upvote';
if (actionElement.getAttribute('data-moodleoverflow-state') === 'clicked') {
await sendVote(postid, isupvote ? RATING_REMOVE_UPVOTE : RATING_REMOVE_DOWNVOTE, userid);
actionElement.setAttribute('data-moodleoverflow-state', 'notclicked');
actionElement.title = await getString('action_' + action, 'mod_moodleoverflow');
} else {
const otherAction = isupvote ? 'downvote' : 'upvote';
await sendVote(postid, isupvote ? RATING_UPVOTE : RATING_DOWNVOTE, userid);
actionElement.setAttribute('data-moodleoverflow-state', 'clicked');
const otherElement = postElement.querySelector(
`[data-moodleoverflow-action="${otherAction}"]`);
otherElement.setAttribute('data-moodleoverflow-state', 'notclicked');
actionElement.title = await getString('action_remove_' + action, 'mod_moodleoverflow');
otherElement.title = await getString('action_' + otherAction, 'mod_moodleoverflow');
}
}
break;
case 'helpful':
case 'solved': {
const isHelpful = action === 'helpful';
const htmlclass = isHelpful ? 'markedhelpful' : 'markedsolution';
const shouldRemove = postElement.classList.contains(htmlclass);
const baseRating = isHelpful ? RATING_HELPFUL : RATING_SOLVED;
const rating = shouldRemove ? baseRating * 10 : baseRating;
await sendVote(postid, rating, userid);
/* If multiplemarks are not allowed (that is the default mode): delete all marks.
else: only delete the mark if the post is being unmarked.
Add a mark, if the post is being marked.
*/
if (!allowmultiplemarks) {
// Delete all marks in the discussion
for (const el of root.querySelectorAll('.moodleoverflowpost.' + htmlclass)) {
el.classList.remove(htmlclass);
el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent =
await getString(`mark${action}`, 'mod_moodleoverflow');
}
} else {
// Remove only the mark of the unmarked post.
if (shouldRemove) {
postElement.classList.remove(htmlclass);
actionElement.textContent = await getString(`mark${action}`, 'mod_moodleoverflow');
changeStrings(htmlclass, action);
}
}
// If the post is being marked, mark it.
if (!shouldRemove) {
postElement.classList.add(htmlclass);
actionElement.textContent = await getString(`marknot${action}`, 'mod_moodleoverflow');
if (allowmultiplemarks) {
changeStrings(htmlclass, action);
}
}
}
}
};
}
/**
* Function to change the String of the post data-action button.
* Only used if multiplemarks are allowed.
* @param {string} htmlclass the class where the String is being updated
* @param {string} action helpful or solved mark
*/
async function changeStrings(htmlclass, action) {
Prefetch.prefetchStrings('mod_moodleoverflow',
['marksolved', 'alsomarksolved', 'markhelpful', 'alsomarkhelpful',]);
// 1. Step: Are there other posts in the Discussion, that are solved/helpful?
var othermarkedposts = false;
for (const el of root.querySelectorAll('.moodleoverflowpost')) {
if (el.classList.contains(htmlclass)) {
othermarkedposts = true;
break;
}
}
// 2. Step: Change the strings of the action Button of the unmarked posts.
for (const el of root.querySelectorAll('.moodleoverflowpost')) {
if (!el.classList.contains(htmlclass) && el.querySelector(`[data-moodleoverflow-action="${action}"]`)) {
if (othermarkedposts) {
el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent =
await getString(`alsomark${action}`, 'mod_moodleoverflow');
} else {
el.querySelector(`[data-moodleoverflow-action="${action}"]`).textContent =
await getString(`mark${action}`, 'mod_moodleoverflow');
}
}
}
}