strapi-plugin-comments 2.0.0-beta.5 → 2.0.0-rc.2

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.
Files changed (60) hide show
  1. package/README.md +472 -118
  2. package/admin/src/components/DiscussionThread/index.js +9 -3
  3. package/admin/src/components/DiscussionThreadItem/index.js +24 -11
  4. package/admin/src/components/DiscussionThreadItemActions/index.js +45 -18
  5. package/admin/src/components/DiscussionThreadItemApprovalFlowActions/index.js +20 -11
  6. package/admin/src/components/DiscussionThreadItemMeta/index.js +16 -5
  7. package/admin/src/components/DiscussionThreadItemWarnings/index.js +15 -9
  8. package/admin/src/components/ReportsReviewModal/index.js +5 -0
  9. package/admin/src/components/ReportsReviewTable/index.js +60 -52
  10. package/admin/src/components/icons/review.js +1 -1
  11. package/admin/src/index.js +1 -1
  12. package/admin/src/pages/Details/components/DetailsEntity/index.js +2 -2
  13. package/admin/src/pages/Details/components/DetailsFilters/index.js +1 -0
  14. package/admin/src/pages/Details/index.js +43 -37
  15. package/admin/src/pages/Discover/components/DiscoverTableRow/index.js +38 -11
  16. package/admin/src/pages/Discover/index.js +72 -59
  17. package/admin/src/permissions.js +10 -8
  18. package/admin/src/translations/en.json +2 -0
  19. package/admin/src/utils/index.js +2 -0
  20. package/admin/src/utils/renderInitials.js +5 -0
  21. package/content-types/comment.js +0 -4
  22. package/package.json +4 -2
  23. package/permissions.js +19 -0
  24. package/public/assets/logo.png +0 -0
  25. package/public/assets/preview.png +0 -0
  26. package/server/bootstrap.js +38 -2
  27. package/server/config/index.js +7 -2
  28. package/server/controllers/client.js +11 -21
  29. package/server/controllers/utils/parsers.js +19 -0
  30. package/server/graphql/index.js +26 -0
  31. package/server/graphql/mutations/createAbuseReport.js +25 -0
  32. package/server/graphql/mutations/createComment.js +25 -0
  33. package/server/graphql/mutations/index.js +21 -0
  34. package/server/graphql/mutations/removeComment.js +25 -0
  35. package/server/graphql/mutations/updateComment.js +25 -0
  36. package/server/graphql/queries/findAllFlat.js +29 -0
  37. package/server/graphql/queries/findAllInHierarchy.js +31 -0
  38. package/server/graphql/queries/index.js +19 -0
  39. package/server/graphql/resolvers-config.js +15 -0
  40. package/server/graphql/types/comment-author.js +9 -0
  41. package/server/graphql/types/comment-nested.js +15 -0
  42. package/server/graphql/types/comment.js +15 -0
  43. package/server/graphql/types/create-comment-author.js +9 -0
  44. package/server/graphql/types/create-comment.js +9 -0
  45. package/server/graphql/types/create-report.js +9 -0
  46. package/server/graphql/types/id.js +24 -0
  47. package/server/graphql/types/identify-comment-author.js +6 -0
  48. package/server/graphql/types/index.js +16 -0
  49. package/server/graphql/types/remove-comment.js +8 -0
  50. package/server/graphql/types/report-reason.js +10 -0
  51. package/server/graphql/types/report.js +11 -0
  52. package/server/graphql/types/update-comment.js +9 -0
  53. package/server/register.js +3 -1
  54. package/server/services/admin.js +20 -16
  55. package/server/services/client.js +72 -49
  56. package/server/services/common.js +23 -12
  57. package/server/services/graphql.js +190 -0
  58. package/server/services/index.js +2 -0
  59. package/server/services/utils/functions.js +30 -11
  60. package/strapi-server.js +33 -0
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ module.exports = {
4
+ flatInput(relation, query) {
5
+ return {
6
+ query: {
7
+ ...query,
8
+ $or: [{ removed: { $null: true } }, { removed: false }],
9
+ related: relation,
10
+ },
11
+ populate: {
12
+ threadOf: {
13
+ populate: { authorUser: true },
14
+ },
15
+ },
16
+ };
17
+ },
18
+
19
+ };
@@ -0,0 +1,26 @@
1
+ 'use strict'
2
+
3
+ const getTypes = require('./types');
4
+ const getQueries = require('./queries');
5
+ const getMutations = require('./mutations');
6
+ const getResolversConfig = require('./resolvers-config');
7
+ const { getModelUid } = require('../services/utils/functions');
8
+
9
+ module.exports = () => {
10
+ const extensionService = strapi.plugin('graphql').service('extension');
11
+
12
+ extensionService.shadowCRUD(getModelUid('comment')).disable();
13
+ extensionService.shadowCRUD(getModelUid('comment-report')).disable();
14
+
15
+ extensionService.use(({ nexus }) => {
16
+ const types = getTypes({ strapi, nexus });
17
+ const queries = getQueries({ strapi, nexus });
18
+ const mutations = getMutations({ strapi, nexus });
19
+ const resolversConfig = getResolversConfig({ strapi });
20
+
21
+ return {
22
+ types: [types, queries, mutations],
23
+ resolversConfig,
24
+ }
25
+ });
26
+ }
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ const { getPluginService } = require('../../utils/functions');
4
+
5
+ module.exports = ({ nexus }) => {
6
+ const { nonNull } = nexus;
7
+
8
+ return {
9
+ type: nonNull('Report'),
10
+ args: {
11
+ input: nonNull('CreateReport'),
12
+ },
13
+ async resolve(obj, args, ctx) {
14
+ const { input } = args;
15
+ const { state: { user } = {} } = ctx;
16
+ const { commentId, relation, ...body } = input;
17
+ try {
18
+ return await getPluginService('client')
19
+ .reportAbuse(commentId, relation, body, user);
20
+ } catch(e) {
21
+ throw new Error(e);
22
+ }
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ const { getPluginService } = require('../../utils/functions');
4
+
5
+ module.exports = ({ nexus }) => {
6
+ const { nonNull } = nexus;
7
+
8
+ return {
9
+ type: nonNull('CommentSingle'),
10
+ args: {
11
+ input: nonNull('CreateComment'),
12
+ },
13
+ async resolve(obj, args, ctx) {
14
+ const { input } = args;
15
+ const { state: { user } = {} } = ctx;
16
+ const { relation, ...body } = input;
17
+ try {
18
+ return await getPluginService('client')
19
+ .create(relation, body, user);
20
+ } catch(e) {
21
+ throw new Error(e);
22
+ }
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,21 @@
1
+ 'use strict'
2
+
3
+ module.exports = (context) => {
4
+ const mutations = {
5
+ createComment: require('./createComment'),
6
+ updateComment: require('./updateComment'),
7
+ removeComment: require('./removeComment'),
8
+ createAbuseReport: require('./createAbuseReport'),
9
+ };
10
+
11
+ return context.nexus.extendType({
12
+ type: 'Mutation',
13
+ definition(t) {
14
+ for (const [name, configFactory] of Object.entries(mutations)) {
15
+ const config = configFactory(context);
16
+
17
+ t.field(name, config);
18
+ }
19
+ },
20
+ });
21
+ };
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ const { getPluginService } = require('../../utils/functions');
4
+
5
+ module.exports = ({ nexus }) => {
6
+ const { nonNull } = nexus;
7
+
8
+ return {
9
+ type: nonNull('CommentSingle'),
10
+ args: {
11
+ input: nonNull('RemoveComment'),
12
+ },
13
+ async resolve(obj, args, ctx) {
14
+ const { input } = args;
15
+ const { state: { user } = {} } = ctx;
16
+ const { id, relation, author } = input;
17
+ try {
18
+ return await getPluginService('client')
19
+ .markAsRemoved(id, relation, author?.id, user);
20
+ } catch(e) {
21
+ throw new Error(e);
22
+ }
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,25 @@
1
+ 'use strict'
2
+
3
+ const { getPluginService } = require('../../utils/functions');
4
+
5
+ module.exports = ({ nexus }) => {
6
+ const { nonNull } = nexus;
7
+
8
+ return {
9
+ type: nonNull('CommentSingle'),
10
+ args: {
11
+ input: nonNull('UpdateComment'),
12
+ },
13
+ async resolve(obj, args, ctx) {
14
+ const { input } = args;
15
+ const { state: { user } = {} } = ctx;
16
+ const { id, relation, ...body } = input;
17
+ try {
18
+ return await getPluginService('client')
19
+ .update(id, relation, body, user);
20
+ } catch(e) {
21
+ throw new Error(e);
22
+ }
23
+ },
24
+ };
25
+ }
@@ -0,0 +1,29 @@
1
+ 'use strict'
2
+
3
+ const contentType = require('../../../content-types/comment');
4
+ const { flatInput } = require('../../controllers/utils/parsers');
5
+ const { getPluginService } = require('../../utils/functions');
6
+
7
+ module.exports = ({ strapi, nexus }) => {
8
+ const { nonNull, list, stringArg } = nexus;
9
+ const { service: getService } = strapi.plugin('graphql');
10
+ const { args } = getService('internals');
11
+
12
+ return {
13
+ type: nonNull(list('CommentSingle')),
14
+ args: {
15
+ relation: nonNull(stringArg()),
16
+ filters: getPluginService('gql').buildContentTypeFilters(contentType),
17
+ pagination: args.PaginationArg,
18
+ sort: args.SortArg,
19
+ },
20
+ async resolve(obj, args) {
21
+ const { relation, filters } = args;
22
+ return await getPluginService('common')
23
+ .findAllFlat(flatInput(
24
+ relation,
25
+ getPluginService('gql').graphQLFiltersToStrapiQuery(filters, contentType)
26
+ ), undefined);
27
+ },
28
+ };
29
+ }
@@ -0,0 +1,31 @@
1
+ 'use strict'
2
+
3
+ const contentType = require('../../../content-types/comment');
4
+ const { flatInput } = require('../../controllers/utils/parsers');
5
+ const { getPluginService } = require('../../utils/functions');
6
+
7
+ module.exports = ({ strapi, nexus }) => {
8
+ const { nonNull, list, stringArg } = nexus;
9
+ const { service: getService } = strapi.plugin('graphql');
10
+ const { args } = getService('internals');
11
+
12
+ return {
13
+ type: nonNull(list('CommentNested')),
14
+ args: {
15
+ relation: nonNull(stringArg()),
16
+ // filters: filtersArg,
17
+ sort: args.SortArg,
18
+ },
19
+ async resolve(obj, args) {
20
+ const { relation, filters } = args;
21
+ return await getPluginService('common')
22
+ .findAllInHierarchy({
23
+ ...flatInput(
24
+ relation,
25
+ getPluginService('gql').graphQLFiltersToStrapiQuery(filters, contentType)
26
+ ),
27
+ dropBlockedThreads: true,
28
+ });
29
+ },
30
+ };
31
+ }
@@ -0,0 +1,19 @@
1
+ 'use strict'
2
+
3
+ module.exports = (context) => {
4
+ const queries = {
5
+ findAllFlat: require('./findAllFlat'),
6
+ findAllInHierarchy: require('./findAllInHierarchy'),
7
+ };
8
+
9
+ return context.nexus.extendType({
10
+ type: 'Query',
11
+ definition(t) {
12
+ for (const [name, configFactory] of Object.entries(queries)) {
13
+ const config = configFactory(context);
14
+
15
+ t.field(name, config);
16
+ }
17
+ },
18
+ });
19
+ };
@@ -0,0 +1,15 @@
1
+ 'use strict'
2
+
3
+ const { getPluginService } = require("../utils/functions");
4
+
5
+ module.exports = () => {
6
+ const auth = getPluginService('common').getConfig('gql.auth', false);
7
+ return {
8
+ 'Query.findAllFlat': { auth },
9
+ 'Query.findAllInHierarchy': { auth },
10
+ 'Mutation.createComment': { auth },
11
+ 'Mutation.updateComment': { auth },
12
+ 'Mutation.removeComment': { auth },
13
+ 'Mutation.createAbuseReport': { auth },
14
+ };
15
+ };
@@ -0,0 +1,9 @@
1
+ module.exports = ({ nexus }) => nexus.objectType({
2
+ name: "CommentAuthor",
3
+ definition(t) {
4
+ t.id("id")
5
+ t.nonNull.string("name")
6
+ t.string("email")
7
+ t.string("avatar")
8
+ }
9
+ })
@@ -0,0 +1,15 @@
1
+ module.exports = ({ nexus }) => nexus.objectType({
2
+ name: "CommentNested",
3
+ definition(t) {
4
+ t.id("id")
5
+ t.nonNull.string("content")
6
+ t.boolean("blocked")
7
+ t.boolean("blockedThread")
8
+ t.string("approvalStatus")
9
+ t.field("threadOf", { type: 'CommentSingle' })
10
+ t.list.field("children", { type: 'CommentNested' })
11
+ t.field("author", { type: 'CommentAuthor' })
12
+ t.string("createdAt")
13
+ t.string("updatedAt")
14
+ }
15
+ })
@@ -0,0 +1,15 @@
1
+ module.exports = ({ nexus }) => nexus.objectType({
2
+ name: "CommentSingle",
3
+ definition(t) {
4
+ t.id("id")
5
+ t.nonNull.string("content")
6
+ t.boolean("blocked")
7
+ t.boolean("blockedThread")
8
+ t.boolean("removed")
9
+ t.string("approvalStatus")
10
+ t.field("threadOf", { type: 'CommentSingle' })
11
+ t.field("author", { type: 'CommentAuthor' })
12
+ t.string("createdAt")
13
+ t.string("updatedAt")
14
+ }
15
+ })
@@ -0,0 +1,9 @@
1
+ module.exports = ({ nexus }) => nexus.inputObjectType({
2
+ name: "CreateCommentAuthor",
3
+ definition(t) {
4
+ t.nonNull.id("id")
5
+ t.nonNull.string("name")
6
+ t.string("email")
7
+ t.string("avatar")
8
+ }
9
+ })
@@ -0,0 +1,9 @@
1
+ module.exports = ({ nexus }) => nexus.inputObjectType({
2
+ name: "CreateComment",
3
+ definition(t) {
4
+ t.nonNull.string("content")
5
+ t.nonNull.string("relation")
6
+ t.id("threadOf")
7
+ t.field("author", { type: 'CreateCommentAuthor' })
8
+ }
9
+ })
@@ -0,0 +1,9 @@
1
+ module.exports = ({ nexus }) => nexus.inputObjectType({
2
+ name: "CreateReport",
3
+ definition(t) {
4
+ t.id("commentId")
5
+ t.nonNull.string("relation")
6
+ t.nonNull.string("content")
7
+ t.field("reason", { type: 'ReportReason' })
8
+ }
9
+ })
@@ -0,0 +1,24 @@
1
+ const { isNumber, parseInt } = require('lodash');
2
+ const { Kind } = require('graphql');
3
+
4
+ module.exports = ({ nexus }) => nexus.scalarType({
5
+ name: "Id",
6
+ asNexusMethod: 'id',
7
+ description: 'Id as string or int',
8
+ parseValue(value) {
9
+ const parsedValue = parseInt(value);
10
+ if (isNumber(parsedValue)) {
11
+ return parsedValue;
12
+ }
13
+ return value;
14
+ },
15
+ serialize(value) {
16
+ return value;
17
+ },
18
+ parseLiteral(ast) {
19
+ if ([Kind.INT, Kind.STRING].includes(ast.kind)) {
20
+ return ast.value;
21
+ }
22
+ return null
23
+ },
24
+ })
@@ -0,0 +1,6 @@
1
+ module.exports = ({ nexus }) => nexus.inputObjectType({
2
+ name: "IdentifyCommentAuthor",
3
+ definition(t) {
4
+ t.nonNull.id("id")
5
+ }
6
+ })
@@ -0,0 +1,16 @@
1
+ const typesFactories = [
2
+ require('./id'),
3
+ require('./comment'),
4
+ require('./comment-nested'),
5
+ require('./comment-author'),
6
+ require('./create-comment'),
7
+ require('./create-comment-author'),
8
+ require('./update-comment'),
9
+ require('./remove-comment'),
10
+ require('./identify-comment-author'),
11
+ require('./report'),
12
+ require('./report-reason'),
13
+ require('./create-report'),
14
+ ];
15
+
16
+ module.exports = context => typesFactories.map(factory => factory(context));
@@ -0,0 +1,8 @@
1
+ module.exports = ({ nexus }) => nexus.inputObjectType({
2
+ name: "RemoveComment",
3
+ definition(t) {
4
+ t.id("id")
5
+ t.nonNull.string("relation")
6
+ t.field("author", { type: 'IdentifyCommentAuthor' })
7
+ }
8
+ })
@@ -0,0 +1,10 @@
1
+ const { getPluginService } = require("../../utils/functions");
2
+
3
+
4
+ module.exports = ({ nexus }) => nexus.enumType({
5
+ name: "ReportReason",
6
+ description: 'Reason of abuse report',
7
+ members: {
8
+ ...getPluginService('common').getConfig('reportReasons', {})
9
+ },
10
+ })
@@ -0,0 +1,11 @@
1
+ module.exports = ({ nexus }) => nexus.objectType({
2
+ name: "Report",
3
+ definition(t) {
4
+ t.id("id")
5
+ t.nonNull.string("content")
6
+ t.field("reason", { type: 'ReportReason' })
7
+ t.field("related", { type: 'CommentSingle' })
8
+ t.string("createdAt")
9
+ t.string("updatedAt")
10
+ }
11
+ })
@@ -0,0 +1,9 @@
1
+ module.exports = ({ nexus }) => nexus.inputObjectType({
2
+ name: "UpdateComment",
3
+ definition(t) {
4
+ t.id("id")
5
+ t.nonNull.string("content")
6
+ t.nonNull.string("relation")
7
+ t.field("author", { type: 'IdentifyCommentAuthor' })
8
+ }
9
+ })
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  module.exports = ({ strapi }) => {
4
- // registeration phase
4
+ if (strapi.plugin('graphql')) {
5
+ require('./graphql')({ strapi });
6
+ }
5
7
  };
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
3
  const { getPluginService, parseParams } = require('./../utils/functions');
4
- const { isEmpty, isNil } = require('lodash');
4
+ const { isEmpty, isNil, isNumber, parseInt } = require('lodash');
5
5
  const PluginError = require('./../utils/error');
6
6
  const {
7
7
  getModelUid,
@@ -88,12 +88,13 @@ const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
88
88
  .map(_ => filterOurResolvedReports(this.getCommonService().sanitizeCommentEntity(_)))
89
89
  .map(_ => this.getCommonService().mergeRelatedEntityTo(_, relatedEntities));
90
90
 
91
+ const pageCount = Math.floor(total / pageSize);
91
92
  return {
92
93
  result,
93
94
  pagination: {
94
95
  page: page,
95
96
  pageSize: pageSize,
96
- pageCount: Math.floor(total / pageSize) + 1,
97
+ pageCount: total % pageSize === 0 ? pageCount : pageCount + 1,
97
98
  total,
98
99
  },
99
100
  };
@@ -116,19 +117,24 @@ const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
116
117
  }
117
118
  };
118
119
 
119
- const entity = await strapi.db.query(getModelUid('comment')).findOne({
120
- where: {
121
- id,
122
- },
120
+ const defaultPopulate = {
123
121
  populate: {
124
122
  authorUser: true,
125
123
  threadOf: {
126
124
  populate: {
125
+ authorUser: true,
127
126
  ...reportsPopulation
128
127
  },
129
128
  },
130
129
  ...reportsPopulation,
131
130
  },
131
+ }
132
+
133
+ const entity = await strapi.db.query(getModelUid('comment')).findOne({
134
+ where: {
135
+ id,
136
+ },
137
+ ...defaultPopulate,
132
138
  });
133
139
 
134
140
  if (!entity){
@@ -136,7 +142,8 @@ const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
136
142
  }
137
143
 
138
144
  const [relatedUid, relatedStringId] = getRelatedGroups(entity.related);
139
- const relatedId = parseInt(relatedStringId, 10);
145
+ const parsedRelatedId = parseInt(relatedStringId);
146
+ const relatedId = isNumber(parsedRelatedId) ? parsedRelatedId : relatedStringId;
140
147
  const relatedEntity = await strapi.db.query(relatedUid).findOne({
141
148
  where: { id: relatedId }
142
149
  }).then(_ => ({
@@ -157,21 +164,18 @@ const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
157
164
  threadOf: levelThreadId,
158
165
  related: entity.related,
159
166
  },
160
- populate: {
161
- ...reportsPopulation,
162
- },
167
+ ...defaultPopulate,
163
168
  startingFromId: levelThreadId,
164
169
  isAdmin: true
165
170
  }, false);
166
-
167
- const selectedEntity = this.getCommonService().sanitizeCommentEntity(entity);
171
+ const selectedEntity = this.getCommonService().sanitizeCommentEntity({
172
+ ...entity,
173
+ threadOf: entity.threadOf || null,
174
+ });
168
175
 
169
176
  return {
170
177
  entity: relatedEntity,
171
- selected: {
172
- ...selectedEntity,
173
- threadOf: selectedEntity.threadOf ? selectedEntity.threadOf : null,
174
- },
178
+ selected: selectedEntity,
175
179
  level: entitiesOnSameLevel,
176
180
  };
177
181
  },