strapi-plugin-comments 2.0.3 → 2.0.4

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.
@@ -1,7 +1,6 @@
1
1
  import { useQuery, useMutation, useQueryClient } from 'react-query';
2
- import { fetchConfig, restoreConfig, updateConfig } from '../pages/Settings/utils/api';
2
+ import { fetchConfig, restartStrapi, restoreConfig, updateConfig } from '../pages/Settings/utils/api';
3
3
  import pluginId from '../pluginId';
4
- import { getMessage } from '../utils';
5
4
 
6
5
  const useConfig = (toggleNotification) => {
7
6
  const queryClient = useQueryClient();
@@ -18,8 +17,10 @@ const useConfig = (toggleNotification) => {
18
17
  callback();
19
18
  };
20
19
 
21
- const handleSuccess = (type, callback = () => {}) => {
22
- queryClient.invalidateQueries('get-config');
20
+ const handleSuccess = (type, callback = () => {}, invalidateQueries = true) => {
21
+ if (invalidateQueries) {
22
+ queryClient.invalidateQueries('get-config');
23
+ };
23
24
  toggleNotification({
24
25
  type: 'success',
25
26
  message: `${pluginId}.page.settings.notification.${type}.success`,
@@ -37,7 +38,12 @@ const useConfig = (toggleNotification) => {
37
38
  onError: () => handleError('restore'),
38
39
  });
39
40
 
40
- return { fetch, submitMutation, restoreMutation };
41
+ const restartMutation = useMutation(restartStrapi, {
42
+ onSuccess: () => handleSuccess('restart', () => {}, false),
43
+ onError: () => handleError('restart'),
44
+ });
45
+
46
+ return { fetch, restartMutation, submitMutation, restoreMutation };
41
47
  };
42
48
 
43
49
  export default useConfig;
@@ -0,0 +1,8 @@
1
+ import styled from 'styled-components';
2
+ import { Alert } from '@strapi/design-system/Alert';
3
+
4
+ export const RestartAlert = styled(Alert)`
5
+ [role="status"] {
6
+ flex-direction: column;
7
+ }
8
+ `
@@ -1,7 +1,7 @@
1
1
  import React, { useRef, useMemo, useState } from 'react';
2
2
  import { useQuery } from 'react-query';
3
3
  import { Formik } from 'formik';
4
- import { capitalize, first, orderBy, isEmpty } from 'lodash';
4
+ import { capitalize, first, orderBy, isEmpty, isEqual } from 'lodash';
5
5
  import {
6
6
  CheckPermissions,
7
7
  LoadingIndicatorPage,
@@ -27,13 +27,14 @@ import {
27
27
  CardBody,
28
28
  CardContent,
29
29
  } from '@strapi/design-system/Card';
30
- import { Check, Refresh } from '@strapi/icons';
30
+ import { Check, Refresh, Play } from '@strapi/icons';
31
31
 
32
32
  import pluginPermissions from '../../permissions';
33
33
  import useConfig from '../../hooks/useConfig';
34
34
  import { fetchAllContentTypes, fetchRoles } from './utils/api';
35
35
  import { getMessage, parseRegExp } from '../../utils';
36
36
  import ConfirmationDialog from '../../components/ConfirmationDialog';
37
+ import { RestartAlert } from './components/RestartAlert/styles';
37
38
 
38
39
 
39
40
  const Settings = () => {
@@ -56,8 +57,9 @@ const Settings = () => {
56
57
  } = useRBAC(viewPermissions);
57
58
 
58
59
  const [restoreConfigmationVisible, setRestoreConfigmationVisible] = useState(false);
60
+ const [restartRequired, setRestartRequired] = useState(false);
59
61
 
60
- const { fetch, submitMutation, restoreMutation } = useConfig(toggleNotification);
62
+ const { fetch, restartMutation, submitMutation, restoreMutation } = useConfig(toggleNotification);
61
63
  const { data: configData, isLoading: isConfigLoading, err: configErr } = fetch;
62
64
 
63
65
  const { data: allCollectionsData, isLoading: areCollectionsLoading, err: collectionsErr } = useQuery(
@@ -131,7 +133,13 @@ const Settings = () => {
131
133
  const handleUpdateConfiguration = async (form) => {
132
134
  if (canChange) {
133
135
  lockApp();
134
- await submitMutation.mutateAsync(preparePayload(form));
136
+ const payload = preparePayload(form);
137
+ await submitMutation.mutateAsync(payload);
138
+ const enabledCollectionsChanged = !isEqual(payload.enabledCollections, configData?.enabledCollections);
139
+ const gqlAuthChanged = !isEqual(payload.gql?.auth, configData?.gql?.auth);
140
+ if (enabledCollectionsChanged || gqlAuthChanged) {
141
+ setRestartRequired(true);
142
+ }
135
143
  unlockApp();
136
144
  }
137
145
  };
@@ -142,11 +150,22 @@ const Settings = () => {
142
150
  lockApp();
143
151
  await restoreMutation.mutateAsync();
144
152
  unlockApp();
153
+ setRestartRequired(true);
145
154
  setRestoreConfigmationVisible(false);
146
155
  }
147
156
  };
148
157
  const handleRestoreCancel = () => setRestoreConfigmationVisible(false);
149
158
 
159
+ const handleRestart = async () => {
160
+ if (canChange) {
161
+ lockApp();
162
+ await restartMutation.mutateAsync();
163
+ setRestartRequired(false);
164
+ unlockApp();
165
+ }
166
+ };
167
+ const handleRestartDiscard = () => setRestartRequired(false);
168
+
150
169
  const boxDefaultProps = {
151
170
  background: "neutral0",
152
171
  hasRadius: true,
@@ -175,7 +194,7 @@ const Settings = () => {
175
194
  subtitle={getMessage('page.settings.header.description')}
176
195
  primaryAction={
177
196
  <CheckPermissions permissions={pluginPermissions.settingsChange}>
178
- <Button type="submit" startIcon={<Check />} >
197
+ <Button type="submit" startIcon={<Check />} disabled={restartRequired} >
179
198
  {getMessage('page.settings.actions.submit')}
180
199
  </Button>
181
200
  </CheckPermissions>
@@ -183,6 +202,15 @@ const Settings = () => {
183
202
  />
184
203
  <ContentLayout>
185
204
  <Stack size={6}>
205
+ { restartRequired && (
206
+ <RestartAlert
207
+ closeLabel={getMessage('page.settings.actions.restart.alert.cancel')}
208
+ title={getMessage('page.settings.actions.restart.alert.title')}
209
+ action={<Box><Button onClick={handleRestart} startIcon={<Play />}>{getMessage('page.settings.actions.restart')}</Button></Box>}
210
+ onClose={handleRestartDiscard}>
211
+ { getMessage('page.settings.actions.restart.alert.description')}
212
+ </RestartAlert>)}
213
+
186
214
  <Box {...boxDefaultProps}>
187
215
  <Stack size={4}>
188
216
  <Typography variant="delta" as="h2">
@@ -198,6 +226,7 @@ const Settings = () => {
198
226
  onClear={() => setFieldValue('enabledCollections', [], false)}
199
227
  value={values.enabledCollections}
200
228
  onChange={(value) => setFieldValue('enabledCollections', value, false)}
229
+ disabled={restartRequired}
201
230
  multi
202
231
  withTags
203
232
  >
@@ -214,6 +243,7 @@ const Settings = () => {
214
243
  onClear={() => setFieldValue('moderatorRoles', [], false)}
215
244
  value={values.moderatorRoles}
216
245
  onChange={(value) => setFieldValue('moderatorRoles', value, false)}
246
+ disabled={restartRequired}
217
247
  multi
218
248
  withTags
219
249
  >
@@ -230,6 +260,7 @@ const Settings = () => {
230
260
  onChange={({ target: { checked } }) => setFieldValue('badWords', checked, false)}
231
261
  onLabel={getMessage('compontents.toogle.enabled')}
232
262
  offLabel={getMessage('compontents.toogle.disabled')}
263
+ disabled={restartRequired}
233
264
  />
234
265
  </GridItem>
235
266
  { isGQLPluginEnabled && (<GridItem col={6} xs={12}>
@@ -241,6 +272,7 @@ const Settings = () => {
241
272
  onChange={({ target: { checked } }) => setFieldValue('gqlAuthEnabled', checked, false)}
242
273
  onLabel={getMessage('compontents.toogle.enabled')}
243
274
  offLabel={getMessage('compontents.toogle.disabled')}
275
+ disabled={restartRequired}
244
276
  />
245
277
  </GridItem>) }
246
278
  </Grid>
@@ -272,6 +304,7 @@ const Settings = () => {
272
304
  onChange={({ target: { checked } }) => setFieldValue('approvalFlow', changeApprovalFlowFor(uid, values.approvalFlow, checked), [])}
273
305
  onLabel={getMessage('compontents.toogle.enabled')}
274
306
  offLabel={getMessage('compontents.toogle.disabled')}
307
+ disabled={restartRequired}
275
308
  />
276
309
  { !isEmpty(stringAttributes) && (<Select
277
310
  name={`collectionSettings-${uid}-entryLabel`}
@@ -283,6 +316,7 @@ const Settings = () => {
283
316
  onChange={(value) => setFieldValue('entryLabel', changeEntryLabelFor(uid, values.entryLabel, value))}
284
317
  multi
285
318
  withTags
319
+ disabled={restartRequired}
286
320
  >
287
321
  { stringAttributes.map(key =>
288
322
  (<Option key={`collectionSettings-${uid}-entryLabel-${key}`} value={key}>{ capitalize(key.split('_').join(' ')) }</Option>))}
@@ -7,7 +7,7 @@ export const fetchConfig = async (toggleNotification) => {
7
7
 
8
8
  return data;
9
9
  } catch (err) {
10
- handleAPIError(err, toggleNotification);
10
+ handleAPIError(err, toggleNotification, 'page.settings.notification.fetch.error');
11
11
  }
12
12
  };
13
13
 
@@ -43,6 +43,16 @@ export const fetchAllContentTypes = async (toggleNotification) => {
43
43
  export const fetchRoles = async (toggleNotification) => {
44
44
  try {
45
45
  const { data } = await axiosInstance.get(`/admin/roles`);
46
+ return data;
47
+ } catch (err) {
48
+ handleAPIError(err, toggleNotification);
49
+ }
50
+ };
51
+
52
+ export const restartStrapi = async (toggleNotification) => {
53
+ try {
54
+ const { data } = await axiosInstance.get(getApiURL(`settings/restart`));
55
+
46
56
  return data;
47
57
  } catch (err) {
48
58
  handleAPIError(err, toggleNotification);
@@ -86,6 +86,7 @@
86
86
  "page.settings.header.description": "Configure your comments moderation capabilities",
87
87
  "page.settings.actions.submit": "Save",
88
88
  "page.settings.actions.restore": "Restore",
89
+ "page.settings.actions.restart": "Restart Strapi",
89
90
  "page.settings.section.general": "General configuration",
90
91
  "page.settings.section.collections": "Collection(s) configuration",
91
92
  "page.settings.section.restore": "Restore default configuration",
@@ -108,10 +109,16 @@
108
109
  "page.settings.actions.restore.confirmation.header": "Restore default configuration",
109
110
  "page.settings.actions.restore.confirmation.description": "You're about to restore plugin configuration to it default values. It might have destructive impact on already collected content. Do you really want to proceed?",
110
111
  "page.settings.actions.restore.confirmation.button.confirm": "Yes, I want to restore",
112
+ "page.settings.actions.restart.alert.title": "Strapi requires restart",
113
+ "page.settings.actions.restart.alert.description": "You've made a configuration changes which requires your Strapi application to be restarted to take an effect in GraphQL schema. Do it manually or by using below trigger.",
114
+ "page.settings.actions.restart.alert.close": "Discard",
115
+ "page.settings.notification.fetch.error": "Failed to fetch configuration. Retrying...",
111
116
  "page.settings.notification.submit.success": "Configuration has been saved successfully",
112
117
  "page.settings.notification.submit.error": "Failed to save configuration. Try again.",
113
118
  "page.settings.notification.restore.success": "Configuration has been restored successfully",
114
119
  "page.settings.notification.restore.error": "Failed to restore configuration. Try again.",
120
+ "page.settings.notification.restart.success": "Application has been restarted successfully",
121
+ "page.settings.notification.restart.error": "Failed to restart your application. Try to do it manually.",
115
122
  "page.settings.loading": "Fetching configuration...",
116
123
  "compontents.confirmation.dialog.header": "Confirmation",
117
124
  "compontents.confirmation.dialog.description": "Do you really want to perform this action?",
@@ -1,8 +1,9 @@
1
+ import pluginId from "../pluginId";
1
2
 
2
- const handleAPIError = (err = null, toggleNotification = null) => {
3
+ const handleAPIError = (err = null, toggleNotification = null, message = 'app.components.notification.error') => {
3
4
  toggleNotification({
4
5
  type: 'warning',
5
- message: 'app.components.notification.error',
6
+ message: `${pluginId}.${message}`,
6
7
  });
7
8
 
8
9
  if (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-comments",
3
- "version": "2.0.3",
3
+ "version": "2.0.4",
4
4
  "description": "Strapi - Comments plugin",
5
5
  "strapi": {
6
6
  "name": "comments",
@@ -10,7 +10,7 @@
10
10
  },
11
11
  "scripts": {
12
12
  "prepare": "husky install",
13
- "publish": "npm publish --tag latest",
13
+ "publish:latest": "npm publish --tag latest",
14
14
  "test:unit": "jest --verbose --coverage"
15
15
  },
16
16
  "repository": {
@@ -43,6 +43,15 @@ module.exports = {
43
43
  }
44
44
  },
45
45
 
46
+ async settingsRestart(ctx) {
47
+ try {
48
+ await this.getService().restart();
49
+ return ctx.send({ status: 200 });
50
+ } catch (e) {
51
+ throwError(ctx, e);
52
+ }
53
+ },
54
+
46
55
  async findAll(ctx) {
47
56
  return this.getService()
48
57
  .findAll(ctx.query);
@@ -113,4 +113,12 @@ module.exports = [
113
113
  policies: [],
114
114
  },
115
115
  },
116
+ {
117
+ method: 'GET',
118
+ path: '/settings/restart',
119
+ handler: 'admin.settingsRestart',
120
+ config: {
121
+ policies: [],
122
+ },
123
+ },
116
124
  ];
@@ -75,19 +75,16 @@ const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
75
75
 
76
76
  async restoreConfig() {
77
77
  const pluginStore = await this.getCommonService().getPluginStore();
78
- const defaultConfig = this.getCommonService().getLocalConfig();
79
-
78
+
80
79
  await pluginStore.delete({key: 'config'})
81
- await pluginStore.set({
82
- key: 'config',
83
- value: {
84
- ...defaultConfig,
85
- }
86
- });
87
80
 
88
81
  return this.config();
89
82
  },
90
83
 
84
+ async restart() {
85
+ setImmediate(() => strapi.reload());
86
+ },
87
+
91
88
  // Find all comments
92
89
  async findAll({ related, entity, ...query }) {
93
90
  const { _q, orderBy, pageSize = 10, page = 1, filters, ...rest } = parseParams(query);
@@ -38,7 +38,8 @@ module.exports = ({ strapi }) => ({
38
38
  throw new PluginError(400, `Relation for field "related" does not exist. Check your payload please.`);
39
39
  }
40
40
 
41
- const isApprovalFlowEnabled = await this.getCommonService().getConfig(CONFIG_PARAMS.APPROVAL_FLOW, []).includes(uid) ||
41
+ const approvalFlow = await this.getCommonService().getConfig(CONFIG_PARAMS.APPROVAL_FLOW, []);
42
+ const isApprovalFlowEnabled = approvalFlow.includes(uid) ||
42
43
  relatedEntity.requireCommentsApproval;
43
44
 
44
45
  const linkToThread = !isNil(threadOf) ? await this.getCommonService().findOne({
@@ -26,7 +26,7 @@ module.exports = ({ strapi }) => ({
26
26
 
27
27
  let result;
28
28
  if (config && !useLocal) {
29
- result = queryProp ? get(config, queryProp) : config;;
29
+ result = queryProp ? get(config, queryProp, defaultValue) : config;
30
30
  } else {
31
31
  result = this.getLocalConfig(queryProp, defaultValue);
32
32
  }