strapi-plugin-navigation 2.2.4 → 2.2.5

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.
Files changed (45) hide show
  1. package/README.md +5 -1
  2. package/admin/src/components/AdditionalFieldInput/index.js +2 -2
  3. package/admin/src/components/AdditionalFieldInput/types.d.ts +1 -0
  4. package/admin/src/components/Item/ItemCardHeader/icons.d.ts +1 -1
  5. package/admin/src/components/Item/ItemCardHeader/icons.js +2 -1
  6. package/admin/src/components/Item/ItemCardHeader/index.d.ts +1 -0
  7. package/admin/src/components/Item/ItemCardHeader/index.js +6 -6
  8. package/admin/src/components/Item/index.js +7 -6
  9. package/admin/src/components/NavigationItemList/index.d.ts +2 -1
  10. package/admin/src/components/NavigationItemList/index.js +2 -2
  11. package/admin/src/hooks/useNavigationManager.d.ts +0 -1
  12. package/admin/src/index.js +1 -1
  13. package/admin/src/pages/DataManagerProvider/reducer.d.ts +1 -1
  14. package/admin/src/pages/NoAccessPage/index.d.ts +3 -0
  15. package/admin/src/pages/NoAccessPage/index.js +31 -0
  16. package/admin/src/pages/SettingsPage/index.d.ts +0 -1
  17. package/admin/src/pages/SettingsPage/index.js +9 -0
  18. package/admin/src/pages/View/components/NavigationHeader/index.d.ts +2 -1
  19. package/admin/src/pages/View/components/NavigationHeader/index.js +9 -8
  20. package/admin/src/pages/View/components/NavigationItemForm/index.js +14 -13
  21. package/admin/src/pages/View/components/NavigationItemForm/types.d.ts +2 -1
  22. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.d.ts +4 -2
  23. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +5 -1
  24. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.d.ts +2 -1
  25. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +6 -2
  26. package/admin/src/pages/View/components/NavigationItemPopup/index.d.ts +2 -1
  27. package/admin/src/pages/View/components/NavigationItemPopup/index.js +4 -3
  28. package/admin/src/pages/View/components/NavigationManager/AllNavigations/icons.d.ts +0 -1
  29. package/admin/src/pages/View/components/NavigationManager/AllNavigations/index.d.ts +0 -1
  30. package/admin/src/pages/View/components/NavigationManager/DeletionConfirm/index.d.ts +0 -1
  31. package/admin/src/pages/View/components/NavigationManager/ErrorDetails/index.d.ts +0 -1
  32. package/admin/src/pages/View/components/NavigationManager/Form/index.d.ts +0 -1
  33. package/admin/src/pages/View/components/NavigationManager/NavigationUpdate/index.d.ts +0 -1
  34. package/admin/src/pages/View/components/NavigationManager/NewNavigation/index.d.ts +0 -1
  35. package/admin/src/pages/View/components/NavigationManager/index.d.ts +0 -1
  36. package/admin/src/pages/View/index.js +39 -19
  37. package/admin/src/permissions.d.ts +4 -0
  38. package/admin/src/permissions.js +1 -0
  39. package/admin/src/translations/en.json +8 -0
  40. package/package.json +2 -2
  41. package/permissions.d.ts +1 -0
  42. package/permissions.js +1 -0
  43. package/server/bootstrap/index.js +6 -0
  44. package/tsconfig.tsbuildinfo +1 -1
  45. package/types/utils.d.ts +5 -0
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { useIntl } from "react-intl";
3
2
  import { Effect } from "../../../../../../../types";
4
3
  import { Navigation } from "../types";
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { Footer } from "../Footer";
3
2
  import { CommonProps, EditState } from "../types";
4
3
  interface Props extends EditState, CommonProps {
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { Footer } from "../Footer";
3
2
  import { CommonProps, CreateState, Navigation } from "../types";
4
3
  interface Props extends CreateState, CommonProps {
@@ -1,4 +1,3 @@
1
- /// <reference types="react" />
2
1
  import { VoidEffect } from "../../../../../../types";
3
2
  import { State } from "./types";
4
3
  interface Props {
@@ -40,6 +40,7 @@ const Select_1 = require("@strapi/design-system/Select");
40
40
  const helper_plugin_1 = require("@strapi/helper-plugin");
41
41
  const EmptyDocuments_1 = __importDefault(require("@strapi/icons/EmptyDocuments"));
42
42
  const Plus_1 = __importDefault(require("@strapi/icons/Plus"));
43
+ const permissions_1 = __importDefault(require("../../permissions"));
43
44
  const NavigationItemList_1 = __importDefault(require("../../components/NavigationItemList"));
44
45
  const NavigationContentHeader_1 = __importDefault(require("./components/NavigationContentHeader"));
45
46
  const NavigationHeader_1 = __importDefault(require("./components/NavigationHeader"));
@@ -49,9 +50,15 @@ const Search_1 = __importDefault(require("../../components/Search"));
49
50
  const useDataManager_1 = __importDefault(require("../../hooks/useDataManager"));
50
51
  const translations_1 = require("../../translations");
51
52
  const parsers_1 = require("./utils/parsers");
53
+ const NoAccessPage_1 = __importDefault(require("../NoAccessPage"));
52
54
  const View = () => {
53
55
  const toggleNotification = (0, helper_plugin_1.useNotification)();
54
56
  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, } = (0, useDataManager_1.default)();
57
+ const viewPermissions = (0, react_1.useMemo)(() => ({
58
+ access: permissions_1.default.access || permissions_1.default.update,
59
+ update: permissions_1.default.update,
60
+ }), []);
61
+ const { isLoading: isLoadingForPermissions, allowedActions: { canAccess, canUpdate, }, } = (0, helper_plugin_1.useRBAC)(viewPermissions);
55
62
  const availableLocale = (0, react_1.useMemo)(() => allAvailableLocale.filter(locale => locale !== changedActiveNavigation?.localeCode), [changedActiveNavigation, allAvailableLocale]);
56
63
  const { i18nCopyItemsModal, i18nCopySourceLocale, setI18nCopyModalOpened, setI18nCopySourceLocale } = (0, useI18nCopyNavigationItemsModal_1.useI18nCopyNavigationItemsModal)((0, react_1.useCallback)((sourceLocale) => {
57
64
  const source = activeNavigation?.localizations?.find(({ localeCode }) => localeCode === sourceLocale);
@@ -80,15 +87,17 @@ const View = () => {
80
87
  handleChangeNavigationItemPopupVisibility(visible);
81
88
  };
82
89
  const addNewNavigationItem = (0, react_1.useCallback)((event, viewParentId = null, isMenuAllowedLevel = true, levelPath = '', parentAttachedToMenu = true, structureId = "0") => {
83
- event.preventDefault();
84
- event.stopPropagation();
85
- changeNavigationItemPopupState(true, {
86
- viewParentId,
87
- isMenuAllowedLevel,
88
- levelPath,
89
- parentAttachedToMenu,
90
- structureId,
91
- });
90
+ if (canUpdate) {
91
+ event.preventDefault();
92
+ event.stopPropagation();
93
+ changeNavigationItemPopupState(true, {
94
+ viewParentId,
95
+ isMenuAllowedLevel,
96
+ levelPath,
97
+ parentAttachedToMenu,
98
+ structureId,
99
+ });
100
+ }
92
101
  }, [changeNavigationItemPopupState]);
93
102
  const usedContentTypesData = (0, react_1.useMemo)(() => changedActiveNavigation ? (0, parsers_1.usedContentTypes)(changedActiveNavigation.items) : [], [changedActiveNavigation]);
94
103
  const pullUsedContentTypeItem = (items = []) => items.reduce((prev, curr) => [...prev, curr.relatedRef ? {
@@ -198,7 +207,9 @@ const View = () => {
198
207
  tradId: 'header.action.collapseAll',
199
208
  margin: '8px',
200
209
  },
201
- {
210
+ ];
211
+ if (canUpdate) {
212
+ endActions.push({
202
213
  onClick: addNewNavigationItem,
203
214
  startIcon: react_1.default.createElement(Plus_1.default, null),
204
215
  disabled: isLoadingForSubmit,
@@ -206,12 +217,17 @@ const View = () => {
206
217
  variant: "default",
207
218
  tradId: 'header.action.newItem',
208
219
  margin: '16px',
209
- },
210
- ];
220
+ });
221
+ }
222
+ if (!canAccess && !isLoadingForPermissions) {
223
+ return (react_1.default.createElement(NoAccessPage_1.default, null));
224
+ }
211
225
  return (react_1.default.createElement(Main_1.Main, { labelledBy: "title", "aria-busy": isLoadingForSubmit },
212
- react_1.default.createElement(NavigationHeader_1.default, { structureHasErrors: structureHasErrors, structureHasChanged: structureChanged, availableNavigations: availableNavigations, activeNavigation: activeNavigation, handleChangeSelection: handleChangeNavigationSelection, handleSave: handleSave, handleLocalizationSelection: handleLocalizationSelection, config: config }),
226
+ react_1.default.createElement(NavigationHeader_1.default, { structureHasErrors: structureHasErrors, structureHasChanged: structureChanged, availableNavigations: availableNavigations, activeNavigation: activeNavigation, handleChangeSelection: handleChangeNavigationSelection, handleSave: handleSave, handleLocalizationSelection: handleLocalizationSelection, config: config, permissions: {
227
+ canAccess, canUpdate
228
+ } }),
213
229
  react_1.default.createElement(Layout_1.ContentLayout, null,
214
- isLoading && react_1.default.createElement(helper_plugin_1.LoadingIndicatorPage, null),
230
+ (isLoading || isLoadingForPermissions) && react_1.default.createElement(helper_plugin_1.LoadingIndicatorPage, null),
215
231
  changedActiveNavigation && (react_1.default.createElement(react_1.default.Fragment, null,
216
232
  react_1.default.createElement(NavigationContentHeader_1.default, { startActions: react_1.default.createElement(Search_1.default, { value: searchValue, setValue: setSearchValue }), endActions: endActions.map(({ tradId, margin, ...item }, i) => react_1.default.createElement(Box_1.Box, { marginLeft: margin, key: i },
217
233
  react_1.default.createElement(Button_1.Button, { ...item },
@@ -222,8 +238,8 @@ const View = () => {
222
238
  react_1.default.createElement(Icon_1.Icon, { as: EmptyDocuments_1.default, width: "160px", height: "88px", color: "" }),
223
239
  react_1.default.createElement(Box_1.Box, { padding: 4 },
224
240
  react_1.default.createElement(Typography_1.Typography, { variant: "beta", textColor: "neutral600" }, formatMessage((0, translations_1.getTrad)('empty')))),
225
- react_1.default.createElement(Button_1.Button, { variant: 'secondary', startIcon: react_1.default.createElement(Plus_1.default, null), label: formatMessage((0, translations_1.getTrad)('empty.cta')), onClick: addNewNavigationItem }, formatMessage((0, translations_1.getTrad)('empty.cta'))),
226
- config.i18nEnabled && availableLocale.length ? (react_1.default.createElement(Flex_1.Flex, { direction: "column", justifyContent: "center" },
241
+ canUpdate && (react_1.default.createElement(Button_1.Button, { variant: 'secondary', startIcon: react_1.default.createElement(Plus_1.default, null), label: formatMessage((0, translations_1.getTrad)('empty.cta')), onClick: addNewNavigationItem }, formatMessage((0, translations_1.getTrad)('empty.cta')))),
242
+ canUpdate && config.i18nEnabled && availableLocale.length ? (react_1.default.createElement(Flex_1.Flex, { direction: "column", justifyContent: "center" },
227
243
  react_1.default.createElement(Box_1.Box, { paddingTop: 3, paddingBottom: 3 },
228
244
  react_1.default.createElement(Typography_1.Typography, { variant: "beta", textColor: "neutral600" }, formatMessage((0, translations_1.getTrad)('view.i18n.fill.cta')))),
229
245
  react_1.default.createElement(Flex_1.Flex, { direction: "row", justifyContent: "center", alignItems: "center" },
@@ -232,9 +248,13 @@ const View = () => {
232
248
  react_1.default.createElement(Box_1.Box, { paddingLeft: 1, paddingRight: 1 },
233
249
  react_1.default.createElement(Button_1.Button, { variant: "tertiary", onClick: openI18nCopyModalOpened, disabled: !i18nCopySourceLocale, size: "S" }, formatMessage((0, translations_1.getTrad)('view.i18n.fill.cta.button'))))))) : null)),
234
250
  !(0, lodash_1.isEmpty)(changedActiveNavigation.items || [])
235
- && react_1.default.createElement(NavigationItemList_1.default, { items: isSearchEmpty ? changedActiveNavigation.items || [] : filteredList, onItemLevelAdd: addNewNavigationItem, onItemRemove: handleItemRemove, onItemEdit: handleItemEdit, onItemRestore: handleItemRestore, onItemReOrder: handleItemReOrder, onItemToggleCollapse: handleItemToggleCollapse, displayFlat: !isSearchEmpty, root: true, error: error, allowedLevels: config.allowedLevels, contentTypes: config.contentTypes, isParentAttachedToMenu: true, contentTypesNameFields: config.contentTypesNameFields })))),
236
- navigationItemPopupOpened && react_1.default.createElement(NavigationItemPopup_1.default, { availableLocale: availableLocale, isLoading: isLoadingForAdditionalDataToBeSet, data: activeNavigationItem, config: config, usedContentTypesData: usedContentTypesData, usedContentTypeItems: usedContentTypeItems, getContentTypeItems: getContentTypeItems, onSubmit: handleSubmitNavigationItem, onClose: onPopUpClose, locale: activeNavigation.localeCode, readNavigationItemFromLocale: readNavigationItemFromLocale, slugify: slugify }),
237
- i18nCopyItemsModal));
251
+ && react_1.default.createElement(NavigationItemList_1.default, { items: isSearchEmpty ? changedActiveNavigation.items || [] : filteredList, onItemLevelAdd: addNewNavigationItem, onItemRemove: handleItemRemove, onItemEdit: handleItemEdit, onItemRestore: handleItemRestore, onItemReOrder: handleItemReOrder, onItemToggleCollapse: handleItemToggleCollapse, displayFlat: !isSearchEmpty, root: true, error: error, allowedLevels: config.allowedLevels, contentTypes: config.contentTypes, isParentAttachedToMenu: true, contentTypesNameFields: config.contentTypesNameFields, permissions: {
252
+ canAccess, canUpdate
253
+ } })))),
254
+ navigationItemPopupOpened && react_1.default.createElement(NavigationItemPopup_1.default, { availableLocale: availableLocale, isLoading: isLoadingForAdditionalDataToBeSet, data: activeNavigationItem, config: config, usedContentTypesData: usedContentTypesData, usedContentTypeItems: usedContentTypeItems, getContentTypeItems: getContentTypeItems, onSubmit: handleSubmitNavigationItem, onClose: onPopUpClose, locale: activeNavigation.localeCode, readNavigationItemFromLocale: readNavigationItemFromLocale, slugify: slugify, permissions: {
255
+ canAccess, canUpdate
256
+ } }),
257
+ canUpdate && i18nCopyItemsModal));
238
258
  };
239
259
  exports.default = (0, react_1.memo)(View);
240
260
  //# sourceMappingURL=index.js.map
@@ -8,5 +8,9 @@ declare namespace pluginPermissions {
8
8
  action: string;
9
9
  subject: null;
10
10
  }[];
11
+ const settings: {
12
+ action: string;
13
+ subject: null;
14
+ }[];
11
15
  }
12
16
  //# sourceMappingURL=permissions.d.ts.map
@@ -7,6 +7,7 @@ const permissions_1 = __importDefault(require("../../permissions"));
7
7
  const pluginPermissions = {
8
8
  access: [{ action: permissions_1.default.render(permissions_1.default.navigation.read), subject: null }],
9
9
  update: [{ action: permissions_1.default.render(permissions_1.default.navigation.update), subject: null }],
10
+ settings: [{ action: permissions_1.default.render(permissions_1.default.navigation.settings), subject: null }],
10
11
  };
11
12
  exports.default = pluginPermissions;
12
13
  //# sourceMappingURL=permissions.js.map
@@ -10,6 +10,7 @@
10
10
  "submit.cta.save": "Save",
11
11
  "empty": "Your navigation is empty",
12
12
  "empty.cta": "Create first item",
13
+ "popup.item.header.view": "View navigation item",
13
14
  "popup.item.header.edit": "Edit navigation item",
14
15
  "popup.item.header.new": "New navigation item",
15
16
  "popup.item.form.title.label": "Title",
@@ -83,6 +84,8 @@
83
84
  "notification.error": "Error while processing request.",
84
85
  "notification.error.customField.type": "Unsupported type of custom field",
85
86
  "notification.error.item.relation": "Relations provided in some items are incorrect",
87
+ "page.auth.noAccess": "No access",
88
+ "page.auth.not.allowed": "Oops! It seems like You do not have access to this page...",
86
89
  "pages.main.search.placeholder": "Type to start searching...",
87
90
  "pages.main.header.localization.select.placeholder": "Select locale",
88
91
  "pages.settings.general.title": "General settings",
@@ -185,6 +188,10 @@
185
188
  "pages.settings.form.customFields.popup.options.description": "Enabling this field will not change already exiting navigation items",
186
189
  "pages.settings.form.customFields.popup.multi.label": "Enable multiple options input",
187
190
  "components.navigationItem.action.newItem": "Add nested item",
191
+ "components.navigationItem.action.edit": "Edit",
192
+ "components.navigationItem.action.view": "View",
193
+ "components.navigationItem.action.restore": "Restore",
194
+ "components.navigationItem.action.remove": "Remove",
188
195
  "components.navigationItem.badge.removed": "Removed",
189
196
  "components.navigationItem.badge.draft": "Draft",
190
197
  "components.navigationItem.badge.published": "Published",
@@ -192,6 +199,7 @@
192
199
  "components.confirmation.dialog.button.confirm": "Confirm",
193
200
  "components.confirmation.dialog.description": "Do you want to continue?",
194
201
  "components.confirmation.dialog.header": "Confirmation",
202
+ "components.notAccessPage.back": "Back to homepage",
195
203
  "view.i18n.fill.cta": "or bootstrap",
196
204
  "view.i18n.fill.option": "{locale} locale",
197
205
  "view.i18n.fill.cta.button": "copy"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "strapi-plugin-navigation",
3
- "version": "2.2.4",
3
+ "version": "2.2.5",
4
4
  "description": "Strapi - Navigation plugin",
5
5
  "strapi": {
6
6
  "name": "navigation",
@@ -15,7 +15,7 @@
15
15
  "scripts": {},
16
16
  "dependencies": {
17
17
  "@sindresorhus/slugify": "1.1.0",
18
- "@strapi/utils": "^4.6.0",
18
+ "@strapi/utils": "^4.9.0",
19
19
  "lodash": "^4.17.11",
20
20
  "pluralize": "^8.0.0",
21
21
  "react": "^16.9.0",
package/permissions.d.ts CHANGED
@@ -3,6 +3,7 @@ declare const _default: {
3
3
  navigation: {
4
4
  read: string;
5
5
  update: string;
6
+ settings: string;
6
7
  };
7
8
  };
8
9
  export default _default;
package/permissions.js CHANGED
@@ -7,6 +7,7 @@ exports.default = {
7
7
  navigation: {
8
8
  read: 'read',
9
9
  update: 'update',
10
+ settings: 'settings',
10
11
  },
11
12
  };
12
13
  //# sourceMappingURL=permissions.js.map
@@ -28,6 +28,12 @@ const setupPermissions = async ({ strapi }) => {
28
28
  uid: permissions_1.default.navigation.update,
29
29
  pluginName: "navigation",
30
30
  },
31
+ {
32
+ section: "plugins",
33
+ displayName: "Settings",
34
+ uid: permissions_1.default.navigation.settings,
35
+ pluginName: "navigation",
36
+ },
31
37
  ];
32
38
  await strapi.admin.services.permission.actionProvider.registerMany(actions);
33
39
  };