diff --git a/admin/src/hooks/useConfig.js b/admin/src/hooks/useConfig.js
index 626f17d..4731bbf 100644
--- a/admin/src/hooks/useConfig.js
+++ b/admin/src/hooks/useConfig.js
@@ -1,7 +1,6 @@
import { useQuery, useMutation, useQueryClient } from 'react-query';
-import { fetchConfig, restoreConfig, updateConfig } from '../pages/Settings/utils/api';
+import { fetchConfig, restartStrapi, restoreConfig, updateConfig } from '../pages/Settings/utils/api';
import pluginId from '../pluginId';
-import { getMessage } from '../utils';
const useConfig = (toggleNotification) => {
const queryClient = useQueryClient();
@@ -18,8 +17,10 @@ const useConfig = (toggleNotification) => {
callback();
};
- const handleSuccess = (type, callback = () => {}) => {
- queryClient.invalidateQueries('get-config');
+ const handleSuccess = (type, callback = () => {}, invalidateQueries = true) => {
+ if (invalidateQueries) {
+ queryClient.invalidateQueries('get-config');
+ };
toggleNotification({
type: 'success',
message: `${pluginId}.page.settings.notification.${type}.success`,
@@ -37,7 +38,12 @@ const useConfig = (toggleNotification) => {
onError: () => handleError('restore'),
});
- return { fetch, submitMutation, restoreMutation };
+ const restartMutation = useMutation(restartStrapi, {
+ onSuccess: () => handleSuccess('restart', () => {}, false),
+ onError: () => handleError('restart'),
+ });
+
+ return { fetch, restartMutation, submitMutation, restoreMutation };
};
export default useConfig;
diff --git a/admin/src/pages/Settings/components/RestartAlert/styles.js b/admin/src/pages/Settings/components/RestartAlert/styles.js
new file mode 100644
index 0000000..3ef8890
--- /dev/null
+++ b/admin/src/pages/Settings/components/RestartAlert/styles.js
@@ -0,0 +1,8 @@
+import styled from 'styled-components';
+import { Alert } from '@strapi/design-system/Alert';
+
+export const RestartAlert = styled(Alert)`
+ [role="status"] {
+ flex-direction: column;
+ }
+`
diff --git a/admin/src/pages/Settings/index.js b/admin/src/pages/Settings/index.js
index 156742a..0a1f0ee 100644
--- a/admin/src/pages/Settings/index.js
+++ b/admin/src/pages/Settings/index.js
@@ -1,7 +1,7 @@
import React, { useRef, useMemo, useState } from 'react';
import { useQuery } from 'react-query';
import { Formik } from 'formik';
-import { capitalize, first, orderBy, isEmpty } from 'lodash';
+import { capitalize, first, orderBy, isEmpty, isEqual } from 'lodash';
import {
CheckPermissions,
LoadingIndicatorPage,
@@ -27,13 +27,14 @@ import {
CardBody,
CardContent,
} from '@strapi/design-system/Card';
-import { Check, Refresh } from '@strapi/icons';
+import { Check, Refresh, Play } from '@strapi/icons';
import pluginPermissions from '../../permissions';
import useConfig from '../../hooks/useConfig';
import { fetchAllContentTypes, fetchRoles } from './utils/api';
import { getMessage, parseRegExp } from '../../utils';
import ConfirmationDialog from '../../components/ConfirmationDialog';
+import { RestartAlert } from './components/RestartAlert/styles';
const Settings = () => {
@@ -56,8 +57,9 @@ const Settings = () => {
} = useRBAC(viewPermissions);
const [restoreConfigmationVisible, setRestoreConfigmationVisible] = useState(false);
+ const [restartRequired, setRestartRequired] = useState(false);
- const { fetch, submitMutation, restoreMutation } = useConfig(toggleNotification);
+ const { fetch, restartMutation, submitMutation, restoreMutation } = useConfig(toggleNotification);
const { data: configData, isLoading: isConfigLoading, err: configErr } = fetch;
const { data: allCollectionsData, isLoading: areCollectionsLoading, err: collectionsErr } = useQuery(
@@ -131,7 +133,13 @@ const Settings = () => {
const handleUpdateConfiguration = async (form) => {
if (canChange) {
lockApp();
- await submitMutation.mutateAsync(preparePayload(form));
+ const payload = preparePayload(form);
+ await submitMutation.mutateAsync(payload);
+ const enabledCollectionsChanged = !isEqual(payload.enabledCollections, configData?.enabledCollections);
+ const gqlAuthChanged = !isEqual(payload.gql?.auth, configData?.gql?.auth);
+ if (enabledCollectionsChanged || gqlAuthChanged) {
+ setRestartRequired(true);
+ }
unlockApp();
}
};
@@ -142,11 +150,22 @@ const Settings = () => {
lockApp();
await restoreMutation.mutateAsync();
unlockApp();
+ setRestartRequired(true);
setRestoreConfigmationVisible(false);
}
};
const handleRestoreCancel = () => setRestoreConfigmationVisible(false);
+ const handleRestart = async () => {
+ if (canChange) {
+ lockApp();
+ await restartMutation.mutateAsync();
+ setRestartRequired(false);
+ unlockApp();
+ }
+ };
+ const handleRestartDiscard = () => setRestartRequired(false);
+
const boxDefaultProps = {
background: "neutral0",
hasRadius: true,
@@ -175,7 +194,7 @@ const Settings = () => {
subtitle={getMessage('page.settings.header.description')}
primaryAction={
- } >
+ } disabled={restartRequired} >
{getMessage('page.settings.actions.submit')}
@@ -183,6 +202,15 @@ const Settings = () => {
/>
+ { restartRequired && (
+ }>{getMessage('page.settings.actions.restart')}}
+ onClose={handleRestartDiscard}>
+ { getMessage('page.settings.actions.restart.alert.description')}
+ )}
+
@@ -198,6 +226,7 @@ const Settings = () => {
onClear={() => setFieldValue('enabledCollections', [], false)}
value={values.enabledCollections}
onChange={(value) => setFieldValue('enabledCollections', value, false)}
+ disabled={restartRequired}
multi
withTags
>
@@ -214,6 +243,7 @@ const Settings = () => {
onClear={() => setFieldValue('moderatorRoles', [], false)}
value={values.moderatorRoles}
onChange={(value) => setFieldValue('moderatorRoles', value, false)}
+ disabled={restartRequired}
multi
withTags
>
@@ -230,6 +260,7 @@ const Settings = () => {
onChange={({ target: { checked } }) => setFieldValue('badWords', checked, false)}
onLabel={getMessage('compontents.toogle.enabled')}
offLabel={getMessage('compontents.toogle.disabled')}
+ disabled={restartRequired}
/>
{ isGQLPluginEnabled && (
@@ -241,6 +272,7 @@ const Settings = () => {
onChange={({ target: { checked } }) => setFieldValue('gqlAuthEnabled', checked, false)}
onLabel={getMessage('compontents.toogle.enabled')}
offLabel={getMessage('compontents.toogle.disabled')}
+ disabled={restartRequired}
/>
) }
@@ -272,6 +304,7 @@ const Settings = () => {
onChange={({ target: { checked } }) => setFieldValue('approvalFlow', changeApprovalFlowFor(uid, values.approvalFlow, checked), [])}
onLabel={getMessage('compontents.toogle.enabled')}
offLabel={getMessage('compontents.toogle.disabled')}
+ disabled={restartRequired}
/>
{ !isEmpty(stringAttributes) && (