ep_comments_page 0.1.98 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.js +3 -9
- package/package.json +6 -6
- package/static/js/index.js +7 -3
- package/static/tests/frontend/specs/commentDelete.js +61 -121
- package/static/tests/frontend/specs/commentIcons.js +270 -306
- package/static/tests/frontend/specs/commentSuggestion.js +67 -50
- package/static/tests/frontend/specs/comment_l10n.js +127 -127
- package/static/tests/frontend/specs/timeFormat.js +202 -202
- package/static/tests/frontend/utils.js +14 -0
- package/templates/comments.html +1 -4
- package/locales/pt-BR.json +0 -26
package/index.js
CHANGED
|
@@ -4,7 +4,7 @@ const AttributePool = require('ep_etherpad-lite/static/js/AttributePool');
|
|
|
4
4
|
const Changeset = require('ep_etherpad-lite/static/js/Changeset');
|
|
5
5
|
const eejs = require('ep_etherpad-lite/node/eejs/');
|
|
6
6
|
const settings = require('ep_etherpad-lite/node/utils/Settings');
|
|
7
|
-
const
|
|
7
|
+
const {Formidable} = require('formidable');
|
|
8
8
|
const commentManager = require('./commentManager');
|
|
9
9
|
const apiUtils = require('./apiUtils');
|
|
10
10
|
const _ = require('underscore');
|
|
@@ -226,10 +226,7 @@ exports.expressCreateServer = (hookName, args, callback) => {
|
|
|
226
226
|
|
|
227
227
|
args.app.post('/p/:pad/:rev?/comments', async (req, res) => {
|
|
228
228
|
const fields = await new Promise((resolve, reject) => {
|
|
229
|
-
|
|
230
|
-
if (err != null) return reject(err);
|
|
231
|
-
resolve(fields);
|
|
232
|
-
});
|
|
229
|
+
new Formidable().parse(req, (err, fields) => err ? reject(err) : resolve(fields));
|
|
233
230
|
});
|
|
234
231
|
|
|
235
232
|
// check the api key
|
|
@@ -289,10 +286,7 @@ exports.expressCreateServer = (hookName, args, callback) => {
|
|
|
289
286
|
|
|
290
287
|
args.app.post('/p/:pad/:rev?/commentReplies', async (req, res) => {
|
|
291
288
|
const fields = await new Promise((resolve, reject) => {
|
|
292
|
-
|
|
293
|
-
if (err != null) return reject(err);
|
|
294
|
-
resolve(fields);
|
|
295
|
-
});
|
|
289
|
+
new Formidable().parse(req, (err, fields) => err ? reject(err) : resolve(fields));
|
|
296
290
|
});
|
|
297
291
|
|
|
298
292
|
// check the api key
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"description": "Adds comments on sidebar and link it to the text. For no-skin use ep_page_view.",
|
|
3
3
|
"name": "ep_comments_page",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Nicolas Lescop",
|
|
7
7
|
"email": "limplementeur@gmail.com"
|
|
@@ -23,14 +23,14 @@
|
|
|
23
23
|
],
|
|
24
24
|
"dependencies": {
|
|
25
25
|
"cheerio": "^0.22.0",
|
|
26
|
-
"formidable": "^
|
|
27
|
-
"underscore": "^1.13.
|
|
26
|
+
"formidable": "^2.0.1",
|
|
27
|
+
"underscore": "^1.13.2"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"eslint": "^8.
|
|
31
|
-
"eslint-config-etherpad": "^3.0.
|
|
30
|
+
"eslint": "^8.11.0",
|
|
31
|
+
"eslint-config-etherpad": "^3.0.9",
|
|
32
32
|
"socket.io-client": "^2.3.0",
|
|
33
|
-
"superagent": "^
|
|
33
|
+
"superagent": "^7.1.1",
|
|
34
34
|
"typescript": "^4.6.2"
|
|
35
35
|
},
|
|
36
36
|
"scripts": {
|
package/static/js/index.js
CHANGED
|
@@ -60,7 +60,7 @@ const EpComments = function (context) {
|
|
|
60
60
|
this.mapFakeComments = [];
|
|
61
61
|
this.mapOriginalCommentsId = [];
|
|
62
62
|
this.shouldCollectComment = false;
|
|
63
|
-
this.init();
|
|
63
|
+
this.initDone = this.init();
|
|
64
64
|
this.preCommentMarker = preCommentMark.init(this.ace);
|
|
65
65
|
};
|
|
66
66
|
|
|
@@ -590,6 +590,10 @@ EpComments.prototype.insertComment = function (commentId, comment, index) {
|
|
|
590
590
|
comment.commentId = commentId;
|
|
591
591
|
comment.reply = true;
|
|
592
592
|
content = $('#commentsTemplate').tmpl(comment);
|
|
593
|
+
content.find('.from-label')[0].dataset.l10nArgs = JSON.stringify({
|
|
594
|
+
changeFrom: comment.changeFrom,
|
|
595
|
+
changeTo: comment.changeTo,
|
|
596
|
+
});
|
|
593
597
|
if (comment.author !== clientVars.userId) {
|
|
594
598
|
$(content).find('.comment-actions-wrapper').addClass('hidden');
|
|
595
599
|
}
|
|
@@ -1226,9 +1230,10 @@ EpComments.prototype.pushComment = function (eventType, callback) {
|
|
|
1226
1230
|
const hooks = {
|
|
1227
1231
|
|
|
1228
1232
|
// Init pad comments
|
|
1229
|
-
postAceInit: (hookName, context
|
|
1233
|
+
postAceInit: async (hookName, context) => {
|
|
1230
1234
|
if (!pad.plugins) pad.plugins = {};
|
|
1231
1235
|
const Comments = new EpComments(context);
|
|
1236
|
+
await Comments.initDone;
|
|
1232
1237
|
pad.plugins.ep_comments_page = Comments;
|
|
1233
1238
|
|
|
1234
1239
|
if (!$('#editorcontainerbox').hasClass('flex-layout')) {
|
|
@@ -1240,7 +1245,6 @@ const hooks = {
|
|
|
1240
1245
|
class_name: 'error',
|
|
1241
1246
|
});
|
|
1242
1247
|
}
|
|
1243
|
-
return cb();
|
|
1244
1248
|
},
|
|
1245
1249
|
|
|
1246
1250
|
postToolbarInit: (hookName, args, cb) => {
|
|
@@ -1,110 +1,87 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
let helperFunctions;
|
|
5
|
-
const textOfComment = 'original comment';
|
|
6
|
-
const textOfReply = 'original reply';
|
|
7
|
-
const FIRST_LINE = 0;
|
|
3
|
+
const utils = require('../utils');
|
|
8
4
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
helperFunctions.addComentAndReplyToLine(FIRST_LINE, textOfComment, textOfReply, done);
|
|
14
|
-
});
|
|
15
|
-
});
|
|
5
|
+
let helperFunctions;
|
|
6
|
+
const textOfComment = 'original comment';
|
|
7
|
+
const textOfReply = 'original reply';
|
|
8
|
+
const FIRST_LINE = 0;
|
|
16
9
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
10
|
+
// create pad with a comment and a reply
|
|
11
|
+
beforeEach(async function () {
|
|
12
|
+
helperFunctions = commentDelete;
|
|
13
|
+
await helperFunctions.createPad(this);
|
|
14
|
+
await helperFunctions.addCommentAndReplyToLine(FIRST_LINE, textOfComment, textOfReply);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
context('when user presses the delete button on a comment', function () {
|
|
18
|
+
it('should delete comment', function (done) {
|
|
19
|
+
const outer$ = helper.padOuter$;
|
|
20
|
+
const inner$ = helper.padInner$;
|
|
21
|
+
outer$('.comment-delete').click();
|
|
22
|
+
helper.waitFor(() => inner$('.comment').length === 0).done(() => {
|
|
23
|
+
if (inner$('.comment').length !== 0) throw new Error('Error deleting comment');
|
|
24
|
+
done();
|
|
26
25
|
});
|
|
27
26
|
});
|
|
27
|
+
});
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
});
|
|
43
|
-
const inner$ = helper.padInner$;
|
|
44
|
-
if (inner$('.comment').length === 0) throw new Error('Comment should not have been deleted');
|
|
29
|
+
context('when user presses the delete button on other users comment', function () {
|
|
30
|
+
it('should not delete comment', async function () {
|
|
31
|
+
let outer$ = helper.padOuter$;
|
|
32
|
+
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
33
|
+
await utils.aNewPad({id: helperFunctions.padId});
|
|
34
|
+
await helper.waitForPromise(() => {
|
|
35
|
+
outer$ = helper.padOuter$;
|
|
36
|
+
return !!outer$ && outer$('.comment-delete').length;
|
|
37
|
+
});
|
|
38
|
+
outer$('.comment-delete').click();
|
|
39
|
+
await helper.waitForPromise(() => {
|
|
40
|
+
const chrome$ = helper.padChrome$;
|
|
41
|
+
return chrome$('#gritter-container').find('.error').length > 0;
|
|
45
42
|
});
|
|
43
|
+
const inner$ = helper.padInner$;
|
|
44
|
+
if (inner$('.comment').length === 0) throw new Error('Comment should not have been deleted');
|
|
46
45
|
});
|
|
47
46
|
});
|
|
48
47
|
|
|
49
48
|
const commentDelete = {
|
|
50
49
|
padId: undefined,
|
|
51
|
-
createPad(test
|
|
52
|
-
const self = this;
|
|
53
|
-
this.padId = helper.newPad(() => {
|
|
54
|
-
self.enlargeScreen(() => {
|
|
55
|
-
self.createOrResetPadText(() => {
|
|
56
|
-
cb();
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
});
|
|
50
|
+
async createPad(test) {
|
|
60
51
|
test.timeout(60000);
|
|
52
|
+
this.padId = await utils.aNewPad();
|
|
53
|
+
this.enlargeScreen();
|
|
54
|
+
await this.createOrResetPadText();
|
|
61
55
|
},
|
|
62
|
-
createOrResetPadText(
|
|
63
|
-
this.cleanPad(
|
|
56
|
+
async createOrResetPadText() {
|
|
57
|
+
await this.cleanPad();
|
|
58
|
+
const inner$ = helper.padInner$;
|
|
59
|
+
inner$('div').first().sendkeys('something\n anything');
|
|
60
|
+
await helper.waitForPromise(() => {
|
|
64
61
|
const inner$ = helper.padInner$;
|
|
65
|
-
inner$('div').
|
|
66
|
-
|
|
67
|
-
const inner$ = helper.padInner$;
|
|
68
|
-
const lineLength = inner$('div').length;
|
|
69
|
-
|
|
70
|
-
return lineLength > 1;
|
|
71
|
-
}).done(cb);
|
|
62
|
+
const lineLength = inner$('div').length;
|
|
63
|
+
return lineLength > 1;
|
|
72
64
|
});
|
|
73
65
|
},
|
|
74
|
-
|
|
75
|
-
test.timeout(20000);
|
|
76
|
-
const self = this;
|
|
77
|
-
const padId = this.padId;
|
|
78
|
-
// we do nothing for a second while we wait for content to be collected before reloading
|
|
79
|
-
// this may be hacky, but we need time for CC to run so... :?
|
|
80
|
-
setTimeout(() => {
|
|
81
|
-
helper.newPad(() => {
|
|
82
|
-
self.enlargeScreen(cb);
|
|
83
|
-
}, padId);
|
|
84
|
-
}, 1000);
|
|
85
|
-
},
|
|
86
|
-
cleanPad(callback) {
|
|
66
|
+
async cleanPad() {
|
|
87
67
|
const inner$ = helper.padInner$;
|
|
88
68
|
const $padContent = inner$('#innerdocbody');
|
|
89
69
|
$padContent.html(' ');
|
|
90
70
|
|
|
91
71
|
// wait for Etherpad to re-create first line
|
|
92
|
-
helper.
|
|
72
|
+
await helper.waitForPromise(() => {
|
|
93
73
|
const lineNumber = inner$('div').length;
|
|
94
74
|
return lineNumber === 1;
|
|
95
|
-
}, 20000)
|
|
75
|
+
}, 20000);
|
|
96
76
|
},
|
|
97
|
-
enlargeScreen(
|
|
77
|
+
enlargeScreen() {
|
|
98
78
|
$('#iframe-container iframe').css('max-width', '3000px');
|
|
99
|
-
callback();
|
|
100
79
|
},
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
this.
|
|
104
|
-
self.addCommentReplyToLine(line, textOfReply, callback);
|
|
105
|
-
});
|
|
80
|
+
async addCommentAndReplyToLine(line, textOfComment, textOfReply) {
|
|
81
|
+
await this.addCommentToLine(line, textOfComment);
|
|
82
|
+
await this.addCommentReplyToLine(line, textOfReply);
|
|
106
83
|
},
|
|
107
|
-
addCommentToLine(line, textOfComment
|
|
84
|
+
async addCommentToLine(line, textOfComment) {
|
|
108
85
|
const chrome$ = helper.padChrome$;
|
|
109
86
|
const $line = this.getLine(line);
|
|
110
87
|
$line.sendkeys('{selectall}'); // needs to select content to add comment to
|
|
@@ -118,9 +95,9 @@ const commentDelete = {
|
|
|
118
95
|
$submittButton.click();
|
|
119
96
|
|
|
120
97
|
// wait until comment is created and comment id is set
|
|
121
|
-
this.createdCommentOnLine(line
|
|
98
|
+
await this.createdCommentOnLine(line);
|
|
122
99
|
},
|
|
123
|
-
addCommentReplyToLine(line, textOfReply
|
|
100
|
+
async addCommentReplyToLine(line, textOfReply) {
|
|
124
101
|
const outer$ = helper.padOuter$;
|
|
125
102
|
const commentId = this.getCommentIdOfLine(line);
|
|
126
103
|
const existingReplies = outer$('.sidebar-comment-reply').length;
|
|
@@ -141,19 +118,18 @@ const commentDelete = {
|
|
|
141
118
|
$submitReplyButton.click();
|
|
142
119
|
|
|
143
120
|
// wait for the reply to be saved
|
|
144
|
-
helper.
|
|
121
|
+
await helper.waitForPromise(() => {
|
|
145
122
|
const hasSavedReply = outer$('.sidebar-comment-reply').length === existingReplies + 1;
|
|
146
123
|
return hasSavedReply;
|
|
147
|
-
})
|
|
124
|
+
});
|
|
148
125
|
},
|
|
149
126
|
getLine(lineNum) {
|
|
150
127
|
const inner$ = helper.padInner$;
|
|
151
128
|
const $line = inner$('div').slice(lineNum, lineNum + 1);
|
|
152
129
|
return $line;
|
|
153
130
|
},
|
|
154
|
-
createdCommentOnLine(line
|
|
155
|
-
|
|
156
|
-
helper.waitFor(() => self.getCommentIdOfLine(line) != null).done(cb);
|
|
131
|
+
async createdCommentOnLine(line) {
|
|
132
|
+
await helper.waitForPromise(() => this.getCommentIdOfLine(line) != null);
|
|
157
133
|
},
|
|
158
134
|
getCommentIdOfLine(line) {
|
|
159
135
|
const $line = this.getLine(line);
|
|
@@ -167,40 +143,4 @@ const commentDelete = {
|
|
|
167
143
|
commentIconsEnabled() {
|
|
168
144
|
return helper.padOuter$('#commentIcons').length > 0;
|
|
169
145
|
},
|
|
170
|
-
clickEditCommentButton() {
|
|
171
|
-
const outer$ = helper.padOuter$;
|
|
172
|
-
const $editButton = outer$('.comment-edit').first();
|
|
173
|
-
$editButton.click();
|
|
174
|
-
},
|
|
175
|
-
clickEditCommentReplyButton() {
|
|
176
|
-
const outer$ = helper.padOuter$;
|
|
177
|
-
const $editButton = outer$('.comment-edit').last();
|
|
178
|
-
$editButton.click();
|
|
179
|
-
},
|
|
180
|
-
getEditForm() {
|
|
181
|
-
const outer$ = helper.padOuter$;
|
|
182
|
-
return outer$('.comment-edit-form');
|
|
183
|
-
},
|
|
184
|
-
checkIfOneFormEditWasAdded() {
|
|
185
|
-
expect(this.getEditForm().length).to.be(1);
|
|
186
|
-
},
|
|
187
|
-
checkIfOneFormEditWasRemoved() {
|
|
188
|
-
expect(this.getEditForm().length).to.be(0);
|
|
189
|
-
},
|
|
190
|
-
checkIfCommentFieldIsHidden(fieldClass) {
|
|
191
|
-
const outer$ = helper.padOuter$;
|
|
192
|
-
const $field = outer$(`.${fieldClass}`).first();
|
|
193
|
-
expect($field.is(':visible')).to.be(false);
|
|
194
|
-
},
|
|
195
|
-
pressCancel() {
|
|
196
|
-
const $cancelButton = this.getEditForm().find('.comment-edit-cancel');
|
|
197
|
-
$cancelButton.click();
|
|
198
|
-
},
|
|
199
|
-
pressSave() {
|
|
200
|
-
const $saveButton = this.getEditForm().find('.comment-edit-submit');
|
|
201
|
-
$saveButton.click();
|
|
202
|
-
},
|
|
203
|
-
writeCommentText(commentText) {
|
|
204
|
-
this.getEditForm().find('.comment-edit-text').text(commentText);
|
|
205
|
-
},
|
|
206
146
|
};
|