strapi-plugin-comments 2.0.0-beta.6 → 2.0.0-beta.7
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/README.md +310 -7
- package/admin/src/components/DiscussionThreadItem/index.js +4 -8
- package/admin/src/components/DiscussionThreadItemMeta/index.js +16 -5
- package/admin/src/pages/Discover/components/DiscoverTableRow/index.js +8 -1
- package/admin/src/pages/Discover/index.js +4 -1
- package/admin/src/translations/en.json +1 -0
- package/admin/src/utils/index.js +2 -0
- package/admin/src/utils/renderInitials.js +5 -0
- package/package.json +2 -1
- package/server/config/index.js +5 -0
- package/server/controllers/client.js +4 -19
- package/server/controllers/utils/parsers.js +17 -0
- package/server/graphql/index.js +26 -0
- package/server/graphql/mutations/createAbuseReport.js +20 -0
- package/server/graphql/mutations/createComment.js +20 -0
- package/server/graphql/mutations/index.js +21 -0
- package/server/graphql/mutations/removeComment.js +20 -0
- package/server/graphql/mutations/updateComment.js +20 -0
- package/server/graphql/queries/findAllFlat.js +29 -0
- package/server/graphql/queries/findAllInHierarchy.js +31 -0
- package/server/graphql/queries/index.js +19 -0
- package/server/graphql/resolvers-config.js +10 -0
- package/server/graphql/types/comment-author-user.js +9 -0
- package/server/graphql/types/comment-author.js +9 -0
- package/server/graphql/types/comment-nested.js +16 -0
- package/server/graphql/types/comment.js +16 -0
- package/server/graphql/types/create-comment-author.js +9 -0
- package/server/graphql/types/create-comment.js +9 -0
- package/server/graphql/types/create-report.js +9 -0
- package/server/graphql/types/id.js +24 -0
- package/server/graphql/types/identify-comment-author.js +6 -0
- package/server/graphql/types/index.js +17 -0
- package/server/graphql/types/remove-comment.js +8 -0
- package/server/graphql/types/report-reason.js +10 -0
- package/server/graphql/types/report.js +11 -0
- package/server/graphql/types/update-comment.js +9 -0
- package/server/register.js +3 -1
- package/server/services/admin.js +8 -8
- package/server/services/client.js +35 -27
- package/server/services/common.js +10 -4
- package/server/services/graphql.js +190 -0
- package/server/services/index.js +2 -0
- package/server/services/utils/functions.js +17 -3
package/README.md
CHANGED
|
@@ -88,6 +88,9 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
88
88
|
'*': ['Title', 'title', 'Name', 'name', 'Subject', 'subject'],
|
|
89
89
|
'api::page.page': ['MyField'],
|
|
90
90
|
},
|
|
91
|
+
reportReasons: {
|
|
92
|
+
'MY_CUSTOM_REASON': 'MY_CUSTOM_REASON',
|
|
93
|
+
},
|
|
91
94
|
},
|
|
92
95
|
...
|
|
93
96
|
```
|
|
@@ -97,10 +100,12 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
97
100
|
- `moderatorRoles` - Optional list of names of roles. Users with those roles will be notified by email when a new abuse report is created. This feature requires a built-in [Strapi email plugin](https://docs.strapi.io/developer-docs/latest/plugins/email.html) configured.
|
|
98
101
|
- `approvalFlow` - list of Content Types which are supporting approval flow. Values must be in format like `'api::<collection name>.<content type name>'`. For not included, posted comments are going to be immediately visible.
|
|
99
102
|
- `entryLabel` - ordered list of property names per Content Type to generate related entity label. Keys must be in format like `'api::<collection name>.<content type name>'`. Default formatting set as `*`.
|
|
103
|
+
- `reportReasons` - set of enums you would like to use for issuing abuse reports. Provided by default `'BAD_LANGUAGE'`, `'DISCRIMINATION'` and `'OTHER'`.
|
|
100
104
|
|
|
101
105
|
## Additional GQL Configuration
|
|
106
|
+
All you need to do is to install and enable `@strapi/plugin-graphql` for you instance based on the **[official Strapi v4 docs](https://docs.strapi.io/developer-docs/latest/plugins/graphql.html#configurations)**.
|
|
102
107
|
|
|
103
|
-
|
|
108
|
+
See [available GQL specification section](#public-graphql-specification).
|
|
104
109
|
|
|
105
110
|
## RBAC
|
|
106
111
|
Plugin provides granular permissions based on Strapi RBAC functionality.
|
|
@@ -127,10 +132,14 @@ Feature / Capability focused permissions:
|
|
|
127
132
|
"blockedThread": true,
|
|
128
133
|
"blockReason": null,
|
|
129
134
|
"authorUser": null,
|
|
130
|
-
"
|
|
131
|
-
"
|
|
132
|
-
"
|
|
133
|
-
|
|
135
|
+
"removed": null,
|
|
136
|
+
"approvalStatus": "APPROVED", // Only in case of enabled approval flow. Default: null
|
|
137
|
+
"author": {
|
|
138
|
+
"id": "207ccfdc-94ba-45eb-979c-790f6f49c392",
|
|
139
|
+
"name": "Joe Doe",
|
|
140
|
+
"email": "jdoe@sample.com",
|
|
141
|
+
"avatar": null,
|
|
142
|
+
},
|
|
134
143
|
"createdAt": "2020-07-14T20:13:01.649Z",
|
|
135
144
|
"updatedAt": "2020-07-14T20:13:01.670Z",
|
|
136
145
|
"related": {}, // Related content type entity
|
|
@@ -145,6 +154,8 @@ Feature / Capability focused permissions:
|
|
|
145
154
|
"blocked": true,
|
|
146
155
|
"blockedThread": null,
|
|
147
156
|
"blockReason": null,
|
|
157
|
+
"removed": null,
|
|
158
|
+
"approvalStatus": "REJECTED", // Only in case of enabled approval flow. Default: null
|
|
148
159
|
"authorUser": {
|
|
149
160
|
"id": 1,
|
|
150
161
|
"username": "Sample User",
|
|
@@ -329,7 +340,7 @@ Deletes a specified Comment based on it `commentId` and related to specified ins
|
|
|
329
340
|
- `409` - Conflict. Occurs when trying to delete a non existing comment.
|
|
330
341
|
|
|
331
342
|
|
|
332
|
-
### Report
|
|
343
|
+
### Issue Abuse Report against specified Comment
|
|
333
344
|
|
|
334
345
|
`POST <host>/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>/report-abuse`
|
|
335
346
|
|
|
@@ -346,7 +357,7 @@ Reports abuse in specified Comment content based on it `commentId` and related t
|
|
|
346
357
|
}
|
|
347
358
|
```
|
|
348
359
|
|
|
349
|
-
*Available reason enums:* `
|
|
360
|
+
*Available reason enums:* `BAD_WORDS`, `OTHER`, `DISCRIMINATION` (want more? See [configuration section](#configuration).)
|
|
350
361
|
|
|
351
362
|
**Example response body**
|
|
352
363
|
|
|
@@ -360,6 +371,298 @@ Reports abuse in specified Comment content based on it `commentId` and related t
|
|
|
360
371
|
- `200` - Successful. Response with reported abuse.
|
|
361
372
|
- `409` - Conflict. Occurs when trying to report an abuse to a non existing comment.
|
|
362
373
|
|
|
374
|
+
## Public GraphQL specification
|
|
375
|
+
|
|
376
|
+
> *To test all queries and understand the schemas use GraphQL Playground exposed by `@strapi/plugin-graphql` on `http://localhost:1337/graphql`*
|
|
377
|
+
|
|
378
|
+
### Get Comments
|
|
379
|
+
|
|
380
|
+
*REST API equivalent: [Public API -> Get Comments](#get-comments)*
|
|
381
|
+
|
|
382
|
+
**Example request**
|
|
383
|
+
|
|
384
|
+
```graphql
|
|
385
|
+
query {
|
|
386
|
+
findAllFlat(
|
|
387
|
+
relation: "api::page.page:1"
|
|
388
|
+
filters: { content: { contains: "Test" } }
|
|
389
|
+
) {
|
|
390
|
+
id
|
|
391
|
+
content
|
|
392
|
+
blocked
|
|
393
|
+
threadOf {
|
|
394
|
+
id
|
|
395
|
+
}
|
|
396
|
+
author {
|
|
397
|
+
id
|
|
398
|
+
name
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
**Example response**
|
|
405
|
+
|
|
406
|
+
```json
|
|
407
|
+
{
|
|
408
|
+
"data": {
|
|
409
|
+
"findAllFlat": [
|
|
410
|
+
{
|
|
411
|
+
"id": 3,
|
|
412
|
+
"content": "Test",
|
|
413
|
+
"blocked": false,
|
|
414
|
+
"threadOf": null,
|
|
415
|
+
"author": {
|
|
416
|
+
"id": "123456",
|
|
417
|
+
"name": "Joe Doe"
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
//...
|
|
421
|
+
]
|
|
422
|
+
}
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Get Comments (flat structure)
|
|
426
|
+
|
|
427
|
+
*REST API equivalent: [Public API -> Get Comments (flat structure)](#get-comments-flat-structure)*
|
|
428
|
+
|
|
429
|
+
**Example request**
|
|
430
|
+
|
|
431
|
+
```graphql
|
|
432
|
+
query {
|
|
433
|
+
findAllInHierarchy(relation: "api::page.page:1") {
|
|
434
|
+
id
|
|
435
|
+
content
|
|
436
|
+
blocked
|
|
437
|
+
children {
|
|
438
|
+
id
|
|
439
|
+
content
|
|
440
|
+
}
|
|
441
|
+
threadOf {
|
|
442
|
+
id
|
|
443
|
+
}
|
|
444
|
+
author {
|
|
445
|
+
id
|
|
446
|
+
name
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
```
|
|
451
|
+
|
|
452
|
+
**Example response**
|
|
453
|
+
|
|
454
|
+
```json
|
|
455
|
+
{
|
|
456
|
+
"data": {
|
|
457
|
+
"findAllInHierarchy": [
|
|
458
|
+
{
|
|
459
|
+
"id": 1,
|
|
460
|
+
"content": "Test",
|
|
461
|
+
"blocked": false,
|
|
462
|
+
"children": [
|
|
463
|
+
{
|
|
464
|
+
"id": 6,
|
|
465
|
+
"content": "Text to search for"
|
|
466
|
+
},
|
|
467
|
+
//...
|
|
468
|
+
],
|
|
469
|
+
"threadOf": null,
|
|
470
|
+
"author": {
|
|
471
|
+
"id": "123456",
|
|
472
|
+
"name": "Joe Doe"
|
|
473
|
+
}
|
|
474
|
+
},
|
|
475
|
+
//...
|
|
476
|
+
]
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
### Post a Comment
|
|
482
|
+
|
|
483
|
+
*REST API equivalent: [Public API -> Post a Comment](#post-a-comment)*
|
|
484
|
+
|
|
485
|
+
**Example request**
|
|
486
|
+
|
|
487
|
+
```graphql
|
|
488
|
+
mutation createComment {
|
|
489
|
+
createComment(
|
|
490
|
+
input: {
|
|
491
|
+
relation: "api::page.page:1"
|
|
492
|
+
content: "Hello World!"
|
|
493
|
+
threadOf: 3
|
|
494
|
+
author: { id: "12345678", name: "John Wick", email: "test@test.pl" }
|
|
495
|
+
}
|
|
496
|
+
) {
|
|
497
|
+
id
|
|
498
|
+
content
|
|
499
|
+
threadOf {
|
|
500
|
+
id
|
|
501
|
+
}
|
|
502
|
+
author {
|
|
503
|
+
id
|
|
504
|
+
name
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
**Example response**
|
|
511
|
+
|
|
512
|
+
```json
|
|
513
|
+
{
|
|
514
|
+
"data": {
|
|
515
|
+
"createComment": {
|
|
516
|
+
"id": 34,
|
|
517
|
+
"content": "Hello World!",
|
|
518
|
+
"threadOf": {
|
|
519
|
+
"id": 3
|
|
520
|
+
},
|
|
521
|
+
"author": {
|
|
522
|
+
"id": "12345678",
|
|
523
|
+
"name": "John Wick"
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
}
|
|
528
|
+
```
|
|
529
|
+
|
|
530
|
+
### Update Comment
|
|
531
|
+
|
|
532
|
+
*REST API equivalent: [Public API -> Update Comment](#update-comment)*
|
|
533
|
+
|
|
534
|
+
**Example request**
|
|
535
|
+
|
|
536
|
+
```graphql
|
|
537
|
+
mutation updateComment {
|
|
538
|
+
updateComment(
|
|
539
|
+
input: {
|
|
540
|
+
id: 34
|
|
541
|
+
relation: "api::page.page:1"
|
|
542
|
+
content: "I've changed it!"
|
|
543
|
+
author: { id: "12345678" }
|
|
544
|
+
}
|
|
545
|
+
) {
|
|
546
|
+
id
|
|
547
|
+
content
|
|
548
|
+
threadOf {
|
|
549
|
+
id
|
|
550
|
+
}
|
|
551
|
+
author {
|
|
552
|
+
id
|
|
553
|
+
name
|
|
554
|
+
}
|
|
555
|
+
createdAt
|
|
556
|
+
updatedAt
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
```
|
|
560
|
+
|
|
561
|
+
**Example response**
|
|
562
|
+
|
|
563
|
+
```json
|
|
564
|
+
{
|
|
565
|
+
"data": {
|
|
566
|
+
"updateComment": {
|
|
567
|
+
"id": 34,
|
|
568
|
+
"content": "I've changed it!",
|
|
569
|
+
"threadOf": {
|
|
570
|
+
"id": 3
|
|
571
|
+
},
|
|
572
|
+
"author": {
|
|
573
|
+
"id": "12345678",
|
|
574
|
+
"name": "John Wick"
|
|
575
|
+
},
|
|
576
|
+
"createdAt": "2022-01-26T07:45:35.978Z",
|
|
577
|
+
"updatedAt": "2022-01-26T07:47:44.659Z"
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
```
|
|
582
|
+
|
|
583
|
+
### Delete Comment
|
|
584
|
+
|
|
585
|
+
*REST API equivalent: [Public API -> Delete Comment](#delete-comment)*
|
|
586
|
+
|
|
587
|
+
**Example request**
|
|
588
|
+
|
|
589
|
+
```graphql
|
|
590
|
+
mutation removeComment {
|
|
591
|
+
removeComment(
|
|
592
|
+
input: { id: 33, relation: "api::page.page:1", author: { id: "12345678" } }
|
|
593
|
+
) {
|
|
594
|
+
id
|
|
595
|
+
removed
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
```
|
|
599
|
+
|
|
600
|
+
**Example response**
|
|
601
|
+
|
|
602
|
+
```json
|
|
603
|
+
{
|
|
604
|
+
"data": {
|
|
605
|
+
"removeComment": {
|
|
606
|
+
"id": 33,
|
|
607
|
+
"removed": true
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
```
|
|
612
|
+
|
|
613
|
+
### Issue Abuse Report against specified Comment
|
|
614
|
+
|
|
615
|
+
*REST API equivalent: [Public API -> Issue Abuse Report against specified Comment](#issue-abuse-report-against-specified-comment)*
|
|
616
|
+
|
|
617
|
+
**Example request body**
|
|
618
|
+
|
|
619
|
+
```graphql
|
|
620
|
+
mutation createAbuseReport {
|
|
621
|
+
createAbuseReport(
|
|
622
|
+
input: {
|
|
623
|
+
commentId: 34
|
|
624
|
+
relation: "api::page.page:1"
|
|
625
|
+
reason: BAD_LANGUAGE
|
|
626
|
+
content: "Rude language"
|
|
627
|
+
}
|
|
628
|
+
) {
|
|
629
|
+
id
|
|
630
|
+
reason
|
|
631
|
+
content
|
|
632
|
+
related {
|
|
633
|
+
id
|
|
634
|
+
author {
|
|
635
|
+
id
|
|
636
|
+
name
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
*Available reason enums:* `BAD_WORDS`, `OTHER`, `DISCRIMINATION` (want more? See [configuration section](#configuration).)
|
|
644
|
+
|
|
645
|
+
**Example response**
|
|
646
|
+
|
|
647
|
+
```json
|
|
648
|
+
{
|
|
649
|
+
"data": {
|
|
650
|
+
"createAbuseReport": {
|
|
651
|
+
"id": 28,
|
|
652
|
+
"content": "Rude language",
|
|
653
|
+
"reason": "DISCRIMINATION",
|
|
654
|
+
"related": {
|
|
655
|
+
"id": 34,
|
|
656
|
+
"author": {
|
|
657
|
+
"id": "12345678",
|
|
658
|
+
"name": "John Wick"
|
|
659
|
+
}
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
```
|
|
665
|
+
|
|
363
666
|
## Examples
|
|
364
667
|
|
|
365
668
|
Live example of plugin usage can be found in the [VirtusLab Strapi Examples](https://github.com/VirtusLab/strapi-examples/tree/master/strapi-plugin-comments) repository.
|
|
@@ -6,7 +6,6 @@
|
|
|
6
6
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import PropTypes from 'prop-types';
|
|
9
|
-
import { first } from 'lodash';
|
|
10
9
|
import { Avatar, Initials } from '@strapi/design-system/Avatar';
|
|
11
10
|
import { Box } from '@strapi/design-system/Box';
|
|
12
11
|
import { Divider } from '@strapi/design-system/Divider';
|
|
@@ -17,7 +16,7 @@ import { ArrowRight } from '@strapi/icons';
|
|
|
17
16
|
import DiscussionThreadItemMeta from '../DiscussionThreadItemMeta';
|
|
18
17
|
import { AvatarWrapper, DiscussionThreadItemBox, DiscussionThreadItemBoxContent, DiscussionThreadItemContent, DiscussionThreadItemLeft, DiscussionThreadItemLinkBox, DiscussionThreadItemRight, DiscussionThreadItemRoot } from './styles';
|
|
19
18
|
import DiscussionThreadItemActions from '../DiscussionThreadItemActions';
|
|
20
|
-
import { getMessage, getUrl } from '../../utils';
|
|
19
|
+
import { getMessage, getUrl, renderInitials } from '../../utils';
|
|
21
20
|
import DiscussionThreadItemWarnings from '../DiscussionThreadItemWarnings';
|
|
22
21
|
|
|
23
22
|
const DiscussionThreadItem = (props) => {
|
|
@@ -34,8 +33,7 @@ const DiscussionThreadItem = (props) => {
|
|
|
34
33
|
gotThread,
|
|
35
34
|
threadFirstItemId,
|
|
36
35
|
authorUser,
|
|
37
|
-
|
|
38
|
-
authorName } = props;
|
|
36
|
+
author } = props;
|
|
39
37
|
|
|
40
38
|
let background = 'neutral100';
|
|
41
39
|
let borderColor = 'neutral200';
|
|
@@ -59,11 +57,9 @@ const DiscussionThreadItem = (props) => {
|
|
|
59
57
|
StyledComponent = DiscussionThreadItemRoot;
|
|
60
58
|
}
|
|
61
59
|
|
|
62
|
-
const avatar =
|
|
63
|
-
const name =
|
|
60
|
+
const avatar = author?.avatar || authorUser?.avatar;
|
|
61
|
+
const name = author?.name || `${authorUser?.firstName} ${authorUser?.lastName}`;
|
|
64
62
|
const isBlocked = blocked || blockedThread;
|
|
65
|
-
|
|
66
|
-
const renderInitials = value => value.split(' ').map(_ => first(_)).join('').toUpperCase();
|
|
67
63
|
|
|
68
64
|
return (<StyledComponent as="li">
|
|
69
65
|
<DiscussionThreadItemContent as={Flex} direction="row">
|
|
@@ -9,22 +9,33 @@ import PropTypes from 'prop-types';
|
|
|
9
9
|
import { useIntl } from 'react-intl';
|
|
10
10
|
import { Box } from '@strapi/design-system/Box';
|
|
11
11
|
import { Flex } from '@strapi/design-system/Flex';
|
|
12
|
+
import { Stack } from '@strapi/design-system/Stack';
|
|
12
13
|
import { Typography } from '@strapi/design-system/Typography';
|
|
13
14
|
|
|
14
|
-
const DiscussionThreadItemMeta = ({
|
|
15
|
+
const DiscussionThreadItemMeta = ({ author, createdAt, updatedAt }) => {
|
|
15
16
|
|
|
16
17
|
const { formatDate } = useIntl();
|
|
17
18
|
|
|
18
19
|
const dateTime = formatDate(updatedAt || createdAt, { dateStyle: 'short', timeStyle: 'short' });
|
|
20
|
+
const { name } = author;
|
|
19
21
|
|
|
20
|
-
return (<Flex as={Box} paddingTop={2} direction="row"
|
|
21
|
-
<
|
|
22
|
-
|
|
22
|
+
return (<Flex as={Box} paddingTop={2} direction="row">
|
|
23
|
+
<Stack size={2} horizontal style={{ flexGrow: 1, justifyContent: 'space-between'}}>
|
|
24
|
+
<Typography variant="pi" fontWeight="bold">{ name }</Typography>
|
|
25
|
+
<Typography variant="pi">{ dateTime }</Typography>
|
|
26
|
+
</Stack>
|
|
23
27
|
</Flex>);
|
|
24
28
|
};
|
|
25
29
|
|
|
26
30
|
DiscussionThreadItemMeta.propTypes = {
|
|
27
|
-
|
|
31
|
+
author: PropTypes.shape({
|
|
32
|
+
id: PropTypes.oneOfType(PropTypes.string, PropTypes.number).isRequired,
|
|
33
|
+
name: PropTypes.string.isRequired,
|
|
34
|
+
email: PropTypes.string,
|
|
35
|
+
avatar: PropTypes.string,
|
|
36
|
+
}).isRequired,
|
|
37
|
+
createdAt: PropTypes.string.isRequired,
|
|
38
|
+
updatedAt: PropTypes.string,
|
|
28
39
|
};
|
|
29
40
|
|
|
30
41
|
export default DiscussionThreadItemMeta;
|
|
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
|
|
|
3
3
|
import { useIntl } from 'react-intl';
|
|
4
4
|
import { useMutation, useQueryClient } from 'react-query';
|
|
5
5
|
import { isNil, isEmpty, orderBy } from 'lodash';
|
|
6
|
+
import { Avatar, Initials } from '@strapi/design-system/Avatar';
|
|
6
7
|
import { Badge } from '@strapi/design-system/Badge';
|
|
7
8
|
import { Box } from '@strapi/design-system/Box';
|
|
8
9
|
import { Button } from '@strapi/design-system/Button';
|
|
@@ -15,7 +16,7 @@ import { Tr, Td } from '@strapi/design-system/Table';
|
|
|
15
16
|
import { Typography } from '@strapi/design-system/Typography';
|
|
16
17
|
import { Eye } from '@strapi/icons';
|
|
17
18
|
import { useNotification, useOverlayBlocker } from '@strapi/helper-plugin';
|
|
18
|
-
import { getMessage, getUrl, handleAPIError, resolveCommentStatus, resolveCommentStatusColor } from '../../../../utils';
|
|
19
|
+
import { getMessage, getUrl, handleAPIError, renderInitials, resolveCommentStatus, resolveCommentStatusColor } from '../../../../utils';
|
|
19
20
|
import ReportsReviewModal from '../../../../components/ReportsReviewModal';
|
|
20
21
|
import ReportsReviewTable from '../../../../components/ReportsReviewTable';
|
|
21
22
|
import { blockItem, blockItemThread, resolveReport } from '../../../utils/api';
|
|
@@ -132,6 +133,12 @@ const DiscoverTableRow = ({ config, item, allowedActions: { canModerate, canAcce
|
|
|
132
133
|
<Td>
|
|
133
134
|
<Typography textColor="neutral800" fontWeight="bold">#{ item.id }</Typography>
|
|
134
135
|
</Td>
|
|
136
|
+
<Td>
|
|
137
|
+
<Stack size={2} horizontal>
|
|
138
|
+
{ item.author?.avatar ? <Avatar src={item.author?.avatar} alt={item.author.name} /> : <Initials>{ renderInitials(item.author.name) }</Initials> }
|
|
139
|
+
<Typography textColor="neutral800" variant="pi">{ item.author.name }</Typography>
|
|
140
|
+
</Stack>
|
|
141
|
+
</Td>
|
|
135
142
|
<Td style={{ maxWidth: '30vw' }}>
|
|
136
143
|
<Typography textColor="neutral800" ellipsis>{item.content}</Typography>
|
|
137
144
|
</Td>
|
|
@@ -91,7 +91,7 @@ const Discover = ({ config }) => {
|
|
|
91
91
|
|
|
92
92
|
const emptyContent = _q ? 'search' : 'comments';
|
|
93
93
|
|
|
94
|
-
const COL_COUNT =
|
|
94
|
+
const COL_COUNT = 8;
|
|
95
95
|
|
|
96
96
|
if (canAccess) {
|
|
97
97
|
return <Box background="neutral100">
|
|
@@ -114,6 +114,9 @@ const Discover = ({ config }) => {
|
|
|
114
114
|
<Th>
|
|
115
115
|
<Typography variant="sigma">{ getMessage('page.discover.table.header.id') }</Typography>
|
|
116
116
|
</Th>
|
|
117
|
+
<Th>
|
|
118
|
+
<Typography variant="sigma">{ getMessage('page.discover.table.header.author') }</Typography>
|
|
119
|
+
</Th>
|
|
117
120
|
<Th>
|
|
118
121
|
<Typography variant="sigma">{ getMessage('page.discover.table.header.message') }</Typography>
|
|
119
122
|
</Th>
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
"page.discover.header": "Discover threads",
|
|
18
18
|
"page.discover.header.count": "entries found",
|
|
19
19
|
"page.discover.table.header.id": "ID",
|
|
20
|
+
"page.discover.table.header.author": "Author",
|
|
20
21
|
"page.discover.table.header.message": "Message",
|
|
21
22
|
"page.discover.table.header.thread": "Thread of",
|
|
22
23
|
"page.discover.table.header.entry": "Entry",
|
package/admin/src/utils/index.js
CHANGED
|
@@ -4,5 +4,7 @@ export { default as getUrl } from './getUrl';
|
|
|
4
4
|
export { default as getMessage } from './getMessage';
|
|
5
5
|
export { default as handleAPIError } from './handleAPIError';
|
|
6
6
|
export { default as getRelatedGroups } from './getRelatedGroups';
|
|
7
|
+
export { default as renderEntryTitle } from './renderEntryTitle';
|
|
8
|
+
export { default as renderInitials } from './renderInitials';
|
|
7
9
|
export { default as resolveCommentStatus } from './resolveCommentStatus';
|
|
8
10
|
export { default as resolveCommentStatusColor } from './resolveCommentStatusColor';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-comments",
|
|
3
|
-
"version": "2.0.0-beta.
|
|
3
|
+
"version": "2.0.0-beta.7",
|
|
4
4
|
"description": "Strapi - Comments plugin",
|
|
5
5
|
"strapi": {
|
|
6
6
|
"name": "comments",
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@strapi/utils": "^4.0.5",
|
|
19
|
+
"@strapi/plugin-graphql": "^4.0.5",
|
|
19
20
|
"bad-words": "^3.0.4"
|
|
20
21
|
},
|
|
21
22
|
"devDependencies": {
|
package/server/config/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
const { getPluginService } = require('./../utils/functions');
|
|
4
4
|
const { parseParams, throwError } = require('./utils/functions');
|
|
5
|
-
const
|
|
5
|
+
const { flatInput } = require('./utils/parsers');
|
|
6
6
|
|
|
7
7
|
module.exports = {
|
|
8
8
|
|
|
@@ -15,16 +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
|
-
$or: [{ removed: { $null: true } }, { removed: false }],
|
|
22
|
-
related: relation,
|
|
23
|
-
},
|
|
24
|
-
populate: {
|
|
25
|
-
threadOf: true,
|
|
26
|
-
},
|
|
27
|
-
});
|
|
18
|
+
.findAllFlat(flatInput(relation, query));
|
|
28
19
|
} catch (e) {
|
|
29
20
|
throwError(ctx, e);
|
|
30
21
|
}
|
|
@@ -36,13 +27,7 @@ module.exports = {
|
|
|
36
27
|
try {
|
|
37
28
|
return await this.getService('common')
|
|
38
29
|
.findAllInHierarchy({
|
|
39
|
-
query
|
|
40
|
-
...query,
|
|
41
|
-
related: relation,
|
|
42
|
-
},
|
|
43
|
-
populate: {
|
|
44
|
-
threadOf: true,
|
|
45
|
-
},
|
|
30
|
+
...flatInput(relation, query),
|
|
46
31
|
dropBlockedThreads: true,
|
|
47
32
|
});
|
|
48
33
|
} catch (e) {
|
|
@@ -102,8 +87,8 @@ module.exports = {
|
|
|
102
87
|
try {
|
|
103
88
|
return await this.getService()
|
|
104
89
|
.markAsRemoved(
|
|
105
|
-
relationId,
|
|
106
90
|
commentId,
|
|
91
|
+
relationId,
|
|
107
92
|
authorId,
|
|
108
93
|
);
|
|
109
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
|
+
}
|