strapi-plugin-comments 2.0.6 → 2.0.9
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/__mocks__/initSetup.js +35 -9
- package/admin/src/pages/Settings/index.js +2 -2
- package/package.json +1 -1
- package/server/controllers/client.js +0 -3
- package/server/graphql/queries/findAllFlat.js +6 -2
- package/server/services/__tests__/common.test.js +155 -2
- package/server/services/common.js +12 -14
package/__mocks__/initSetup.js
CHANGED
|
@@ -1,14 +1,32 @@
|
|
|
1
|
-
const { get, set } = require('lodash');
|
|
1
|
+
const { get, set, isEmpty } = require('lodash');
|
|
2
2
|
|
|
3
|
-
module.exports = (config = {}, toStore = false) => {
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
config: { ...config },
|
|
9
|
-
},
|
|
3
|
+
module.exports = (config = {}, toStore = false, database = {}) => {
|
|
4
|
+
const dbConfig = toStore ? {
|
|
5
|
+
plugin: {
|
|
6
|
+
comments: {
|
|
7
|
+
config: { ...config },
|
|
10
8
|
},
|
|
11
|
-
}
|
|
9
|
+
},
|
|
10
|
+
}: {};
|
|
11
|
+
|
|
12
|
+
let mock = {
|
|
13
|
+
db: {
|
|
14
|
+
query: (uid) => {
|
|
15
|
+
const [handler, rest] = uid.split('::');
|
|
16
|
+
const [collection] = rest.split('.');
|
|
17
|
+
const values = get(mock.db, `${handler}.${collection}.records`, []);
|
|
18
|
+
return {
|
|
19
|
+
findOne: async () => new Promise(resolve => resolve(values[0])),
|
|
20
|
+
findMany: async () => new Promise(resolve => resolve(values)),
|
|
21
|
+
findWithCount: async () => new Promise(resolve => resolve([values, values.length])),
|
|
22
|
+
count: async () => new Promise(resolve => resolve(values.length)),
|
|
23
|
+
create: async (value) => new Promise(resolve => resolve(value)),
|
|
24
|
+
update: async (value) => new Promise(resolve => resolve(value)),
|
|
25
|
+
delete: async (value) => new Promise(resolve => resolve(value)),
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
...dbConfig,
|
|
29
|
+
},
|
|
12
30
|
getRef: function() {
|
|
13
31
|
return this;
|
|
14
32
|
},
|
|
@@ -78,5 +96,13 @@ module.exports = (config = {}, toStore = false) => {
|
|
|
78
96
|
}
|
|
79
97
|
}
|
|
80
98
|
};
|
|
99
|
+
|
|
100
|
+
if (!isEmpty(database)) {
|
|
101
|
+
Object.keys(database).forEach((uid) => {
|
|
102
|
+
const [handler, collection] = uid.split('::');
|
|
103
|
+
set(mock.db, `${handler}.${collection}.records`, database[uid]);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
|
|
81
107
|
return mock;
|
|
82
108
|
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useRef, useMemo, useState } from 'react';
|
|
2
2
|
import { useQuery } from 'react-query';
|
|
3
3
|
import { Formik } from 'formik';
|
|
4
|
-
import { capitalize, first, orderBy, isEmpty, isEqual } from 'lodash';
|
|
4
|
+
import { capitalize, first, orderBy, isEmpty, isEqual, isNil } from 'lodash';
|
|
5
5
|
import {
|
|
6
6
|
CheckPermissions,
|
|
7
7
|
LoadingIndicatorPage,
|
|
@@ -109,7 +109,7 @@ const Settings = () => {
|
|
|
109
109
|
.filter(_ => _) || [];
|
|
110
110
|
const entryLabel = configData?.entryLabel || {};
|
|
111
111
|
const approvalFlow = configData?.approvalFlow || [];
|
|
112
|
-
const badWords = configData?.badWords
|
|
112
|
+
const badWords = isNil(configData?.badWords) ? true : configData?.badWords;
|
|
113
113
|
const isGQLPluginEnabled = configData?.isGQLPluginEnabled;
|
|
114
114
|
const gqlAuthEnabled = configData?.gql?.auth || undefined;
|
|
115
115
|
const moderatorRoles = configData?.moderatorRoles
|
package/package.json
CHANGED
|
@@ -16,9 +16,6 @@ module.exports = {
|
|
|
16
16
|
|
|
17
17
|
const { sort: querySort, pagination: queryPagination, ...filterQuery } = query || {};
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
console.log(filterQuery);
|
|
21
|
-
|
|
22
19
|
try {
|
|
23
20
|
return this.getService('common')
|
|
24
21
|
.findAllFlat(flatInput(relation, filterQuery, sort || querySort, pagination || queryPagination));
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
'use strict'
|
|
2
2
|
|
|
3
|
+
const { isEmpty } = require('lodash');
|
|
3
4
|
const contentType = require('../../../content-types/comment');
|
|
4
5
|
const { flatInput } = require('../../controllers/utils/parsers');
|
|
5
6
|
const { getPluginService } = require('../../utils/functions');
|
|
6
7
|
|
|
7
8
|
module.exports = ({ strapi, nexus }) => {
|
|
8
|
-
const { nonNull,
|
|
9
|
+
const { nonNull, stringArg } = nexus;
|
|
9
10
|
const { service: getService } = strapi.plugin('graphql');
|
|
10
11
|
const { args } = getService('internals');
|
|
11
12
|
|
|
@@ -24,7 +25,10 @@ module.exports = ({ strapi, nexus }) => {
|
|
|
24
25
|
relation,
|
|
25
26
|
getPluginService('gql').graphQLFiltersToStrapiQuery(filters, contentType),
|
|
26
27
|
sort,
|
|
27
|
-
pagination
|
|
28
|
+
pagination ? {
|
|
29
|
+
...pagination,
|
|
30
|
+
withCount: !isEmpty(pagination),
|
|
31
|
+
} : undefined
|
|
28
32
|
), undefined);
|
|
29
33
|
},
|
|
30
34
|
};
|
|
@@ -5,9 +5,9 @@ const { getPluginService } = require('../../utils/functions');
|
|
|
5
5
|
jest.mock
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
const setup = function(config) {
|
|
8
|
+
const setup = function(config, toStore, database) {
|
|
9
9
|
Object.defineProperty(global, 'strapi', {
|
|
10
|
-
value: require('../../../__mocks__/initSetup')(config),
|
|
10
|
+
value: require('../../../__mocks__/initSetup')(config, toStore, database),
|
|
11
11
|
writable: true,
|
|
12
12
|
});
|
|
13
13
|
}
|
|
@@ -242,5 +242,158 @@ describe('Test Comments service functions utils', () => {
|
|
|
242
242
|
}
|
|
243
243
|
});
|
|
244
244
|
});
|
|
245
|
+
|
|
246
|
+
describe('Merge related entity', () => {
|
|
247
|
+
beforeEach(() => setup({ enabledCollections: [uid] }));
|
|
248
|
+
const collection = 'api::collection.test';
|
|
249
|
+
const related = `${collection}:1`;
|
|
250
|
+
const comment = {
|
|
251
|
+
id: 1,
|
|
252
|
+
content: 'ABC',
|
|
253
|
+
threadOf: null,
|
|
254
|
+
related,
|
|
255
|
+
authorId: 1,
|
|
256
|
+
authorName: 'Joe Doe',
|
|
257
|
+
authorEmail: 'joe@example.com'
|
|
258
|
+
};
|
|
259
|
+
const relatedEntity = { id: 1, title: 'Test', uid: collection};
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
test('Should merge related entity', async () => {
|
|
263
|
+
const result = await getPluginService('common').mergeRelatedEntityTo(comment, [relatedEntity]);
|
|
264
|
+
expect(result).toHaveProperty('id', 1);
|
|
265
|
+
expect(result).not.toHaveProperty('related', related);
|
|
266
|
+
expect(result).toHaveProperty(['related', 'title'], relatedEntity.title);
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
describe('Client API', () => {
|
|
271
|
+
const collection = 'api::collection.test';
|
|
272
|
+
const related = `${collection}:1`;
|
|
273
|
+
const db = [{
|
|
274
|
+
id: 1,
|
|
275
|
+
content: 'ABC',
|
|
276
|
+
threadOf: null,
|
|
277
|
+
related,
|
|
278
|
+
authorId: 1,
|
|
279
|
+
authorName: 'Joe Doe',
|
|
280
|
+
authorEmail: 'joe@example.com'
|
|
281
|
+
}, {
|
|
282
|
+
id: 2,
|
|
283
|
+
content: 'DEF',
|
|
284
|
+
threadOf: 1,
|
|
285
|
+
related,
|
|
286
|
+
authorId: 1,
|
|
287
|
+
authorName: 'Joe Doe',
|
|
288
|
+
authorEmail: 'joe@example.com',
|
|
289
|
+
blockedThread: true,
|
|
290
|
+
}, {
|
|
291
|
+
id: 3,
|
|
292
|
+
content: 'GHJ',
|
|
293
|
+
threadOf: null,
|
|
294
|
+
related,
|
|
295
|
+
authorId: 1,
|
|
296
|
+
authorName: 'Joe Doe',
|
|
297
|
+
authorEmail: 'joe@example.com'
|
|
298
|
+
}, {
|
|
299
|
+
id: 4,
|
|
300
|
+
content: 'IKL',
|
|
301
|
+
threadOf: 2,
|
|
302
|
+
related,
|
|
303
|
+
authorId: 1,
|
|
304
|
+
authorName: 'Joe Doe',
|
|
305
|
+
authorEmail: 'joe@example.com',
|
|
306
|
+
}];
|
|
307
|
+
const relatedEntity = { id: 1, title: 'Test', uid: collection};
|
|
308
|
+
|
|
309
|
+
beforeEach(() => setup({ enabledCollections: [collection] }, true, {
|
|
310
|
+
'plugins::comments': db,
|
|
311
|
+
'api::collection': [relatedEntity, { id: 2, title: 'Test 2', uid: collection }],
|
|
312
|
+
}));
|
|
313
|
+
|
|
314
|
+
describe('findAllFlat', () => {
|
|
315
|
+
test('Should return proper structure', async () => {
|
|
316
|
+
const result = await getPluginService('common').findAllFlat({ query: { related }}, relatedEntity);
|
|
317
|
+
expect(result).toHaveProperty('data');
|
|
318
|
+
expect(result).not.toHaveProperty('meta');
|
|
319
|
+
expect(result.data.length).toBe(4);
|
|
320
|
+
expect(result).toHaveProperty(['data', 0, 'content'], db[0].content);
|
|
321
|
+
expect(result).toHaveProperty(['data', 3, 'content'], db[3].content);
|
|
322
|
+
});
|
|
323
|
+
|
|
324
|
+
test('Should return structure with pagination', async () => {
|
|
325
|
+
const result = await getPluginService('common').findAllFlat({ query: { related }, pagination: { page: 1, pageSize: 5 }}, relatedEntity);
|
|
326
|
+
expect(result).toHaveProperty('data');
|
|
327
|
+
expect(result).toHaveProperty('meta');
|
|
328
|
+
expect(result.data.length).toBe(4);
|
|
329
|
+
expect(result).toHaveProperty(['data', 0, 'content'], db[0].content);
|
|
330
|
+
expect(result).toHaveProperty(['data', 0, 'author']);
|
|
331
|
+
expect(result).toHaveProperty(['data', 0, 'author', 'id'], db[0].authorId);
|
|
332
|
+
expect(result).toHaveProperty(['data', 0, 'author', 'name'], db[0].authorName);
|
|
333
|
+
expect(result).toHaveProperty(['data', 0, 'author', 'email'], db[0].authorEmail);
|
|
334
|
+
expect(result).toHaveProperty(['data', 3, 'content'], db[3].content);
|
|
335
|
+
expect(result).toHaveProperty(['meta', 'pagination', 'page'], 1);
|
|
336
|
+
expect(result).toHaveProperty(['meta', 'pagination', 'pageSize'], 5);
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
describe('findAllInHierarchy', () => {
|
|
341
|
+
test('Should return nested structure starting for root', async () => {
|
|
342
|
+
const result = await getPluginService('common').findAllInHierarchy({ query: { related }}, relatedEntity);
|
|
343
|
+
expect(result).not.toHaveProperty('data');
|
|
344
|
+
expect(result).not.toHaveProperty('meta');
|
|
345
|
+
expect(result.length).toBe(2);
|
|
346
|
+
expect(result).toHaveProperty([0, 'content'], db[0].content);
|
|
347
|
+
expect(result).toHaveProperty([0, 'children']);
|
|
348
|
+
expect(result[0].children.length).toBe(1);
|
|
349
|
+
expect(result).toHaveProperty([0, 'children', 0, 'content'], 'DEF');
|
|
350
|
+
expect(result).toHaveProperty([0, 'children', 0, 'children']);
|
|
351
|
+
expect(result[0].children[0].children.length).toBe(1);
|
|
352
|
+
expect(result).toHaveProperty([0, 'children', 0, 'children', 0, 'content'], 'IKL');
|
|
353
|
+
expect(result).toHaveProperty([1, 'content'], db[2].content);
|
|
354
|
+
});
|
|
355
|
+
|
|
356
|
+
test('Should return nested structure starting for comment id: 1', async () => {
|
|
357
|
+
const result = await getPluginService('common').findAllInHierarchy({ query: { related }, startingFromId: 1}, relatedEntity);
|
|
358
|
+
expect(result).not.toHaveProperty('data');
|
|
359
|
+
expect(result).not.toHaveProperty('meta');
|
|
360
|
+
expect(result.length).toBe(1);
|
|
361
|
+
expect(result).toHaveProperty([0, 'content'], db[1].content);
|
|
362
|
+
expect(result).toHaveProperty([0, 'children']);
|
|
363
|
+
expect(result[0].children.length).toBe(1);
|
|
364
|
+
expect(result).toHaveProperty([0, 'children', 0, 'content'], 'IKL');
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
test('Should return nested structure starting for comment id: 1 without blocked comments', async () => {
|
|
368
|
+
const result = await getPluginService('common').findAllInHierarchy({ query: { related }, startingFromId: 1, dropBlockedThreads: true}, relatedEntity);
|
|
369
|
+
expect(result).not.toHaveProperty('data');
|
|
370
|
+
expect(result).not.toHaveProperty('meta');
|
|
371
|
+
expect(result.length).toBe(1);
|
|
372
|
+
expect(result).toHaveProperty([0, 'content'], db[1].content);
|
|
373
|
+
expect(result).toHaveProperty([0, 'children']);
|
|
374
|
+
expect(result[0].children.length).toBe(0);
|
|
375
|
+
});
|
|
376
|
+
});
|
|
377
|
+
|
|
378
|
+
describe('findOne', () => {
|
|
379
|
+
test('Should return proper structure', async () => {
|
|
380
|
+
const result = await getPluginService('common').findOne({ related });
|
|
381
|
+
expect(result).toHaveProperty('id', db[0].id);
|
|
382
|
+
expect(result).toHaveProperty('content', db[0].content);
|
|
383
|
+
expect(result).toHaveProperty(['author', 'id'], db[0].authorId);
|
|
384
|
+
expect(result).toHaveProperty(['author', 'name'], db[0].authorName);
|
|
385
|
+
expect(result).toHaveProperty(['author', 'email'], db[0].authorEmail);
|
|
386
|
+
});
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
describe('findRelatedEntitiesFor', () => {
|
|
390
|
+
test('Should return proper structure', async () => {
|
|
391
|
+
const result = await getPluginService('common').findRelatedEntitiesFor(db);
|
|
392
|
+
expect(result).toHaveProperty([0, 'id'], relatedEntity.id);
|
|
393
|
+
expect(result).toHaveProperty([0, 'title'], relatedEntity.title);
|
|
394
|
+
expect(result).toHaveProperty([0, 'uid'], relatedEntity.uid);
|
|
395
|
+
});
|
|
396
|
+
});
|
|
397
|
+
});
|
|
245
398
|
});
|
|
246
399
|
});
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const BadWordsFilter = require('bad-words');
|
|
4
|
-
const { isArray, isNumber, isObject, isNil, isString, first, parseInt, set, get } = require('lodash');
|
|
4
|
+
const { isArray, isNumber, isObject, isNil, isString, isEmpty, first, parseInt, set, get } = require('lodash');
|
|
5
5
|
const { REGEX, CONFIG_PARAMS } = require('../utils/constants');
|
|
6
6
|
const PluginError = require('./../utils/error');
|
|
7
7
|
const {
|
|
@@ -74,8 +74,8 @@ module.exports = ({ strapi }) => ({
|
|
|
74
74
|
...prev,
|
|
75
75
|
[curr]: parseInt(pagination[curr]),
|
|
76
76
|
}), {});
|
|
77
|
-
const { page, pageSize = 10,
|
|
78
|
-
const paginationByPage = !isNil(page);
|
|
77
|
+
const { page = 1, pageSize = 10, start = 0, limit = 10 } = parsedPagination;
|
|
78
|
+
const paginationByPage = !isNil(parsedPagination?.page) || !isNil(parsedPagination?.pageSize);
|
|
79
79
|
|
|
80
80
|
queryExtension = {
|
|
81
81
|
...queryExtension,
|
|
@@ -143,6 +143,8 @@ module.exports = ({ strapi }) => ({
|
|
|
143
143
|
}));
|
|
144
144
|
|
|
145
145
|
const relatedEntities = relatedEntity !== null ? [relatedEntity] : await this.findRelatedEntitiesFor([...entries]);
|
|
146
|
+
const hasRelatedEntitiesToMap = relatedEntities.filter(_ => _).length > 0;
|
|
147
|
+
|
|
146
148
|
const result = entries
|
|
147
149
|
.map(_ => {
|
|
148
150
|
const threadedItem = entriesWithThreads.find(item => item.id === _.id);
|
|
@@ -154,16 +156,12 @@ module.exports = ({ strapi }) => ({
|
|
|
154
156
|
});
|
|
155
157
|
});
|
|
156
158
|
|
|
157
|
-
if (relatedEntities.filter(_ => _).length > 0) {
|
|
158
|
-
return {
|
|
159
|
-
data: result.map(_ => this.mergeRelatedEntityTo(_, relatedEntities)),
|
|
160
|
-
meta,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
159
|
return {
|
|
164
|
-
data:
|
|
165
|
-
|
|
166
|
-
|
|
160
|
+
data: hasRelatedEntitiesToMap ?
|
|
161
|
+
result.map(_ => this.mergeRelatedEntityTo(_, relatedEntities)) :
|
|
162
|
+
result,
|
|
163
|
+
...(isEmpty(meta) ? {} : { meta }),
|
|
164
|
+
};
|
|
167
165
|
},
|
|
168
166
|
|
|
169
167
|
// Find comments and create relations tree structure
|
|
@@ -174,8 +172,8 @@ module.exports = ({ strapi }) => ({
|
|
|
174
172
|
startingFromId = null,
|
|
175
173
|
dropBlockedThreads = false,
|
|
176
174
|
}, relatedEntity) {
|
|
177
|
-
const entities = await this.findAllFlat({ query, populate, sort }, relatedEntity)
|
|
178
|
-
return buildNestedStructure(entities, startingFromId, 'threadOf', dropBlockedThreads, false);
|
|
175
|
+
const entities = await this.findAllFlat({ query, populate, sort }, relatedEntity);
|
|
176
|
+
return buildNestedStructure(entities?.data, startingFromId, 'threadOf', dropBlockedThreads, false);
|
|
179
177
|
},
|
|
180
178
|
|
|
181
179
|
// Find single comment
|