strapi-plugin-navigation 2.3.1 → 2.4.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 +47 -6
- package/admin/src/components/AdditionalFieldInput/index.d.ts +2 -2
- package/admin/src/components/AdditionalFieldInput/index.js +36 -8
- package/admin/src/components/AdditionalFieldInput/types.d.ts +1 -1
- package/admin/src/components/DragButton/index.d.ts +3 -1
- package/admin/src/components/DragButton/index.js +2 -1
- package/admin/src/components/Item/ItemCardHeader/index.d.ts +1 -0
- package/admin/src/components/Item/ItemCardHeader/index.js +10 -5
- package/admin/src/components/Item/index.js +24 -4
- package/admin/src/components/NavigationItemList/index.js +1 -1
- package/admin/src/components/Search/index.d.ts +10 -4
- package/admin/src/components/Search/index.js +45 -6
- package/admin/src/components/TextArrayInput/index.d.ts +2 -1
- package/admin/src/hooks/useAllContentTypes.d.ts +1 -1
- package/admin/src/hooks/useNavigationConfig.d.ts +3 -3
- package/admin/src/index.d.ts +3 -1
- package/admin/src/pages/SettingsPage/common/const.d.ts +2 -0
- package/admin/src/pages/SettingsPage/common/const.js +5 -0
- package/admin/src/pages/SettingsPage/common/index.d.ts +2 -0
- package/admin/src/pages/SettingsPage/common/index.js +18 -0
- package/admin/src/pages/SettingsPage/components/CustomFieldForm/index.js +27 -12
- package/admin/src/pages/SettingsPage/components/CustomFieldTable/index.js +1 -1
- package/admin/src/pages/SettingsPage/components/DisableI18nModal/index.d.ts +2 -3
- package/admin/src/pages/SettingsPage/components/DisableI18nModal/index.js +12 -14
- package/admin/src/pages/SettingsPage/index.js +3 -2
- package/admin/src/pages/SettingsPage/utils/form.js +2 -1
- package/admin/src/pages/View/components/NavigationItemForm/index.js +49 -19
- package/admin/src/pages/View/components/NavigationItemForm/types.d.ts +2 -1
- package/admin/src/pages/View/components/NavigationItemForm/utils/form.js +2 -0
- package/admin/src/pages/View/index.js +20 -10
- package/admin/src/pages/View/utils/form.d.ts +1 -1
- package/admin/src/pages/View/utils/types.d.ts +3 -0
- package/admin/src/pages/View/utils/types.js +3 -0
- package/admin/src/translations/ca.json +1 -0
- package/admin/src/translations/en.json +3 -0
- package/admin/src/translations/fr.json +1 -0
- package/admin/src/utils/api.d.ts +4 -4
- package/admin/src/utils/api.js +1 -1
- package/package.json +8 -3
- package/server/content-types/index.d.ts +2 -0
- package/server/content-types/navigation/index.d.ts +1 -0
- package/server/content-types/navigation/index.js +3 -1
- package/server/content-types/navigation/lifecycles.d.ts +3 -0
- package/server/content-types/navigation/lifecycles.js +7 -0
- package/server/content-types/navigation-item/index.d.ts +1 -0
- package/server/content-types/navigation-item/index.js +3 -1
- package/server/content-types/navigation-item/lifecycles.d.ts +3 -0
- package/server/content-types/navigation-item/lifecycles.js +7 -0
- package/server/controllers/admin.js +19 -16
- package/server/controllers/client.js +6 -4
- package/server/graphql/queries/render-navigation-child.d.ts +1 -1
- package/server/graphql/queries/render-navigation.d.ts +1 -1
- package/server/graphql/types/index.js +1 -0
- package/server/graphql/types/navigation-item-additional-field-media.d.ts +5 -0
- package/server/graphql/types/navigation-item-additional-field-media.js +13 -0
- package/server/graphql/types/navigation-item.js +3 -0
- package/server/i18n/utils.d.ts +1 -0
- package/server/i18n/utils.js +4 -0
- package/server/index.d.ts +2 -0
- package/server/services/admin.js +18 -8
- package/server/services/client.js +42 -11
- package/server/services/common.js +17 -5
- package/server/utils/constant.d.ts +3 -0
- package/server/utils/constant.js +21 -1
- package/server/utils/functions.d.ts +16 -4
- package/server/utils/functions.js +54 -8
- package/strapi-server.d.ts +2 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/types/contentTypes.d.ts +7 -2
- package/types/controllers.d.ts +4 -3
- package/types/index.d.ts +1 -0
- package/types/index.js +1 -0
- package/types/lifecycle.d.ts +22 -0
- package/types/lifecycle.js +3 -0
- package/types/services.d.ts +13 -1
|
@@ -31,7 +31,6 @@ const react_1 = __importStar(require("react"));
|
|
|
31
31
|
const ConfirmationDialog_1 = __importDefault(require("../../../../components/ConfirmationDialog"));
|
|
32
32
|
const utils_1 = require("../../../../utils");
|
|
33
33
|
const formik_1 = require("formik");
|
|
34
|
-
const helper_plugin_1 = require("@strapi/helper-plugin");
|
|
35
34
|
const Stack_1 = require("@strapi/design-system/Stack");
|
|
36
35
|
const Box_1 = require("@strapi/design-system/Box");
|
|
37
36
|
const Grid_1 = require("@strapi/design-system/Grid");
|
|
@@ -45,25 +44,24 @@ const DisableI18nModal = ({ onSubmit, onCancel }) => {
|
|
|
45
44
|
onSubmit(state);
|
|
46
45
|
}, [onSubmit, state]);
|
|
47
46
|
return (react_1.default.createElement(ConfirmationDialog_1.default, { isVisible: true, header: (0, utils_1.getMessage)("pages.settings.actions.disableI18n.confirmation.header"), labelConfirm: (0, utils_1.getMessage)("pages.settings.actions.disableI18n.confirmation.confirm"), iconConfirm: refreshIcon, mainIcon: refreshIcon, onConfirm: onConfirm, onCancel: onCancel },
|
|
48
|
-
react_1.default.createElement(formik_1.Formik, { initialValues: INITIAL_VALUES, onSubmit: onConfirm }, ({
|
|
47
|
+
react_1.default.createElement(formik_1.Formik, { initialValues: INITIAL_VALUES, onSubmit: onConfirm }, ({ setFieldValue, values }) => (react_1.default.createElement(react_1.default.Fragment, null,
|
|
49
48
|
react_1.default.createElement(Grid_1.Grid, { gap: 4 },
|
|
50
49
|
react_1.default.createElement(Grid_1.GridItem, { col: 12 },
|
|
51
50
|
react_1.default.createElement(Box_1.Box, { padding: 2 }, (0, utils_1.getMessage)("pages.settings.actions.disableI18n.confirmation.description.line1")),
|
|
52
51
|
react_1.default.createElement(Box_1.Box, { padding: 2 }, (0, utils_1.getMessage)("pages.settings.actions.disableI18n.confirmation.description.line2")),
|
|
53
52
|
react_1.default.createElement(Box_1.Box, { padding: 2 },
|
|
54
53
|
react_1.default.createElement(Typography_1.Typography, { fontWeight: "bold" }, (0, utils_1.getMessage)("pages.settings.actions.disableI18n.confirmation.description.line3"))))),
|
|
55
|
-
react_1.default.createElement(
|
|
56
|
-
react_1.default.createElement(
|
|
57
|
-
react_1.default.createElement(Grid_1.
|
|
58
|
-
react_1.default.createElement(
|
|
59
|
-
react_1.default.createElement(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}, onLabel: (0, utils_1.getMessage)("pages.settings.actions.disableI18n.prune.on"), offLabel: (0, utils_1.getMessage)("pages.settings.actions.disableI18n.prune.off") })))))))))));
|
|
54
|
+
react_1.default.createElement(Stack_1.Stack, { spacing: 4 },
|
|
55
|
+
react_1.default.createElement(Grid_1.Grid, { gap: 4 },
|
|
56
|
+
react_1.default.createElement(Grid_1.GridItem, { col: 12 },
|
|
57
|
+
react_1.default.createElement(Box_1.Box, { padding: 2 },
|
|
58
|
+
react_1.default.createElement(ToggleInput_1.ToggleInput, { name: "audienceFieldChecked", label: (0, utils_1.getMessage)("pages.settings.actions.disableI18n.prune.label"), hint: "", checked: values.pruneNavigations, onChange: ({ target: { checked }, }) => {
|
|
59
|
+
setFieldValue("pruneNavigations", checked, false);
|
|
60
|
+
setState((state) => ({
|
|
61
|
+
...state,
|
|
62
|
+
pruneNavigations: checked,
|
|
63
|
+
}));
|
|
64
|
+
}, onLabel: (0, utils_1.getMessage)("pages.settings.actions.disableI18n.prune.on"), offLabel: (0, utils_1.getMessage)("pages.settings.actions.disableI18n.prune.off") }))))))))));
|
|
67
65
|
};
|
|
68
66
|
exports.DisableI18nModal = DisableI18nModal;
|
|
69
67
|
const useDisableI18nModal = (onSubmit) => {
|
|
@@ -67,9 +67,10 @@ const BOX_DEFAULT_PROPS = {
|
|
|
67
67
|
shadow: "filterShadow",
|
|
68
68
|
padding: 6,
|
|
69
69
|
};
|
|
70
|
+
const noopFallback = () => { };
|
|
70
71
|
const SettingsPage = () => {
|
|
71
|
-
const { lockApp, unlockApp } = (0, helper_plugin_1.useOverlayBlocker)();
|
|
72
|
-
const { lockAppWithAutoreload, unlockAppWithAutoreload } = (0, helper_plugin_1.useAutoReloadOverlayBlocker)();
|
|
72
|
+
const { lockApp = noopFallback, unlockApp = noopFallback } = (0, helper_plugin_1.useOverlayBlocker)();
|
|
73
|
+
const { lockAppWithAutoreload = noopFallback, unlockAppWithAutoreload = noopFallback } = (0, helper_plugin_1.useAutoReloadOverlayBlocker)();
|
|
73
74
|
const [restartStatus, setRestartStatus] = (0, react_1.useState)(RESTART_NOT_REQUIRED);
|
|
74
75
|
const [pruneObsoleteI18nNavigations, setPruneObsoleteI18nNavigations] = (0, react_1.useState)(false);
|
|
75
76
|
const [isCustomFieldModalOpen, setIsCustomFieldModalOpen] = (0, react_1.useState)(false);
|
|
@@ -4,11 +4,12 @@ exports.defaultValues = exports.schemaFactory = void 0;
|
|
|
4
4
|
const yup_1 = require("yup");
|
|
5
5
|
const helper_plugin_1 = require("@strapi/helper-plugin");
|
|
6
6
|
const translations_1 = require("../../../translations");
|
|
7
|
+
const common_1 = require("../common");
|
|
7
8
|
const schemaFactory = (usedCustomFieldNames) => {
|
|
8
9
|
return (0, yup_1.object)({
|
|
9
10
|
name: (0, yup_1.string)().matches(/^\S+$/, "Invalid name string. Name cannot contain spaces").required(helper_plugin_1.translatedErrors.required).notOneOf(usedCustomFieldNames, helper_plugin_1.translatedErrors.unique),
|
|
10
11
|
label: (0, yup_1.string)().required(helper_plugin_1.translatedErrors.required),
|
|
11
|
-
type: (0, yup_1.mixed)().required(helper_plugin_1.translatedErrors.required).oneOf(
|
|
12
|
+
type: (0, yup_1.mixed)().required(helper_plugin_1.translatedErrors.required).oneOf(common_1.customFieldsTypes, (0, translations_1.getTradId)("notification.error.customField.type")),
|
|
12
13
|
required: (0, yup_1.bool)().required(helper_plugin_1.translatedErrors.required),
|
|
13
14
|
multi: (0, yup_1.mixed)().when('type', {
|
|
14
15
|
is: (val) => val === 'select',
|
|
@@ -47,9 +47,9 @@ const utils_2 = require("../../../../utils");
|
|
|
47
47
|
const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading, inputsPrefix, data, contentTypes = [], contentTypeEntities = [], usedContentTypeEntities = [], availableAudience = [], additionalFields = [], contentTypesNameFields = {}, onSubmit, onCancel, getContentTypeEntities, usedContentTypesData, appendLabelPublicationStatus = appendLabelPublicationStatusFallback, locale, readNavigationItemFromLocale, slugify, permissions = {}, }) => {
|
|
48
48
|
const [isLoading, setIsLoading] = (0, react_1.useState)(isPreloading);
|
|
49
49
|
const [hasBeenInitialized, setInitializedState] = (0, react_1.useState)(false);
|
|
50
|
+
const [autoSync, setAutoSync] = (0, react_1.useState)(true);
|
|
50
51
|
const [hasChanged, setChangedState] = (0, react_1.useState)(false);
|
|
51
52
|
const [contentTypeSearchQuery, setContentTypeSearchQuery] = (0, react_1.useState)(undefined);
|
|
52
|
-
const [contentTypeSearchInputValue, setContentTypeSearchInputValue] = (0, react_1.useState)(undefined);
|
|
53
53
|
const { canUpdate } = permissions;
|
|
54
54
|
const formik = (0, formik_1.useFormik)({
|
|
55
55
|
initialValues: formDefinition.defaultValues,
|
|
@@ -61,14 +61,17 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
61
61
|
const relatedTypeSelectValue = formik.values.relatedType;
|
|
62
62
|
const relatedSelectValue = formik.values.related;
|
|
63
63
|
const isI18nBootstrapAvailable = !!(config.i18nEnabled && availableLocale && availableLocale.length);
|
|
64
|
-
const availableLocaleOptions = (0, react_1.useMemo)(() => availableLocale.map((locale) => ({
|
|
64
|
+
const availableLocaleOptions = (0, react_1.useMemo)(() => availableLocale.map((locale, index) => ({
|
|
65
|
+
key: `${locale}-${index}`,
|
|
65
66
|
value: locale,
|
|
66
67
|
label: locale,
|
|
67
68
|
metadatas: {
|
|
68
69
|
intlLabel: {
|
|
69
70
|
id: `i18n.locale.${locale}`,
|
|
70
71
|
defaultMessage: locale,
|
|
71
|
-
}
|
|
72
|
+
},
|
|
73
|
+
hidden: false,
|
|
74
|
+
disabled: false,
|
|
72
75
|
},
|
|
73
76
|
})), [availableLocale]);
|
|
74
77
|
const relatedFieldName = `${inputsPrefix}related`;
|
|
@@ -107,7 +110,7 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
107
110
|
values: { value }
|
|
108
111
|
};
|
|
109
112
|
}
|
|
110
|
-
return
|
|
113
|
+
return undefined;
|
|
111
114
|
};
|
|
112
115
|
const getDefaultTitle = (0, react_1.useCallback)((related, relatedType, isSingleSelected) => {
|
|
113
116
|
let selectedEntity;
|
|
@@ -155,6 +158,28 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
155
158
|
updated: true,
|
|
156
159
|
[name]: value,
|
|
157
160
|
}));
|
|
161
|
+
if (name === "related" && relatedTypeSelectValue && autoSync) {
|
|
162
|
+
const { contentTypesNameFields, pathDefaultFields } = config;
|
|
163
|
+
const selectedRelated = contentTypeEntities.find(({ id, __collectionUid }) => `${id}` === `${value}` && __collectionUid === relatedTypeSelectValue);
|
|
164
|
+
const newPath = pathDefaultFields[relatedTypeSelectValue]?.reduce((acc, field) => {
|
|
165
|
+
return acc ? acc : selectedRelated?.[field];
|
|
166
|
+
}, null);
|
|
167
|
+
const newTitle = (contentTypesNameFields[relatedTypeSelectValue] ?? []).concat(contentTypesNameFields.default || []).reduce((acc, field) => {
|
|
168
|
+
return acc ? acc : selectedRelated?.[field];
|
|
169
|
+
}, null);
|
|
170
|
+
const batch = [];
|
|
171
|
+
if (newPath) {
|
|
172
|
+
batch.push({ name: "path", value: newPath });
|
|
173
|
+
}
|
|
174
|
+
if (newTitle) {
|
|
175
|
+
batch.push({ name: "title", value: newTitle });
|
|
176
|
+
}
|
|
177
|
+
batch.forEach((next, i) => {
|
|
178
|
+
setTimeout(() => {
|
|
179
|
+
onChange(next);
|
|
180
|
+
}, i * 100);
|
|
181
|
+
});
|
|
182
|
+
}
|
|
158
183
|
if (name === "type") {
|
|
159
184
|
formik.setErrors({});
|
|
160
185
|
}
|
|
@@ -181,9 +206,12 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
181
206
|
const onAudienceChange = (0, react_1.useCallback)((value) => {
|
|
182
207
|
onChange({ name: "audience", value });
|
|
183
208
|
}, [onChange]);
|
|
184
|
-
const onAdditionalFieldChange = (name, newValue) => {
|
|
209
|
+
const onAdditionalFieldChange = (name, newValue, fieldType) => {
|
|
185
210
|
const fieldsValue = formik.values.additionalFields;
|
|
186
|
-
const value = {
|
|
211
|
+
const value = {
|
|
212
|
+
...fieldsValue,
|
|
213
|
+
[name]: fieldType === "media" && newValue ? JSON.stringify(newValue) : newValue
|
|
214
|
+
};
|
|
187
215
|
onChange({
|
|
188
216
|
name: "additionalFields",
|
|
189
217
|
value,
|
|
@@ -212,7 +240,9 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
212
240
|
intlLabel: {
|
|
213
241
|
id: (0, translations_1.getTradId)(`popup.item.form.type.${value}.label`),
|
|
214
242
|
defaultMessage: (0, translations_1.getTradId)(`popup.item.form.type.${value}.label`),
|
|
215
|
-
}
|
|
243
|
+
},
|
|
244
|
+
hidden: false,
|
|
245
|
+
disabled: false,
|
|
216
246
|
}
|
|
217
247
|
};
|
|
218
248
|
});
|
|
@@ -228,29 +258,25 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
228
258
|
__collectionUid: (0, lodash_1.get)(relatedTypeSelectValue, 'value', relatedTypeSelectValue),
|
|
229
259
|
}, contentTypesNameFields, { contentTypes }), item);
|
|
230
260
|
return ({
|
|
231
|
-
key: (0, lodash_1.get)(item, 'id'),
|
|
261
|
+
key: (0, lodash_1.get)(item, 'id').toString(),
|
|
232
262
|
metadatas: {
|
|
233
263
|
intlLabel: {
|
|
234
264
|
id: label || `${item.__collectionUid} ${item.id}`,
|
|
235
265
|
defaultMessage: label || `${item.__collectionUid} ${item.id}`,
|
|
236
|
-
}
|
|
266
|
+
},
|
|
267
|
+
hidden: false,
|
|
268
|
+
disabled: false,
|
|
237
269
|
},
|
|
238
|
-
value: item.id,
|
|
270
|
+
value: item.id.toString(),
|
|
239
271
|
label: label,
|
|
240
272
|
});
|
|
241
273
|
}), item => item.metadatas.intlLabel.id);
|
|
242
274
|
const isExternal = formik.values.type === utils_1.navigationItemType.EXTERNAL;
|
|
243
275
|
const pathSourceName = isExternal ? 'externalPath' : 'path';
|
|
244
276
|
const submitDisabled = (formik.values.type === utils_1.navigationItemType.INTERNAL && !isSingleSelected && (0, lodash_1.isNil)(formik.values.related)) || isLoading;
|
|
245
|
-
const debouncedSearch = (0, react_1.useCallback)((0, lodash_1.debounce)(nextValue => setContentTypeSearchQuery(nextValue), 500), []);
|
|
246
|
-
const debounceContentTypeSearchQuery = (value) => {
|
|
247
|
-
setContentTypeSearchInputValue(value);
|
|
248
|
-
debouncedSearch(value);
|
|
249
|
-
};
|
|
250
277
|
const onChangeRelatedType = ({ target: { name, value } }) => {
|
|
251
278
|
const relatedTypeBeingReverted = data.relatedType && (data.relatedType.value === (0, lodash_1.get)(value, 'value', value));
|
|
252
279
|
setContentTypeSearchQuery(undefined);
|
|
253
|
-
setContentTypeSearchInputValue(undefined);
|
|
254
280
|
formik.setValues(prevState => ({
|
|
255
281
|
...prevState,
|
|
256
282
|
updated: true,
|
|
@@ -277,7 +303,9 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
277
303
|
intlLabel: {
|
|
278
304
|
id: (0, lodash_1.get)(item, 'label', (0, lodash_1.get)(item, 'name')),
|
|
279
305
|
defaultMessage: (0, lodash_1.get)(item, 'label', (0, lodash_1.get)(item, 'name')),
|
|
280
|
-
}
|
|
306
|
+
},
|
|
307
|
+
disabled: false,
|
|
308
|
+
hidden: false,
|
|
281
309
|
},
|
|
282
310
|
value: (0, lodash_1.get)(item, 'uid'),
|
|
283
311
|
label: (0, lodash_1.get)(item, 'label', (0, lodash_1.get)(item, 'name')),
|
|
@@ -386,7 +414,7 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
386
414
|
react_1.default.createElement(ModalLayout_1.ModalBody, null,
|
|
387
415
|
react_1.default.createElement(Grid_1.Grid, { gap: 5 },
|
|
388
416
|
react_1.default.createElement(Grid_1.GridItem, { key: "title", col: 12 },
|
|
389
|
-
react_1.default.createElement(helper_plugin_1.GenericInput, {
|
|
417
|
+
react_1.default.createElement(helper_plugin_1.GenericInput, { intlLabel: (0, translations_1.getTrad)('popup.item.form.title.label', 'Title'), name: "title", placeholder: (0, translations_1.getTrad)("e.g. Blog", 'e.g. Blog'), description: (0, translations_1.getTrad)('popup.item.form.title.placeholder', 'e.g. Blog'), type: "text", disabled: !canUpdate, error: formik.errors.title, onChange: ({ target: { name, value } }) => onChange({ name, value }), value: formik.values.title })),
|
|
390
418
|
react_1.default.createElement(Grid_1.GridItem, { key: "type", col: 4, lg: 12 },
|
|
391
419
|
react_1.default.createElement(helper_plugin_1.GenericInput, { intlLabel: (0, translations_1.getTrad)('popup.item.form.type.label', 'Internal link'), name: "type", options: navigationItemTypeOptions, type: "select", disabled: !canUpdate, error: formik.errors.type, onChange: ({ target: { name, value } }) => onChange({ name, value }), value: formik.values.type })),
|
|
392
420
|
react_1.default.createElement(Grid_1.GridItem, { key: "menuAttached", col: 4, lg: 12 },
|
|
@@ -394,12 +422,14 @@ const NavigationItemForm = ({ config, availableLocale, isLoading: isPreloading,
|
|
|
394
422
|
react_1.default.createElement(Grid_1.GridItem, { key: "path", col: 12 },
|
|
395
423
|
react_1.default.createElement(helper_plugin_1.GenericInput, { intlLabel: (0, translations_1.getTrad)(`popup.item.form.${pathSourceName}.label`, 'Path'), name: pathSourceName, placeholder: (0, translations_1.getTrad)(`popup.item.form.${pathSourceName}.placeholder`, 'e.g. Blog'), type: "text", disabled: !canUpdate, error: formik.errors[pathSourceName], onChange: ({ target: { name, value } }) => onChange({ name, value }), value: formik.values[pathSourceName], description: generatePreviewPath() })),
|
|
396
424
|
formik.values.type === utils_1.navigationItemType.INTERNAL && (react_1.default.createElement(react_1.default.Fragment, null,
|
|
425
|
+
react_1.default.createElement(Grid_1.GridItem, { key: "menuAttached", col: 12 },
|
|
426
|
+
react_1.default.createElement(helper_plugin_1.GenericInput, { intlLabel: (0, translations_1.getTrad)('popup.item.form.autoSync.label', 'Read fields from related'), name: "autoSync", type: "bool", onChange: ({ target: { value } }) => setAutoSync(value), value: autoSync })),
|
|
397
427
|
react_1.default.createElement(Grid_1.GridItem, { col: 6, lg: 12 },
|
|
398
428
|
react_1.default.createElement(helper_plugin_1.GenericInput, { type: "select", intlLabel: (0, translations_1.getTrad)('popup.item.form.relatedType.label', 'Related Type'), placeholder: (0, translations_1.getTrad)('popup.item.form.relatedType.placeholder', 'Related Type'), name: "relatedType", error: formik.errors.relatedType, onChange: onChangeRelatedType, options: relatedTypeSelectOptions, value: formik.values.relatedType, disabled: isLoading || (0, lodash_1.isEmpty)(relatedTypeSelectOptions) || !canUpdate, description: !isLoading && (0, lodash_1.isEmpty)(relatedTypeSelectOptions)
|
|
399
429
|
? (0, translations_1.getTrad)('popup.item.form.relatedType.empty', 'There are no more content types')
|
|
400
430
|
: undefined })),
|
|
401
431
|
formik.values.relatedType && !isSingleSelected && (react_1.default.createElement(Grid_1.GridItem, { col: 6, lg: 12 },
|
|
402
|
-
react_1.default.createElement(helper_plugin_1.GenericInput, { type: "select", intlLabel: (0, translations_1.getTrad)('popup.item.form.related.label', 'Related'), placeholder: (0, translations_1.getTrad)('popup.item.form.related.label', 'Related'), name: "related", error: formik.errors.related, onChange: ({ target: { name, value } }) => onChange({ name, value }),
|
|
432
|
+
react_1.default.createElement(helper_plugin_1.GenericInput, { type: "select", intlLabel: (0, translations_1.getTrad)('popup.item.form.related.label', 'Related'), placeholder: (0, translations_1.getTrad)('popup.item.form.related.label', 'Related'), name: "related", error: formik.errors.related, onChange: ({ target: { name, value } }) => onChange({ name, value }), options: relatedSelectOptions, value: formik.values.related, disabled: isLoading || thereAreNoMoreContentTypes || !canUpdate, description: !isLoading && thereAreNoMoreContentTypes
|
|
403
433
|
? {
|
|
404
434
|
id: (0, translations_1.getTradId)('popup.item.form.related.empty'),
|
|
405
435
|
defaultMessage: 'There are no more entities',
|
|
@@ -40,6 +40,7 @@ export type NavigationItemFormData = {
|
|
|
40
40
|
};
|
|
41
41
|
relatedRef?: ToBeFixed;
|
|
42
42
|
structureId: ToBeFixed;
|
|
43
|
+
additionalFields?: ToBeFixed;
|
|
43
44
|
};
|
|
44
45
|
export type NavigationItemFormProps = {
|
|
45
46
|
additionalFields: NavigationItemAdditionalField[];
|
|
@@ -63,7 +64,7 @@ export type NavigationItemFormProps = {
|
|
|
63
64
|
slugify: (q: string) => Promise<{
|
|
64
65
|
slug: string;
|
|
65
66
|
}>;
|
|
66
|
-
permissions: PluginPermissions
|
|
67
|
+
permissions: Partial<PluginPermissions>;
|
|
67
68
|
};
|
|
68
69
|
export type ContentTypeSearchQuery = ToBeFixed;
|
|
69
70
|
export type RawFormPayload = {
|
|
@@ -89,6 +89,8 @@ const schemaFactory = (isSingleSelected, additionalFields) => {
|
|
|
89
89
|
value = yup.array().of(yup.string());
|
|
90
90
|
else if (current.type === 'select' && !current.multi)
|
|
91
91
|
value = yup.string();
|
|
92
|
+
else if (current.type === 'media')
|
|
93
|
+
value = yup.mixed();
|
|
92
94
|
else
|
|
93
95
|
throw new Error(`Type "${current.type}" is unsupported by custom fields`);
|
|
94
96
|
if (current.required)
|
|
@@ -66,7 +66,7 @@ const View = () => {
|
|
|
66
66
|
const openI18nCopyModalOpened = (0, react_1.useCallback)(() => { i18nCopySourceLocale && setI18nCopyModalOpened(true); }, [setI18nCopyModalOpened, i18nCopySourceLocale]);
|
|
67
67
|
const [activeNavigationItem, setActiveNavigationItemState] = (0, react_1.useState)({});
|
|
68
68
|
const { formatMessage } = (0, react_intl_1.useIntl)();
|
|
69
|
-
const [searchValue, setSearchValue] = (0, react_1.useState)('');
|
|
69
|
+
const [{ value: searchValue, index: searchIndex }, setSearchValue] = (0, react_1.useState)({ value: '' });
|
|
70
70
|
const [structureChanged, setStructureChanged] = (0, react_1.useState)(false);
|
|
71
71
|
const isSearchEmpty = (0, lodash_1.isEmpty)(searchValue);
|
|
72
72
|
const normalisedSearchValue = (searchValue || '').toLowerCase();
|
|
@@ -114,14 +114,23 @@ const View = () => {
|
|
|
114
114
|
handleChangeNavigationData(changedStructure, true);
|
|
115
115
|
setStructureChanged(true);
|
|
116
116
|
};
|
|
117
|
-
const filteredListFactory = (items, doUse
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
117
|
+
const filteredListFactory = (items, doUse, activeIndex) => {
|
|
118
|
+
const filteredItems = items.reduce((acc, item) => {
|
|
119
|
+
const subItems = !(0, lodash_1.isEmpty)(item.items) ? filteredListFactory(item.items, doUse) : [];
|
|
120
|
+
if (doUse(item))
|
|
121
|
+
return [item, ...subItems, ...acc];
|
|
122
|
+
else
|
|
123
|
+
return [...subItems, ...acc];
|
|
124
|
+
}, []);
|
|
125
|
+
if (activeIndex !== undefined) {
|
|
126
|
+
const index = activeIndex % filteredItems.length;
|
|
127
|
+
return filteredItems.map((item, currentIndex) => {
|
|
128
|
+
return index === currentIndex ? ({ ...item, isSearchActive: true }) : item;
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return filteredItems;
|
|
132
|
+
};
|
|
133
|
+
const filteredList = !isSearchEmpty ? filteredListFactory(changedActiveNavigation.items.map(_ => ({ ..._ })), (item) => (item?.title || '').toLowerCase().includes(normalisedSearchValue), normalisedSearchValue ? searchIndex : undefined) : [];
|
|
125
134
|
const changeCollapseItemDeep = (item, isCollapsed) => {
|
|
126
135
|
if (item.collapsed !== isCollapsed) {
|
|
127
136
|
return {
|
|
@@ -173,6 +182,7 @@ const View = () => {
|
|
|
173
182
|
...item,
|
|
174
183
|
collapsed: !item.collapsed,
|
|
175
184
|
updated: true,
|
|
185
|
+
isSearchActive: false,
|
|
176
186
|
});
|
|
177
187
|
};
|
|
178
188
|
const handleItemEdit = (item, levelPath = '', parentAttachedToMenu = true) => {
|
|
@@ -191,7 +201,7 @@ const View = () => {
|
|
|
191
201
|
};
|
|
192
202
|
const handleChangeNavigationSelection = (...args) => {
|
|
193
203
|
handleChangeSelection(...args);
|
|
194
|
-
setSearchValue('');
|
|
204
|
+
setSearchValue({ value: '', index: 0 });
|
|
195
205
|
};
|
|
196
206
|
const endActions = [
|
|
197
207
|
{
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export function checkFormValidity(data: any, schema: any): Promise<
|
|
1
|
+
export function checkFormValidity(data: any, schema: any): Promise<Record<string, import("@strapi/helper-plugin").TranslationMessage> | null>;
|
|
2
2
|
//# sourceMappingURL=form.d.ts.map
|
|
@@ -27,6 +27,7 @@
|
|
|
27
27
|
"notification.navigation.submit": "S'han desat els canvis de navegació",
|
|
28
28
|
"pages.main.header.localization.select.placeholder": "Seleccioneu la configuració regional",
|
|
29
29
|
"pages.main.search.placeholder": "Escriviu per començar a cercar...",
|
|
30
|
+
"pages.main.search.subLabel": "appuyez sur ENTER pour mettre en surbrillance l'élément suivant",
|
|
30
31
|
"pages.settings.actions.disableI18n.confirmation.confirm": "entenc",
|
|
31
32
|
"pages.settings.actions.disableI18n.confirmation.description.line1": "Esteu desactivant la internacionalització per a la navegació. Les navegacions per a configuracions regionals diferents de les predeterminades no estan disponibles per a la visualització i modificacions mitjançant aquesta extensió.",
|
|
32
33
|
"pages.settings.actions.disableI18n.confirmation.description.line2": "Podeu optar per eliminar les navegacions per a altres configuracions regionals.",
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
"popup.item.header.edit": "Edit navigation item",
|
|
16
16
|
"popup.item.header.new": "New navigation item",
|
|
17
17
|
"popup.item.form.title.label": "Title",
|
|
18
|
+
"popup.item.form.autoSync.label": "Read fields from related",
|
|
18
19
|
"popup.item.form.title.placeholder": "Enter the item title or leave blank to pull from related entity",
|
|
19
20
|
"popup.item.form.uiRouterKey.label": "UI router key",
|
|
20
21
|
"popup.item.form.uiRouterKey.placeholder": "If empty, auto generated by \"Title\"",
|
|
@@ -84,11 +85,13 @@
|
|
|
84
85
|
"notification.navigation.item.relation.status.published": "published",
|
|
85
86
|
"notification.error": "Error while processing request.",
|
|
86
87
|
"notification.error.customField.type": "Unsupported type of custom field",
|
|
88
|
+
"notification.error.customField.media.missing": "Media input component is missing",
|
|
87
89
|
"notification.error.item.relation": "Relations provided in some items are incorrect",
|
|
88
90
|
"notification.error.item.slug": "Unable to create valid UI Router Key(slug) from \"{ query }\". \"{ result }\" received",
|
|
89
91
|
"page.auth.noAccess": "No access",
|
|
90
92
|
"page.auth.not.allowed": "Oops! It seems like You do not have access to this page...",
|
|
91
93
|
"pages.main.search.placeholder": "Type to start searching...",
|
|
94
|
+
"pages.main.search.subLabel": "press ENTER to highlight next item",
|
|
92
95
|
"pages.main.header.localization.select.placeholder": "Select locale",
|
|
93
96
|
"pages.settings.general.title": "General settings",
|
|
94
97
|
"pages.settings.additional.title": "Additional settings",
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
"empty.cta": "Créer un premier élément",
|
|
10
10
|
"popup.item.header": "Modifiez les éléments de navigation",
|
|
11
11
|
"popup.item.form.title.label": "Titre",
|
|
12
|
+
"popup.item.form.autoSync.label": "Lire les champs associés",
|
|
12
13
|
"popup.item.form.title.placeholder": "Saisissez le titre de l'élément ou laissez le champ vide pour utiliser celui de l'entité associée",
|
|
13
14
|
"popup.item.form.uiRouterKey.label": "Clé de routeur pour l'interface utilisateur",
|
|
14
15
|
"popup.item.form.uiRouterKey.placeholder": "Si vide, généré automatiquement par \"Title\"",
|
package/admin/src/utils/api.d.ts
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { NavigationPluginConfig } from '../../../types';
|
|
2
|
-
export declare const fetchNavigationConfig: () =>
|
|
2
|
+
export declare const fetchNavigationConfig: () => Promise<unknown>;
|
|
3
3
|
export declare const updateNavigationConfig: ({ body }: {
|
|
4
4
|
body: NavigationPluginConfig;
|
|
5
|
-
}) =>
|
|
6
|
-
export declare const restoreNavigationConfig: () =>
|
|
5
|
+
}) => Promise<unknown>;
|
|
6
|
+
export declare const restoreNavigationConfig: () => Promise<unknown>;
|
|
7
7
|
export declare const fetchAllContentTypes: () => Promise<any>;
|
|
8
|
-
export declare const restartStrapi: () =>
|
|
8
|
+
export declare const restartStrapi: () => Promise<unknown>;
|
|
9
9
|
//# sourceMappingURL=api.d.ts.map
|
package/admin/src/utils/api.js
CHANGED
|
@@ -9,7 +9,7 @@ const fp_1 = require("lodash/fp");
|
|
|
9
9
|
const pluginId_1 = __importDefault(require("../pluginId"));
|
|
10
10
|
const fetchNavigationConfig = () => (0, helper_plugin_1.request)(`/${pluginId_1.default}/settings/config`, { method: 'GET' });
|
|
11
11
|
exports.fetchNavigationConfig = fetchNavigationConfig;
|
|
12
|
-
const updateNavigationConfig = ({ body }) => (0, helper_plugin_1.request)(`/${pluginId_1.default}/config`, { method: 'PUT', body }, true);
|
|
12
|
+
const updateNavigationConfig = ({ body }) => (0, helper_plugin_1.request)(`/${pluginId_1.default}/config`, { method: 'PUT', body: body }, true);
|
|
13
13
|
exports.updateNavigationConfig = updateNavigationConfig;
|
|
14
14
|
const restoreNavigationConfig = () => (0, helper_plugin_1.request)(`/${pluginId_1.default}/config`, { method: 'DELETE' }, true);
|
|
15
15
|
exports.restoreNavigationConfig = restoreNavigationConfig;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "strapi-plugin-navigation",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "Strapi - Navigation plugin",
|
|
5
5
|
"strapi": {
|
|
6
6
|
"name": "navigation",
|
|
@@ -16,7 +16,7 @@
|
|
|
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.20.0",
|
|
20
20
|
"lodash": "^4.17.21",
|
|
21
21
|
"pluralize": "^8.0.0",
|
|
22
22
|
"react": "^18.2.0",
|
|
@@ -28,7 +28,12 @@
|
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {},
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"@strapi/
|
|
31
|
+
"@strapi/data-transfer": "4.15.5",
|
|
32
|
+
"@strapi/strapi": "4.x",
|
|
33
|
+
"react": "^17.0.0 || ^18.0.0",
|
|
34
|
+
"react-dom": "^17.0.0 || ^18.0.0",
|
|
35
|
+
"react-router-dom": "^5.2.0",
|
|
36
|
+
"styled-components": "^5.2.1"
|
|
32
37
|
},
|
|
33
38
|
"author": {
|
|
34
39
|
"name": "VirtusLab",
|
|
@@ -79,6 +79,7 @@ declare const _default: {
|
|
|
79
79
|
};
|
|
80
80
|
};
|
|
81
81
|
};
|
|
82
|
+
lifecycles: Record<import("../../types").LifeCycleHookName, import("../../types").Effect<import("../../types").LifeCycleEvent<import("../../types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
|
|
82
83
|
};
|
|
83
84
|
"navigation-item": {
|
|
84
85
|
schema: {
|
|
@@ -182,6 +183,7 @@ declare const _default: {
|
|
|
182
183
|
};
|
|
183
184
|
};
|
|
184
185
|
};
|
|
186
|
+
lifecycles: Record<import("../../types").LifeCycleHookName, import("../../types").Effect<import("../../types").LifeCycleEvent<import("../../types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
|
|
185
187
|
};
|
|
186
188
|
"navigations-items-related": {
|
|
187
189
|
schema: {
|
|
@@ -53,6 +53,7 @@ declare const _default: {
|
|
|
53
53
|
};
|
|
54
54
|
};
|
|
55
55
|
};
|
|
56
|
+
lifecycles: Record<import("../../../types").LifeCycleHookName, import("../../../types").Effect<import("../../../types").LifeCycleEvent<import("../../../types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
|
|
56
57
|
};
|
|
57
58
|
export default _default;
|
|
58
59
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -3,8 +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
|
+
const lifecycles_1 = __importDefault(require("./lifecycles"));
|
|
6
7
|
const schema_1 = __importDefault(require("./schema"));
|
|
7
8
|
exports.default = {
|
|
8
|
-
schema: schema_1.default
|
|
9
|
+
schema: schema_1.default,
|
|
10
|
+
lifecycles: lifecycles_1.default,
|
|
9
11
|
};
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const _default: Record<import("../../../types").LifeCycleHookName, import("../../../types").Effect<import("../../../types").LifeCycleEvent<import("../../../types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
|
|
2
|
+
export default _default;
|
|
3
|
+
//# sourceMappingURL=lifecycles.d.ts.map
|
|
@@ -100,6 +100,7 @@ declare const _default: {
|
|
|
100
100
|
};
|
|
101
101
|
};
|
|
102
102
|
};
|
|
103
|
+
lifecycles: Record<import("../../../types").LifeCycleHookName, import("../../../types").Effect<import("../../../types").LifeCycleEvent<import("../../../types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
|
|
103
104
|
};
|
|
104
105
|
export default _default;
|
|
105
106
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -3,8 +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
|
+
const lifecycles_1 = __importDefault(require("./lifecycles"));
|
|
6
7
|
const schema_1 = __importDefault(require("./schema"));
|
|
7
8
|
exports.default = {
|
|
8
|
-
schema: schema_1.default
|
|
9
|
+
schema: schema_1.default,
|
|
10
|
+
lifecycles: lifecycles_1.default
|
|
9
11
|
};
|
|
10
12
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
declare const _default: Record<import("../../../types").LifeCycleHookName, import("../../../types").Effect<import("../../../types").LifeCycleEvent<import("../../../types").LifeCycleHookName, unknown, Record<string, unknown>>>>;
|
|
2
|
+
export default _default;
|
|
3
|
+
//# sourceMappingURL=lifecycles.d.ts.map
|