strapi-plugin-navigation 1.1.1 → 2.0.0-beta.3

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 (129) hide show
  1. package/README.md +36 -15
  2. package/admin/src/components/EmptyView/index.js +7 -16
  3. package/admin/src/components/Item/ItemCardBadge/index.js +8 -0
  4. package/admin/src/components/Item/ItemCardHeader/Wrapper.js +21 -0
  5. package/admin/src/components/Item/ItemCardHeader/index.js +59 -0
  6. package/admin/src/components/Item/Wrapper.js +39 -0
  7. package/admin/src/components/Item/index.js +76 -124
  8. package/admin/src/components/NavigationItemList/Wrapper.js +22 -0
  9. package/admin/src/components/NavigationItemList/index.js +54 -0
  10. package/admin/src/components/PluginIcon/index.js +6 -0
  11. package/admin/src/index.js +49 -45
  12. package/admin/src/pages/App/index.js +31 -0
  13. package/admin/src/{containers → pages}/DataManagerProvider/actions.js +0 -0
  14. package/admin/src/{containers → pages}/DataManagerProvider/index.js +77 -84
  15. package/admin/src/{containers → pages}/DataManagerProvider/init.js +0 -0
  16. package/admin/src/pages/DataManagerProvider/reducer.js +125 -0
  17. package/admin/src/pages/View/components/NavigationContentHeader/index.js +18 -0
  18. package/admin/src/pages/View/components/NavigationHeader/index.js +60 -0
  19. package/admin/src/pages/View/components/NavigationItemForm/index.js +403 -0
  20. package/admin/src/{containers → pages}/View/components/NavigationItemForm/utils/form.js +2 -2
  21. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupFooter.js +40 -0
  22. package/admin/src/pages/View/components/NavigationItemPopup/NavigationItemPopupHeader.js +20 -0
  23. package/admin/src/{containers → pages}/View/components/NavigationItemPopup/index.js +16 -16
  24. package/admin/src/pages/View/index.js +209 -0
  25. package/admin/src/{containers → pages}/View/utils/enums.js +0 -0
  26. package/admin/src/{containers → pages}/View/utils/form.js +1 -1
  27. package/admin/src/{containers → pages}/View/utils/index.js +0 -0
  28. package/admin/src/{containers → pages}/View/utils/parsers.js +13 -12
  29. package/admin/src/pluginId.js +3 -2
  30. package/admin/src/translations/en.json +47 -38
  31. package/admin/src/translations/fr.json +7 -1
  32. package/admin/src/utils/getTrad.js +2 -2
  33. package/package.json +14 -6
  34. package/server/bootstrap.js +41 -0
  35. package/server/config.js +8 -0
  36. package/server/content-types/audience/index.js +9 -0
  37. package/{models/audience.js → server/content-types/audience/lifecycle.js} +0 -0
  38. package/{models/audience.settings.json → server/content-types/audience/schema.json} +4 -2
  39. package/server/content-types/index.js +13 -0
  40. package/server/content-types/navigation/index.js +9 -0
  41. package/{models/navigation.js → server/content-types/navigation/lifecycle.js} +0 -0
  42. package/server/content-types/navigation/schema.js +45 -0
  43. package/server/content-types/navigation-item/index.js +9 -0
  44. package/{models/navigationItem.js → server/content-types/navigation-item/lifecycle.js} +0 -0
  45. package/{models/navigationItem.settings.json → server/content-types/navigation-item/schema.json} +16 -12
  46. package/server/content-types/navigations-items-related/index.js +9 -0
  47. package/{models/navigations_items_related.js → server/content-types/navigations-items-related/lifecycle.js} +0 -0
  48. package/{models/navigations_items_related.settings.json → server/content-types/navigations-items-related/schema.json} +4 -2
  49. package/server/controllers/index.js +7 -0
  50. package/{controllers → server/controllers}/navigation.js +7 -39
  51. package/server/routes/admin.js +38 -0
  52. package/server/routes/index.js +3 -0
  53. package/{services → server/services}/__tests__/navigation.test.js +0 -0
  54. package/server/services/index.js +7 -0
  55. package/server/services/navigation.js +463 -0
  56. package/{services → server/services}/utils/constant.js +3 -1
  57. package/server/services/utils/functions.js +103 -0
  58. package/strapi-admin.js +1 -0
  59. package/strapi-server.js +18 -0
  60. package/__mocks__/helpers/another-plugin/blog-post.settings.json +0 -31
  61. package/__mocks__/helpers/another-plugin/pages.settings.json +0 -28
  62. package/__mocks__/helpers/blog-post.settings.json +0 -31
  63. package/__mocks__/helpers/home-page.settings.json +0 -4
  64. package/__mocks__/helpers/my-homepage.settings.json +0 -27
  65. package/__mocks__/helpers/pages.settings.json +0 -27
  66. package/__mocks__/helpers/strapi.js +0 -101
  67. package/admin/src/assets/images/icon-cross-blue.svg +0 -1
  68. package/admin/src/assets/images/icon_remove.svg +0 -19
  69. package/admin/src/components/Container/index.js +0 -7
  70. package/admin/src/components/Input/index.js +0 -41
  71. package/admin/src/components/Item/CardItem.js +0 -46
  72. package/admin/src/components/Item/CardItemLevelAdd.js +0 -41
  73. package/admin/src/components/Item/CardItemLevelWrapper.js +0 -27
  74. package/admin/src/components/Item/CardItemPath.js +0 -9
  75. package/admin/src/components/Item/CardItemRestore.js +0 -19
  76. package/admin/src/components/Item/CardItemTitle.js +0 -5
  77. package/admin/src/components/Item/CardWrapper.js +0 -78
  78. package/admin/src/components/ItemFooter/CardItemError.js +0 -11
  79. package/admin/src/components/ItemFooter/CardItemRelation.js +0 -18
  80. package/admin/src/components/ItemFooter/CardItemRelationStatus.js +0 -17
  81. package/admin/src/components/ItemFooter/CardItemType.js +0 -18
  82. package/admin/src/components/ItemFooter/Wrapper.js +0 -26
  83. package/admin/src/components/ItemFooter/index.js +0 -66
  84. package/admin/src/components/ItemOrdering/CardOrderingButton.js +0 -24
  85. package/admin/src/components/ItemOrdering/Wrapper.js +0 -24
  86. package/admin/src/components/ItemOrdering/index.js +0 -36
  87. package/admin/src/components/List/Container.js +0 -34
  88. package/admin/src/components/List/ListLevelRoot.js +0 -18
  89. package/admin/src/components/List/index.js +0 -81
  90. package/admin/src/components/Option/OptionButton.js +0 -18
  91. package/admin/src/components/Option/OptionSet.js +0 -14
  92. package/admin/src/components/Option/Wrapper.js +0 -15
  93. package/admin/src/components/Option/index.js +0 -47
  94. package/admin/src/components/Search/index.js +0 -86
  95. package/admin/src/components/Select/ClearIndicator.js +0 -15
  96. package/admin/src/components/Select/DropdownIndicator.js +0 -39
  97. package/admin/src/components/Select/ErrorMessage.js +0 -10
  98. package/admin/src/components/Select/IndicatorSeparator.js +0 -3
  99. package/admin/src/components/Select/MultiValueContainer.js +0 -43
  100. package/admin/src/components/Select/StyledOption.js +0 -11
  101. package/admin/src/components/Select/index.js +0 -68
  102. package/admin/src/components/Select/utils/styles.js +0 -92
  103. package/admin/src/containers/App/Wrapper.js +0 -14
  104. package/admin/src/containers/App/index.js +0 -34
  105. package/admin/src/containers/DataManagerProvider/reducer.js +0 -136
  106. package/admin/src/containers/DetailsView/Wrapper.js +0 -21
  107. package/admin/src/containers/DetailsView/index.js +0 -111
  108. package/admin/src/containers/Initializer/index.js +0 -26
  109. package/admin/src/containers/ListView/Footer.js +0 -56
  110. package/admin/src/containers/ListView/components.js +0 -138
  111. package/admin/src/containers/ListView/index.js +0 -54
  112. package/admin/src/containers/View/FadedWrapper.js +0 -51
  113. package/admin/src/containers/View/HeaderForm.js +0 -9
  114. package/admin/src/containers/View/HeaderFormCell.js +0 -25
  115. package/admin/src/containers/View/Wrapper.js +0 -17
  116. package/admin/src/containers/View/components/NavigationItemForm/ModalFooter.js +0 -45
  117. package/admin/src/containers/View/components/NavigationItemForm/index.js +0 -427
  118. package/admin/src/containers/View/components/NavigationItemPopup/MediumPopup.js +0 -6
  119. package/admin/src/containers/View/index.js +0 -240
  120. package/admin/src/lifecycles.js +0 -3
  121. package/admin/src/permissions.js +0 -14
  122. package/config/functions/bootstrap.js +0 -138
  123. package/config/routes.json +0 -60
  124. package/config/schema.graphql.js +0 -204
  125. package/examples/audit-log-integrations.js.md +0 -38
  126. package/models/navigation.settings.json +0 -43
  127. package/public/assets/preview.png +0 -0
  128. package/services/navigation.js +0 -730
  129. package/services/utils/functions.js +0 -186
@@ -1,49 +1,53 @@
1
- import pluginPkg from "../../package.json";
2
- import pluginId from "./pluginId";
3
- import App from "./containers/App";
4
- import Initializer from "./containers/Initializer";
5
- import lifecycles from "./lifecycles";
6
- import trads from "./translations";
7
- import pluginPermissions from "./permissions";
1
+ import { prefixPluginTranslations } from '@strapi/helper-plugin';
2
+ import PluginIcon from './components/PluginIcon';
3
+ import pluginPkg from '../../package.json';
4
+ import pluginId from './pluginId';
8
5
 
9
- export default (strapi) => {
10
- const pluginDescription =
11
- pluginPkg.strapi.description || pluginPkg.description;
12
- const { icon, name } = pluginPkg.strapi;
6
+ const name = pluginPkg.strapi.name;
13
7
 
14
- const plugin = {
15
- blockerComponent: null,
16
- blockerComponentProps: {},
17
- description: pluginDescription,
18
- icon,
19
- id: pluginId,
20
- initializer: Initializer,
21
- injectedComponents: [],
22
- isReady: false,
23
- isRequired: pluginPkg.strapi.required || false,
24
- layout: null,
25
- lifecycles,
26
- leftMenuLinks: [],
27
- leftMenuSections: [],
28
- mainComponent: App,
29
- name,
30
- preventComponentRendering: false,
31
- trads,
32
- menu: {
33
- pluginsSectionLinks: [
34
- {
35
- destination: `/plugins/${pluginId}`,
36
- icon,
37
- name,
38
- label: {
39
- id: `${pluginId}.plugin.name`,
40
- defaultMessage: "NAVIGATION",
41
- },
42
- permissions: pluginPermissions.main,
43
- },
44
- ],
45
- },
46
- };
8
+ export default {
9
+ register(app) {
10
+ app.addMenuLink({
11
+ to: `/plugins/${pluginId}`,
12
+ icon: PluginIcon,
13
+ intlLabel: {
14
+ id: `${pluginId}.plugin.name`,
15
+ defaultMessage: 'Navigation',
16
+ },
17
+ Component: async () => {
18
+ const component = await import(/* webpackChunkName: "my-plugin" */ './pages/App');
47
19
 
48
- return strapi.registerPlugin(plugin);
20
+ return component;
21
+ },
22
+ permissions: [],
23
+ });
24
+ app.registerPlugin({
25
+ id: pluginId,
26
+ name,
27
+ });
28
+ },
29
+ bootstrap() {},
30
+ async registerTrads({ locales }) {
31
+ const importedTrads = await Promise.all(
32
+ locales.map(locale => {
33
+ return import(
34
+ /* webpackChunkName: "[pluginId]-[request]" */ `./translations/${locale}.json`
35
+ )
36
+ .then(({ default: data }) => {
37
+ return {
38
+ data: prefixPluginTranslations(data, pluginId),
39
+ locale,
40
+ };
41
+ })
42
+ .catch(() => {
43
+ return {
44
+ data: {},
45
+ locale,
46
+ };
47
+ });
48
+ })
49
+ );
50
+
51
+ return Promise.resolve(importedTrads);
52
+ },
49
53
  };
@@ -0,0 +1,31 @@
1
+ /**
2
+ *
3
+ * This component is the skeleton around the actual pages, and should only
4
+ * contain code that should be seen on all pages. (e.g. navigation bar)
5
+ *
6
+ */
7
+
8
+ import React, { Suspense, lazy } from "react";
9
+ import { Switch, Route } from "react-router-dom";
10
+ import { NotFound, LoadingIndicatorPage } from "@strapi/helper-plugin";
11
+ // Utils
12
+ import DataManagerProvider from "../DataManagerProvider";
13
+ import pluginId from "../../pluginId";
14
+ // Containers
15
+ const View = lazy(() => import("../View"));
16
+
17
+ const App = () => {
18
+ return (
19
+ <DataManagerProvider>
20
+ <Suspense fallback={<LoadingIndicatorPage />}>
21
+ <Switch>
22
+ <Route path={`/plugins/${pluginId}`} component={View} exact />
23
+ <Route component={NotFound} />
24
+ </Switch>
25
+ </Suspense>
26
+ </DataManagerProvider>
27
+ );
28
+ };
29
+
30
+ export default App;
31
+
@@ -1,12 +1,14 @@
1
1
  import React, { memo, useEffect, useReducer, useRef } from "react";
2
+ import { useLocation, useRouteMatch } from "react-router-dom";
3
+ import { useIntl } from 'react-intl';
2
4
  import PropTypes from "prop-types";
3
5
  import { get, find, first, isEmpty } from "lodash";
4
6
  import {
5
7
  request,
6
8
  LoadingIndicatorPage,
7
- useGlobalContext,
8
- } from "strapi-helper-plugin";
9
- import { useLocation, useRouteMatch } from "react-router-dom";
9
+ useNotification,
10
+ useAppInfos,
11
+ } from "@strapi/helper-plugin";
10
12
  import DataManagerContext from "../../contexts/DataManagerContext";
11
13
  import getTrad from "../../utils/getTrad";
12
14
  import pluginId from "../../pluginId";
@@ -30,16 +32,13 @@ import {
30
32
  SUBMIT_NAVIGATION_ERROR,
31
33
  } from './actions';
32
34
  import { prepareItemToViewPayload } from '../View/utils/parsers';
33
- import { getTradId } from "../../translations";
34
35
 
35
36
  const DataManagerProvider = ({ children }) => {
36
37
  const [reducerState, dispatch] = useReducer(reducer, initialState, init);
37
- const {
38
- autoReload,
39
- emitEvent,
40
- currentEnvironment,
41
- formatMessage,
42
- } = useGlobalContext();
38
+ const toggleNotification = useNotification();
39
+ const { autoReload } = useAppInfos();
40
+ const { formatMessage } = useIntl();
41
+
43
42
  const {
44
43
  items,
45
44
  config,
@@ -54,9 +53,8 @@ const DataManagerProvider = ({ children }) => {
54
53
  isLoadingForAdditionalDataToBeSet,
55
54
  isLoadingForSubmit,
56
55
  error
57
- } = reducerState.toJS();
56
+ } = reducerState;
58
57
  const { pathname } = useLocation();
59
-
60
58
  const formatMessageRef = useRef();
61
59
  formatMessageRef.current = formatMessage;
62
60
 
@@ -64,8 +62,7 @@ const DataManagerProvider = ({ children }) => {
64
62
  getLayoutSettingRef.current = (settingName) =>
65
63
  get({}, ["settings", settingName], "");
66
64
 
67
- const isInDevelopmentMode =
68
- currentEnvironment === "development" && autoReload;
65
+ const isInDevelopmentMode = autoReload;
69
66
 
70
67
  const abortController = new AbortController();
71
68
  const { signal } = abortController;
@@ -95,9 +92,11 @@ const DataManagerProvider = ({ children }) => {
95
92
  });
96
93
  }
97
94
  } catch (err) {
98
- // please don't do this, because js stringify a error and that error is not readable in dev tool
99
- console.error(err);
100
- strapi.notification.error("notification.error");
95
+ console.error({ err });
96
+ toggleNotification({
97
+ type: 'error',
98
+ message: { id: 'notification.error' },
99
+ });
101
100
  }
102
101
  };
103
102
 
@@ -110,7 +109,6 @@ const DataManagerProvider = ({ children }) => {
110
109
  method: "GET",
111
110
  signal,
112
111
  });
113
-
114
112
  dispatch({
115
113
  type: GET_CONFIG_SUCCEEDED,
116
114
  config,
@@ -134,7 +132,10 @@ const DataManagerProvider = ({ children }) => {
134
132
  }
135
133
  } catch (err) {
136
134
  console.error({ err });
137
- strapi.notification.error("notification.error");
135
+ toggleNotification({
136
+ type: 'error',
137
+ message: { id: 'notification.error' },
138
+ });
138
139
  }
139
140
  };
140
141
 
@@ -152,21 +153,19 @@ const DataManagerProvider = ({ children }) => {
152
153
  }, [isLoading, pathname]);
153
154
 
154
155
  useEffect(() => {
155
- if (currentEnvironment === "development" && !autoReload) {
156
- strapi.notification.info(
157
- formatMessageRef.current({
158
- id: getTrad("notification.info.autoreaload-disable"),
159
- }),
160
- );
156
+ if (!autoReload) {
157
+ toggleNotification({
158
+ type: 'info',
159
+ message: { id: getTrad('notification.info.autoreaload-disable') },
160
+ });
161
161
  }
162
- }, [autoReload, currentEnvironment]);
162
+ }, [autoReload]);
163
163
 
164
- const getContentTypeItems = async ({type, query}, plugin = "") => {
164
+ const getContentTypeItems = async ({ modelUID, query }) => {
165
165
  dispatch({
166
166
  type: GET_CONTENT_TYPE_ITEMS,
167
167
  });
168
- const url = plugin ? `/${plugin}/${type}` : `/${type}`;
169
-
168
+ const url =`/navigation/content-type-items/${modelUID}`;
170
169
  const queryParams = new URLSearchParams();
171
170
  queryParams.append('_publicationState', 'preview');
172
171
  if (query) {
@@ -178,14 +177,13 @@ const DataManagerProvider = ({ children }) => {
178
177
  signal,
179
178
  });
180
179
 
181
- const fetchedContentType = find(config.contentTypes, ct => ct.endpoint === type);
182
-
180
+ const fetchedContentType = find(config.contentTypes, ct => ct.uid === modelUID);
183
181
  const isArray = Array.isArray(contentTypeItems);
184
182
  dispatch({
185
183
  type: GET_CONTENT_TYPE_ITEMS_SUCCEEDED,
186
184
  contentTypeItems: (isArray ? contentTypeItems : [contentTypeItems]).map(item => ({
187
185
  ...item,
188
- __collectionName: get(fetchedContentType, 'collectionName', type),
186
+ __collectionUid: get(fetchedContentType, 'collectionUid', modelUID),
189
187
  })),
190
188
  });
191
189
  };
@@ -195,86 +193,81 @@ const DataManagerProvider = ({ children }) => {
195
193
  };
196
194
 
197
195
  const handleChangeNavigationPopupVisibility = (visible) => {
198
- emitEvent("willChangeNavigationPopupVisibility");
199
196
  dispatch({
200
197
  type: CHANGE_NAVIGATION_POPUP_VISIBILITY,
201
198
  navigationPopupOpened: visible,
202
199
  });
203
- emitEvent("didChangeNavigationPopupVisibility");
204
- emitEvent(`navigationPopup${visible ? "Visible" : "Hidden"}`);
205
200
  };
206
201
 
207
202
  const handleChangeNavigationItemPopupVisibility = (visible) => {
208
- emitEvent("willChangeNavigationItemPopupVisibility");
209
203
  dispatch({
210
204
  type: CHANGE_NAVIGATION_ITEM_POPUP_VISIBILITY,
211
205
  navigationItemPopupOpened: visible,
212
206
  });
213
- emitEvent("didChangeNavigationItemPopupVisibility");
214
- emitEvent(`navigationItemPopup${visible ? "Visible" : "Hidden"}`);
215
207
  };
216
208
 
217
209
  const handleChangeNavigationData = (payload, forceClosePopups) => {
218
- emitEvent("willChangeNavigationData");
219
210
  dispatch({
220
211
  type: CHANGE_NAVIGATION_DATA,
221
212
  changedActiveItem: payload,
222
213
  forceClosePopups,
223
214
  });
224
- emitEvent("didChangeNavigationData");
225
215
  };
226
216
 
227
217
  const handleResetNavigationData = () => {
228
- emitEvent("willResetNavigationChanges");
229
- dispatch({
218
+ dispatch({
230
219
  type: RESET_NAVIGATION_DATA,
231
220
  activeItem,
232
221
  });
233
- emitEvent("didResetNavigationChanges");
234
222
  };
235
223
 
236
224
  const handleSubmitNavigation = async (formatMessage, payload = {}) => {
237
- try {
238
- emitEvent("willSubmitNavigation");
239
- dispatch({
240
- type: SUBMIT_NAVIGATION,
241
- });
242
-
243
- const nagivationId = payload.id ? `/${payload.id}` : "";
244
- const method = payload.id ? "PUT" : "POST";
245
- const navigation = await request(`/${pluginId}${nagivationId}`, {
246
- method,
247
- signal,
248
- body: payload,
249
- });
250
-
251
- dispatch({
252
- type: SUBMIT_NAVIGATION_SUCCEEDED,
253
- navigation: {
254
- ...navigation,
255
- items: prepareItemToViewPayload(navigation.items, null, config),
256
- },
257
- });
258
- emitEvent("didSubmitNavigation");
259
-
260
- strapi.notification.success(getTradId('notification.navigation.submit'));
261
- } catch (err) {
262
- dispatch({
263
- type: SUBMIT_NAVIGATION_ERROR,
264
- error: err.response.payload.data
265
- });
266
- console.error({ err: err.response });
267
- emitEvent('didNotSubmitNavigation');
268
- if (err.response.payload.data && err.response.payload.data.errorTitles) {
269
- return strapi.notification.error(
270
- formatMessage(
271
- getTrad('notification.navigation.error'),
272
- { ...err.response.payload.data, errorTitles: err.response.payload.data.errorTitles.join(' and ') },
273
- ),
274
- );
275
- }
276
- strapi.notification.error('notification.error');
277
- }
225
+ try {
226
+ dispatch({
227
+ type: SUBMIT_NAVIGATION,
228
+ });
229
+
230
+ const nagivationId = payload.id ? `/${payload.id}` : "";
231
+ const method = payload.id ? "PUT" : "POST";
232
+ const navigation = await request(`/${pluginId}${nagivationId}`, {
233
+ method,
234
+ signal,
235
+ body: payload,
236
+ });
237
+ dispatch({
238
+ type: SUBMIT_NAVIGATION_SUCCEEDED,
239
+ navigation: {
240
+ ...navigation,
241
+ items: prepareItemToViewPayload(navigation.items, null, config),
242
+ },
243
+ });
244
+ toggleNotification({
245
+ type: 'success',
246
+ message: { id: getTrad('notification.navigation.submit') },
247
+ });
248
+ } catch (err) {
249
+ dispatch({
250
+ type: SUBMIT_NAVIGATION_ERROR,
251
+ error: err.response.payload.data
252
+ });
253
+ console.error({ err: err.response });
254
+
255
+ if (err.response.payload.data && err.response.payload.data.errorTitles) {
256
+ return toggleNotification({
257
+ type: 'error',
258
+ message: {
259
+ id: formatMessage(
260
+ getTrad('notification.navigation.error'),
261
+ { ...err.response.payload.data, errorTitles: err.response.payload.data.errorTitles.join(' and ') },
262
+ )
263
+ },
264
+ });
265
+ }
266
+ toggleNotification({
267
+ type: 'error',
268
+ message: { id: getTrad('notification.error') },
269
+ });
270
+ }
278
271
  };
279
272
 
280
273
  return (
@@ -0,0 +1,125 @@
1
+ import produce from 'immer';
2
+
3
+ import {
4
+ GET_LIST_DATA,
5
+ GET_LIST_DATA_SUCCEEDED,
6
+ GET_NAVIGATION_DATA,
7
+ GET_NAVIGATION_DATA_SUCCEEDED,
8
+ RELOAD_PLUGIN,
9
+ RESET_NAVIGATION_DATA,
10
+ CHANGE_NAVIGATION_POPUP_VISIBILITY,
11
+ CHANGE_NAVIGATION_ITEM_POPUP_VISIBILITY,
12
+ CHANGE_NAVIGATION_DATA,
13
+ GET_CONFIG,
14
+ GET_CONFIG_SUCCEEDED,
15
+ GET_CONTENT_TYPE_ITEMS,
16
+ GET_CONTENT_TYPE_ITEMS_SUCCEEDED,
17
+ SUBMIT_NAVIGATION_SUCCEEDED,
18
+ SUBMIT_NAVIGATION,
19
+ SUBMIT_NAVIGATION_ERROR,
20
+ } from './actions';
21
+
22
+ const initialState = {
23
+ items: [],
24
+ activeItem: undefined,
25
+ changedActiveItem: undefined,
26
+ navigationPopupOpened: false,
27
+ navigationItemPopupOpened: false,
28
+ config: {},
29
+ isLoading: true,
30
+ isLoadingForDataToBeSet: false,
31
+ isLoadingForDetailsDataToBeSet: false,
32
+ isLoadingForAdditionalDataToBeSet: false,
33
+ isLoadingForSubmit: false,
34
+ error: undefined,
35
+ };
36
+
37
+ const reducer = (state, action) => produce(state, draftState => {
38
+ switch (action.type) {
39
+ case GET_CONFIG: {
40
+ draftState.isLoadingForDetailsDataToBeSet = true;
41
+ draftState.config = {};
42
+ break;
43
+ }
44
+ case GET_CONFIG_SUCCEEDED: {
45
+ draftState.isLoadingForDetailsDataToBeSet = false;
46
+ draftState.config = action.config;
47
+ break;
48
+ }
49
+ case GET_LIST_DATA: {
50
+ draftState.items = [];
51
+ draftState.isLoadingForDataToBeSet = true;
52
+ break;
53
+ }
54
+ case GET_LIST_DATA_SUCCEEDED: {
55
+ draftState.items = action.items;
56
+ draftState.isLoading = false;
57
+ draftState.isLoadingForDataToBeSet = false;
58
+ break;
59
+ }
60
+ case GET_NAVIGATION_DATA: {
61
+ draftState.activeItem = undefined;
62
+ draftState.changedActiveItem = undefined;
63
+ draftState.isLoadingForDetailsDataToBeSet = true;
64
+ break;
65
+ }
66
+ case GET_NAVIGATION_DATA_SUCCEEDED: {
67
+ const activeItem = action.activeItem || {};
68
+ draftState.activeItem = activeItem;
69
+ draftState.changedActiveItem = activeItem;
70
+ draftState.isLoadingForDetailsDataToBeSet = false;
71
+ break;
72
+ }
73
+ case CHANGE_NAVIGATION_DATA: {
74
+ draftState.changedActiveItem = action.changedActiveItem;
75
+ draftState.navigationPopupOpened = action.forceClosePopups ? false : state.navigationPopupOpened;
76
+ draftState.navigationItemPopupOpened = action.forceClosePopups ? false : state.navigationItemPopupOpened;
77
+ break;
78
+ }
79
+ case RESET_NAVIGATION_DATA : {
80
+ draftState.changedActiveItem = action.activeItem || {};
81
+ break;
82
+ }
83
+ case GET_CONTENT_TYPE_ITEMS: {
84
+ draftState.isLoadingForAdditionalDataToBeSet = true;
85
+ break;
86
+ }
87
+ case GET_CONTENT_TYPE_ITEMS_SUCCEEDED: {
88
+ draftState.isLoadingForAdditionalDataToBeSet = false;
89
+ draftState.config.contentTypeItems = action.contentTypeItems;
90
+ break;
91
+ }
92
+ case CHANGE_NAVIGATION_POPUP_VISIBILITY: {
93
+ draftState.navigationPopupOpened = action.navigationPopupOpened;
94
+ break;
95
+ }
96
+ case CHANGE_NAVIGATION_ITEM_POPUP_VISIBILITY: {
97
+ draftState.navigationItemPopupOpened = action.navigationItemPopupOpened;
98
+ break;
99
+ }
100
+ case SUBMIT_NAVIGATION: {
101
+ draftState.isLoadingForSubmit = true;
102
+ draftState.error = undefined;
103
+ break;
104
+ }
105
+ case SUBMIT_NAVIGATION_SUCCEEDED: {
106
+ draftState.activeItem = action.navigation || {};
107
+ draftState.changedActiveItem = action.navigation || {};
108
+ draftState.isLoadingForSubmit = false;
109
+ break;
110
+ }
111
+ case SUBMIT_NAVIGATION_ERROR: {
112
+ draftState.isLoadingForSubmit = false;
113
+ draftState.error = action.error;
114
+ break;
115
+ }
116
+ case RELOAD_PLUGIN: {
117
+ return initialState;
118
+ }
119
+ default:
120
+ return draftState;
121
+ }
122
+ });
123
+
124
+ export default reducer;
125
+ export { initialState };
@@ -0,0 +1,18 @@
1
+ import React from 'react';
2
+
3
+ import { Flex } from '@strapi/design-system/Flex';
4
+
5
+ const NavigationContentHeader = ({ startActions, endActions }) => {
6
+ return (
7
+ <Flex justifyContent="space-between" width="100%">
8
+ <Flex alignItems="space-between">
9
+ {startActions}
10
+ </Flex>
11
+ <Flex alignItems="space-between">
12
+ {endActions}
13
+ </Flex>
14
+ </Flex>
15
+ );
16
+ }
17
+
18
+ export default NavigationContentHeader;
@@ -0,0 +1,60 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import { HeaderLayout } from '@strapi/design-system/Layout';
4
+ import { Stack } from '@strapi/design-system/Stack';
5
+ import { Button } from '@strapi/design-system/Button';
6
+ import { IconButton } from '@strapi/design-system/IconButton';
7
+ import Check from '@strapi/icons/Check';
8
+ import More from '@strapi/icons/More';
9
+ import Plus from '@strapi/icons/Plus';
10
+ import styled from 'styled-components';
11
+ import { getTrad } from '../../../../translations';
12
+ import { transformToRESTPayload } from '../../utils/parsers';
13
+ const MoreButton = styled(IconButton)`
14
+ margin: ${({ theme }) => `0 ${theme.spaces[2]}`};
15
+ padding: ${({ theme }) => theme.spaces[2]};
16
+
17
+ svg {
18
+ width: ${18 / 16}rem;
19
+ height: ${18 / 16}rem;
20
+ }
21
+ `;
22
+
23
+ const NavigationHeader = ({
24
+ structureHasErrors,
25
+ handleSave,
26
+ }) => {
27
+ const { formatMessage } = useIntl();
28
+
29
+ return (
30
+ <HeaderLayout
31
+ primaryAction={
32
+ <Stack horizontal size={2}>
33
+ <Button
34
+ onClick={handleSave}
35
+ startIcon={<Check />}
36
+ disabled={structureHasErrors}
37
+ type="submit"
38
+ >
39
+ {formatMessage(getTrad('submit.cta.save'))}
40
+ </Button>
41
+ <MoreButton
42
+ id="more"
43
+ label="More"
44
+ icon={<More />}
45
+ />
46
+ </Stack>
47
+ }
48
+ title={formatMessage({
49
+ id: getTrad('header.title'),
50
+ defaultMessage: 'UI Navigation',
51
+ })}
52
+ subtitle={formatMessage({
53
+ id: getTrad('header.description'),
54
+ defaultMessage: 'Define your portal navigation',
55
+ })}
56
+ />
57
+ );
58
+ };
59
+
60
+ export default NavigationHeader;