strapi-plugin-navigation 2.4.0 โ 2.5.0
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/README.md +12 -1
- package/admin/src/pages/DataManagerProvider/actions.d.ts +2 -0
- package/admin/src/pages/DataManagerProvider/actions.js +3 -1
- package/admin/src/pages/DataManagerProvider/index.js +28 -0
- package/admin/src/pages/DataManagerProvider/reducer.js +8 -0
- package/admin/src/pages/SettingsPage/index.js +19 -7
- package/admin/src/pages/SettingsPage/types.d.ts +2 -1
- package/admin/src/pages/View/components/NavigationHeader/index.d.ts +2 -1
- package/admin/src/pages/View/components/NavigationHeader/index.js +5 -3
- package/admin/src/pages/View/components/NavigationManager/AllNavigations/icons.d.ts +1 -0
- package/admin/src/pages/View/components/NavigationManager/AllNavigations/icons.js +2 -1
- package/admin/src/pages/View/components/NavigationManager/AllNavigations/index.js +16 -4
- package/admin/src/pages/View/components/NavigationManager/PurgeCacheConfirm/index.d.ts +8 -0
- package/admin/src/pages/View/components/NavigationManager/PurgeCacheConfirm/index.js +34 -0
- package/admin/src/pages/View/components/NavigationManager/index.js +15 -2
- package/admin/src/pages/View/components/NavigationManager/types.d.ts +5 -1
- package/admin/src/pages/View/index.js +5 -2
- package/admin/src/translations/en.json +7 -0
- package/package.json +6 -6
- package/server/bootstrap/index.js +3 -0
- package/server/cache/index.d.ts +2 -0
- package/server/cache/index.js +18 -0
- package/server/cache/serviceEnhancers.d.ts +3 -0
- package/server/cache/serviceEnhancers.js +16 -0
- package/server/cache/setupStrategy.d.ts +3 -0
- package/server/cache/setupStrategy.js +38 -0
- package/server/cache/types.d.ts +11 -0
- package/server/cache/types.js +3 -0
- package/server/cache/utils.d.ts +11 -0
- package/server/cache/utils.js +19 -0
- package/server/config/index.js +1 -0
- package/server/config/setupStrategy.js +1 -0
- package/server/controllers/admin.js +18 -0
- package/server/i18n/navigationSetupStrategy.js +1 -1
- package/server/routes/admin.js +20 -0
- package/server/services/admin.js +42 -8
- package/server/utils/functions.d.ts +1 -1
- package/server/utils/functions.js +2 -2
- package/tsconfig.tsbuildinfo +1 -1
- package/types/bootstrap.d.ts +3 -0
- package/types/config.d.ts +1 -0
- package/types/controllers.d.ts +10 -0
- package/types/services.d.ts +7 -1
package/README.md
CHANGED
|
@@ -52,6 +52,7 @@ Strapi Navigation Plugin provides a website navigation / menu builder feature fo
|
|
|
52
52
|
- [GraphQL API](#graphql-api)
|
|
53
53
|
10. [๐ Extensions](#-extensions)
|
|
54
54
|
11. [๐ฟ Model lifecycle hooks](#model-life-cycle-hooks)
|
|
55
|
+
11. [๐งน REST Cache](#rest-cache)
|
|
55
56
|
12. [๐งฉ Examples](#-examples)
|
|
56
57
|
13. [๐ฌ FAQ](#-faq)
|
|
57
58
|
14. [๐ค Contributing](#-contributing)
|
|
@@ -123,7 +124,7 @@ Complete installation requirements are exact same as for Strapi itself and can b
|
|
|
123
124
|
|
|
124
125
|
**Supported Strapi versions**:
|
|
125
126
|
|
|
126
|
-
- Strapi v4.
|
|
127
|
+
- Strapi v4.23.x (recently tested)
|
|
127
128
|
- Strapi v4.x
|
|
128
129
|
|
|
129
130
|
> This plugin is designed for **Strapi v4** and is not working with v3.x. To get version for **Strapi v3** install version [v1.x](https://github.com/VirtusLab-Open-Source/strapi-plugin-navigation/tree/strapi-v3).
|
|
@@ -774,6 +775,16 @@ Example:
|
|
|
774
775
|
});
|
|
775
776
|
```
|
|
776
777
|
|
|
778
|
+
## ๐งน REST Cache
|
|
779
|
+
|
|
780
|
+
If your strapi server uses [REST Cache plugin](https://strapi-community.github.io/strapi-plugin-rest-cache/) this plugin can take integrate with it. All you need to do is to enable it in configuration of Navigation plugin. After integration is enabled all client calls will be wrapped with caching middleware.
|
|
781
|
+
|
|
782
|
+
In admin panel new controls will be available. Cache clearing is done manually or after cache will timeout(`rest-cache` plugin's settings are used).
|
|
783
|
+
|
|
784
|
+
Navigation edit screen will have "Clear cache" button.
|
|
785
|
+
|
|
786
|
+
Navigation management modal items will also have icon button for clearing the cache.
|
|
787
|
+
|
|
777
788
|
## ๐งฉ Examples
|
|
778
789
|
|
|
779
790
|
Live example of plugin usage can be found in the [VirtusLab Strapi Examples](https://github.com/VirtusLab/strapi-examples/tree/master/strapi-plugin-navigation) repository.
|
|
@@ -13,6 +13,8 @@ export const GET_CONFIG_SUCCEEDED: "GET_CONFIG_SUCCEEDED";
|
|
|
13
13
|
export const SUBMIT_NAVIGATION: "SUBMIT_NAVIGATION";
|
|
14
14
|
export const SUBMIT_NAVIGATION_SUCCEEDED: "SUBMIT_NAVIGATION_SUCCEEDED";
|
|
15
15
|
export const SUBMIT_NAVIGATION_ERROR: "SUBMIT_NAVIGATION_ERROR";
|
|
16
|
+
export const CACHE_CLEAR: "CACHE_CLEAR";
|
|
17
|
+
export const CACHE_CLEAR_SUCCEEDED: "CACHE_CLEAR_SUCCEEDED";
|
|
16
18
|
export const RELOAD_PLUGIN: "RELOAD_PLUGIN";
|
|
17
19
|
export const I18N_COPY_NAVIGATION: "I18N_COPY_NAVIGATION";
|
|
18
20
|
export const I18N_COPY_NAVIGATION_SUCCESS: "I18N_COPY_NAVIGATION_SUCCESS";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.I18N_COPY_NAVIGATION_SUCCESS = exports.I18N_COPY_NAVIGATION = exports.RELOAD_PLUGIN = exports.SUBMIT_NAVIGATION_ERROR = exports.SUBMIT_NAVIGATION_SUCCEEDED = exports.SUBMIT_NAVIGATION = exports.GET_CONFIG_SUCCEEDED = exports.GET_CONFIG = exports.GET_CONTENT_TYPE_ITEMS_SUCCEEDED = exports.GET_CONTENT_TYPE_ITEMS = exports.CHANGE_NAVIGATION_ITEM_POPUP_VISIBILITY = exports.CHANGE_NAVIGATION_POPUP_VISIBILITY = exports.RESET_NAVIGATION_DATA = exports.CHANGE_NAVIGATION_DATA = exports.GET_NAVIGATION_DATA_SUCCEEDED = exports.GET_NAVIGATION_DATA = exports.GET_LIST_DATA_SUCCEEDED = exports.GET_LIST_DATA = void 0;
|
|
3
|
+
exports.I18N_COPY_NAVIGATION_SUCCESS = exports.I18N_COPY_NAVIGATION = exports.RELOAD_PLUGIN = exports.CACHE_CLEAR_SUCCEEDED = exports.CACHE_CLEAR = exports.SUBMIT_NAVIGATION_ERROR = exports.SUBMIT_NAVIGATION_SUCCEEDED = exports.SUBMIT_NAVIGATION = exports.GET_CONFIG_SUCCEEDED = exports.GET_CONFIG = exports.GET_CONTENT_TYPE_ITEMS_SUCCEEDED = exports.GET_CONTENT_TYPE_ITEMS = exports.CHANGE_NAVIGATION_ITEM_POPUP_VISIBILITY = exports.CHANGE_NAVIGATION_POPUP_VISIBILITY = exports.RESET_NAVIGATION_DATA = exports.CHANGE_NAVIGATION_DATA = exports.GET_NAVIGATION_DATA_SUCCEEDED = exports.GET_NAVIGATION_DATA = exports.GET_LIST_DATA_SUCCEEDED = exports.GET_LIST_DATA = void 0;
|
|
4
4
|
exports.GET_LIST_DATA = "GET_LIST_DATA";
|
|
5
5
|
exports.GET_LIST_DATA_SUCCEEDED = "GET_LIST_DATA_SUCCEEDED";
|
|
6
6
|
exports.GET_NAVIGATION_DATA = "GET_NAVIGATION_DATA";
|
|
@@ -16,6 +16,8 @@ exports.GET_CONFIG_SUCCEEDED = "GET_CONFIG_SUCCEEDED";
|
|
|
16
16
|
exports.SUBMIT_NAVIGATION = "SUBMIT_NAVIGATION";
|
|
17
17
|
exports.SUBMIT_NAVIGATION_SUCCEEDED = "SUBMIT_NAVIGATION_SUCCEEDED";
|
|
18
18
|
exports.SUBMIT_NAVIGATION_ERROR = "SUBMIT_NAVIGATION_ERROR";
|
|
19
|
+
exports.CACHE_CLEAR = "CACHE_CLEAR";
|
|
20
|
+
exports.CACHE_CLEAR_SUCCEEDED = "CACHE_CLEAR_SUCCEEDED";
|
|
19
21
|
exports.RELOAD_PLUGIN = "RELOAD_PLUGIN";
|
|
20
22
|
exports.I18N_COPY_NAVIGATION = "I18N_COPY_NAVIGATION";
|
|
21
23
|
exports.I18N_COPY_NAVIGATION_SUCCESS = "I18N_COPY_NAVIGATION_SUCCESS";
|
|
@@ -296,6 +296,33 @@ const DataManagerProvider = ({ children }) => {
|
|
|
296
296
|
}
|
|
297
297
|
};
|
|
298
298
|
const handleNavigationsDeletion = (ids) => Promise.all(ids.map(handleNavigationDeletion));
|
|
299
|
+
const handleNavigationsPurge = async (ids, withLangVersions = false, skipDispatch = false) => {
|
|
300
|
+
if (!skipDispatch) {
|
|
301
|
+
dispatch({ type: actions_1.CACHE_CLEAR });
|
|
302
|
+
}
|
|
303
|
+
try {
|
|
304
|
+
if (ids.length) {
|
|
305
|
+
await Promise.all(ids.map((id) => handleNavigationPurgeReq(id, withLangVersions)));
|
|
306
|
+
}
|
|
307
|
+
else {
|
|
308
|
+
await handleNavigationsPurgeReq();
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
catch (error) {
|
|
312
|
+
console.error("Unable to clear navigation cache");
|
|
313
|
+
}
|
|
314
|
+
if (!skipDispatch) {
|
|
315
|
+
dispatch({ type: actions_1.CACHE_CLEAR_SUCCEEDED });
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
const handleNavigationPurgeReq = (id, withLangVersions) => (0, helper_plugin_1.request)(`/${pluginId_1.default}/cache/purge/${id}?clearLocalisations=${!!withLangVersions}`, {
|
|
319
|
+
method: "DELETE",
|
|
320
|
+
signal,
|
|
321
|
+
});
|
|
322
|
+
const handleNavigationsPurgeReq = () => (0, helper_plugin_1.request)(`/${pluginId_1.default}/cache/purge`, {
|
|
323
|
+
method: "DELETE",
|
|
324
|
+
signal,
|
|
325
|
+
});
|
|
299
326
|
const handleNavigationDeletion = (id) => (0, helper_plugin_1.request)(`/${pluginId_1.default}/${id}`, {
|
|
300
327
|
method: "DELETE",
|
|
301
328
|
signal,
|
|
@@ -340,6 +367,7 @@ const DataManagerProvider = ({ children }) => {
|
|
|
340
367
|
availableLocale,
|
|
341
368
|
readNavigationItemFromLocale,
|
|
342
369
|
handleNavigationsDeletion,
|
|
370
|
+
handleNavigationsPurge,
|
|
343
371
|
hardReset,
|
|
344
372
|
slugify,
|
|
345
373
|
permissions: {
|
|
@@ -116,6 +116,14 @@ const reducer = (state, action) => (0, immer_1.default)(state, draftState => {
|
|
|
116
116
|
draftState.isLoading = false;
|
|
117
117
|
break;
|
|
118
118
|
}
|
|
119
|
+
case actions_1.CACHE_CLEAR: {
|
|
120
|
+
draftState.isLoading = true;
|
|
121
|
+
break;
|
|
122
|
+
}
|
|
123
|
+
case actions_1.CACHE_CLEAR_SUCCEEDED: {
|
|
124
|
+
draftState.isLoading = false;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
119
127
|
default:
|
|
120
128
|
return draftState;
|
|
121
129
|
}
|
|
@@ -96,6 +96,7 @@ const SettingsPage = () => {
|
|
|
96
96
|
pathDefaultFields: (0, lodash_1.get)(navigationConfigData, "pathDefaultFields", {}),
|
|
97
97
|
populate: (0, lodash_1.get)(navigationConfigData, "contentTypesPopulate", {}),
|
|
98
98
|
selectedContentTypes: configContentTypes.map(item => item.uid),
|
|
99
|
+
isCacheEnabled: (0, lodash_1.get)(navigationConfigData, "isCacheEnabled", false),
|
|
99
100
|
}), [configContentTypes, navigationConfigData, utils_1.navigationItemAdditionalFields]);
|
|
100
101
|
const { disableI18nModal, setDisableI18nModalOpened, setI18nModalOnCancel, } = (0, DisableI18nModal_1.useDisableI18nModal)(({ pruneNavigations }) => {
|
|
101
102
|
setPruneObsoleteI18nNavigations(pruneNavigations);
|
|
@@ -105,7 +106,7 @@ const SettingsPage = () => {
|
|
|
105
106
|
?.filter((field) => field !== utils_1.navigationItemAdditionalFields.AUDIENCE);
|
|
106
107
|
setCustomFields(additionalFields || []);
|
|
107
108
|
}, [navigationConfigData]);
|
|
108
|
-
const preparePayload = (0, react_1.useCallback)(({ form: { allowedLevels, audienceFieldChecked, cascadeMenuAttachedChecked, i18nEnabled, nameFields, pathDefaultFields, populate, selectedContentTypes, }, pruneObsoleteI18nNavigations }) => ({
|
|
109
|
+
const preparePayload = (0, react_1.useCallback)(({ form: { allowedLevels, audienceFieldChecked, cascadeMenuAttachedChecked, i18nEnabled, nameFields, pathDefaultFields, populate, selectedContentTypes, isCacheEnabled, }, pruneObsoleteI18nNavigations }) => ({
|
|
109
110
|
additionalFields: audienceFieldChecked ? ['audience', ...customFields] : [...customFields],
|
|
110
111
|
allowedLevels,
|
|
111
112
|
cascadeMenuAttached: cascadeMenuAttachedChecked,
|
|
@@ -117,7 +118,8 @@ const SettingsPage = () => {
|
|
|
117
118
|
pruneObsoleteI18nNavigations,
|
|
118
119
|
gql: {
|
|
119
120
|
navigationItemRelated: selectedContentTypes.map((uid) => (0, functions_1.resolveGlobalLikeId)(uid)),
|
|
120
|
-
}
|
|
121
|
+
},
|
|
122
|
+
isCacheEnabled,
|
|
121
123
|
}), [customFields]);
|
|
122
124
|
const onSave = async (form) => {
|
|
123
125
|
lockApp();
|
|
@@ -125,10 +127,14 @@ const SettingsPage = () => {
|
|
|
125
127
|
await submitMutation({ body: payload });
|
|
126
128
|
const isContentTypesChanged = !(0, lodash_1.isEqual)(payload.contentTypes, navigationConfigData.contentTypes);
|
|
127
129
|
const isI18nChanged = !(0, lodash_1.isEqual)(payload.i18nEnabled, navigationConfigData.i18nEnabled);
|
|
130
|
+
const isCacheChanged = !(0, lodash_1.isEqual)(payload.isCacheEnabled, navigationConfigData.isCacheEnabled);
|
|
128
131
|
const restartReasons = [];
|
|
129
132
|
if (isI18nChanged) {
|
|
130
133
|
restartReasons.push('I18N');
|
|
131
134
|
}
|
|
135
|
+
if (isCacheChanged) {
|
|
136
|
+
restartReasons.push('CACHE');
|
|
137
|
+
}
|
|
132
138
|
if (isContentTypesChanged && navigationConfigData.isGQLPluginEnabled) {
|
|
133
139
|
restartReasons.push('GRAPH_QL');
|
|
134
140
|
}
|
|
@@ -186,6 +192,7 @@ const SettingsPage = () => {
|
|
|
186
192
|
return ct;
|
|
187
193
|
}), ct => ct.info.displayName) : [];
|
|
188
194
|
const isI18NPluginEnabled = navigationConfigData?.isI18NPluginEnabled;
|
|
195
|
+
const isCachePluginEnabled = navigationConfigData?.isCachePluginEnabled;
|
|
189
196
|
const defaultLocale = navigationConfigData?.defaultLocale;
|
|
190
197
|
const handleSubmitCustomField = (field) => {
|
|
191
198
|
const filteredFields = customFields.filter(f => f.name !== field.name);
|
|
@@ -252,17 +259,17 @@ const SettingsPage = () => {
|
|
|
252
259
|
react_1.default.createElement(Stack_1.Stack, { size: 4 },
|
|
253
260
|
react_1.default.createElement(Typography_1.Typography, { variant: "delta", as: "h2" }, (0, utils_2.getMessage)('pages.settings.additional.title')),
|
|
254
261
|
react_1.default.createElement(Grid_1.Grid, { gap: 4 },
|
|
255
|
-
react_1.default.createElement(Grid_1.GridItem, { col:
|
|
262
|
+
react_1.default.createElement(Grid_1.GridItem, { col: 6, s: 6, xs: 12 },
|
|
256
263
|
react_1.default.createElement(Box_1.Box, { style: { maxWidth: 257 } },
|
|
257
264
|
react_1.default.createElement(NumberInput_1.NumberInput, { name: "allowedLevels", label: (0, utils_2.getMessage)('pages.settings.form.allowedLevels.label'), placeholder: (0, utils_2.getMessage)('pages.settings.form.allowedLevels.placeholder'), hint: (0, utils_2.getMessage)('pages.settings.form.allowedLevels.hint'), onValueChange: (value) => setFieldValue('allowedLevels', value, false), value: values.allowedLevels, disabled: restartStatus.required }))),
|
|
258
|
-
react_1.default.createElement(Grid_1.GridItem, { col:
|
|
265
|
+
react_1.default.createElement(Grid_1.GridItem, { col: 6, s: 12, xs: 12 },
|
|
259
266
|
react_1.default.createElement(ToggleInput_1.ToggleInput, { name: "cascadeMenuAttachedChecked", label: (0, utils_2.getMessage)('pages.settings.form.cascadeMenuAttached.label'), hint: (0, utils_2.getMessage)('pages.settings.form.cascadeMenuAttached.hint'), checked: values.cascadeMenuAttachedChecked, onChange: ({ target: { checked } }) => {
|
|
260
267
|
setFieldValue('cascadeMenuAttachedChecked', checked, true);
|
|
261
268
|
}, onLabel: "Enabled", offLabel: "Disabled", disabled: restartStatus.required }))),
|
|
262
269
|
react_1.default.createElement(Grid_1.Grid, { gap: 4 },
|
|
263
|
-
react_1.default.createElement(Grid_1.GridItem, { col:
|
|
270
|
+
react_1.default.createElement(Grid_1.GridItem, { col: 6, s: 12, xs: 12 },
|
|
264
271
|
react_1.default.createElement(ToggleInput_1.ToggleInput, { name: "audienceFieldChecked", label: (0, utils_2.getMessage)('pages.settings.form.audience.label'), hint: (0, utils_2.getMessage)('pages.settings.form.audience.hint'), checked: values.audienceFieldChecked, onChange: () => setFieldValue('audienceFieldChecked', !values.audienceFieldChecked, false), onLabel: "Enabled", offLabel: "Disabled", disabled: restartStatus.required })),
|
|
265
|
-
isI18NPluginEnabled && (react_1.default.createElement(Grid_1.GridItem, { col:
|
|
272
|
+
isI18NPluginEnabled && (react_1.default.createElement(Grid_1.GridItem, { col: 6, s: 12, xs: 12 },
|
|
266
273
|
react_1.default.createElement(ToggleInput_1.ToggleInput, { name: "i18nEnabled", label: (0, utils_2.getMessage)('pages.settings.form.i18n.label'), hint: defaultLocale
|
|
267
274
|
? (0, utils_2.getMessage)('pages.settings.form.i18n.hint')
|
|
268
275
|
: (0, utils_2.getMessage)('pages.settings.form.i18n.hint.missingDefaultLocale'), checked: values.i18nEnabled, onChange: ({ target: { checked } }) => {
|
|
@@ -276,7 +283,12 @@ const SettingsPage = () => {
|
|
|
276
283
|
setFieldValue('i18nEnabled', true);
|
|
277
284
|
});
|
|
278
285
|
}
|
|
279
|
-
}, onLabel: "Enabled", offLabel: "Disabled", disabled: restartStatus.required || !defaultLocale }))))
|
|
286
|
+
}, onLabel: "Enabled", offLabel: "Disabled", disabled: restartStatus.required || !defaultLocale })))),
|
|
287
|
+
isCachePluginEnabled && (react_1.default.createElement(Grid_1.Grid, { gap: 4 },
|
|
288
|
+
react_1.default.createElement(Grid_1.GridItem, { col: 12, s: 12, xs: 12 },
|
|
289
|
+
react_1.default.createElement(ToggleInput_1.ToggleInput, { name: "cacheEnabled", label: (0, utils_2.getMessage)('pages.settings.form.cache.label'), hint: (0, utils_2.getMessage)('pages.settings.form.cache.hint'), checked: values.isCacheEnabled, onChange: ({ target: { checked } }) => {
|
|
290
|
+
setFieldValue('isCacheEnabled', checked, false);
|
|
291
|
+
}, onLabel: "Enabled", offLabel: "Disabled", disabled: restartStatus.required })))))),
|
|
280
292
|
react_1.default.createElement(Box_1.Box, { ...BOX_DEFAULT_PROPS },
|
|
281
293
|
react_1.default.createElement(Stack_1.Stack, { size: 4 },
|
|
282
294
|
react_1.default.createElement(Typography_1.Typography, { variant: "delta", as: "h2" }, (0, utils_2.getMessage)('pages.settings.customFields.title')),
|
|
@@ -9,6 +9,7 @@ export type RawPayload = {
|
|
|
9
9
|
pathDefaultFields: Record<string, string[]>;
|
|
10
10
|
populate: Record<string, string[]>;
|
|
11
11
|
selectedContentTypes: string[];
|
|
12
|
+
isCacheEnabled: boolean;
|
|
12
13
|
};
|
|
13
14
|
export type StrapiContentTypeSchema = StrapiContentTypeFullSchema & {
|
|
14
15
|
available: boolean;
|
|
@@ -23,7 +24,7 @@ export type PreparePayload = (payload: {
|
|
|
23
24
|
export type OnSave = Effect<RawPayload>;
|
|
24
25
|
export type OnPopupClose = Effect<boolean>;
|
|
25
26
|
export type HandleSetContentTypeExpanded = Effect<string | undefined>;
|
|
26
|
-
export type RestartReasons = 'I18N' | 'GRAPH_QL' | 'I18N_NAVIGATIONS_PRUNE';
|
|
27
|
+
export type RestartReasons = 'I18N' | 'GRAPH_QL' | 'I18N_NAVIGATIONS_PRUNE' | 'CACHE';
|
|
27
28
|
export type RestartStatus = {
|
|
28
29
|
required: true;
|
|
29
30
|
reasons?: RestartReasons[];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default NavigationHeader;
|
|
2
|
-
declare function NavigationHeader({ activeNavigation, availableNavigations, structureHasErrors, structureHasChanged, handleChangeSelection, handleLocalizationSelection, handleSave, config, permissions, }: {
|
|
2
|
+
declare function NavigationHeader({ activeNavigation, availableNavigations, structureHasErrors, structureHasChanged, handleChangeSelection, handleLocalizationSelection, handleSave, handleCachePurge, config, permissions, }: {
|
|
3
3
|
activeNavigation: any;
|
|
4
4
|
availableNavigations: any;
|
|
5
5
|
structureHasErrors: any;
|
|
@@ -7,6 +7,7 @@ declare function NavigationHeader({ activeNavigation, availableNavigations, stru
|
|
|
7
7
|
handleChangeSelection: any;
|
|
8
8
|
handleLocalizationSelection: any;
|
|
9
9
|
handleSave: any;
|
|
10
|
+
handleCachePurge: any;
|
|
10
11
|
config: any;
|
|
11
12
|
permissions?: {} | undefined;
|
|
12
13
|
}): JSX.Element;
|
|
@@ -50,7 +50,7 @@ const pickDefaultLocaleNavigation = ({ activeNavigation, config }) => config.i18
|
|
|
50
50
|
: activeNavigation?.localizations.find(({ localeCode }) => localeCode === config.defaultLocale)
|
|
51
51
|
: null
|
|
52
52
|
: activeNavigation;
|
|
53
|
-
const NavigationHeader = ({ activeNavigation, availableNavigations, structureHasErrors, structureHasChanged, handleChangeSelection, handleLocalizationSelection, handleSave, config, permissions = {}, }) => {
|
|
53
|
+
const NavigationHeader = ({ activeNavigation, availableNavigations, structureHasErrors, structureHasChanged, handleChangeSelection, handleLocalizationSelection, handleSave, handleCachePurge, config, permissions = {}, }) => {
|
|
54
54
|
const { formatMessage } = (0, react_intl_1.useIntl)();
|
|
55
55
|
const allLocaleVersions = (0, react_1.useMemo)(() => activeNavigation?.localizations.length && config.i18nEnabled
|
|
56
56
|
? (0, lodash_1.uniqBy)([activeNavigation, ...(activeNavigation.localizations ?? [])].sort((a, b) => a.localeCode.localeCompare(b.localeCode)), 'id')
|
|
@@ -66,7 +66,7 @@ const NavigationHeader = ({ activeNavigation, availableNavigations, structureHas
|
|
|
66
66
|
})
|
|
67
67
|
: null), primaryAction: react_1.default.createElement(Stack_1.Stack, { horizontal: true, size: 2 },
|
|
68
68
|
react_1.default.createElement(Box_1.Box, { marginRight: "8px" },
|
|
69
|
-
react_1.default.createElement(Grid_1.Grid, { gap: 4 },
|
|
69
|
+
react_1.default.createElement(Grid_1.Grid, { gap: 4, style: config.isCacheEnabled ? { display: "flex" } : undefined },
|
|
70
70
|
!hasLocalizations ? (react_1.default.createElement(Grid_1.GridItem, { col: 2 })) : null,
|
|
71
71
|
canUpdate && (react_1.default.createElement(Grid_1.GridItem, { col: 3 },
|
|
72
72
|
react_1.default.createElement(Button_1.Button, { onClick: openNavigationManagerModal, startIcon: null, type: "button", variant: "secondary", fullWidth: true, size: "S" }, formatMessage((0, translations_1.getTrad)('header.action.manage'))))),
|
|
@@ -77,7 +77,9 @@ const NavigationHeader = ({ activeNavigation, availableNavigations, structureHas
|
|
|
77
77
|
react_1.default.createElement(Select_1.Select, { type: "select", placeholder: formatMessage((0, translations_1.getTrad)('pages.main.header.localization.select.placeholder')), name: "navigationLocalizationSelect", onChange: handleLocalizationSelection, value: activeNavigation?.id, size: "S" }, allLocaleVersions.map(({ id, localeCode }) => react_1.default.createElement(Select_1.Option, { key: id, value: id }, localeCode))))
|
|
78
78
|
: null,
|
|
79
79
|
canUpdate && (react_1.default.createElement(Grid_1.GridItem, { col: 3 },
|
|
80
|
-
react_1.default.createElement(Button_1.Button, { onClick: handleSave, startIcon: submitIcon, disabled: structureHasErrors || !structureHasChanged, type: "submit", fullWidth: true, size: "S" }, formatMessage((0, translations_1.getTrad)('submit.cta.save')))))
|
|
80
|
+
react_1.default.createElement(Button_1.Button, { onClick: handleSave, startIcon: submitIcon, disabled: structureHasErrors || !structureHasChanged, type: "submit", fullWidth: true, size: "S" }, formatMessage((0, translations_1.getTrad)('submit.cta.save'))))),
|
|
81
|
+
config.isCacheEnabled && (react_1.default.createElement(Grid_1.GridItem, { col: 3 },
|
|
82
|
+
react_1.default.createElement(Button_1.Button, { onClick: handleCachePurge, variant: "danger", type: "submit", fullWidth: true, size: "S" }, formatMessage((0, translations_1.getTrad)('submit.cta.cache.purge'))))))),
|
|
81
83
|
canUpdate && navigationManagerModal), title: formatMessage({
|
|
82
84
|
id: (0, translations_1.getTrad)('header.title'),
|
|
83
85
|
defaultMessage: 'UI Navigation',
|
|
@@ -3,9 +3,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.deleteIcon = exports.edit = void 0;
|
|
6
|
+
exports.brushIcon = exports.deleteIcon = exports.edit = void 0;
|
|
7
7
|
const react_1 = __importDefault(require("react"));
|
|
8
8
|
const icons_1 = require("@strapi/icons");
|
|
9
9
|
exports.edit = react_1.default.createElement(icons_1.Pencil, null);
|
|
10
10
|
exports.deleteIcon = react_1.default.createElement(icons_1.Trash, null);
|
|
11
|
+
exports.brushIcon = react_1.default.createElement(icons_1.Brush, null);
|
|
11
12
|
//# sourceMappingURL=icons.js.map
|
|
@@ -43,7 +43,7 @@ const Footer_1 = require("../Footer");
|
|
|
43
43
|
const NewNavigation_1 = require("../NewNavigation");
|
|
44
44
|
const icons = __importStar(require("./icons"));
|
|
45
45
|
const AllNavigations = ({ navigations, selected, setState }) => {
|
|
46
|
-
const { config: { i18nEnabled }, } = (0, useDataManager_1.default)();
|
|
46
|
+
const { config: { i18nEnabled, isCacheEnabled }, } = (0, useDataManager_1.default)();
|
|
47
47
|
const hasAnySelected = !!selected.length;
|
|
48
48
|
const toggleSelected = (0, react_1.useCallback)(() => setState({
|
|
49
49
|
navigations,
|
|
@@ -73,7 +73,14 @@ const AllNavigations = ({ navigations, selected, setState }) => {
|
|
|
73
73
|
navigations,
|
|
74
74
|
});
|
|
75
75
|
};
|
|
76
|
+
const purgeCache = (navigations) => () => {
|
|
77
|
+
setState({
|
|
78
|
+
view: "CACHE_PURGE",
|
|
79
|
+
navigations,
|
|
80
|
+
});
|
|
81
|
+
};
|
|
76
82
|
const deleteSelected = (0, react_1.useCallback)(_delete(selected), [_delete]);
|
|
83
|
+
const purgeSelected = (0, react_1.useCallback)(purgeCache(selected), [purgeCache]);
|
|
77
84
|
return (react_1.default.createElement(react_1.default.Fragment, null,
|
|
78
85
|
react_1.default.createElement(Grid_1.Grid, null,
|
|
79
86
|
react_1.default.createElement(Grid_1.GridItem, { col: 12, paddingBottom: 3 }, hasAnySelected ? (react_1.default.createElement(Flex_1.Flex, { direction: "row", gap: 1 },
|
|
@@ -83,7 +90,8 @@ const AllNavigations = ({ navigations, selected, setState }) => {
|
|
|
83
90
|
count: selected.length,
|
|
84
91
|
},
|
|
85
92
|
})),
|
|
86
|
-
react_1.default.createElement(Button_1.Button, { onClick: deleteSelected, variant: "tertiary" }, (0, utils_1.getMessage)("popup.navigation.manage.button.delete"))
|
|
93
|
+
react_1.default.createElement(Button_1.Button, { onClick: deleteSelected, variant: "tertiary" }, (0, utils_1.getMessage)("popup.navigation.manage.button.delete")),
|
|
94
|
+
isCacheEnabled ? (react_1.default.createElement(Button_1.Button, { onClick: purgeSelected, variant: "tertiary" }, (0, utils_1.getMessage)("popup.navigation.manage.button.purge"))) : null)) : null)),
|
|
87
95
|
react_1.default.createElement(Table_1.Table, { rowCount: navigations.length, colCount: i18nEnabled ? 6 : 5 },
|
|
88
96
|
react_1.default.createElement(Table_1.Thead, null,
|
|
89
97
|
react_1.default.createElement(Table_1.Tr, null,
|
|
@@ -97,7 +105,9 @@ const AllNavigations = ({ navigations, selected, setState }) => {
|
|
|
97
105
|
react_1.default.createElement(Typography_1.Typography, { textColor: "neutral800" }, (0, utils_1.getMessage)("popup.navigation.manage.table.locale")))) : null,
|
|
98
106
|
react_1.default.createElement(Table_1.Th, null,
|
|
99
107
|
react_1.default.createElement(Typography_1.Typography, { textColor: "neutral800" }, (0, utils_1.getMessage)("popup.navigation.manage.table.visibility"))),
|
|
100
|
-
react_1.default.createElement(Table_1.Th, null
|
|
108
|
+
react_1.default.createElement(Table_1.Th, null, isCacheEnabled ? (react_1.default.createElement(Flex_1.Flex, { direction: "row" },
|
|
109
|
+
react_1.default.createElement(Box_1.Box, { paddingLeft: 1 },
|
|
110
|
+
react_1.default.createElement(IconButton_1.IconButton, { onClick: purgeCache([]), label: (0, utils_1.getMessage)("popup.navigation.manage.button.purge"), noBorder: true, icon: icons.brushIcon })))) : null))),
|
|
101
111
|
react_1.default.createElement(Table_1.Tbody, null, navigations.map((navigation) => (react_1.default.createElement(Table_1.Tr, { key: navigation.id },
|
|
102
112
|
react_1.default.createElement(Table_1.Td, null,
|
|
103
113
|
react_1.default.createElement(BaseCheckbox_1.BaseCheckbox, { onValueChange: handleSelect(navigation, currentlySelectedSet.has(navigation.id)), value: currentlySelectedSet.has(navigation.id) })),
|
|
@@ -117,7 +127,9 @@ const AllNavigations = ({ navigations, selected, setState }) => {
|
|
|
117
127
|
react_1.default.createElement(Box_1.Box, { paddingLeft: 1 },
|
|
118
128
|
react_1.default.createElement(IconButton_1.IconButton, { onClick: edit(navigation), label: (0, utils_1.getMessage)("popup.navigation.manage.button.edit"), noBorder: true, icon: icons.edit })),
|
|
119
129
|
react_1.default.createElement(Box_1.Box, { paddingLeft: 1 },
|
|
120
|
-
react_1.default.createElement(IconButton_1.IconButton, { onClick: _delete([navigation]), label: (0, utils_1.getMessage)("popup.navigation.manage.button.delete"), noBorder: true, icon: icons.deleteIcon }))
|
|
130
|
+
react_1.default.createElement(IconButton_1.IconButton, { onClick: _delete([navigation]), label: (0, utils_1.getMessage)("popup.navigation.manage.button.delete"), noBorder: true, icon: icons.deleteIcon })),
|
|
131
|
+
isCacheEnabled ? (react_1.default.createElement(Box_1.Box, { paddingLeft: 1 },
|
|
132
|
+
react_1.default.createElement(IconButton_1.IconButton, { onClick: purgeCache([navigation]), label: (0, utils_1.getMessage)("popup.navigation.manage.button.purge"), noBorder: true, icon: icons.brushIcon }))) : null)))))))));
|
|
121
133
|
};
|
|
122
134
|
exports.AllNavigations = AllNavigations;
|
|
123
135
|
const AllNavigationsFooter = ({ onClose, state, setState, navigations, }) => (react_1.default.createElement(Footer_1.FooterBase, { start: {
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Footer } from "../Footer";
|
|
2
|
+
import { CommonProps, PurgeCacheState } from "../types";
|
|
3
|
+
interface Props extends PurgeCacheState, CommonProps {
|
|
4
|
+
}
|
|
5
|
+
export declare const PurgeCacheConfirm: ({ navigations }: Props) => JSX.Element;
|
|
6
|
+
export declare const PurgeCacheConfirmFooter: Footer;
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.PurgeCacheConfirmFooter = exports.PurgeCacheConfirm = void 0;
|
|
7
|
+
const Flex_1 = require("@strapi/design-system/Flex");
|
|
8
|
+
const Grid_1 = require("@strapi/design-system/Grid");
|
|
9
|
+
const Typography_1 = require("@strapi/design-system/Typography");
|
|
10
|
+
const fp_1 = require("lodash/fp");
|
|
11
|
+
const react_1 = __importDefault(require("react"));
|
|
12
|
+
const utils_1 = require("../../../../../utils");
|
|
13
|
+
const Footer_1 = require("../Footer");
|
|
14
|
+
const PurgeCacheConfirm = ({ navigations }) => (react_1.default.createElement(Grid_1.Grid, null,
|
|
15
|
+
react_1.default.createElement(Grid_1.GridItem, { col: 12, paddingBottom: 1 },
|
|
16
|
+
react_1.default.createElement(Flex_1.Flex, null,
|
|
17
|
+
react_1.default.createElement(Typography_1.Typography, { variant: "beta" }, (0, utils_1.getMessage)("popup.navigation.manage.purge.header")))),
|
|
18
|
+
react_1.default.createElement(Grid_1.GridItem, { col: 12, paddingBottom: 1 },
|
|
19
|
+
react_1.default.createElement(Typography_1.Typography, { variant: "omega", fontWeight: "semiBold" }, renderItems(navigations)))));
|
|
20
|
+
exports.PurgeCacheConfirm = PurgeCacheConfirm;
|
|
21
|
+
const PurgeCacheConfirmFooter = ({ state, onSubmit, onReset }) => (react_1.default.createElement(Footer_1.FooterBase, { start: {
|
|
22
|
+
children: (0, utils_1.getMessage)("popup.item.form.button.cancel"),
|
|
23
|
+
disabled: state.isLoading,
|
|
24
|
+
onClick: onReset,
|
|
25
|
+
variant: "tertiary",
|
|
26
|
+
}, end: {
|
|
27
|
+
children: (0, utils_1.getMessage)("popup.navigation.manage.footer.button.purge"),
|
|
28
|
+
disabled: state.isLoading,
|
|
29
|
+
onClick: onSubmit,
|
|
30
|
+
variant: "danger",
|
|
31
|
+
} }));
|
|
32
|
+
exports.PurgeCacheConfirmFooter = PurgeCacheConfirmFooter;
|
|
33
|
+
const renderItems = (navigations) => navigations.map((0, fp_1.prop)("name")).join(", ");
|
|
34
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -41,10 +41,11 @@ const DeletionConfirm_1 = require("./DeletionConfirm");
|
|
|
41
41
|
const ErrorDetails_1 = require("./ErrorDetails");
|
|
42
42
|
const NavigationUpdate_1 = require("./NavigationUpdate");
|
|
43
43
|
const NewNavigation_1 = require("./NewNavigation");
|
|
44
|
+
const PurgeCacheConfirm_1 = require("./PurgeCacheConfirm");
|
|
44
45
|
const NavigationManager = ({ initialState, isOpened, onClose, }) => {
|
|
45
46
|
const { formatMessage } = (0, react_intl_1.useIntl)();
|
|
46
47
|
const [state, setState] = (0, react_1.useState)(initialState);
|
|
47
|
-
const { items = [], handleNavigationsDeletion, handleSubmitNavigation, hardReset, } = (0, useDataManager_1.default)();
|
|
48
|
+
const { items = [], handleNavigationsDeletion, handleNavigationsPurge, handleSubmitNavigation, hardReset, } = (0, useDataManager_1.default)();
|
|
48
49
|
const navigations = (0, react_1.useMemo)(() => (0, lodash_1.sortBy)(items, "id"), [items]);
|
|
49
50
|
const onReset = (0, react_1.useCallback)(() => setState({ view: "INITIAL" }), [setState]);
|
|
50
51
|
const onSubmit = (0, react_1.useCallback)(async () => {
|
|
@@ -58,7 +59,12 @@ const NavigationManager = ({ initialState, isOpened, onClose, }) => {
|
|
|
58
59
|
await handleSubmitNavigation(formatMessage, state.current);
|
|
59
60
|
await hardReset();
|
|
60
61
|
}
|
|
61
|
-
:
|
|
62
|
+
: state.view === "CACHE_PURGE"
|
|
63
|
+
? async () => {
|
|
64
|
+
await handleNavigationsPurge(state.navigations.map((0, fp_1.prop)("id")), true, true);
|
|
65
|
+
await hardReset();
|
|
66
|
+
}
|
|
67
|
+
: () => { };
|
|
62
68
|
try {
|
|
63
69
|
setState({
|
|
64
70
|
...state,
|
|
@@ -110,6 +116,7 @@ const renderHeader = (state) => {
|
|
|
110
116
|
case "LIST":
|
|
111
117
|
case "CREATE":
|
|
112
118
|
case "ERROR":
|
|
119
|
+
case "CACHE_PURGE":
|
|
113
120
|
case "DELETE": {
|
|
114
121
|
return (react_1.default.createElement(Flex_1.Flex, { direction: "row" },
|
|
115
122
|
state.isLoading ? react_1.default.createElement(Loader_1.Loader, { small: true }) : null,
|
|
@@ -149,6 +156,9 @@ const renderContent = (state, setState) => {
|
|
|
149
156
|
case "DELETE": {
|
|
150
157
|
return react_1.default.createElement(DeletionConfirm_1.DeletionConfirm, { ...state, ...commonProps });
|
|
151
158
|
}
|
|
159
|
+
case "CACHE_PURGE": {
|
|
160
|
+
return react_1.default.createElement(PurgeCacheConfirm_1.PurgeCacheConfirm, { ...state, ...commonProps });
|
|
161
|
+
}
|
|
152
162
|
case "INITIAL": {
|
|
153
163
|
return react_1.default.createElement(Loader_1.Loader, { small: true });
|
|
154
164
|
}
|
|
@@ -173,6 +183,9 @@ const renderFooter = (props) => {
|
|
|
173
183
|
case "DELETE": {
|
|
174
184
|
return react_1.default.createElement(DeletionConfirm_1.DeleteConfirmFooter, { ...props });
|
|
175
185
|
}
|
|
186
|
+
case "CACHE_PURGE": {
|
|
187
|
+
return react_1.default.createElement(PurgeCacheConfirm_1.PurgeCacheConfirmFooter, { ...props });
|
|
188
|
+
}
|
|
176
189
|
case "ERROR": {
|
|
177
190
|
return react_1.default.createElement(ErrorDetails_1.ErrorDetailsFooter, { ...props });
|
|
178
191
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Dispatch, SetStateAction } from "react";
|
|
2
2
|
import { Navigation as FullNavigationEntity } from "../../../../../../types";
|
|
3
3
|
export type Navigation = Pick<FullNavigationEntity, "id" | "items" | "name" | "localeCode" | "localizations" | "visible">;
|
|
4
|
-
export type State = InitialState | ListState | EditState | CreateState | DeleteState | ErrorState;
|
|
4
|
+
export type State = InitialState | ListState | EditState | CreateState | DeleteState | PurgeCacheState | ErrorState;
|
|
5
5
|
export type SetState = Dispatch<SetStateAction<State>>;
|
|
6
6
|
interface CommonState {
|
|
7
7
|
isLoading?: boolean;
|
|
@@ -32,6 +32,10 @@ export interface DeleteState extends CommonState {
|
|
|
32
32
|
view: "DELETE";
|
|
33
33
|
navigations: Array<Navigation>;
|
|
34
34
|
}
|
|
35
|
+
export interface PurgeCacheState extends CommonState {
|
|
36
|
+
view: "CACHE_PURGE";
|
|
37
|
+
navigations: Array<Navigation>;
|
|
38
|
+
}
|
|
35
39
|
export interface ErrorState extends CommonState {
|
|
36
40
|
view: "ERROR";
|
|
37
41
|
errors: Array<Error>;
|
|
@@ -54,7 +54,7 @@ const parsers_1 = require("./utils/parsers");
|
|
|
54
54
|
const NoAccessPage_1 = __importDefault(require("../NoAccessPage"));
|
|
55
55
|
const View = () => {
|
|
56
56
|
const toggleNotification = (0, helper_plugin_1.useNotification)();
|
|
57
|
-
const { items: availableNavigations, activeItem: activeNavigation, changedActiveItem: changedActiveNavigation, config, navigationItemPopupOpened, isLoading, isLoadingForAdditionalDataToBeSet, isLoadingForSubmit, handleChangeNavigationItemPopupVisibility, handleChangeSelection, handleChangeNavigationData, handleResetNavigationData, handleSubmitNavigation, handleLocalizationSelection, handleI18nCopy, getContentTypeItems, error, availableLocale: allAvailableLocale, readNavigationItemFromLocale, slugify, permissions, } = (0, useDataManager_1.default)();
|
|
57
|
+
const { items: availableNavigations, activeItem: activeNavigation, changedActiveItem: changedActiveNavigation, config, navigationItemPopupOpened, isLoading, isLoadingForAdditionalDataToBeSet, isLoadingForSubmit, handleChangeNavigationItemPopupVisibility, handleChangeSelection, handleChangeNavigationData, handleResetNavigationData, handleSubmitNavigation, handleLocalizationSelection, handleI18nCopy, getContentTypeItems, error, availableLocale: allAvailableLocale, readNavigationItemFromLocale, slugify, permissions, handleNavigationsPurge, } = (0, useDataManager_1.default)();
|
|
58
58
|
const { canAccess, canUpdate } = permissions;
|
|
59
59
|
const availableLocale = (0, react_1.useMemo)(() => allAvailableLocale.filter(locale => locale !== changedActiveNavigation?.localeCode), [changedActiveNavigation, allAvailableLocale]);
|
|
60
60
|
const { i18nCopyItemsModal, i18nCopySourceLocale, setI18nCopyModalOpened, setI18nCopySourceLocale } = (0, useI18nCopyNavigationItemsModal_1.useI18nCopyNavigationItemsModal)((0, react_1.useCallback)((sourceLocale) => {
|
|
@@ -83,6 +83,9 @@ const View = () => {
|
|
|
83
83
|
const handleSave = () => isLoadingForSubmit || structureHasErrors
|
|
84
84
|
? null
|
|
85
85
|
: handleSubmitNavigation(formatMessage, (0, parsers_1.transformToRESTPayload)(changedActiveNavigation, config));
|
|
86
|
+
const handleCachePurge = () => {
|
|
87
|
+
handleNavigationsPurge([navigationSelectValue]);
|
|
88
|
+
};
|
|
86
89
|
const changeNavigationItemPopupState = (visible, editedItem = {}) => {
|
|
87
90
|
setActiveNavigationItemState(editedItem);
|
|
88
91
|
handleChangeNavigationItemPopupVisibility(visible);
|
|
@@ -233,7 +236,7 @@ const View = () => {
|
|
|
233
236
|
});
|
|
234
237
|
}
|
|
235
238
|
return (react_1.default.createElement(Main_1.Main, { labelledBy: "title", "aria-busy": isLoadingForSubmit },
|
|
236
|
-
react_1.default.createElement(NavigationHeader_1.default, { structureHasErrors: structureHasErrors, structureHasChanged: structureChanged, availableNavigations: availableNavigations, activeNavigation: activeNavigation, handleChangeSelection: handleChangeNavigationSelection, handleSave: handleSave, handleLocalizationSelection: handleLocalizationSelection, config: config, permissions: {
|
|
239
|
+
react_1.default.createElement(NavigationHeader_1.default, { structureHasErrors: structureHasErrors, structureHasChanged: structureChanged, availableNavigations: availableNavigations, activeNavigation: activeNavigation, handleChangeSelection: handleChangeNavigationSelection, handleSave: handleSave, handleCachePurge: handleCachePurge, handleLocalizationSelection: handleLocalizationSelection, config: config, permissions: {
|
|
237
240
|
canAccess, canUpdate
|
|
238
241
|
} }),
|
|
239
242
|
react_1.default.createElement(Layout_1.ContentLayout, null,
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"header.action.expandAll": "Expand All",
|
|
10
10
|
"submit.cta.cancel": "Cancel",
|
|
11
11
|
"submit.cta.save": "Save",
|
|
12
|
+
"submit.cta.cache.purge": "Clear cache",
|
|
12
13
|
"empty": "Your navigation is empty",
|
|
13
14
|
"empty.cta": "Create first item",
|
|
14
15
|
"popup.item.header.view": "View navigation item",
|
|
@@ -66,10 +67,14 @@
|
|
|
66
67
|
"popup.navigation.manage.button.goBack": "Go back",
|
|
67
68
|
"popup.navigation.manage.button.cancel": "Cancel",
|
|
68
69
|
"popup.navigation.manage.button.delete": "Delete",
|
|
70
|
+
"popup.navigation.manage.button.purge": "Clear read cache",
|
|
71
|
+
"popup.navigation.manage.footer.button.purge": "Clear",
|
|
72
|
+
"popup.navigation.manage.purge.header": "This action will clear API read cache. This will result in brief slowdown of reads for navigations below.",
|
|
69
73
|
"popup.navigation.manage.button.save": "Save",
|
|
70
74
|
"popup.navigation.manage.button.edit": "Edit",
|
|
71
75
|
"popup.navigation.manage.button.create": "Create",
|
|
72
76
|
"popup.navigation.manage.delete.header": "Following navigations will be removed:",
|
|
77
|
+
"popup.navigation.manage.header.CACHE_PURGE": "Read cache clear",
|
|
73
78
|
"popup.navigation.manage.header.LIST": "All navigations",
|
|
74
79
|
"popup.navigation.manage.header.CREATE": "New navigation",
|
|
75
80
|
"popup.navigation.manage.header.DELETE": "Deleting",
|
|
@@ -134,6 +139,8 @@
|
|
|
134
139
|
"pages.settings.form.cascadeMenuAttached.label": "Cascade menu attached",
|
|
135
140
|
"pages.settings.form.cascadeMenuAttached.hint": "Disable if you don't want \"Menu attached\" to cascade on child items",
|
|
136
141
|
"pages.settings.form.contentTypes.label": "Enable navigation for",
|
|
142
|
+
"pages.settings.form.cache.label": "REST cache",
|
|
143
|
+
"pages.settings.form.cache.hint": "Enable caching of client read requests",
|
|
137
144
|
"pages.settings.form.i18n.label": "i18n",
|
|
138
145
|
"pages.settings.form.i18n.hint": "Enable internationalisation",
|
|
139
146
|
"pages.settings.form.i18n.hint.missingDefaultLocale": "Default locale missing!",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-navigation",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Strapi - Navigation plugin",
|
|
5
5
|
"strapi": {
|
|
6
6
|
"name": "navigation",
|
|
@@ -16,19 +16,19 @@
|
|
|
16
16
|
"types": "./types/index.d.ts",
|
|
17
17
|
"dependencies": {
|
|
18
18
|
"@sindresorhus/slugify": "1.1.0",
|
|
19
|
-
"@strapi/utils": "^4.
|
|
19
|
+
"@strapi/utils": "^4.23.1",
|
|
20
20
|
"lodash": "^4.17.21",
|
|
21
21
|
"pluralize": "^8.0.0",
|
|
22
|
-
"react": "^18.
|
|
23
|
-
"react-dom": "^18.
|
|
22
|
+
"react": "^17.0.0 || ^18.0.0",
|
|
23
|
+
"react-dom": "^17.0.0 || ^18.0.0",
|
|
24
24
|
"react-intl": "6.4.1",
|
|
25
25
|
"react-router": "^5.3.4",
|
|
26
|
-
"react-router-dom": "^5.
|
|
26
|
+
"react-router-dom": "^5.2.0",
|
|
27
27
|
"uuid": "^8.3.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@strapi/data-transfer": "4.
|
|
31
|
+
"@strapi/data-transfer": "4.23.1",
|
|
32
32
|
"@strapi/strapi": "4.x",
|
|
33
33
|
"react": "^17.0.0 || ^18.0.0",
|
|
34
34
|
"react-dom": "^17.0.0 || ^18.0.0",
|
|
@@ -6,6 +6,7 @@ const permissions_1 = __importDefault(require("../../permissions"));
|
|
|
6
6
|
const graphql_1 = require("../graphql");
|
|
7
7
|
const navigation_1 = require("../navigation");
|
|
8
8
|
const config_1 = require("../config");
|
|
9
|
+
const cache_1 = require("../cache");
|
|
9
10
|
const assertUserPermissionsAvailability = ({ strapi }) => {
|
|
10
11
|
if (!strapi.plugin("users-permissions")) {
|
|
11
12
|
throw new Error("In order to make the navigation plugin work the users-permissions plugin is required");
|
|
@@ -14,6 +15,7 @@ const assertUserPermissionsAvailability = ({ strapi }) => {
|
|
|
14
15
|
const setupGraphQL = graphql_1.graphQLSetupStrategy;
|
|
15
16
|
const setupNavigation = navigation_1.navigationSetupStrategy;
|
|
16
17
|
const setupConfig = config_1.configSetupStrategy;
|
|
18
|
+
const setupCache = cache_1.setupCacheStrategy;
|
|
17
19
|
const setupPermissions = async ({ strapi }) => {
|
|
18
20
|
const actions = [
|
|
19
21
|
{
|
|
@@ -43,5 +45,6 @@ module.exports = async ({ strapi }) => {
|
|
|
43
45
|
await setupConfig({ strapi });
|
|
44
46
|
await setupGraphQL({ strapi });
|
|
45
47
|
await setupNavigation({ strapi });
|
|
48
|
+
await setupCache({ strapi });
|
|
46
49
|
};
|
|
47
50
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./setupStrategy"), exports);
|
|
18
|
+
//# sourceMappingURL=index.js.map
|