Skip to content

Commit

Permalink
fix: issue-110 gql configuration not applying, issues with old config…
Browse files Browse the repository at this point in the history
…urations
  • Loading branch information
cyp3rius committed Feb 15, 2022
1 parent 2000942 commit ff662d3
Show file tree
Hide file tree
Showing 11 changed files with 103 additions and 15 deletions.
16 changes: 11 additions & 5 deletions admin/src/hooks/useConfig.js
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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`,
Expand All @@ -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;
8 changes: 8 additions & 0 deletions admin/src/pages/Settings/components/RestartAlert/styles.js
Original file line number Diff line number Diff line change
@@ -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;
}
`
44 changes: 39 additions & 5 deletions admin/src/pages/Settings/index.js
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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 = () => {
Expand All @@ -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(
Expand Down Expand Up @@ -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();
}
};
Expand All @@ -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,
Expand Down Expand Up @@ -175,14 +194,23 @@ const Settings = () => {
subtitle={getMessage('page.settings.header.description')}
primaryAction={
<CheckPermissions permissions={pluginPermissions.settingsChange}>
<Button type="submit" startIcon={<Check />} >
<Button type="submit" startIcon={<Check />} disabled={restartRequired} >
{getMessage('page.settings.actions.submit')}
</Button>
</CheckPermissions>
}
/>
<ContentLayout>
<Stack size={6}>
{ restartRequired && (
<RestartAlert
closeLabel={getMessage('page.settings.actions.restart.alert.cancel')}
title={getMessage('page.settings.actions.restart.alert.title')}
action={<Box><Button onClick={handleRestart} startIcon={<Play />}>{getMessage('page.settings.actions.restart')}</Button></Box>}
onClose={handleRestartDiscard}>
{ getMessage('page.settings.actions.restart.alert.description')}
</RestartAlert>)}

<Box {...boxDefaultProps}>
<Stack size={4}>
<Typography variant="delta" as="h2">
Expand All @@ -198,6 +226,7 @@ const Settings = () => {
onClear={() => setFieldValue('enabledCollections', [], false)}
value={values.enabledCollections}
onChange={(value) => setFieldValue('enabledCollections', value, false)}
disabled={restartRequired}
multi
withTags
>
Expand All @@ -214,6 +243,7 @@ const Settings = () => {
onClear={() => setFieldValue('moderatorRoles', [], false)}
value={values.moderatorRoles}
onChange={(value) => setFieldValue('moderatorRoles', value, false)}
disabled={restartRequired}
multi
withTags
>
Expand All @@ -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}
/>
</GridItem>
{ isGQLPluginEnabled && (<GridItem col={6} xs={12}>
Expand All @@ -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}
/>
</GridItem>) }
</Grid>
Expand Down Expand Up @@ -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) && (<Select
name={`collectionSettings-${uid}-entryLabel`}
Expand All @@ -283,6 +316,7 @@ const Settings = () => {
onChange={(value) => setFieldValue('entryLabel', changeEntryLabelFor(uid, values.entryLabel, value))}
multi
withTags
disabled={restartRequired}
>
{ stringAttributes.map(key =>
(<Option key={`collectionSettings-${uid}-entryLabel-${key}`} value={key}>{ capitalize(key.split('_').join(' ')) }</Option>))}
Expand Down
12 changes: 11 additions & 1 deletion admin/src/pages/Settings/utils/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export const fetchConfig = async (toggleNotification) => {

return data;
} catch (err) {
handleAPIError(err, toggleNotification);
handleAPIError(err, toggleNotification, 'page.settings.notification.fetch.error');
}
};

Expand Down Expand Up @@ -43,6 +43,16 @@ export const fetchAllContentTypes = async (toggleNotification) => {
export const fetchRoles = async (toggleNotification) => {
try {
const { data } = await axiosInstance.get(`/admin/roles`);
return data;
} catch (err) {
handleAPIError(err, toggleNotification);
}
};

export const restartStrapi = async (toggleNotification) => {
try {
const { data } = await axiosInstance.get(getApiURL(`settings/restart`));

return data;
} catch (err) {
handleAPIError(err, toggleNotification);
Expand Down
7 changes: 7 additions & 0 deletions admin/src/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
"page.settings.header.description": "Configure your comments moderation capabilities",
"page.settings.actions.submit": "Save",
"page.settings.actions.restore": "Restore",
"page.settings.actions.restart": "Restart Strapi",
"page.settings.section.general": "General configuration",
"page.settings.section.collections": "Collection(s) configuration",
"page.settings.section.restore": "Restore default configuration",
Expand All @@ -108,10 +109,16 @@
"page.settings.actions.restore.confirmation.header": "Restore default configuration",
"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?",
"page.settings.actions.restore.confirmation.button.confirm": "Yes, I want to restore",
"page.settings.actions.restart.alert.title": "Strapi requires restart",
"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.",
"page.settings.actions.restart.alert.close": "Discard",
"page.settings.notification.fetch.error": "Failed to fetch configuration. Retrying...",
"page.settings.notification.submit.success": "Configuration has been saved successfully",
"page.settings.notification.submit.error": "Failed to save configuration. Try again.",
"page.settings.notification.restore.success": "Configuration has been restored successfully",
"page.settings.notification.restore.error": "Failed to restore configuration. Try again.",
"page.settings.notification.restart.success": "Application has been restarted successfully",
"page.settings.notification.restart.error": "Failed to restart your application. Try to do it manually.",
"page.settings.loading": "Fetching configuration...",
"compontents.confirmation.dialog.header": "Confirmation",
"compontents.confirmation.dialog.description": "Do you really want to perform this action?",
Expand Down
5 changes: 3 additions & 2 deletions admin/src/utils/handleAPIError.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import pluginId from "../pluginId";

const handleAPIError = (err = null, toggleNotification = null) => {
const handleAPIError = (err = null, toggleNotification = null, message = 'app.components.notification.error') => {
toggleNotification({
type: 'warning',
message: 'app.components.notification.error',
message: `${pluginId}.${message}`,
});

if (err) {
Expand Down
9 changes: 9 additions & 0 deletions server/controllers/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,15 @@ module.exports = {
}
},

async settingsRestart(ctx) {
try {
await this.getService().restart();
return ctx.send({ status: 200 });
} catch (e) {
throwError(ctx, e);
}
},

async findAll(ctx) {
return this.getService()
.findAll(ctx.query);
Expand Down
8 changes: 8 additions & 0 deletions server/routes/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -113,4 +113,12 @@ module.exports = [
policies: [],
},
},
{
method: 'GET',
path: '/settings/restart',
handler: 'admin.settingsRestart',
config: {
policies: [],
},
},
];
4 changes: 4 additions & 0 deletions server/services/admin.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,10 @@ const { APPROVAL_STATUS, REGEX } = require('./../utils/constants')
return this.config();
},

async restart() {
setImmediate(() => strapi.reload());
},

// Find all comments
async findAll({ related, entity, ...query }) {
const { _q, orderBy, pageSize = 10, page = 1, filters, ...rest } = parseParams(query);
Expand Down
3 changes: 2 additions & 1 deletion server/services/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ module.exports = ({ strapi }) => ({
throw new PluginError(400, `Relation for field "related" does not exist. Check your payload please.`);
}

const isApprovalFlowEnabled = await this.getCommonService().getConfig(CONFIG_PARAMS.APPROVAL_FLOW, []).includes(uid) ||
const approvalFlow = await this.getCommonService().getConfig(CONFIG_PARAMS.APPROVAL_FLOW, []);
const isApprovalFlowEnabled = approvalFlow.includes(uid) ||
relatedEntity.requireCommentsApproval;

const linkToThread = !isNil(threadOf) ? await this.getCommonService().findOne({
Expand Down
2 changes: 1 addition & 1 deletion server/services/common.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ module.exports = ({ strapi }) => ({

let result;
if (config && !useLocal) {
result = queryProp ? get(config, queryProp) : config;;
result = queryProp ? get(config, queryProp, defaultValue) : config;
} else {
result = this.getLocalConfig(queryProp, defaultValue);
}
Expand Down

0 comments on commit ff662d3

Please sign in to comment.