strapi-plugin-comments 1.0.2 → 2.0.0-beta.3
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 +70 -109
- 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 +59 -0
- package/admin/src/components/DiscussionThreadItem/index.js +87 -0
- package/admin/src/components/DiscussionThreadItem/styles.js +88 -0
- package/admin/src/components/DiscussionThreadItemActions/index.js +178 -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 +141 -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 +43 -0
- package/admin/src/components/ReportsReviewTable/index.js +146 -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/components/icons/index.js +6 -0
- package/admin/src/components/icons/lock.js +22 -0
- package/admin/src/components/icons/review.js +18 -0
- package/admin/src/components/icons/unlock.js +20 -0
- package/admin/src/index.js +58 -42
- package/admin/src/pages/App/index.js +71 -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 +26 -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 +12 -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/components/DiscoverTableRow/index.js +196 -0
- package/admin/src/pages/Discover/index.js +157 -0
- package/admin/src/pages/Discover/utils/api.js +14 -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 +73 -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 +21 -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 +117 -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 +215 -0
- package/server/services/client.js +227 -0
- package/server/services/common.js +197 -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,63 @@ 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
|
-
comments: {
|
|
102
|
-
enableUsers: true,
|
|
76
|
+
comments: {
|
|
103
77
|
badWords: false,
|
|
104
|
-
|
|
78
|
+
moderatorRoles: ["Authenticated"],
|
|
79
|
+
entryLabel: {
|
|
80
|
+
'*': ['Title', 'title', 'Name', 'name', 'Subject', 'subject'],
|
|
81
|
+
'api::page.page': ['MyField'],
|
|
82
|
+
},
|
|
105
83
|
},
|
|
106
84
|
...
|
|
107
85
|
```
|
|
108
86
|
|
|
109
87
|
### Properties
|
|
110
|
-
- `
|
|
111
|
-
- `
|
|
88
|
+
- `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`.
|
|
89
|
+
- `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.
|
|
90
|
+
- `entryLabel` - ordered list of property names per Content Type to generate related entity label. Default set as `*`.
|
|
91
|
+
|
|
92
|
+
## Additional GQL Configuration
|
|
93
|
+
|
|
94
|
+
> To be done
|
|
112
95
|
|
|
113
96
|
## Public API Comment model
|
|
114
97
|
|
|
115
98
|
### Generic (non Strapi User)
|
|
116
|
-
```
|
|
99
|
+
```json
|
|
117
100
|
{
|
|
118
101
|
"id": 1,
|
|
119
102
|
"content": "My comment content",
|
|
120
103
|
"blocked": null,
|
|
121
104
|
"blockedThread": true,
|
|
122
105
|
"blockReason": null,
|
|
123
|
-
"points": 1,
|
|
124
106
|
"authorUser": null,
|
|
125
107
|
"authorId": "207ccfdc-94ba-45eb-979c-790f6f49c392",
|
|
126
108
|
"authorName": "Joe Doe",
|
|
127
109
|
"authorEmail": "jdoe@sample.com",
|
|
128
110
|
"authorAvatar": null,
|
|
129
|
-
"
|
|
130
|
-
"
|
|
111
|
+
"createdAt": "2020-07-14T20:13:01.649Z",
|
|
112
|
+
"updatedAt": "2020-07-14T20:13:01.670Z",
|
|
113
|
+
"related": {}, // Related content type entity
|
|
114
|
+
"reports": [] // Reports issued against this comment
|
|
131
115
|
}
|
|
132
116
|
```
|
|
133
117
|
### Strapi User
|
|
134
|
-
```
|
|
118
|
+
```json
|
|
135
119
|
{
|
|
136
120
|
"id": 1,
|
|
137
121
|
"content": "My comment content",
|
|
138
122
|
"blocked": true,
|
|
139
123
|
"blockedThread": null,
|
|
140
124
|
"blockReason": null,
|
|
141
|
-
"points": null,
|
|
142
125
|
"authorUser": {
|
|
143
126
|
"id": 1,
|
|
144
127
|
"username": "Sample User",
|
|
@@ -154,8 +137,10 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
154
137
|
"authorName": null,
|
|
155
138
|
"authorEmail": null,
|
|
156
139
|
"authorAvatar": null,
|
|
157
|
-
"
|
|
158
|
-
"
|
|
140
|
+
"createdAt": "2020-07-14T20:13:01.649Z",
|
|
141
|
+
"updatedAt": "2020-07-14T20:13:01.670Z",
|
|
142
|
+
"related": {}, // Related content type entity
|
|
143
|
+
"reports": [] // Reports issued against this comment
|
|
159
144
|
}
|
|
160
145
|
|
|
161
146
|
```
|
|
@@ -164,11 +149,11 @@ To setup amend default plugin configuration we recommend to put following snippe
|
|
|
164
149
|
|
|
165
150
|
### Get Comments
|
|
166
151
|
|
|
167
|
-
`GET <host>/comments
|
|
152
|
+
`GET <host>/comments/api::<collection name>.<content type name>:<entity id>`
|
|
168
153
|
|
|
169
|
-
Return a hierarchical tree structure of comments for specified instance of Content Type like for example `
|
|
154
|
+
Return a hierarchical tree structure of comments for specified instance of Content Type like for example `Page` with `ID: 1`
|
|
170
155
|
|
|
171
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
156
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1`
|
|
172
157
|
|
|
173
158
|
**Example response body**
|
|
174
159
|
|
|
@@ -190,11 +175,11 @@ Return a hierarchical tree structure of comments for specified instance of Conte
|
|
|
190
175
|
|
|
191
176
|
### Get Comments (flat structure)
|
|
192
177
|
|
|
193
|
-
`GET <host>/comments
|
|
178
|
+
`GET <host>/comments/api::<collection name>.<content type name>:<entity id>/flat`
|
|
194
179
|
|
|
195
|
-
Return a flat structure of comments for specified instance of Content Type like for example `
|
|
180
|
+
Return a flat structure of comments for specified instance of Content Type like for example `Page` with `ID: 1`
|
|
196
181
|
|
|
197
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
182
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/flat`
|
|
198
183
|
|
|
199
184
|
**Example response body**
|
|
200
185
|
|
|
@@ -216,27 +201,26 @@ Return a flat structure of comments for specified instance of Content Type like
|
|
|
216
201
|
|
|
217
202
|
### Post a Comment
|
|
218
203
|
|
|
219
|
-
`POST <host>/comments
|
|
204
|
+
`POST <host>/comments/api::<collection name>.<content type name>:<entity id>`
|
|
220
205
|
|
|
221
|
-
Posts a Comment related to specified instance of Content Type like for example `
|
|
206
|
+
Posts a Comment related to specified instance of Content Type like for example `Page` with `ID: 1`
|
|
222
207
|
|
|
223
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
208
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1`
|
|
224
209
|
|
|
225
210
|
**Example request body**
|
|
226
211
|
|
|
227
212
|
*Generic (non Strapi User)*
|
|
228
213
|
```
|
|
229
214
|
{
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
215
|
+
"author": {
|
|
216
|
+
"id": "<any ID like value>",
|
|
217
|
+
"name": "Joe Doe",
|
|
218
|
+
"email": "jdoe@sample.com",
|
|
219
|
+
"avatar": "<any image url>"
|
|
220
|
+
},
|
|
233
221
|
"content": "My sample response",
|
|
234
222
|
"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
|
-
}]
|
|
223
|
+
"related": "api::page.page:1"
|
|
240
224
|
}
|
|
241
225
|
```
|
|
242
226
|
|
|
@@ -246,11 +230,7 @@ Posts a Comment related to specified instance of Content Type like for example `
|
|
|
246
230
|
"authorUser": 1, // id of a author user. Optional in case of 'enableUsers: true' in the plugin configuration
|
|
247
231
|
"content": "My sample response",
|
|
248
232
|
"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
|
-
}]
|
|
233
|
+
"related": "api::page.page:1"
|
|
254
234
|
}
|
|
255
235
|
```
|
|
256
236
|
|
|
@@ -268,20 +248,20 @@ Posts a Comment related to specified instance of Content Type like for example `
|
|
|
268
248
|
|
|
269
249
|
### Update Comment
|
|
270
250
|
|
|
271
|
-
`PUT <host>/comments
|
|
251
|
+
`PUT <host>/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>`
|
|
272
252
|
|
|
273
|
-
Updates a specified Comment content based on it `commentId` and related to specified instance of Content Type like for example `
|
|
253
|
+
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
254
|
|
|
275
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
255
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/comment/2`
|
|
276
256
|
|
|
277
257
|
**Example request body**
|
|
278
258
|
|
|
279
259
|
*Generic (non Strapi User)*
|
|
280
260
|
```
|
|
281
261
|
{
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
262
|
+
"author": {
|
|
263
|
+
"id": "<any ID like value>"
|
|
264
|
+
},
|
|
285
265
|
"content": "My sample response"
|
|
286
266
|
}
|
|
287
267
|
```
|
|
@@ -309,11 +289,11 @@ Updates a specified Comment content based on it `commentId` and related to speci
|
|
|
309
289
|
|
|
310
290
|
### Delete Comment
|
|
311
291
|
|
|
312
|
-
`DELETE <host>/comments
|
|
292
|
+
`DELETE <host>/comments/api::<collection name>.<content type name>:<entity id>/<commentId>?authorId=<authorId>`
|
|
313
293
|
|
|
314
|
-
Deletes a specified Comment based on it `commentId` and related to specified instance of Content Type like for example `
|
|
294
|
+
Deletes a specified Comment based on it `commentId` and related to specified instance of Content Type like for example `Page` with `ID: 1`.
|
|
315
295
|
|
|
316
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
296
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/comment/1?authorId=1`
|
|
317
297
|
|
|
318
298
|
**Example response body**
|
|
319
299
|
|
|
@@ -327,33 +307,14 @@ Deletes a specified Comment based on it `commentId` and related to specified ins
|
|
|
327
307
|
- `200` - Successful with blank Response.
|
|
328
308
|
- `409` - Conflict. Occurs when trying to delete a non existing comment.
|
|
329
309
|
|
|
330
|
-
### Like Comment
|
|
331
|
-
|
|
332
|
-
`PATCH <host>/comments/<content-type>:<id>/comment/<commentId>/like`
|
|
333
|
-
|
|
334
|
-
Likes a specified Comment based on it `commentId` and related to specified instance of Content Type like for example `Article` with `ID: 1`.
|
|
335
|
-
|
|
336
|
-
**Example URL**: `https://localhost:1337/comments/article:1/comment/2/like`
|
|
337
|
-
|
|
338
|
-
**Example response body**
|
|
339
|
-
|
|
340
|
-
```
|
|
341
|
-
{
|
|
342
|
-
-- Comment Model fields ---
|
|
343
|
-
}
|
|
344
|
-
```
|
|
345
|
-
|
|
346
|
-
**Possible response codes**
|
|
347
|
-
- `200` - Successful. Response with liked Comment Model.
|
|
348
|
-
- `409` - Conflict. Occurs when trying to like a non existing comment.
|
|
349
310
|
|
|
350
311
|
### Report abuse in the Comment
|
|
351
312
|
|
|
352
|
-
`POST <host>/comments
|
|
313
|
+
`POST <host>/comments/api::<collection name>.<content type name>:<entity id>/comment/<commentId>/report-abuse`
|
|
353
314
|
|
|
354
|
-
Reports abuse in specified Comment content based on it `commentId` and related to specified instance of Content Type like for example `
|
|
315
|
+
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.
|
|
355
316
|
|
|
356
|
-
**Example URL**: `https://localhost:1337/comments/
|
|
317
|
+
**Example URL**: `https://localhost:1337/comments/api::page.page:1/comment/2/report-abuse`
|
|
357
318
|
|
|
358
319
|
**Example request body**
|
|
359
320
|
|
|
@@ -390,10 +351,10 @@ Feel free to fork and make a Pull Request to this plugin project. All the input
|
|
|
390
351
|
|
|
391
352
|
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:
|
|
392
353
|
|
|
393
|
-
- [
|
|
354
|
+
- [Discord](https://discord.strapi.io/) We're present on official Strapi Discord workspace. Look for @cyp3r and DM.
|
|
394
355
|
- [Slack - VirtusLab Open Source](https://virtuslab-oss.slack.com) We're present on a public channel #strapi-molecules
|
|
395
|
-
- [GitHub](https://github.com/VirtusLab/strapi-plugin-comments/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
356
|
+
- [GitHub](https://github.com/VirtusLab-Open-Source/strapi-plugin-comments/issues) (Bug reports, Contributions, Questions and Discussions)
|
|
396
357
|
|
|
397
358
|
## License
|
|
398
359
|
|
|
399
|
-
[MIT License](LICENSE.md) Copyright (c)
|
|
360
|
+
[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,59 @@
|
|
|
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 pinned />) }
|
|
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
|
+
root={isNil(rootThread)}
|
|
44
|
+
blockedThread={rootThread?.blockedThread || item.blockedThread}
|
|
45
|
+
isSelected={isSelected}
|
|
46
|
+
isThreadAuthor={isThreadAuthor}
|
|
47
|
+
/>);
|
|
48
|
+
})}
|
|
49
|
+
</Flex>
|
|
50
|
+
</LoadingIndicatorContainer>);
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
DiscussionThread.propTypes = {
|
|
54
|
+
level: PropTypes.array.isRequired,
|
|
55
|
+
selected: PropTypes.object.isRequired,
|
|
56
|
+
isReloading: PropTypes.bool,
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
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, pinned, 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 || pinned} />) }
|
|
66
|
+
</DiscussionThreadItemBoxContent>
|
|
67
|
+
{ !(preview || isBlocked) && (<DiscussionThreadItemWarnings { ...item } gotThread={gotThread || root} />) }
|
|
68
|
+
</Flex>
|
|
69
|
+
<Divider background={dividerColor} />
|
|
70
|
+
<DiscussionThreadItemMeta { ...item } />
|
|
71
|
+
</DiscussionThreadItemBox>
|
|
72
|
+
</DiscussionThreadItemContent>
|
|
73
|
+
|
|
74
|
+
{ (gotThread && !(preview || pinned)) && (<DiscussionThreadItemLinkBox direction="column" 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
|
+
|