strapi-plugin-comments 2.0.0-rc.1 → 2.0.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.
- package/README.md +109 -67
- package/__mocks__/initSetup.js +53 -0
- package/admin/src/components/ActionButton/styles.js +10 -0
- package/admin/src/components/DiscussionThread/index.js +3 -7
- package/admin/src/components/DiscussionThreadItem/index.js +25 -70
- package/admin/src/components/DiscussionThreadItem/styles.js +4 -79
- package/admin/src/components/DiscussionThreadItemActions/index.js +82 -40
- package/admin/src/components/DiscussionThreadItemActions/styles.js +1 -12
- package/admin/src/components/DiscussionThreadItemApprovalFlowActions/index.js +2 -3
- package/admin/src/components/DiscussionThreadItemFooter/index.js +47 -0
- package/admin/src/components/DiscussionThreadItemFooter/styles.js +13 -0
- package/admin/src/components/DiscussionThreadItemReviewAction/index.js +131 -0
- package/admin/src/components/IconButton/styles.js +14 -0
- package/admin/src/components/ReportsReviewModal/index.js +1 -1
- package/admin/src/components/ReportsReviewTable/index.js +12 -6
- package/admin/src/components/StatusBadge/index.js +17 -0
- package/admin/src/components/StatusBadge/styles.js +17 -0
- package/admin/src/pages/Details/components/DetailsEntity/index.js +42 -24
- package/admin/src/pages/Details/components/DetailsFilters/index.js +8 -10
- package/admin/src/pages/Details/index.js +6 -15
- package/admin/src/pages/Discover/components/DiscoverTableRow/index.js +30 -67
- package/admin/src/translations/en.json +13 -15
- package/admin/src/utils/resolveCommentStatus.js +4 -4
- package/content-types/comment.js +0 -4
- package/package.json +8 -5
- package/server/controllers/client.js +11 -6
- package/server/controllers/utils/__tests__/functions.test.js +2 -2
- package/server/controllers/utils/parsers.js +6 -2
- package/server/graphql/mutations/createAbuseReport.js +8 -3
- package/server/graphql/mutations/createComment.js +8 -3
- package/server/graphql/mutations/removeComment.js +8 -3
- package/server/graphql/mutations/updateComment.js +8 -3
- package/server/graphql/queries/findAllFlat.js +4 -2
- package/server/graphql/queries/findAllInHierarchy.js +3 -3
- package/server/graphql/resolvers-config.js +13 -8
- package/server/graphql/types/comment-nested.js +1 -1
- package/server/graphql/types/comment.js +0 -1
- package/server/graphql/types/create-comment-author.js +1 -1
- package/server/graphql/types/identify-comment-author.js +1 -1
- package/server/graphql/types/index.js +0 -1
- package/server/services/__tests__/common.test.js +165 -0
- package/server/services/admin.js +10 -7
- package/server/services/client.js +45 -31
- package/server/services/common.js +71 -19
- package/server/services/utils/__tests__/functions.test.js +9 -73
- package/server/services/utils/functions.js +23 -34
- package/server/utils/__tests__/functions.test.js +17 -0
- package/server/utils/constants.js +1 -0
- package/.circleci/config.yml +0 -48
- package/.eslintrc +0 -35
- package/.github/pull_request_template.md +0 -13
- package/.nvmrc +0 -1
- package/admin/src/components/DiscussionThreadItemMeta/index.js +0 -42
- package/admin/src/components/DiscussionThreadItemWarnings/index.js +0 -147
- package/admin/src/components/DiscussionThreadItemWarnings/styles.js +0 -7
- package/codecov.yml +0 -4
- package/public/assets/logo.png +0 -0
- package/public/assets/preview.png +0 -0
- package/server/graphql/types/comment-author-user.js +0 -9
package/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
<div align="center">
|
|
1
|
+
<div align="center" width="150px">
|
|
2
2
|
<img style="width: 150px; height: auto;" src="public/assets/logo.png" alt="Logo - Strapi Comments plugin" />
|
|
3
|
+
</div>
|
|
4
|
+
<div align="center">
|
|
3
5
|
<h1>Strapi v4 - Comments plugin</h1>
|
|
4
|
-
<p>
|
|
6
|
+
<p>Powerful Strapi based comments moderation tool for you and your users</p>
|
|
5
7
|
<a href="https://www.npmjs.org/package/strapi-plugin-comments">
|
|
6
|
-
<img src="https://img.shields.io/
|
|
8
|
+
<img alt="GitHub package.json version" src="https://img.shields.io/github/package-json/v/VirtusLab-Open-Source/strapi-plugin-comments?label=npm&logo=npm">
|
|
7
9
|
</a>
|
|
8
10
|
<a href="https://www.npmjs.org/package/strapi-plugin-comments">
|
|
9
11
|
<img src="https://img.shields.io/npm/dm/strapi-plugin-comments.svg" alt="Monthly download on NPM" />
|
|
@@ -14,6 +16,12 @@
|
|
|
14
16
|
<a href="https://codecov.io/gh/VirtusLab-Open-Source/strapi-plugin-comments">
|
|
15
17
|
<img src="https://codecov.io/gh/VirtusLab-Open-Source/strapi-plugin-comments/coverage.svg?branch=master" alt="codecov.io" />
|
|
16
18
|
</a>
|
|
19
|
+
<a href="https://sharing.clickup.com/tl/xhcmx-83/strapiv-4-comments-roadmap">
|
|
20
|
+
<img src="https://img.shields.io/website?down_message=roadmap&label=product&up_message=roadmap&url=https%3A%2F%2Fsharing.clickup.com%2Ftl%2Fxhcmx-83%2Fstrapiv-4-comments-roadmap" />
|
|
21
|
+
</a>
|
|
22
|
+
<a href="https://sharing.clickup.com/b/xhcmx-63/strapiv-4-comments-board">
|
|
23
|
+
<img src="https://img.shields.io/website?down_message=board&label=product&up_color=blue&up_message=board&url=https%3A%2F%2Fsharing.clickup.com%2Fb%2Fxhcmx-63%2Fstrapiv-4-comments-board" />
|
|
24
|
+
</a>
|
|
17
25
|
</div>
|
|
18
26
|
|
|
19
27
|
---
|
|
@@ -29,10 +37,10 @@ A plugin for [Strapi Headless CMS](https://github.com/strapi/strapi) that provid
|
|
|
29
37
|
|
|
30
38
|
- **Comments Public REST + GraphQL API:** Elegant, entirely customizable and a fully extensible admin panel.
|
|
31
39
|
- **Strapi & generic users:** Support for built-in & also generic non-Strapi users that might be the comments authors.
|
|
32
|
-
- **Any Content Type relation:** Comments can
|
|
40
|
+
- **Any Content Type relation:** Comments can be linked to any of your Content Types by default. Simply, you're controlling it.
|
|
33
41
|
- **Moderation Panel:** Search & Filter through the bucket with your auditory comments. Manage them by blocking single ones or full threads. All in combined list & hierarchical tree view of threads.
|
|
34
|
-
- **Automated Bad Words filtering:** By
|
|
35
|
-
- **Abuse Reporting & Reviewing:** Don't allow inferior language, react to reports from your community, send email
|
|
42
|
+
- **Automated Bad Words filtering:** By default end users are not allowed to post abusing comments where bad words have been used.
|
|
43
|
+
- **Abuse Reporting & Reviewing:** Don't allow inferior language, react to reports from your community, send email notifications about issued reports
|
|
36
44
|
|
|
37
45
|
## ⚙️ Versions
|
|
38
46
|
|
|
@@ -60,7 +68,7 @@ or just run Strapi in the development mode with `--watch-admin` option:
|
|
|
60
68
|
yarn develop --watch-admin
|
|
61
69
|
```
|
|
62
70
|
|
|
63
|
-
The **Comments** plugin should appear in the
|
|
71
|
+
The **Comments** plugin should appear in the **Plugins** section of Strapi sidebar after you run app again.
|
|
64
72
|
|
|
65
73
|
Enjoy 🎉
|
|
66
74
|
|
|
@@ -76,7 +84,7 @@ In our minimum support we're following [official Node.js releases timelines](htt
|
|
|
76
84
|
|
|
77
85
|
**Supported Strapi versions**:
|
|
78
86
|
|
|
79
|
-
- Strapi v4.0.
|
|
87
|
+
- Strapi v4.0.7 (recently tested)
|
|
80
88
|
- Strapi v4.x
|
|
81
89
|
|
|
82
90
|
> This plugin is designed for **Strapi v4** and is not working with v3.x. To get version for **Strapi v3** install version [v1.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-comments/tree/strapi-v3).
|
|
@@ -101,6 +109,9 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
101
109
|
reportReasons: {
|
|
102
110
|
'MY_CUSTOM_REASON': 'MY_CUSTOM_REASON',
|
|
103
111
|
},
|
|
112
|
+
gql: {
|
|
113
|
+
// ...
|
|
114
|
+
},
|
|
104
115
|
},
|
|
105
116
|
//...
|
|
106
117
|
});
|
|
@@ -112,12 +123,36 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
112
123
|
- `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.
|
|
113
124
|
- `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 `*`.
|
|
114
125
|
- `reportReasons` - set of enums you would like to use for issuing abuse reports. Provided by default `'BAD_LANGUAGE'`, `'DISCRIMINATION'` and `'OTHER'`.
|
|
126
|
+
- `gql` - specific configuration for GraphQL. See [Additional GQL Configuration](#additional-gql-configuration)
|
|
115
127
|
|
|
116
128
|
## Additional GQL Configuration
|
|
117
|
-
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)
|
|
129
|
+
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)** and decide if you would like to call it by anyone (open for world) or only by authenticated users (Strapi users).
|
|
130
|
+
|
|
131
|
+
```json
|
|
132
|
+
{
|
|
133
|
+
// ...
|
|
134
|
+
gql: {
|
|
135
|
+
auth: true, // Default: false
|
|
136
|
+
},
|
|
137
|
+
// ...
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Properties
|
|
142
|
+
- `auth` - does GraphQL Queries should be authenticated or not? Default: `false`
|
|
143
|
+
|
|
144
|
+
### Queries
|
|
118
145
|
|
|
119
146
|
See [available GQL specification section](#public-graphql-specification).
|
|
120
147
|
|
|
148
|
+
> If `auth` is set to `true` you must provide relevant authentication headers to all requests like for example:
|
|
149
|
+
>
|
|
150
|
+
> ```json
|
|
151
|
+
> {
|
|
152
|
+
> "Authorization": "Bearer <your token here>"
|
|
153
|
+
> }
|
|
154
|
+
> ```
|
|
155
|
+
|
|
121
156
|
## 👤 RBAC
|
|
122
157
|
Plugin provides granular permissions based on Strapi RBAC functionality.
|
|
123
158
|
|
|
@@ -134,7 +169,6 @@ Feature / Capability focused permissions:
|
|
|
134
169
|
|
|
135
170
|
## Base Comment model
|
|
136
171
|
|
|
137
|
-
### Generic (non Strapi User)
|
|
138
172
|
```json
|
|
139
173
|
{
|
|
140
174
|
"id": 1,
|
|
@@ -146,8 +180,8 @@ Feature / Capability focused permissions:
|
|
|
146
180
|
"removed": null,
|
|
147
181
|
"approvalStatus": "APPROVED", // Only in case of enabled approval flow. Default: null
|
|
148
182
|
"author": {
|
|
149
|
-
"id": "207ccfdc-94ba-45eb-979c-790f6f49c392",
|
|
150
|
-
"name": "Joe Doe",
|
|
183
|
+
"id": "207ccfdc-94ba-45eb-979c-790f6f49c392", // For Strapi users id reflects to the format used by your Strapi
|
|
184
|
+
"name": "Joe Doe", // For Strapi users it is equal to 'username' field
|
|
151
185
|
"email": "jdoe@sample.com",
|
|
152
186
|
"avatar": null,
|
|
153
187
|
},
|
|
@@ -156,49 +190,20 @@ Feature / Capability focused permissions:
|
|
|
156
190
|
"related": {}, // Related content type entity
|
|
157
191
|
"reports": [] // Reports issued against this comment
|
|
158
192
|
}
|
|
159
|
-
```
|
|
160
|
-
### Strapi User
|
|
161
|
-
```json
|
|
162
|
-
{
|
|
163
|
-
"id": 1,
|
|
164
|
-
"content": "My comment content",
|
|
165
|
-
"blocked": true,
|
|
166
|
-
"blockedThread": null,
|
|
167
|
-
"blockReason": null,
|
|
168
|
-
"removed": null,
|
|
169
|
-
"approvalStatus": "REJECTED", // Only in case of enabled approval flow. Default: null
|
|
170
|
-
"authorUser": {
|
|
171
|
-
"id": 1,
|
|
172
|
-
"username": "Sample User",
|
|
173
|
-
"email": "user@sample.com",
|
|
174
|
-
"provider": "local",
|
|
175
|
-
"confirmed": true,
|
|
176
|
-
"blocked": false,
|
|
177
|
-
"role": 1,
|
|
178
|
-
"created_at": "2020-07-10T08:38:03.157Z",
|
|
179
|
-
"updated_at": "2020-07-10T08:38:03.170Z"
|
|
180
|
-
},
|
|
181
|
-
"authorId": null,
|
|
182
|
-
"authorName": null,
|
|
183
|
-
"authorEmail": null,
|
|
184
|
-
"authorAvatar": null,
|
|
185
|
-
"createdAt": "2020-07-14T20:13:01.649Z",
|
|
186
|
-
"updatedAt": "2020-07-14T20:13:01.670Z",
|
|
187
|
-
"related": {}, // Related content type entity
|
|
188
|
-
"reports": [] // Reports issued against this comment
|
|
189
|
-
}
|
|
190
|
-
|
|
191
193
|
```
|
|
192
194
|
|
|
193
195
|
## 🕸️ Public REST API specification
|
|
194
196
|
|
|
197
|
+
**Strapi Users vs. Generic authors**
|
|
198
|
+
> Keep in mind that if you're using auth / authz your requests to setup proper user contexts it has got higher priority in order to take author data comparing to `author` property provided as part of your payload.
|
|
199
|
+
|
|
195
200
|
### Get Comments
|
|
196
201
|
|
|
197
202
|
*GraphQL equivalent: [Public GraphQL API -> Get Comments](#get-comments-1)*
|
|
198
203
|
|
|
199
|
-
`GET <host>/comments/api::<collection name>.<content type name>:<entity id>`
|
|
204
|
+
`GET <host>/api/comments/api::<collection name>.<content type name>:<entity id>`
|
|
200
205
|
|
|
201
|
-
Return a hierarchical tree structure of comments for specified instance of Content Type like for example `Page` with `ID: 1
|
|
206
|
+
Return a hierarchical tree structure of comments for specified instance of Content Type like for example `Page` with `ID: 1`.
|
|
202
207
|
|
|
203
208
|
**Example URL**: `https://localhost:1337/comments/api::page.page:1`
|
|
204
209
|
|
|
@@ -221,12 +226,14 @@ Return a hierarchical tree structure of comments for specified instance of Conte
|
|
|
221
226
|
// ...
|
|
222
227
|
]
|
|
223
228
|
```
|
|
229
|
+
#### Strapi REST API properties support:
|
|
230
|
+
- [sorting](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/sort-pagination.html#sorting)
|
|
224
231
|
|
|
225
232
|
### Get Comments (flat structure)
|
|
226
233
|
|
|
227
234
|
*GraphQL equivalent: [Public GraphQL API -> Get Comments (flat structure)](#get-comments-flat-structure-1)*
|
|
228
235
|
|
|
229
|
-
`GET <host>/comments/api::<collection name>.<content type name>:<entity id>/flat`
|
|
236
|
+
`GET <host>/api/comments/api::<collection name>.<content type name>:<entity id>/flat`
|
|
230
237
|
|
|
231
238
|
Return a flat structure of comments for specified instance of Content Type like for example `Page` with `ID: 1`
|
|
232
239
|
|
|
@@ -250,11 +257,16 @@ Return a flat structure of comments for specified instance of Content Type like
|
|
|
250
257
|
- `200` - Successful. Response with list of comments (can be empty)
|
|
251
258
|
- `400` - Bad Request. Requested list for not valid / not existing Content Type
|
|
252
259
|
|
|
260
|
+
#### Strapi REST API properties support:
|
|
261
|
+
- [filtering](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/filtering-locale-publication.html#filtering)
|
|
262
|
+
- [sorting](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/sort-pagination.html#sorting)
|
|
263
|
+
- [pagination](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/rest/sort-pagination.html#pagination)
|
|
264
|
+
|
|
253
265
|
### Post a Comment
|
|
254
266
|
|
|
255
267
|
*GraphQL equivalent: [Public GraphQL API -> Post a Comments](#post-a-comment-1)*
|
|
256
268
|
|
|
257
|
-
`POST <host>/comments/api::<collection name>.<content type name>:<entity id>`
|
|
269
|
+
`POST <host>/api/comments/api::<collection name>.<content type name>:<entity id>`
|
|
258
270
|
|
|
259
271
|
Posts a Comment related to specified instance of Content Type like for example `Page` with `ID: 1`
|
|
260
272
|
|
|
@@ -265,21 +277,23 @@ Posts a Comment related to specified instance of Content Type like for example `
|
|
|
265
277
|
*Generic (non Strapi User)*
|
|
266
278
|
```json
|
|
267
279
|
{
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
280
|
+
"author": {
|
|
281
|
+
"id": "<any ID like value>",
|
|
282
|
+
"name": "Joe Doe",
|
|
283
|
+
"email": "jdoe@sample.com",
|
|
284
|
+
"avatar": "<any image url>"
|
|
285
|
+
},
|
|
274
286
|
"content": "My sample response",
|
|
275
287
|
"threadOf": 2, // id of comment we would like to start / continue the thread (Optional)
|
|
276
288
|
}
|
|
277
289
|
```
|
|
278
290
|
|
|
279
291
|
*Strapi user*
|
|
292
|
+
|
|
293
|
+
> Author is taken directly from the request context
|
|
294
|
+
|
|
280
295
|
```json
|
|
281
296
|
{
|
|
282
|
-
"authorUser": 1, // id of a author user. Optional in case of 'enableUsers: true' in the plugin configuration
|
|
283
297
|
"content": "My sample response",
|
|
284
298
|
"threadOf": 2, // id of comment we would like to start / continue the thread (Optional)
|
|
285
299
|
}
|
|
@@ -301,7 +315,7 @@ Posts a Comment related to specified instance of Content Type like for example `
|
|
|
301
315
|
|
|
302
316
|
*GraphQL equivalent: [Public GraphQL API -> Update Comments](#update-comment-1)*
|
|
303
317
|
|
|
304
|
-
`PUT <host>/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>`
|
|
318
|
+
`PUT <host>/api/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>`
|
|
305
319
|
|
|
306
320
|
Updates a specified Comment content based on it `commentId` and related to specified instance of Content Type like for example `Page` with `ID: 1`
|
|
307
321
|
|
|
@@ -312,17 +326,19 @@ Updates a specified Comment content based on it `commentId` and related to speci
|
|
|
312
326
|
*Generic (non Strapi User)*
|
|
313
327
|
```json
|
|
314
328
|
{
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
329
|
+
"author": {
|
|
330
|
+
"id": "<any ID like value>"
|
|
331
|
+
},
|
|
318
332
|
"content": "My sample response"
|
|
319
333
|
}
|
|
320
334
|
```
|
|
321
335
|
|
|
322
336
|
*Strapi user*
|
|
337
|
+
|
|
338
|
+
> Author is taken directly from the request context
|
|
339
|
+
|
|
323
340
|
```json
|
|
324
341
|
{
|
|
325
|
-
"authorUser": 1, // id of a author user. Optional in case of 'enableUsers: true' in the plugin configuration
|
|
326
342
|
"content": "My sample response"
|
|
327
343
|
}
|
|
328
344
|
```
|
|
@@ -344,7 +360,7 @@ Updates a specified Comment content based on it `commentId` and related to speci
|
|
|
344
360
|
|
|
345
361
|
*GraphQL equivalent: [Public GraphQL API -> Delete Comment](#delete-comment-1)*
|
|
346
362
|
|
|
347
|
-
`DELETE <host>/comments/api::<collection name>.<content type name>:<entity id>/<commentId>?authorId=<authorId>`
|
|
363
|
+
`DELETE <host>/api/comments/api::<collection name>.<content type name>:<entity id>/<commentId>?authorId=<authorId>`
|
|
348
364
|
|
|
349
365
|
Deletes a specified Comment based on it `commentId` and related to specified instance of Content Type like for example `Page` with `ID: 1`.
|
|
350
366
|
|
|
@@ -367,7 +383,7 @@ Deletes a specified Comment based on it `commentId` and related to specified ins
|
|
|
367
383
|
|
|
368
384
|
*GraphQL equivalent: [Public GraphQL API -> Issue Abuse Report against specified Comment](#issue-abuse-report-against-specified-comment-1)*
|
|
369
385
|
|
|
370
|
-
`POST <host>/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>/report-abuse`
|
|
386
|
+
`POST <host>/api/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>/report-abuse`
|
|
371
387
|
|
|
372
388
|
Reports abuse in specified Comment content based on it `commentId` and related to specified instance of Content Type like for example `Page` with `ID: 1` and requests moderator attention.
|
|
373
389
|
|
|
@@ -398,7 +414,11 @@ Reports abuse in specified Comment content based on it `commentId` and related t
|
|
|
398
414
|
|
|
399
415
|
## 🕸️ Public GraphQL specification
|
|
400
416
|
|
|
401
|
-
|
|
417
|
+
**Strapi Users vs. Generic authors**
|
|
418
|
+
> Keep in mind that if you're using auth / authz your requests to setup proper user contexts it has got higher priority in order to take author data comparing to `author` property provided as part of your payload.
|
|
419
|
+
|
|
420
|
+
**Testing**
|
|
421
|
+
> To test all queries and understand the schemas use GraphQL Playground exposed by `@strapi/plugin-graphql` on `http://localhost:1337/graphql`
|
|
402
422
|
|
|
403
423
|
### Get Comments
|
|
404
424
|
|
|
@@ -447,6 +467,9 @@ query {
|
|
|
447
467
|
}
|
|
448
468
|
```
|
|
449
469
|
|
|
470
|
+
#### Strapi GraphQL API properties support:
|
|
471
|
+
- [sorting](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.html#sorting)
|
|
472
|
+
|
|
450
473
|
### Get Comments (flat structure)
|
|
451
474
|
|
|
452
475
|
*REST API equivalent: [Public REST API -> Get Comments (flat structure)](#get-comments-flat-structure)*
|
|
@@ -503,6 +526,11 @@ query {
|
|
|
503
526
|
}
|
|
504
527
|
```
|
|
505
528
|
|
|
529
|
+
#### Strapi GraphQL API properties support:
|
|
530
|
+
- [filtering](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.html#filters)
|
|
531
|
+
- [sorting](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.html#sorting)
|
|
532
|
+
- [pagination](https://docs.strapi.io/developer-docs/latest/developer-resources/database-apis-reference/graphql-api.html#pagination)
|
|
533
|
+
|
|
506
534
|
### Post a Comment
|
|
507
535
|
|
|
508
536
|
*REST API equivalent: [Public REST API -> Post a Comment](#post-a-comment)*
|
|
@@ -516,7 +544,7 @@ mutation createComment {
|
|
|
516
544
|
relation: "api::page.page:1"
|
|
517
545
|
content: "Hello World!"
|
|
518
546
|
threadOf: 3
|
|
519
|
-
author: { id: "12345678", name: "John Wick", email: "test@test.pl" }
|
|
547
|
+
author: { id: "12345678", name: "John Wick", email: "test@test.pl" } # Optional if using auth / authz requests
|
|
520
548
|
}
|
|
521
549
|
) {
|
|
522
550
|
id
|
|
@@ -565,7 +593,7 @@ mutation updateComment {
|
|
|
565
593
|
id: 34
|
|
566
594
|
relation: "api::page.page:1"
|
|
567
595
|
content: "I've changed it!"
|
|
568
|
-
author: { id: "12345678" }
|
|
596
|
+
author: { id: "12345678" } # Optional if using auth / authz requests
|
|
569
597
|
}
|
|
570
598
|
) {
|
|
571
599
|
id
|
|
@@ -614,7 +642,11 @@ mutation updateComment {
|
|
|
614
642
|
```graphql
|
|
615
643
|
mutation removeComment {
|
|
616
644
|
removeComment(
|
|
617
|
-
input: {
|
|
645
|
+
input: {
|
|
646
|
+
id: 33,
|
|
647
|
+
relation: "api::page.page:1",
|
|
648
|
+
author: { id: "12345678" } # Optional if using auth / authz requests
|
|
649
|
+
}
|
|
618
650
|
) {
|
|
619
651
|
id
|
|
620
652
|
removed
|
|
@@ -694,15 +726,25 @@ Live example of plugin usage can be found in the [VirtusLab Strapi Examples](htt
|
|
|
694
726
|
|
|
695
727
|
## 🤝 Contributing
|
|
696
728
|
|
|
729
|
+
<div>
|
|
730
|
+
<a href="https://sharing.clickup.com/tl/xhcmx-83/strapiv-4-comments-roadmap">
|
|
731
|
+
<img src="https://img.shields.io/website?down_message=roadmap&label=product&up_message=roadmap&url=https%3A%2F%2Fsharing.clickup.com%2Ftl%2Fxhcmx-83%2Fstrapiv-4-comments-roadmap" />
|
|
732
|
+
</a>
|
|
733
|
+
<a href="https://sharing.clickup.com/b/xhcmx-63/strapiv-4-comments-board">
|
|
734
|
+
<img src="https://img.shields.io/website?down_message=board&label=product&up_color=blue&up_message=board&url=https%3A%2F%2Fsharing.clickup.com%2Fb%2Fxhcmx-63%2Fstrapiv-4-comments-board" />
|
|
735
|
+
</a>
|
|
736
|
+
</div>
|
|
737
|
+
|
|
697
738
|
Feel free to fork and make a Pull Request to this plugin project. All the input is warmly welcome!
|
|
698
739
|
|
|
699
740
|
## 👨💻 Community support
|
|
700
741
|
|
|
701
742
|
For general help using Strapi, please refer to [the official Strapi documentation](https://strapi.io/documentation/). For additional help, you can use one of these channels to ask a question:
|
|
702
743
|
|
|
703
|
-
- [Discord](https://discord.strapi.io/) We're present on official Strapi Discord workspace.
|
|
744
|
+
- [Discord](https://discord.strapi.io/) We're present on official Strapi Discord workspace. Find us by `[VirtusLab]` prefix and DM.
|
|
704
745
|
- [Slack - VirtusLab Open Source](https://virtuslab-oss.slack.com) We're present on a public channel #strapi-molecules
|
|
705
746
|
- [GitHub](https://github.com/VirtusLab-Open-Source/strapi-plugin-comments/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
747
|
+
- [E-mail](mailto:strapi@virtuslab.com) - we will respond back as soon as possible
|
|
706
748
|
|
|
707
749
|
## 📝 License
|
|
708
750
|
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const { get, set } = require('lodash');
|
|
2
|
+
|
|
3
|
+
module.exports = (config = {}) => {
|
|
4
|
+
const mock = {
|
|
5
|
+
getRef: function() {
|
|
6
|
+
return this;
|
|
7
|
+
},
|
|
8
|
+
plugin: function(name) {
|
|
9
|
+
return this.plugins[name];
|
|
10
|
+
},
|
|
11
|
+
plugins: {
|
|
12
|
+
comments: {
|
|
13
|
+
service: function(name) {
|
|
14
|
+
return this.services[name]({ strapi: mock.getRef() });
|
|
15
|
+
},
|
|
16
|
+
package: require('../package.json'),
|
|
17
|
+
services: {
|
|
18
|
+
common: require('../server/services/common'),
|
|
19
|
+
client: require('../server/services/client'),
|
|
20
|
+
admin: require('../server/services/admin'),
|
|
21
|
+
},
|
|
22
|
+
contentTypes: {
|
|
23
|
+
comment: {
|
|
24
|
+
...require('../content-types/comment'),
|
|
25
|
+
uid: 'plugins::comments.comment',
|
|
26
|
+
},
|
|
27
|
+
'comment-report': {
|
|
28
|
+
...require('../content-types/report'),
|
|
29
|
+
uid: 'plugins::comments.comment-report'
|
|
30
|
+
},
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
config: {
|
|
35
|
+
get: function(prop = '') {
|
|
36
|
+
return get(this.plugins, prop.replace('plugin.', ''));
|
|
37
|
+
},
|
|
38
|
+
set: function(prop = '', value) {
|
|
39
|
+
return set(this.plugins, prop.replace('plugin.', ''), value);
|
|
40
|
+
},
|
|
41
|
+
plugins: {
|
|
42
|
+
comments: {
|
|
43
|
+
approvalFlow: ['api::blog-post.blog-post'],
|
|
44
|
+
entryLabel: {
|
|
45
|
+
'api::blog-post.blog-post': ['alternative_subject'],
|
|
46
|
+
},
|
|
47
|
+
...config
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
return mock;
|
|
53
|
+
};
|
|
@@ -8,7 +8,6 @@ import React from 'react';
|
|
|
8
8
|
import PropTypes from 'prop-types';
|
|
9
9
|
import { isNil } from 'lodash';
|
|
10
10
|
import { Box } from '@strapi/design-system/Box';
|
|
11
|
-
import { Divider } from '@strapi/design-system/Divider';
|
|
12
11
|
import { Flex } from '@strapi/design-system/Flex';
|
|
13
12
|
import { Link } from '@strapi/design-system/Link';
|
|
14
13
|
import { Typography } from '@strapi/design-system/Typography';
|
|
@@ -22,22 +21,19 @@ const DiscussionThread = ({ level = [], selected = {}, allowedActions, isReloadi
|
|
|
22
21
|
const rootThread = selected?.threadOf;
|
|
23
22
|
return (<LoadingIndicatorContainer as={Box} padding={4}>
|
|
24
23
|
{ isReloading && <LoadingIndicatorOverlay />}
|
|
25
|
-
<Flex as={Box} direction="row" justifyContent="space-between">
|
|
26
|
-
<Typography variant="
|
|
24
|
+
<Flex as={Box} direction="row" justifyContent="space-between" marginBottom={2}>
|
|
25
|
+
<Typography variant="delta" textColor="neutral800" id="discussion-thread">
|
|
27
26
|
{ getMessage('page.details.panel.discussion', 'Discussion') }
|
|
28
27
|
</Typography>
|
|
29
28
|
{ rootThread && (<Link to={getUrl(`discover/${rootThread.id}`)} startIcon={<ArrowUp />}>
|
|
30
29
|
{ getMessage('page.details.panel.discussion.nav.back') }
|
|
31
30
|
</Link>) }
|
|
32
31
|
</Flex>
|
|
33
|
-
<Box paddingTop={2} paddingBottom={6}>
|
|
34
|
-
<Divider />
|
|
35
|
-
</Box>
|
|
36
32
|
<Flex as="ul" direction="column" alignItems="flex-start">
|
|
37
33
|
{ rootThread && (<DiscussionThreadItem {...rootThread} allowedActions={allowedActions} isThreadAuthor root pinned />) }
|
|
38
34
|
{ level.map(item => {
|
|
39
35
|
const isSelected = selected.id === item.id;
|
|
40
|
-
const isThreadAuthor = !isNil(selected?.threadOf?.
|
|
36
|
+
const isThreadAuthor = !isNil(selected?.threadOf?.author?.id) && (selected?.threadOf?.author?.id === item?.author?.id);
|
|
41
37
|
return (<DiscussionThreadItem
|
|
42
38
|
key={`comment-${item.id}`}
|
|
43
39
|
{...item}
|
|
@@ -1,92 +1,47 @@
|
|
|
1
1
|
/**
|
|
2
2
|
*
|
|
3
|
-
*
|
|
3
|
+
* Discussion thread - Item
|
|
4
4
|
*
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import React from 'react';
|
|
8
8
|
import PropTypes from 'prop-types';
|
|
9
|
-
import { Avatar, Initials } from '@strapi/design-system/Avatar';
|
|
10
9
|
import { Box } from '@strapi/design-system/Box';
|
|
11
|
-
import { Divider } from '@strapi/design-system/Divider';
|
|
12
10
|
import { Flex } from '@strapi/design-system/Flex';
|
|
13
|
-
import { Link } from '@strapi/design-system/Link';
|
|
14
11
|
import { Typography } from '@strapi/design-system/Typography';
|
|
15
|
-
import
|
|
16
|
-
import DiscussionThreadItemMeta from '../DiscussionThreadItemMeta';
|
|
17
|
-
import { AvatarWrapper, DiscussionThreadItemBox, DiscussionThreadItemBoxContent, DiscussionThreadItemContent, DiscussionThreadItemLeft, DiscussionThreadItemLinkBox, DiscussionThreadItemRight, DiscussionThreadItemRoot } from './styles';
|
|
12
|
+
import DiscussionThreadItemFooter from '../DiscussionThreadItemFooter';
|
|
18
13
|
import DiscussionThreadItemActions from '../DiscussionThreadItemActions';
|
|
19
|
-
import {
|
|
20
|
-
import DiscussionThreadItemWarnings from '../DiscussionThreadItemWarnings';
|
|
14
|
+
import { DiscussionThreadItemContainer, DiscussionThreadFullsize, DiscussionThreadItemContent } from './styles';
|
|
21
15
|
|
|
22
16
|
const DiscussionThreadItem = (props) => {
|
|
23
17
|
const {
|
|
18
|
+
as = "li",
|
|
24
19
|
isSelected,
|
|
25
|
-
isThreadAuthor,
|
|
26
20
|
content,
|
|
27
21
|
root,
|
|
28
22
|
preview,
|
|
29
|
-
pinned
|
|
30
|
-
blocked,
|
|
31
|
-
removed,
|
|
32
|
-
blockedThread,
|
|
33
|
-
gotThread,
|
|
34
|
-
threadFirstItemId,
|
|
35
|
-
authorUser,
|
|
36
|
-
author } = props;
|
|
37
|
-
|
|
38
|
-
let background = 'neutral100';
|
|
39
|
-
let borderColor = 'neutral200';
|
|
40
|
-
let dividerColor = 'neutral200';
|
|
41
|
-
let StyledComponent = DiscussionThreadItemRight;
|
|
42
|
-
|
|
43
|
-
if(isThreadAuthor || root){
|
|
44
|
-
StyledComponent = DiscussionThreadItemLeft;
|
|
45
|
-
borderColor = 'neutral100';
|
|
46
|
-
dividerColor = 'neutral100';
|
|
47
|
-
background = null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
if (isSelected) {
|
|
51
|
-
background = 'secondary100'
|
|
52
|
-
borderColor = 'secondary500';
|
|
53
|
-
dividerColor = 'secondary200';
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
if (root) {
|
|
57
|
-
StyledComponent = DiscussionThreadItemRoot;
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
const avatar = author?.avatar || authorUser?.avatar;
|
|
61
|
-
const name = author?.name || `${authorUser?.firstName} ${authorUser?.lastName}`;
|
|
62
|
-
const isBlocked = blocked || blockedThread;
|
|
23
|
+
pinned } = props;
|
|
63
24
|
|
|
64
|
-
return (<
|
|
65
|
-
<
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
</
|
|
79
|
-
<
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
</
|
|
83
|
-
|
|
84
|
-
{ (gotThread && !(removed || preview || pinned)) && (<DiscussionThreadItemLinkBox direction="column" alignItems="flex-end">
|
|
85
|
-
<Link to={getUrl(`discover/${threadFirstItemId}`)} endIcon={<ArrowRight />}>
|
|
86
|
-
{ getMessage('page.details.panel.discussion.nav.drilldown') }
|
|
87
|
-
</Link>
|
|
88
|
-
</DiscussionThreadItemLinkBox>) }
|
|
89
|
-
</StyledComponent>);
|
|
25
|
+
return (<DiscussionThreadFullsize as={as} marginBottom={preview ? 4 : 0}>
|
|
26
|
+
<DiscussionThreadItemContainer
|
|
27
|
+
as={Flex}
|
|
28
|
+
direction="column"
|
|
29
|
+
alignItems="flex-start"
|
|
30
|
+
hasRadius
|
|
31
|
+
background={isSelected ? 'neutral100' : null}
|
|
32
|
+
paddingLeft={2} paddingRight={2} paddingTop={4} paddingBottom={4}>
|
|
33
|
+
<DiscussionThreadItemContent
|
|
34
|
+
as={Flex}
|
|
35
|
+
paddingBottom={2}
|
|
36
|
+
direction="row">
|
|
37
|
+
<Box as={Flex} grow={1} alignItems="center" marginTop="6px">
|
|
38
|
+
<Typography variant="omega" textColor="neutral800">{ content }</Typography>
|
|
39
|
+
</Box>
|
|
40
|
+
{ !preview && (<DiscussionThreadItemActions { ...props } root={root || pinned} preview={preview} />) }
|
|
41
|
+
</DiscussionThreadItemContent>
|
|
42
|
+
<DiscussionThreadItemFooter { ...props } />
|
|
43
|
+
</DiscussionThreadItemContainer>
|
|
44
|
+
</DiscussionThreadFullsize>);
|
|
90
45
|
};
|
|
91
46
|
|
|
92
47
|
DiscussionThreadItem.propTypes = {
|