strapi-plugin-comments 2.0.0-beta.4 → 2.0.0-rc.1

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 (75) hide show
  1. package/README.md +421 -72
  2. package/admin/src/components/DiscussionThread/index.js +9 -2
  3. package/admin/src/components/DiscussionThreadItem/index.js +27 -12
  4. package/admin/src/components/DiscussionThreadItemActions/index.js +61 -50
  5. package/admin/src/components/DiscussionThreadItemActions/styles.js +0 -4
  6. package/admin/src/components/DiscussionThreadItemApprovalFlowActions/index.js +81 -0
  7. package/admin/src/components/DiscussionThreadItemApprovalFlowActions/styles.js +6 -0
  8. package/admin/src/components/DiscussionThreadItemMeta/index.js +16 -5
  9. package/admin/src/components/DiscussionThreadItemWarnings/index.js +16 -10
  10. package/admin/src/components/Nav/index.js +5 -1
  11. package/admin/src/components/ReportsReviewModal/index.js +5 -0
  12. package/admin/src/components/ReportsReviewTable/index.js +60 -52
  13. package/admin/src/components/icons/review.js +2 -2
  14. package/admin/src/index.js +1 -1
  15. package/admin/src/pages/Details/components/DetailsEntity/index.js +66 -0
  16. package/admin/src/pages/Details/components/DetailsFilters/index.js +37 -0
  17. package/admin/src/pages/Details/components/DetailsFilters/styles.js +8 -0
  18. package/admin/src/pages/Details/index.js +75 -42
  19. package/admin/src/pages/Discover/components/DiscoverTableRow/index.js +69 -48
  20. package/admin/src/pages/Discover/components/DiscoverTableRow/styles.js +8 -0
  21. package/admin/src/pages/Discover/index.js +72 -56
  22. package/admin/src/pages/{Details/utils → utils}/api.js +15 -3
  23. package/admin/src/permissions.js +10 -8
  24. package/admin/src/translations/en.json +17 -4
  25. package/admin/src/utils/constants.js +3 -6
  26. package/admin/src/utils/getMessage.js +1 -1
  27. package/admin/src/utils/getRelatedGroups.js +1 -3
  28. package/admin/src/utils/index.js +5 -1
  29. package/admin/src/utils/renderEntryTitle.js +14 -0
  30. package/admin/src/utils/renderInitials.js +5 -0
  31. package/admin/src/utils/resolveCommentStatus.js +30 -0
  32. package/admin/src/utils/resolveCommentStatusColor.js +22 -0
  33. package/package.json +8 -3
  34. package/permissions.js +19 -0
  35. package/public/assets/logo.png +0 -0
  36. package/public/assets/preview.png +0 -0
  37. package/server/bootstrap.js +38 -2
  38. package/server/config/index.js +9 -3
  39. package/server/controllers/admin.js +3 -3
  40. package/server/controllers/client.js +4 -18
  41. package/server/controllers/utils/parsers.js +17 -0
  42. package/server/graphql/index.js +26 -0
  43. package/server/graphql/mutations/createAbuseReport.js +20 -0
  44. package/server/graphql/mutations/createComment.js +20 -0
  45. package/server/graphql/mutations/index.js +21 -0
  46. package/server/graphql/mutations/removeComment.js +20 -0
  47. package/server/graphql/mutations/updateComment.js +20 -0
  48. package/server/graphql/queries/findAllFlat.js +29 -0
  49. package/server/graphql/queries/findAllInHierarchy.js +31 -0
  50. package/server/graphql/queries/index.js +19 -0
  51. package/server/graphql/resolvers-config.js +10 -0
  52. package/server/graphql/types/comment-author-user.js +9 -0
  53. package/server/graphql/types/comment-author.js +9 -0
  54. package/server/graphql/types/comment-nested.js +16 -0
  55. package/server/graphql/types/comment.js +16 -0
  56. package/server/graphql/types/create-comment-author.js +9 -0
  57. package/server/graphql/types/create-comment.js +9 -0
  58. package/server/graphql/types/create-report.js +9 -0
  59. package/server/graphql/types/id.js +24 -0
  60. package/server/graphql/types/identify-comment-author.js +6 -0
  61. package/server/graphql/types/index.js +17 -0
  62. package/server/graphql/types/remove-comment.js +8 -0
  63. package/server/graphql/types/report-reason.js +10 -0
  64. package/server/graphql/types/report.js +11 -0
  65. package/server/graphql/types/update-comment.js +9 -0
  66. package/server/register.js +3 -1
  67. package/server/services/admin.js +42 -15
  68. package/server/services/client.js +54 -38
  69. package/server/services/common.js +38 -67
  70. package/server/services/graphql.js +190 -0
  71. package/server/services/index.js +2 -0
  72. package/server/services/utils/functions.js +24 -17
  73. package/server/utils/constants.js +3 -3
  74. package/strapi-server.js +33 -0
  75. package/admin/src/components/EntityDetails/index.js +0 -53
package/permissions.js ADDED
@@ -0,0 +1,19 @@
1
+ 'use strict';
2
+
3
+ module.exports = {
4
+ render: function(uid) {
5
+ return `plugin::comments.${uid}`;
6
+ },
7
+ comments: {
8
+ read: 'read',
9
+ moderate: 'moderate',
10
+ },
11
+ reports: {
12
+ read: 'reports.read',
13
+ action: 'reports.action',
14
+ },
15
+ settings: {
16
+ read: 'settings.read',
17
+ change: 'settings.change',
18
+ },
19
+ };
Binary file
Binary file
@@ -1,5 +1,41 @@
1
1
  'use strict';
2
2
 
3
- module.exports = ({ strapi }) => {
4
- // bootstrap phase
3
+ const permissions = require('./../permissions');
4
+
5
+ module.exports = async ({ strapi }) => {
6
+ // Check if the plugin users-permissions is installed because the navigation needs it
7
+ if (Object.keys(strapi.plugins).indexOf("users-permissions") === -1) {
8
+ throw new Error(
9
+ "In order to make the comments plugin work the users-permissions plugin is required",
10
+ );
11
+ }
12
+ // Add permissions
13
+ const actions = [
14
+ {
15
+ section: "plugins",
16
+ displayName: "Comments: Read",
17
+ uid: permissions.comments.read,
18
+ pluginName: "comments",
19
+ },
20
+ {
21
+ section: "plugins",
22
+ displayName: "Comments: Moderate",
23
+ uid: permissions.comments.moderate,
24
+ pluginName: "comments",
25
+ },
26
+ {
27
+ section: "plugins",
28
+ displayName: "Reports: Read",
29
+ uid: permissions.reports.read,
30
+ pluginName: "comments",
31
+ },
32
+ {
33
+ section: "plugins",
34
+ displayName: "Reports: Moderate",
35
+ uid: permissions.reports.action,
36
+ pluginName: "comments",
37
+ },
38
+ ];
39
+
40
+ await strapi.admin.services.permission.actionProvider.registerMany(actions);
5
41
  };
@@ -2,9 +2,15 @@
2
2
 
3
3
  module.exports = {
4
4
  default: {
5
+ moderatorRoles: [],
6
+ approvalFlow: [],
5
7
  entryLabel: {
6
8
  '*': ['Title', 'title', 'Name', 'name', 'Subject', 'subject']
7
- }
8
- },
9
- validator() {},
9
+ },
10
+ reportReasons: {
11
+ 'BAD_LANGUAGE': 'BAD_LANGUAGE',
12
+ 'DISCRIMINATION': 'DISCRIMINATION',
13
+ 'OTHER': 'OTHER',
14
+ },
15
+ }
10
16
  };
@@ -16,11 +16,11 @@ module.exports = {
16
16
  },
17
17
 
18
18
  async findOne(ctx) {
19
- const { params = {} } = ctx;
19
+ const { params = {}, query } = ctx;
20
20
  const { id } = parseParams(params);
21
21
  try {
22
22
  return await this.getService()
23
- .findOneAndThread(id);
23
+ .findOneAndThread(id, query);
24
24
  } catch (e) {
25
25
  throwError(ctx, e);
26
26
  }
@@ -101,7 +101,7 @@ module.exports = {
101
101
  }
102
102
  },
103
103
 
104
- async config() {
104
+ async config(ctx) {
105
105
  try {
106
106
  return await this.getService().config();
107
107
  } catch (e) {
@@ -2,7 +2,7 @@
2
2
 
3
3
  const { getPluginService } = require('./../utils/functions');
4
4
  const { parseParams, throwError } = require('./utils/functions');
5
- const _ = require('lodash');
5
+ const { flatInput } = require('./utils/parsers');
6
6
 
7
7
  module.exports = {
8
8
 
@@ -15,15 +15,7 @@ module.exports = {
15
15
  const { relation } = parseParams(params);
16
16
  try {
17
17
  return this.getService('common')
18
- .findAllFlat({
19
- query: {
20
- ...query,
21
- related: relation,
22
- },
23
- populate: {
24
- threadOf: true,
25
- },
26
- });
18
+ .findAllFlat(flatInput(relation, query));
27
19
  } catch (e) {
28
20
  throwError(ctx, e);
29
21
  }
@@ -35,13 +27,7 @@ module.exports = {
35
27
  try {
36
28
  return await this.getService('common')
37
29
  .findAllInHierarchy({
38
- query: {
39
- ...query,
40
- related: relation,
41
- },
42
- populate: {
43
- threadOf: true,
44
- },
30
+ ...flatInput(relation, query),
45
31
  dropBlockedThreads: true,
46
32
  });
47
33
  } catch (e) {
@@ -101,8 +87,8 @@ module.exports = {
101
87
  try {
102
88
  return await this.getService()
103
89
  .markAsRemoved(
104
- relationId,
105
90
  commentId,
91
+ relationId,
106
92
  authorId,
107
93
  );
108
94
  } catch (e) {
@@ -0,0 +1,17 @@
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: true,
13
+ },
14
+ };
15
+ },
16
+
17
+ };
@@ -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,20 @@
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) {
14
+ const { input } = args;
15
+ const { commentId, relation, ...body } = input;
16
+ return await getPluginService('client')
17
+ .reportAbuse(commentId, relation, body);
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,20 @@
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) {
14
+ const { input } = args;
15
+ const { relation, ...body } = input;
16
+ return await getPluginService('client')
17
+ .create(relation, body);
18
+ },
19
+ };
20
+ }
@@ -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,20 @@
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) {
14
+ const { input } = args;
15
+ const { id, relation, author } = input;
16
+ return await getPluginService('client')
17
+ .markAsRemoved(id, relation, author?.id);
18
+ },
19
+ };
20
+ }
@@ -0,0 +1,20 @@
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) {
14
+ const { input } = args;
15
+ const { id, relation, ...body } = input;
16
+ return await getPluginService('client')
17
+ .update(id, relation, body);
18
+ },
19
+ };
20
+ }
@@ -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,10 @@
1
+ 'use strict'
2
+
3
+ module.exports = ({ }) => ({
4
+ 'Query.findAllFlat': { auth: false },
5
+ 'Query.findAllInHierarchy': { auth: false },
6
+ 'Mutation.createComment': { auth: false },
7
+ 'Mutation.updateComment': { auth: false },
8
+ 'Mutation.removeComment': { auth: false },
9
+ 'Mutation.createAbuseReport': { auth: false },
10
+ });
@@ -0,0 +1,9 @@
1
+ module.exports = ({ nexus }) => nexus.objectType({
2
+ name: "CommentAuthorUser",
3
+ definition(t) {
4
+ t.id("id")
5
+ t.nonNull.string("firstName")
6
+ t.string("lastName")
7
+ t.string("email")
8
+ }
9
+ })
@@ -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,16 @@
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("authorUser", { type: 'CommentAuthorUser' })
12
+ t.field("author", { type: 'CommentAuthor' })
13
+ t.string("createdAt")
14
+ t.string("updatedAt")
15
+ }
16
+ })
@@ -0,0 +1,16 @@
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("authorUser", { type: 'CommentAuthorUser' })
12
+ t.field("author", { type: 'CommentAuthor' })
13
+ t.string("createdAt")
14
+ t.string("updatedAt")
15
+ }
16
+ })
@@ -0,0 +1,9 @@
1
+ module.exports = ({ nexus }) => nexus.inputObjectType({
2
+ name: "CreateCommentAuthor",
3
+ definition(t) {
4
+ t.nonNull.string("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.string("id")
5
+ }
6
+ })
@@ -0,0 +1,17 @@
1
+ const typesFactories = [
2
+ require('./id'),
3
+ require('./comment'),
4
+ require('./comment-nested'),
5
+ require('./comment-author'),
6
+ require('./comment-author-user'),
7
+ require('./create-comment'),
8
+ require('./create-comment-author'),
9
+ require('./update-comment'),
10
+ require('./remove-comment'),
11
+ require('./identify-comment-author'),
12
+ require('./report'),
13
+ require('./report-reason'),
14
+ require('./create-report'),
15
+ ];
16
+
17
+ 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
  };