strapi-plugin-comments 1.0.2-beta.1 → 2.0.0-beta.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/.circleci/config.yml +2 -2
- package/README.md +71 -95
- package/admin/src/components/ConfirmationDialog/index.js +56 -0
- package/admin/src/components/DiscussionStatus/index.js +33 -0
- package/admin/src/components/DiscussionThread/index.js +58 -0
- package/admin/src/components/DiscussionThreadItem/index.js +87 -0
- package/admin/src/components/DiscussionThreadItem/styles.js +87 -0
- package/admin/src/components/DiscussionThreadItemActions/index.js +176 -0
- package/admin/src/components/DiscussionThreadItemActions/styles.js +22 -0
- package/admin/src/components/DiscussionThreadItemMeta/index.js +31 -0
- package/admin/src/components/DiscussionThreadItemWarnings/index.js +137 -0
- package/admin/src/components/DiscussionThreadItemWarnings/styles.js +7 -0
- package/admin/src/components/EntityDetails/index.js +53 -0
- package/admin/src/{containers → components}/Initializer/index.js +4 -4
- package/admin/src/components/LoadingIndicatorOverlay/index.js +15 -0
- package/admin/src/components/LoadingIndicatorOverlay/styles.js +20 -0
- package/admin/src/components/Nav/index.js +45 -0
- package/admin/src/components/PluginIcon/index.js +12 -0
- package/admin/src/components/ReportsReviewModal/index.js +45 -0
- package/admin/src/components/ReportsReviewTable/index.js +142 -0
- package/admin/src/components/TableFilters/index.js +53 -0
- package/admin/src/components/TablePagination/index.js +35 -0
- package/admin/src/components/icons/comments.js +9 -0
- package/admin/src/index.js +58 -42
- package/admin/src/pages/App/index.js +60 -0
- package/admin/src/pages/App/reducer/actions.js +8 -0
- package/admin/src/pages/App/reducer/constants.js +4 -0
- package/admin/src/pages/App/reducer/index.js +27 -0
- package/admin/src/pages/App/reducer/init.js +7 -0
- package/admin/src/pages/App/reducer/selectors.js +35 -0
- package/admin/src/pages/App/utils/api.js +20 -0
- package/admin/src/pages/ComingSoonPage/index.js +25 -0
- package/admin/src/pages/Details/index.js +109 -0
- package/admin/src/pages/Details/utils/api.js +41 -0
- package/admin/src/pages/Discover/index.js +203 -0
- package/admin/src/pages/Discover/utils/api.js +20 -0
- package/admin/src/pages/Discover/utils/filtersSchema.js +9 -0
- package/admin/src/permissions.js +13 -33
- package/admin/src/pluginId.js +2 -4
- package/admin/src/reducers.js +8 -0
- package/admin/src/translations/en.json +72 -33
- package/admin/src/translations/fr.json +1 -0
- package/admin/src/utils/axiosInstance.js +35 -0
- package/admin/src/utils/constants.js +28 -0
- package/admin/src/utils/getApiUrl.js +5 -0
- package/admin/src/utils/getMessage.js +14 -0
- package/admin/src/utils/getRelatedGroups.js +5 -0
- package/admin/src/utils/getUrl.js +5 -0
- package/admin/src/utils/handleAPIError.js +15 -0
- package/admin/src/utils/index.js +6 -0
- package/codecov.yml +2 -1
- package/content-types/comment.js +97 -0
- package/content-types/index.js +11 -0
- package/content-types/report.js +54 -0
- package/package.json +11 -25
- package/server/bootstrap.js +5 -0
- package/server/config/index.js +10 -0
- package/server/controllers/admin.js +134 -0
- package/server/controllers/client.js +109 -0
- package/server/controllers/index.js +9 -0
- package/{controllers → server/controllers}/utils/__tests__/functions.test.js +0 -0
- package/{controllers → server/controllers}/utils/functions.js +1 -1
- package/server/destroy.js +5 -0
- package/server/index.js +22 -0
- package/server/register.js +5 -0
- package/server/routes/admin.js +92 -0
- package/server/routes/client.js +52 -0
- package/server/routes/index.js +15 -0
- package/server/services/admin.js +186 -0
- package/server/services/client.js +227 -0
- package/server/services/common.js +191 -0
- package/server/services/index.js +11 -0
- package/{services → server/services}/utils/__tests__/functions.test.js +7 -9
- package/{services → server/services}/utils/functions.js +19 -8
- package/server/utils/constants.js +16 -0
- package/{services → server}/utils/error.js +0 -0
- package/server/utils/functions.js +19 -0
- package/strapi-admin.js +3 -0
- package/strapi-server.js +9 -0
- package/admin/src/assets/images/icon-cross-blue.svg +0 -1
- package/admin/src/assets/images/icon_remove.svg +0 -19
- package/admin/src/assets/images/logo.svg +0 -5
- package/admin/src/components/AbuseReportsPopUp/ItemPreviewContainer.js +0 -8
- package/admin/src/components/AbuseReportsPopUp/ModalFooter.js +0 -31
- package/admin/src/components/AbuseReportsPopUp/TableContainer.js +0 -63
- package/admin/src/components/AbuseReportsPopUp/index.js +0 -148
- package/admin/src/components/Container/index.js +0 -7
- package/admin/src/components/EmptyView/index.js +0 -25
- package/admin/src/components/Filters/index.js +0 -151
- package/admin/src/components/Filters/index.styled.js +0 -82
- package/admin/src/components/Filters/utils.js +0 -21
- package/admin/src/components/Item/CardItem.js +0 -30
- package/admin/src/components/Item/CardWrapper.js +0 -10
- package/admin/src/components/Item/index.js +0 -92
- package/admin/src/components/ItemDetails/CardItem.js +0 -33
- package/admin/src/components/ItemDetails/CardLevelCounter.js +0 -46
- package/admin/src/components/ItemDetails/CardLevelCounterLink.js +0 -24
- package/admin/src/components/ItemDetails/CardLevelWrapper.js +0 -22
- package/admin/src/components/ItemDetails/CardWrapper.js +0 -52
- package/admin/src/components/ItemDetails/index.js +0 -151
- package/admin/src/components/ItemFooter/CardItemAuthor.js +0 -10
- package/admin/src/components/ItemFooter/CardItemRelation.js +0 -18
- package/admin/src/components/ItemFooter/Wrapper.js +0 -20
- package/admin/src/components/ItemFooter/index.js +0 -87
- package/admin/src/components/ItemHeader/CardHeaderBlocked.js +0 -24
- package/admin/src/components/ItemHeader/CardHeaderIndicator.js +0 -30
- package/admin/src/components/ItemHeader/CardHeaderIndicatorBlue.js +0 -11
- package/admin/src/components/ItemHeader/CardHeaderIndicatorRed.js +0 -11
- package/admin/src/components/ItemHeader/CardHeaderIndicatorsContainer.js +0 -18
- package/admin/src/components/ItemHeader/CardHeaderReports.js +0 -40
- package/admin/src/components/ItemHeader/Wrapper.js +0 -16
- package/admin/src/components/ItemHeader/index.js +0 -80
- package/admin/src/components/ItemModeration/Wrapper.js +0 -19
- package/admin/src/components/ItemModeration/index.js +0 -47
- package/admin/src/components/List/Container.js +0 -20
- package/admin/src/components/List/index.js +0 -21
- package/admin/src/components/Search/index.js +0 -83
- package/admin/src/containers/App/Wrapper.js +0 -14
- package/admin/src/containers/App/index.js +0 -47
- package/admin/src/containers/DataManagerProvider/actions.js +0 -11
- package/admin/src/containers/DataManagerProvider/index.js +0 -280
- package/admin/src/containers/DataManagerProvider/init.js +0 -5
- package/admin/src/containers/DataManagerProvider/reducer.js +0 -59
- package/admin/src/containers/DetailsView/Wrapper.js +0 -18
- package/admin/src/containers/DetailsView/index.js +0 -100
- package/admin/src/containers/ListView/FadedWrapper.js +0 -42
- package/admin/src/containers/ListView/Footer.js +0 -53
- package/admin/src/containers/ListView/Wrapper.js +0 -17
- package/admin/src/containers/ListView/components.js +0 -138
- package/admin/src/containers/ListView/index.js +0 -45
- package/admin/src/containers/Panel/actions.js +0 -5
- package/admin/src/containers/Panel/index.js +0 -191
- package/admin/src/containers/Panel/index.styled.js +0 -6
- package/admin/src/containers/Panel/reducer.js +0 -44
- package/admin/src/contexts/DataManagerContext.js +0 -5
- package/admin/src/hooks/useDataManager.js +0 -6
- package/admin/src/lifecycles.js +0 -3
- package/admin/src/translations/index.js +0 -7
- package/admin/src/utils/getTrad.js +0 -5
- package/admin/src/utils/getTradId.js +0 -5
- package/config/functions/bootstrap.js +0 -48
- package/config/routes.json +0 -116
- package/config/schema.graphql.js +0 -270
- package/controllers/comments.js +0 -211
- package/models/comment.js +0 -8
- package/models/comment.settings.json +0 -98
- package/models/report.js +0 -8
- package/models/report.settings.json +0 -49
- package/services/comments.js +0 -486
package/.circleci/config.yml
CHANGED
|
@@ -20,7 +20,7 @@ jobs:
|
|
|
20
20
|
- restore_cache:
|
|
21
21
|
keys:
|
|
22
22
|
# when lock file changes, use increasingly general patterns to restore cache
|
|
23
|
-
- strapi-plugin-comments-
|
|
23
|
+
- strapi-plugin-comments-v2-{{ checksum "yarn.lock" }}
|
|
24
24
|
- strapi-plugin-comments-
|
|
25
25
|
- run:
|
|
26
26
|
name: Echo versions
|
|
@@ -41,7 +41,7 @@ jobs:
|
|
|
41
41
|
- save_cache:
|
|
42
42
|
paths:
|
|
43
43
|
- ./node_modules
|
|
44
|
-
key: strapi-plugin-comments-
|
|
44
|
+
key: strapi-plugin-comments-v2-{{ checksum "yarn.lock" }}
|
|
45
45
|
workflows:
|
|
46
46
|
build-and-test:
|
|
47
47
|
jobs:
|
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Strapi - Comments plugin
|
|
1
|
+
# Strapi v4 - Comments plugin - BETA
|
|
2
2
|
|
|
3
3
|
<p align="center">
|
|
4
4
|
<a href="https://www.npmjs.org/package/strapi-plugin-comments">
|
|
@@ -7,17 +7,19 @@
|
|
|
7
7
|
<a href="https://www.npmjs.org/package/strapi-plugin-comments">
|
|
8
8
|
<img src="https://img.shields.io/npm/dm/strapi-plugin-comments.svg" alt="Monthly download on NPM" />
|
|
9
9
|
</a>
|
|
10
|
-
<a href="https://circleci.com/gh/VirtusLab/strapi-plugin-comments">
|
|
11
|
-
<img src="https://circleci.com/gh/VirtusLab/strapi-plugin-comments.svg?style=shield" alt="CircleCI" />
|
|
10
|
+
<a href="https://circleci.com/gh/VirtusLab-Open-Source/strapi-plugin-comments">
|
|
11
|
+
<img src="https://circleci.com/gh/VirtusLab-Open-Source/strapi-plugin-comments.svg?style=shield" alt="CircleCI" />
|
|
12
12
|
</a>
|
|
13
|
-
<a href="https://codecov.io/gh/VirtusLab/strapi-plugin-comments">
|
|
14
|
-
<img src="https://codecov.io/gh/VirtusLab/strapi-plugin-comments/coverage.svg?branch=master" alt="codecov.io" />
|
|
13
|
+
<a href="https://codecov.io/gh/VirtusLab-Open-Source/strapi-plugin-comments">
|
|
14
|
+
<img src="https://codecov.io/gh/VirtusLab-Open-Source/strapi-plugin-comments/coverage.svg?branch=master" alt="codecov.io" />
|
|
15
15
|
</a>
|
|
16
16
|
</p>
|
|
17
17
|
|
|
18
18
|
A plugin for [Strapi Headless CMS](https://github.com/strapi/strapi) that provides end to end comments feature with their moderation panel, bad words filtering, abuse reporting and more.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
### Versions
|
|
21
|
+
- **Stable** - [v1.0.4](https://github.com/VirtusLab-Open-Source/strapi-plugin-comments)
|
|
22
|
+
- **Beta** - v4 support - [v2.0.0-beta.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-comments/tree/feat/strapi-v4)
|
|
21
23
|
|
|
22
24
|
### ⏳ Installation
|
|
23
25
|
|
|
@@ -46,14 +48,13 @@ Enjoy 🎉
|
|
|
46
48
|
|
|
47
49
|
### 🖐 Requirements
|
|
48
50
|
|
|
49
|
-
Complete installation requirements are exact same as for Strapi itself and can be found in the documentation under
|
|
51
|
+
Complete installation requirements are exact same as for Strapi itself and can be found in the documentation under [Installation Requirements](https://docs.strapi.io/developer-docs/latest/getting-started/introduction.html).
|
|
50
52
|
|
|
51
53
|
**Supported Strapi versions**:
|
|
52
54
|
|
|
53
|
-
- Strapi
|
|
54
|
-
- Strapi v3.x
|
|
55
|
+
- Strapi v4.0.2 (recently tested)
|
|
55
56
|
|
|
56
|
-
(This plugin may work with the older Strapi versions, but these are not tested nor officially supported at this time.)
|
|
57
|
+
(This plugin is not working with v3.x and not may work with the older Strapi v4 versions, but these are not tested nor officially supported at this time.)
|
|
57
58
|
|
|
58
59
|
**We recommend always using the latest version of Strapi to start your new projects**.
|
|
59
60
|
|
|
@@ -64,81 +65,58 @@ Complete installation requirements are exact same as for Strapi itself and can b
|
|
|
64
65
|
- **Any Content Type relation:** Comments can by linked to any of your Content Types by default. Simply, you're controlling it.
|
|
65
66
|
- **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.
|
|
66
67
|
- **Automated Bad Words filtering:** By detault end users are not allowed to post abusing comments where bad words have been used.
|
|
67
|
-
- **Abuse Reporting & Reviewing:** Don't allow inferior language, react to reports from your community
|
|
68
|
-
|
|
69
|
-
## Content Type model relation to Comment
|
|
70
|
-
|
|
71
|
-
To enable Content Type to work with Comments, you've to add following field to your model `*.settings.json`:
|
|
72
|
-
|
|
73
|
-
```
|
|
74
|
-
"comments": {
|
|
75
|
-
"plugin": "comments",
|
|
76
|
-
"collection": "comment",
|
|
77
|
-
"via": "related"
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
inside the `attributes` section like in example below:
|
|
82
|
-
|
|
83
|
-
```
|
|
84
|
-
"attributes": {
|
|
85
|
-
...,
|
|
86
|
-
"comments": {
|
|
87
|
-
"plugin": "comments",
|
|
88
|
-
"collection": "comment",
|
|
89
|
-
"via": "related"
|
|
90
|
-
},
|
|
91
|
-
...
|
|
92
|
-
},
|
|
93
|
-
```
|
|
68
|
+
- **Abuse Reporting & Reviewing:** Don't allow inferior language, react to reports from your community, send email notifiactions about abuse reports
|
|
94
69
|
|
|
95
70
|
## Configuration
|
|
96
|
-
To setup amend default plugin configuration we recommend to put following snippet as part of `config/
|
|
71
|
+
To setup amend default plugin configuration we recommend to put following snippet as part of `config/plugins.js` or `config/<env>/plugins.js` file. If the file does not exist yet, you have to create it manually. If you've got already configurations for other plugins stores by this way, use just the `comments` part within exising `plugins` item.
|
|
97
72
|
|
|
98
|
-
|
|
73
|
+
|
|
74
|
+
```js
|
|
99
75
|
...
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
badWords: false,
|
|
104
|
-
},
|
|
76
|
+
comments: {
|
|
77
|
+
badWords: false,
|
|
78
|
+
moderatorRoles: ["Authenticated"]
|
|
105
79
|
},
|
|
106
80
|
...
|
|
107
81
|
```
|
|
108
82
|
|
|
109
83
|
### Properties
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
84
|
+
- `badWords` - Enabled support for [bad words filtering](https://www.npmjs.com/package/bad-words). Can be turned off or overwritten using [options reference](https://www.npmjs.com/package/bad-words#constructor). Default value: `true`.
|
|
85
|
+
- `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.
|
|
86
|
+
|
|
87
|
+
## Additional GQL Configuration
|
|
88
|
+
|
|
89
|
+
> To be done
|
|
112
90
|
|
|
113
91
|
## Public API Comment model
|
|
114
92
|
|
|
115
93
|
### Generic (non Strapi User)
|
|
116
|
-
```
|
|
94
|
+
```json
|
|
117
95
|
{
|
|
118
96
|
"id": 1,
|
|
119
97
|
"content": "My comment content",
|
|
120
98
|
"blocked": null,
|
|
121
99
|
"blockedThread": true,
|
|
122
100
|
"blockReason": null,
|
|
123
|
-
"points": 1,
|
|
124
101
|
"authorUser": null,
|
|
125
102
|
"authorId": "207ccfdc-94ba-45eb-979c-790f6f49c392",
|
|
126
103
|
"authorName": "Joe Doe",
|
|
127
104
|
"authorEmail": "jdoe@sample.com",
|
|
128
105
|
"authorAvatar": null,
|
|
129
|
-
"
|
|
130
|
-
"
|
|
106
|
+
"createdAt": "2020-07-14T20:13:01.649Z",
|
|
107
|
+
"updatedAt": "2020-07-14T20:13:01.670Z",
|
|
108
|
+
"related": {}, // Related content type entity
|
|
109
|
+
"reports": [] // Reports issued against this comment
|
|
131
110
|
}
|
|
132
111
|
```
|
|
133
112
|
### Strapi User
|
|
134
|
-
```
|
|
113
|
+
```json
|
|
135
114
|
{
|
|
136
115
|
"id": 1,
|
|
137
116
|
"content": "My comment content",
|
|
138
117
|
"blocked": true,
|
|
139
118
|
"blockedThread": null,
|
|
140
119
|
"blockReason": null,
|
|
141
|
-
"points": null,
|
|
142
120
|
"authorUser": {
|
|
143
121
|
"id": 1,
|
|
144
122
|
"username": "Sample User",
|
|
@@ -154,8 +132,10 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
154
132
|
"authorName": null,
|
|
155
133
|
"authorEmail": null,
|
|
156
134
|
"authorAvatar": null,
|
|
157
|
-
"
|
|
158
|
-
"
|
|
135
|
+
"createdAt": "2020-07-14T20:13:01.649Z",
|
|
136
|
+
"updatedAt": "2020-07-14T20:13:01.670Z",
|
|
137
|
+
"related": {}, // Related content type entity
|
|
138
|
+
"reports": [] // Reports issued against this comment
|
|
159
139
|
}
|
|
160
140
|
|
|
161
141
|
```
|
|
@@ -164,11 +144,11 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
164
144
|
|
|
165
145
|
### Get Comments
|
|
166
146
|
|
|
167
|
-
`GET <host>/comments
|
|
147
|
+
`GET <host>/comments/api::<collection name>.<content type name>:<entity id>`
|
|
168
148
|
|
|
169
|
-
Return a hierarchical tree structure of comments for specified instance of Content Type like for example `
|
|
149
|
+
Return a hierarchical tree structure of comments for specified instance of Content Type like for example `Page` with `ID: 1`
|
|
170
150
|
|
|
171
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
151
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1`
|
|
172
152
|
|
|
173
153
|
**Example response body**
|
|
174
154
|
|
|
@@ -190,11 +170,11 @@ Return a hierarchical tree structure of comments for specified instance of Conte
|
|
|
190
170
|
|
|
191
171
|
### Get Comments (flat structure)
|
|
192
172
|
|
|
193
|
-
`GET <host>/comments
|
|
173
|
+
`GET <host>/comments/api::<collection name>.<content type name>:<entity id>/flat`
|
|
194
174
|
|
|
195
|
-
Return a flat structure of comments for specified instance of Content Type like for example `
|
|
175
|
+
Return a flat structure of comments for specified instance of Content Type like for example `Page` with `ID: 1`
|
|
196
176
|
|
|
197
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
177
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/flat`
|
|
198
178
|
|
|
199
179
|
**Example response body**
|
|
200
180
|
|
|
@@ -216,27 +196,26 @@ Return a flat structure of comments for specified instance of Content Type like
|
|
|
216
196
|
|
|
217
197
|
### Post a Comment
|
|
218
198
|
|
|
219
|
-
`POST <host>/comments
|
|
199
|
+
`POST <host>/comments/api::<collection name>.<content type name>:<entity id>`
|
|
220
200
|
|
|
221
|
-
Posts a Comment related to specified instance of Content Type like for example `
|
|
201
|
+
Posts a Comment related to specified instance of Content Type like for example `Page` with `ID: 1`
|
|
222
202
|
|
|
223
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
203
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1`
|
|
224
204
|
|
|
225
205
|
**Example request body**
|
|
226
206
|
|
|
227
207
|
*Generic (non Strapi User)*
|
|
228
208
|
```
|
|
229
209
|
{
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
210
|
+
"author": {
|
|
211
|
+
"id": "<any ID like value>",
|
|
212
|
+
"name": "Joe Doe",
|
|
213
|
+
"email": "jdoe@sample.com",
|
|
214
|
+
"avatar": "<any image url>"
|
|
215
|
+
},
|
|
233
216
|
"content": "My sample response",
|
|
234
217
|
"threadOf": 2, // id of comment we would like to start / continue the thread (Optional)
|
|
235
|
-
"related":
|
|
236
|
-
"refId": 1,
|
|
237
|
-
"ref": "article",
|
|
238
|
-
"field": "comments"
|
|
239
|
-
}]
|
|
218
|
+
"related": "api::page.page:1"
|
|
240
219
|
}
|
|
241
220
|
```
|
|
242
221
|
|
|
@@ -246,11 +225,7 @@ Posts a Comment related to specified instance of Content Type like for example `
|
|
|
246
225
|
"authorUser": 1, // id of a author user. Optional in case of 'enableUsers: true' in the plugin configuration
|
|
247
226
|
"content": "My sample response",
|
|
248
227
|
"threadOf": 2, // id of comment we would like to start / continue the thread (Optional)
|
|
249
|
-
"related":
|
|
250
|
-
"refId": 1,
|
|
251
|
-
"ref": "article",
|
|
252
|
-
"field": "comments"
|
|
253
|
-
}]
|
|
228
|
+
"related": "api::page.page:1"
|
|
254
229
|
}
|
|
255
230
|
```
|
|
256
231
|
|
|
@@ -268,20 +243,20 @@ Posts a Comment related to specified instance of Content Type like for example `
|
|
|
268
243
|
|
|
269
244
|
### Update Comment
|
|
270
245
|
|
|
271
|
-
`PUT <host>/comments
|
|
246
|
+
`PUT <host>/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>`
|
|
272
247
|
|
|
273
|
-
Updates a specified Comment content based on it `commentId` and related to specified instance of Content Type like for example `
|
|
248
|
+
Updates a specified Comment content based on it `commentId` and related to specified instance of Content Type like for example `Page` with `ID: 1`
|
|
274
249
|
|
|
275
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
250
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/comment/2`
|
|
276
251
|
|
|
277
252
|
**Example request body**
|
|
278
253
|
|
|
279
254
|
*Generic (non Strapi User)*
|
|
280
255
|
```
|
|
281
256
|
{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
257
|
+
"author": {
|
|
258
|
+
"id": "<any ID like value>"
|
|
259
|
+
},
|
|
285
260
|
"content": "My sample response"
|
|
286
261
|
}
|
|
287
262
|
```
|
|
@@ -307,33 +282,34 @@ Updates a specified Comment content based on it `commentId` and related to speci
|
|
|
307
282
|
- `400` - Bad Request. Missing field values or bad words check fails. Error message will provide relevant reason.
|
|
308
283
|
- `409` - Conflict. Occurs when trying to update a non existing or not own comment. Possible cause might be that `authorId` or `authorUser` mismatch with existing comment.
|
|
309
284
|
|
|
310
|
-
###
|
|
285
|
+
### Delete Comment
|
|
311
286
|
|
|
312
|
-
`
|
|
287
|
+
`DELETE <host>/comments/api::<collection name>.<content type name>:<entity id>/<commentId>?authorId=<authorId>`
|
|
313
288
|
|
|
314
|
-
|
|
289
|
+
Deletes a specified Comment based on it `commentId` and related to specified instance of Content Type like for example `Page` with `ID: 1`.
|
|
315
290
|
|
|
316
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
291
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/comment/1?authorId=1`
|
|
317
292
|
|
|
318
293
|
**Example response body**
|
|
319
294
|
|
|
320
295
|
```
|
|
321
296
|
{
|
|
322
|
-
--
|
|
297
|
+
-- Empty Response ---
|
|
323
298
|
}
|
|
324
299
|
```
|
|
325
300
|
|
|
326
301
|
**Possible response codes**
|
|
327
|
-
- `200` - Successful
|
|
328
|
-
- `409` - Conflict. Occurs when trying to
|
|
302
|
+
- `200` - Successful with blank Response.
|
|
303
|
+
- `409` - Conflict. Occurs when trying to delete a non existing comment.
|
|
304
|
+
|
|
329
305
|
|
|
330
306
|
### Report abuse in the Comment
|
|
331
307
|
|
|
332
|
-
`POST <host>/comments
|
|
308
|
+
`POST <host>/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>/report-abuse`
|
|
333
309
|
|
|
334
|
-
Reports abuse in specified Comment content based on it `commentId` and related to specified instance of Content Type like for example `
|
|
310
|
+
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.
|
|
335
311
|
|
|
336
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
312
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/comment/2/report-abuse`
|
|
337
313
|
|
|
338
314
|
**Example request body**
|
|
339
315
|
|
|
@@ -370,10 +346,10 @@ Feel free to fork and make a Pull Request to this plugin project. All the input
|
|
|
370
346
|
|
|
371
347
|
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:
|
|
372
348
|
|
|
373
|
-
- [
|
|
349
|
+
- [Discord](https://discord.strapi.io/) We're present on official Strapi Discord workspace. Look for @cyp3r and DM.
|
|
374
350
|
- [Slack - VirtusLab Open Source](https://virtuslab-oss.slack.com) We're present on a public channel #strapi-molecules
|
|
375
|
-
- [GitHub](https://github.com/VirtusLab/strapi-plugin-comments/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
351
|
+
- [GitHub](https://github.com/VirtusLab-Open-Source/strapi-plugin-comments/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
376
352
|
|
|
377
353
|
## License
|
|
378
354
|
|
|
379
|
-
[MIT License](LICENSE.md) Copyright (c)
|
|
355
|
+
[MIT License](LICENSE.md) Copyright (c) [VirtusLab Sp. z o.o.](https://virtuslab.com/) & [Strapi Solutions](https://strapi.io/).
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Entity Details
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { Button } from '@strapi/design-system/Button';
|
|
10
|
+
import { Dialog, DialogBody, DialogFooter } from '@strapi/design-system/Dialog';
|
|
11
|
+
import { Flex } from '@strapi/design-system/Flex';
|
|
12
|
+
import { Stack } from '@strapi/design-system/Stack';
|
|
13
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
14
|
+
import { ExclamationMarkCircle, Check } from '@strapi/icons';
|
|
15
|
+
import { getMessage } from '../../utils';
|
|
16
|
+
|
|
17
|
+
const ConfirmationDialog = ({
|
|
18
|
+
isVisible = false,
|
|
19
|
+
isActionAsync = false,
|
|
20
|
+
children,
|
|
21
|
+
onConfirm,
|
|
22
|
+
onCancel,
|
|
23
|
+
header,
|
|
24
|
+
labelCancel,
|
|
25
|
+
labelConfirm,
|
|
26
|
+
iconConfirm
|
|
27
|
+
}) => (
|
|
28
|
+
<Dialog onClose={onCancel} title={header || getMessage('compontents.confirmation.dialog.header', 'Confirmation')} isOpen={isVisible}>
|
|
29
|
+
<DialogBody icon={<ExclamationMarkCircle />}>
|
|
30
|
+
<Stack size={2}>
|
|
31
|
+
<Flex justifyContent="center">
|
|
32
|
+
<Typography id="dialog-confirm-description">{children || getMessage('compontents.confirmation.dialog.description') }</Typography>
|
|
33
|
+
</Flex>
|
|
34
|
+
</Stack>
|
|
35
|
+
</DialogBody>
|
|
36
|
+
<DialogFooter startAction={<Button onClick={onCancel} variant="tertiary" disabled={isActionAsync}>
|
|
37
|
+
{ labelCancel || getMessage('compontents.confirmation.dialog.button.cancel', 'Cancel') }
|
|
38
|
+
</Button>} endAction={<Button onClick={onConfirm} variant="danger-light" startIcon={iconConfirm || <Check />} disabled={isActionAsync}>
|
|
39
|
+
{ labelConfirm || getMessage('compontents.confirmation.dialog.button.confirm', 'Confirm') }
|
|
40
|
+
</Button>} />
|
|
41
|
+
</Dialog>
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
ConfirmationDialog.propTypes = {
|
|
45
|
+
isVisible: PropTypes.bool,
|
|
46
|
+
isActionAsync: PropTypes.bool,
|
|
47
|
+
children: PropTypes.array.isRequired,
|
|
48
|
+
header: PropTypes.string,
|
|
49
|
+
labelCancel: PropTypes.string,
|
|
50
|
+
labelConfirm: PropTypes.string,
|
|
51
|
+
iconConfirm: PropTypes.object,
|
|
52
|
+
onConfirm: PropTypes.func.isRequired,
|
|
53
|
+
onCancel: PropTypes.func.isRequired,
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export default ConfirmationDialog;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Entity Details
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { isNil } from 'lodash';
|
|
10
|
+
import { Box } from '@strapi/design-system/Box';
|
|
11
|
+
import { Status } from '@strapi/design-system/Status';
|
|
12
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
13
|
+
import { getMessage } from '../../utils';
|
|
14
|
+
|
|
15
|
+
const DiscussionStatus = ({ blocked, blockedThread }) => {
|
|
16
|
+
let variant = 'success';
|
|
17
|
+
|
|
18
|
+
return (
|
|
19
|
+
<Box styles={{ marginBottom: 10 }}>
|
|
20
|
+
<Status variant={variant}>
|
|
21
|
+
<Typography>
|
|
22
|
+
{ getMessage('page.details.panel.status', 'Discussion is') } <Typography fontWeight="bold">{ getMessage('page.details.panel.open', 'OPEN') } </Typography>
|
|
23
|
+
</Typography>
|
|
24
|
+
</Status>
|
|
25
|
+
</Box>);
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
DiscussionStatus.propTypes = {
|
|
29
|
+
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
export default DiscussionStatus;
|
|
33
|
+
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Entity Details
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { isNil } from 'lodash';
|
|
10
|
+
import { Box } from '@strapi/design-system/Box';
|
|
11
|
+
import { Divider } from '@strapi/design-system/Divider';
|
|
12
|
+
import { Flex } from '@strapi/design-system/Flex';
|
|
13
|
+
import { Link } from '@strapi/design-system/Link';
|
|
14
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
15
|
+
import { ArrowUp } from '@strapi/icons';
|
|
16
|
+
import DiscussionThreadItem from '../DiscussionThreadItem';
|
|
17
|
+
import { getMessage, getUrl } from '../../utils';
|
|
18
|
+
import LoadingIndicatorOverlay from '../LoadingIndicatorOverlay';
|
|
19
|
+
import { LoadingIndicatorContainer } from '../LoadingIndicatorOverlay/styles';
|
|
20
|
+
|
|
21
|
+
const DiscussionThread = ({ level = [], selected = {}, isReloading }) => {
|
|
22
|
+
const rootThread = selected?.threadOf;
|
|
23
|
+
return (<LoadingIndicatorContainer as={Box} padding={4}>
|
|
24
|
+
{ isReloading && <LoadingIndicatorOverlay />}
|
|
25
|
+
<Flex as={Box} direction="row" justifyContent="space-between">
|
|
26
|
+
<Typography variant="sigma" textColor="neutral600" id="entity-details">
|
|
27
|
+
{ getMessage('page.details.panel.discussion', 'Discussion') }
|
|
28
|
+
</Typography>
|
|
29
|
+
{ rootThread && (<Link to={getUrl(`discover/${rootThread.id}`)} startIcon={<ArrowUp />}>
|
|
30
|
+
{ getMessage('page.details.panel.discussion.nav.back') }
|
|
31
|
+
</Link>) }
|
|
32
|
+
</Flex>
|
|
33
|
+
<Box paddingTop={2} paddingBottom={6}>
|
|
34
|
+
<Divider />
|
|
35
|
+
</Box>
|
|
36
|
+
<Flex as="ul" direction="column" alignItems="flex-start">
|
|
37
|
+
{ rootThread && (<DiscussionThreadItem {...rootThread} isThreadAuthor root />) }
|
|
38
|
+
{ level.map(item => {
|
|
39
|
+
const isSelected = selected.id === item.id;
|
|
40
|
+
const isThreadAuthor = !isNil(selected?.threadOf?.authorId) && (selected?.threadOf?.authorId === item.authorId);
|
|
41
|
+
return (<DiscussionThreadItem
|
|
42
|
+
{...item}
|
|
43
|
+
blockedThread={rootThread?.blockedThread || item.blockedThread}
|
|
44
|
+
isSelected={isSelected}
|
|
45
|
+
isThreadAuthor={isThreadAuthor}
|
|
46
|
+
/>);
|
|
47
|
+
})}
|
|
48
|
+
</Flex>
|
|
49
|
+
</LoadingIndicatorContainer>);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
DiscussionThread.propTypes = {
|
|
53
|
+
level: PropTypes.array.isRequired,
|
|
54
|
+
selected: PropTypes.object.isRequired,
|
|
55
|
+
isReloading: PropTypes.bool,
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
export default DiscussionThread;
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
*
|
|
3
|
+
* Entity Details
|
|
4
|
+
*
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import React from 'react';
|
|
8
|
+
import PropTypes from 'prop-types';
|
|
9
|
+
import { first } from 'lodash';
|
|
10
|
+
import { Avatar, Initials } from '@strapi/design-system/Avatar';
|
|
11
|
+
import { Box } from '@strapi/design-system/Box';
|
|
12
|
+
import { Divider } from '@strapi/design-system/Divider';
|
|
13
|
+
import { Flex } from '@strapi/design-system/Flex';
|
|
14
|
+
import { Link } from '@strapi/design-system/Link';
|
|
15
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
16
|
+
import { ArrowRight } from '@strapi/icons';
|
|
17
|
+
import DiscussionThreadItemMeta from '../DiscussionThreadItemMeta';
|
|
18
|
+
import { AvatarWrapper, DiscussionThreadItemBox, DiscussionThreadItemBoxContent, DiscussionThreadItemContent, DiscussionThreadItemLeft, DiscussionThreadItemLinkBox, DiscussionThreadItemRight, DiscussionThreadItemRoot } from './styles';
|
|
19
|
+
import DiscussionThreadItemActions from '../DiscussionThreadItemActions';
|
|
20
|
+
import { getMessage, getUrl } from '../../utils';
|
|
21
|
+
import DiscussionThreadItemWarnings from '../DiscussionThreadItemWarnings';
|
|
22
|
+
|
|
23
|
+
const DiscussionThreadItem = (item) => {
|
|
24
|
+
const { id, isSelected, isThreadAuthor, content, root, preview, blocked, blockedThread, gotThread, threadFirstItemId, authorUser, authorAvatar, authorName } = item;
|
|
25
|
+
|
|
26
|
+
let background = 'neutral100';
|
|
27
|
+
let borderColor = 'neutral200';
|
|
28
|
+
let dividerColor = 'neutral200';
|
|
29
|
+
let StyledComponent = DiscussionThreadItemRight;
|
|
30
|
+
|
|
31
|
+
if(isThreadAuthor || root){
|
|
32
|
+
StyledComponent = DiscussionThreadItemLeft;
|
|
33
|
+
borderColor = 'neutral100';
|
|
34
|
+
dividerColor = 'neutral100';
|
|
35
|
+
background = null;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (isSelected) {
|
|
39
|
+
background = 'secondary100'
|
|
40
|
+
borderColor = 'secondary500';
|
|
41
|
+
dividerColor = 'secondary200';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
if (root) {
|
|
45
|
+
StyledComponent = DiscussionThreadItemRoot;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const avatar = authorAvatar || authorUser?.avatar;
|
|
49
|
+
const name = authorName || `${authorUser?.firstName} ${authorUser?.lastName}`;
|
|
50
|
+
const isBlocked = blocked || blockedThread;
|
|
51
|
+
|
|
52
|
+
const renderInitials = value => value.split(' ').map(_ => first(_)).join('').toUpperCase();
|
|
53
|
+
|
|
54
|
+
return (<StyledComponent as="li">
|
|
55
|
+
<DiscussionThreadItemContent as={Flex} direction="row">
|
|
56
|
+
<AvatarWrapper>
|
|
57
|
+
{ avatar ? <Avatar src={avatar} alt={name} /> : <Initials>{ renderInitials(name) }</Initials> }
|
|
58
|
+
</AvatarWrapper>
|
|
59
|
+
<DiscussionThreadItemBox hasRadius shadow="filterShadow" borderColor={borderColor} background={background} padding={2}>
|
|
60
|
+
<Flex as={Box} paddingBottom={2} direction="column">
|
|
61
|
+
<DiscussionThreadItemBoxContent as={Flex} direction="row">
|
|
62
|
+
<Box as={Flex} grow={1} alignItems="center">
|
|
63
|
+
<Typography variant="omega">{ content }</Typography>
|
|
64
|
+
</Box>
|
|
65
|
+
{ !preview && (<DiscussionThreadItemActions { ...item } root={root} />) }
|
|
66
|
+
</DiscussionThreadItemBoxContent>
|
|
67
|
+
{ !(preview || isBlocked) && (<DiscussionThreadItemWarnings { ...item } />) }
|
|
68
|
+
</Flex>
|
|
69
|
+
<Divider background={dividerColor} />
|
|
70
|
+
<DiscussionThreadItemMeta { ...item } />
|
|
71
|
+
</DiscussionThreadItemBox>
|
|
72
|
+
</DiscussionThreadItemContent>
|
|
73
|
+
|
|
74
|
+
{ (gotThread && !preview) && (<DiscussionThreadItemLinkBox direction="row" alignItems="flex-end">
|
|
75
|
+
<Link to={getUrl(`discover/${threadFirstItemId}`)} endIcon={<ArrowRight />}>
|
|
76
|
+
{ getMessage('page.details.panel.discussion.nav.drilldown') }
|
|
77
|
+
</Link>
|
|
78
|
+
</DiscussionThreadItemLinkBox>) }
|
|
79
|
+
</StyledComponent>);
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
DiscussionThreadItem.propTypes = {
|
|
83
|
+
content: PropTypes.string.isRequired,
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default DiscussionThreadItem;
|
|
87
|
+
|