@akemona-org/strapi-plugin-content-type-builder 3.7.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.
Files changed (223) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +19 -0
  3. package/admin/src/InjectedComponents/ContentManager/EditSettingViewButton.js +76 -0
  4. package/admin/src/InjectedComponents/ContentManager/EditViewLink.js +44 -0
  5. package/admin/src/assets/images/logo.svg +1 -0
  6. package/admin/src/components/AllowedTypesSelect/MenuList.js +115 -0
  7. package/admin/src/components/AllowedTypesSelect/Text.js +26 -0
  8. package/admin/src/components/AllowedTypesSelect/index.js +55 -0
  9. package/admin/src/components/AttributeOption/Button.js +50 -0
  10. package/admin/src/components/AttributeOption/Card.js +26 -0
  11. package/admin/src/components/AttributeOption/index.js +127 -0
  12. package/admin/src/components/BooleanBox/CT.js +21 -0
  13. package/admin/src/components/BooleanBox/Enumeration.js +10 -0
  14. package/admin/src/components/BooleanBox/EnumerationWrapper.js +14 -0
  15. package/admin/src/components/BooleanBox/Label.js +9 -0
  16. package/admin/src/components/BooleanBox/ST.js +21 -0
  17. package/admin/src/components/BooleanBox/Wrapper.js +75 -0
  18. package/admin/src/components/BooleanBox/icons/CTSelected.js +136 -0
  19. package/admin/src/components/BooleanBox/icons/CTUnselected.js +136 -0
  20. package/admin/src/components/BooleanBox/icons/STSelected.js +80 -0
  21. package/admin/src/components/BooleanBox/icons/STUnselected.js +76 -0
  22. package/admin/src/components/BooleanBox/index.js +103 -0
  23. package/admin/src/components/CheckboxWithDescription/Wrapper.js +12 -0
  24. package/admin/src/components/CheckboxWithDescription/index.js +40 -0
  25. package/admin/src/components/ComponentCard/Close.js +12 -0
  26. package/admin/src/components/ComponentCard/Wrapper.js +84 -0
  27. package/admin/src/components/ComponentCard/index.js +62 -0
  28. package/admin/src/components/ComponentIconPicker/Cell.js +40 -0
  29. package/admin/src/components/ComponentIconPicker/CellRenderer.js +36 -0
  30. package/admin/src/components/ComponentIconPicker/Search.js +12 -0
  31. package/admin/src/components/ComponentIconPicker/SearchWrapper.js +34 -0
  32. package/admin/src/components/ComponentIconPicker/Wrapper.js +60 -0
  33. package/admin/src/components/ComponentIconPicker/index.js +143 -0
  34. package/admin/src/components/ComponentList/index.js +78 -0
  35. package/admin/src/components/ComponentSelect/Category.js +20 -0
  36. package/admin/src/components/ComponentSelect/CategoryName.js +11 -0
  37. package/admin/src/components/ComponentSelect/MenuList.js +110 -0
  38. package/admin/src/components/ComponentSelect/MultipleMenuList.js +271 -0
  39. package/admin/src/components/ComponentSelect/Value.js +83 -0
  40. package/admin/src/components/ComponentSelect/index.js +83 -0
  41. package/admin/src/components/ComponentSelect/utils/HasSomeSubArray.js +5 -0
  42. package/admin/src/components/ComponentSelect/utils/hasSubArray.js +5 -0
  43. package/admin/src/components/CreatableSelect/index.js +58 -0
  44. package/admin/src/components/CustomCheckbox/StyledCustomCheckbox.js +25 -0
  45. package/admin/src/components/CustomCheckbox/index.js +71 -0
  46. package/admin/src/components/CustomLink/P.js +17 -0
  47. package/admin/src/components/CustomLink/StyledCustomLink.js +20 -0
  48. package/admin/src/components/CustomLink/index.js +31 -0
  49. package/admin/src/components/DynamicZoneList/ComponentButton.js +39 -0
  50. package/admin/src/components/DynamicZoneList/index.js +124 -0
  51. package/admin/src/components/HeaderModalNavContainer/index.js +25 -0
  52. package/admin/src/components/HeaderNavLink/Wrapper.js +21 -0
  53. package/admin/src/components/HeaderNavLink/index.js +50 -0
  54. package/admin/src/components/List/List.js +131 -0
  55. package/admin/src/components/List/index.js +295 -0
  56. package/admin/src/components/ListButton/index.js +9 -0
  57. package/admin/src/components/ListHeader/Title.js +19 -0
  58. package/admin/src/components/ListHeader/Wrapper.js +24 -0
  59. package/admin/src/components/ListHeader/index.js +37 -0
  60. package/admin/src/components/ListRow/Wrapper.js +76 -0
  61. package/admin/src/components/ListRow/index.js +334 -0
  62. package/admin/src/components/ModalHeader/ComponentIcon.js +21 -0
  63. package/admin/src/components/ModalHeader/ComponentInfos.js +22 -0
  64. package/admin/src/components/ModalHeader/ComponentInfosWrapper.js +9 -0
  65. package/admin/src/components/ModalHeader/DropdownInfos.js +50 -0
  66. package/admin/src/components/ModalHeader/Icon.js +26 -0
  67. package/admin/src/components/ModalHeader/IconWrapper.js +11 -0
  68. package/admin/src/components/ModalHeader/Item.js +19 -0
  69. package/admin/src/components/ModalHeader/Menu.js +8 -0
  70. package/admin/src/components/ModalHeader/Toggle.js +14 -0
  71. package/admin/src/components/ModalHeader/Wrapper.js +12 -0
  72. package/admin/src/components/ModalHeader/index.js +105 -0
  73. package/admin/src/components/RelationForm/Wrapper.js +9 -0
  74. package/admin/src/components/RelationForm/index.js +66 -0
  75. package/admin/src/components/RelationFormBox/Wrapper.js +34 -0
  76. package/admin/src/components/RelationFormBox/index.js +85 -0
  77. package/admin/src/components/RelationFormNaturePicker/Wrapper.js +53 -0
  78. package/admin/src/components/RelationFormNaturePicker/index.js +112 -0
  79. package/admin/src/components/RelationTargetPicker/Item.js +62 -0
  80. package/admin/src/components/RelationTargetPicker/Wrapper.js +89 -0
  81. package/admin/src/components/RelationTargetPicker/index.js +88 -0
  82. package/admin/src/components/SelectCheckbox/index.js +8 -0
  83. package/admin/src/components/SelectMenuSubUl/ToggleUl.js +23 -0
  84. package/admin/src/components/SelectMenuSubUl/index.js +23 -0
  85. package/admin/src/components/SelectMenuUl/index.js +66 -0
  86. package/admin/src/components/Td/index.js +37 -0
  87. package/admin/src/components/UpperFirst/index.js +14 -0
  88. package/admin/src/components/WrapperSelect/index.js +89 -0
  89. package/admin/src/containers/App/Wrapper.js +14 -0
  90. package/admin/src/containers/App/index.js +39 -0
  91. package/admin/src/containers/App/utils/icons.json +962 -0
  92. package/admin/src/containers/DataManagerProvider/constants.js +15 -0
  93. package/admin/src/containers/DataManagerProvider/index.js +610 -0
  94. package/admin/src/containers/DataManagerProvider/reducer.js +461 -0
  95. package/admin/src/containers/DataManagerProvider/selectors.js +25 -0
  96. package/admin/src/containers/DataManagerProvider/utils/cleanData.js +167 -0
  97. package/admin/src/containers/DataManagerProvider/utils/createDataObject.js +8 -0
  98. package/admin/src/containers/DataManagerProvider/utils/createModifiedDataSchema.js +91 -0
  99. package/admin/src/containers/DataManagerProvider/utils/retrieveComponentsFromSchema.js +55 -0
  100. package/admin/src/containers/DataManagerProvider/utils/retrieveComponentsThatHaveComponents.js +35 -0
  101. package/admin/src/containers/DataManagerProvider/utils/retrieveNestedComponents.js +34 -0
  102. package/admin/src/containers/DataManagerProvider/utils/retrieveSpecificInfoFromComponents.js +12 -0
  103. package/admin/src/containers/FormModal/CustomButton.js +12 -0
  104. package/admin/src/containers/FormModal/attributes/advancedForm.js +269 -0
  105. package/admin/src/containers/FormModal/attributes/attributeOptions.js +99 -0
  106. package/admin/src/containers/FormModal/attributes/baseForm.js +322 -0
  107. package/admin/src/containers/FormModal/attributes/commonBaseForm.js +7 -0
  108. package/admin/src/containers/FormModal/attributes/form.js +9 -0
  109. package/admin/src/containers/FormModal/attributes/index.js +4 -0
  110. package/admin/src/containers/FormModal/attributes/nameField.js +19 -0
  111. package/admin/src/containers/FormModal/attributes/types.js +309 -0
  112. package/admin/src/containers/FormModal/attributes/uiHelpers.js +11 -0
  113. package/admin/src/containers/FormModal/attributes/validation/common.js +151 -0
  114. package/admin/src/containers/FormModal/category/createCategorySchema.js +28 -0
  115. package/admin/src/containers/FormModal/category/form.js +27 -0
  116. package/admin/src/containers/FormModal/category/index.js +3 -0
  117. package/admin/src/containers/FormModal/category/regex.js +3 -0
  118. package/admin/src/containers/FormModal/component/componentField.js +25 -0
  119. package/admin/src/containers/FormModal/component/createComponentSchema.js +49 -0
  120. package/admin/src/containers/FormModal/component/form.js +67 -0
  121. package/admin/src/containers/FormModal/component/index.js +4 -0
  122. package/admin/src/containers/FormModal/constants.js +11 -0
  123. package/admin/src/containers/FormModal/contentType/createContentTypeSchema.js +44 -0
  124. package/admin/src/containers/FormModal/contentType/form.js +116 -0
  125. package/admin/src/containers/FormModal/contentType/index.js +2 -0
  126. package/admin/src/containers/FormModal/dynamicZone/form.js +45 -0
  127. package/admin/src/containers/FormModal/dynamicZone/index.js +2 -0
  128. package/admin/src/containers/FormModal/forms/index.js +164 -0
  129. package/admin/src/containers/FormModal/index.js +1552 -0
  130. package/admin/src/containers/FormModal/reducer.js +293 -0
  131. package/admin/src/containers/FormModal/selectors.js +24 -0
  132. package/admin/src/containers/FormModal/utils/canEditContentType.js +19 -0
  133. package/admin/src/containers/FormModal/utils/createHeadersArray.js +37 -0
  134. package/admin/src/containers/FormModal/utils/createHeadersObjectFromArray.js +27 -0
  135. package/admin/src/containers/FormModal/utils/createUid.js +17 -0
  136. package/admin/src/containers/FormModal/utils/getAttributesToDisplay.js +35 -0
  137. package/admin/src/containers/FormModal/utils/getModalTitleSubHeader.js +25 -0
  138. package/admin/src/containers/FormModal/utils/getNextSearch.js +17 -0
  139. package/admin/src/containers/FormModal/utils/index.js +6 -0
  140. package/admin/src/containers/FormModal/utils/relations.js +9 -0
  141. package/admin/src/containers/FormModal/utils/staticData.js +43 -0
  142. package/admin/src/containers/Initializer/index.js +26 -0
  143. package/admin/src/containers/LeftMenu/Wrapper.js +14 -0
  144. package/admin/src/containers/LeftMenu/index.js +220 -0
  145. package/admin/src/containers/ListView/Wrapper.js +16 -0
  146. package/admin/src/containers/ListView/index.js +322 -0
  147. package/admin/src/containers/NotFoundPage/index.js +20 -0
  148. package/admin/src/containers/RecursivePath/index.js +22 -0
  149. package/admin/src/contexts/DataManagerContext.js +5 -0
  150. package/admin/src/contexts/ListViewContext.js +5 -0
  151. package/admin/src/hooks/useDataManager.js +6 -0
  152. package/admin/src/hooks/useListView.js +6 -0
  153. package/admin/src/icons/Curve.js +26 -0
  154. package/admin/src/icons/ManyToMany.js +98 -0
  155. package/admin/src/icons/ManyToOne.js +64 -0
  156. package/admin/src/icons/ManyWay.js +36 -0
  157. package/admin/src/icons/OneToMany.js +65 -0
  158. package/admin/src/icons/OneToOne.js +47 -0
  159. package/admin/src/icons/OneWay.js +38 -0
  160. package/admin/src/index.js +83 -0
  161. package/admin/src/lifecycles.js +13 -0
  162. package/admin/src/permissions.js +9 -0
  163. package/admin/src/pluginId.js +5 -0
  164. package/admin/src/reducers.js +10 -0
  165. package/admin/src/translations/ar.json +48 -0
  166. package/admin/src/translations/cs.json +151 -0
  167. package/admin/src/translations/de.json +187 -0
  168. package/admin/src/translations/dk.json +181 -0
  169. package/admin/src/translations/en.json +188 -0
  170. package/admin/src/translations/es.json +188 -0
  171. package/admin/src/translations/fr.json +87 -0
  172. package/admin/src/translations/id.json +187 -0
  173. package/admin/src/translations/index.js +51 -0
  174. package/admin/src/translations/it.json +187 -0
  175. package/admin/src/translations/ja.json +50 -0
  176. package/admin/src/translations/ko.json +57 -0
  177. package/admin/src/translations/ms.json +179 -0
  178. package/admin/src/translations/nl.json +171 -0
  179. package/admin/src/translations/pl.json +152 -0
  180. package/admin/src/translations/pt-BR.json +51 -0
  181. package/admin/src/translations/pt.json +51 -0
  182. package/admin/src/translations/ru.json +188 -0
  183. package/admin/src/translations/sk.json +186 -0
  184. package/admin/src/translations/th.json +181 -0
  185. package/admin/src/translations/tr.json +51 -0
  186. package/admin/src/translations/uk.json +180 -0
  187. package/admin/src/translations/zh-Hans.json +188 -0
  188. package/admin/src/translations/zh.json +178 -0
  189. package/admin/src/utils/convertAttrObjToArray.js +7 -0
  190. package/admin/src/utils/formAPI.js +112 -0
  191. package/admin/src/utils/getAttributeDisplayedType.js +31 -0
  192. package/admin/src/utils/getComponents.js +31 -0
  193. package/admin/src/utils/getTrad.js +5 -0
  194. package/admin/src/utils/makeSearch.js +15 -0
  195. package/admin/src/utils/makeUnique.js +3 -0
  196. package/config/functions/bootstrap.js +14 -0
  197. package/config/routes.json +144 -0
  198. package/controllers/Builder.js +7 -0
  199. package/controllers/ComponentCategories.js +43 -0
  200. package/controllers/Components.js +152 -0
  201. package/controllers/Connections.js +9 -0
  202. package/controllers/ContentTypes.js +143 -0
  203. package/controllers/validation/common.js +118 -0
  204. package/controllers/validation/component-category.js +21 -0
  205. package/controllers/validation/component.js +89 -0
  206. package/controllers/validation/content-type.js +161 -0
  207. package/controllers/validation/data-transform.js +32 -0
  208. package/controllers/validation/model-schema.js +91 -0
  209. package/controllers/validation/relations.js +56 -0
  210. package/controllers/validation/types.js +277 -0
  211. package/package.json +63 -0
  212. package/services/Builder.js +7 -0
  213. package/services/ComponentCategories.js +88 -0
  214. package/services/Components.js +103 -0
  215. package/services/ContentTypes.js +263 -0
  216. package/services/api-handler.js +158 -0
  217. package/services/constants.js +59 -0
  218. package/services/schema-builder/component-builder.js +137 -0
  219. package/services/schema-builder/content-type-builder.js +256 -0
  220. package/services/schema-builder/index.js +196 -0
  221. package/services/schema-builder/schema-handler.js +297 -0
  222. package/utils/attributes.js +154 -0
  223. package/utils/helpers.js +31 -0
@@ -0,0 +1,15 @@
1
+ export const ADD_ATTRIBUTE = 'ContentTypeBuilder/DataManagerProvider/ADD_ATTRIBUTE';
2
+ export const ADD_CREATED_COMPONENT_TO_DYNAMIC_ZONE = 'ContentTypeBuilder/DataManagerProvider/ADD_CREATED_COMPONENT_TO_DYNAMIC_ZONE';
3
+ export const CANCEL_CHANGES = 'ContentTypeBuilder/DataManagerProvider/CANCEL_CHANGES';
4
+ export const CHANGE_DYNAMIC_ZONE_COMPONENTS = 'ContentTypeBuilder/DataManagerProvider/CHANGE_DYNAMIC_ZONE_COMPONENTS';
5
+ export const CREATE_SCHEMA = 'ContentTypeBuilder/DataManagerProvider/CREATE_SCHEMA';
6
+ export const CREATE_COMPONENT_SCHEMA = 'ContentTypeBuilder/DataManagerProvider/CREATE_COMPONENT_SCHEMA';
7
+ export const DELETE_NOT_SAVED_TYPE = 'ContentTypeBuilder/DataManagerProvider/DELETE_NOT_SAVED_TYPE';
8
+ export const EDIT_ATTRIBUTE = 'ContentTypeBuilder/DataManagerProvider/EDIT_ATTRIBUTE';
9
+ export const GET_DATA_SUCCEEDED = 'ContentTypeBuilder/DataManagerProvider/GET_DATA_SUCCEEDED';
10
+ export const RELOAD_PLUGIN = 'ContentTypeBuilder/DataManagerProvider/RELOAD_PLUGIN';
11
+ export const REMOVE_FIELD_FROM_DISPLAYED_COMPONENT = 'ContentTypeBuilder/DataManagerProvider/REMOVE_FIELD_FROM_DISPLAYED_COMPONENT';
12
+ export const REMOVE_COMPONENT_FROM_DYNAMIC_ZONE = 'ContentTypeBuilder/DataManagerProvider/REMOVE_COMPONENT_FROM_DYNAMIC_ZONE';
13
+ export const REMOVE_FIELD = 'ContentTypeBuilder/DataManagerProvider/REMOVE_FIELD';
14
+ export const SET_MODIFIED_DATA = 'ContentTypeBuilder/DataManagerProvider/SET_MODIFIED_DATA';
15
+ export const UPDATE_SCHEMA = 'ContentTypeBuilder/DataManagerProvider/UPDATE_SCHEMA';
@@ -0,0 +1,610 @@
1
+ import React, { memo, useEffect, useMemo, useState, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { get, groupBy, set, size } from 'lodash';
4
+ import {
5
+ request,
6
+ LoadingIndicatorPage,
7
+ useGlobalContext,
8
+ PopUpWarning,
9
+ useStrapi,
10
+ useUser,
11
+ } from 'strapi-helper-plugin';
12
+ import { useHistory, useLocation, useRouteMatch, Redirect } from 'react-router-dom';
13
+ import { connect, useDispatch } from 'react-redux';
14
+ import { compose } from 'redux';
15
+ import DataManagerContext from '../../contexts/DataManagerContext';
16
+ import getTrad from '../../utils/getTrad';
17
+ import makeUnique from '../../utils/makeUnique';
18
+ import pluginId from '../../pluginId';
19
+ import FormModal from '../FormModal';
20
+ import createDataObject from './utils/createDataObject';
21
+ import createModifiedDataSchema, {
22
+ orderAllDataAttributesWithImmutable,
23
+ } from './utils/createModifiedDataSchema';
24
+ import retrieveSpecificInfoFromComponents from './utils/retrieveSpecificInfoFromComponents';
25
+ import retrieveComponentsFromSchema from './utils/retrieveComponentsFromSchema';
26
+ import retrieveNestedComponents from './utils/retrieveNestedComponents';
27
+ import { retrieveComponentsThatHaveComponents } from './utils/retrieveComponentsThatHaveComponents';
28
+ import {
29
+ getComponentsToPost,
30
+ formatMainDataType,
31
+ getCreatedAndModifiedComponents,
32
+ sortContentType,
33
+ } from './utils/cleanData';
34
+
35
+ import {
36
+ ADD_ATTRIBUTE,
37
+ ADD_CREATED_COMPONENT_TO_DYNAMIC_ZONE,
38
+ CANCEL_CHANGES,
39
+ CHANGE_DYNAMIC_ZONE_COMPONENTS,
40
+ CREATE_SCHEMA,
41
+ CREATE_COMPONENT_SCHEMA,
42
+ DELETE_NOT_SAVED_TYPE,
43
+ EDIT_ATTRIBUTE,
44
+ GET_DATA_SUCCEEDED,
45
+ RELOAD_PLUGIN,
46
+ REMOVE_FIELD_FROM_DISPLAYED_COMPONENT,
47
+ REMOVE_COMPONENT_FROM_DYNAMIC_ZONE,
48
+ REMOVE_FIELD,
49
+ SET_MODIFIED_DATA,
50
+ UPDATE_SCHEMA,
51
+ } from './constants';
52
+ import makeSelectDataManagerProvider from './selectors';
53
+
54
+ const DataManagerProvider = ({
55
+ allIcons,
56
+ children,
57
+ components,
58
+ contentTypes,
59
+ isLoading,
60
+ isLoadingForDataToBeSet,
61
+ initialData,
62
+ modifiedData,
63
+ reservedNames,
64
+ }) => {
65
+ const dispatch = useDispatch();
66
+ const {
67
+ strapi: { getPlugin },
68
+ } = useStrapi();
69
+ const { apis } = getPlugin(pluginId);
70
+ const [infoModals, toggleInfoModal] = useState({ cancel: false });
71
+ const { autoReload, emitEvent, formatMessage } = useGlobalContext();
72
+ const { fetchUserPermissions } = useUser();
73
+
74
+ const { pathname } = useLocation();
75
+ const { push } = useHistory();
76
+ const contentTypeMatch = useRouteMatch(`/plugins/${pluginId}/content-types/:uid`);
77
+ const componentMatch = useRouteMatch(
78
+ `/plugins/${pluginId}/component-categories/:categoryUid/:componentUid`
79
+ );
80
+
81
+ const formatMessageRef = useRef();
82
+ formatMessageRef.current = formatMessage;
83
+ const isInDevelopmentMode = autoReload;
84
+
85
+ const isInContentTypeView = contentTypeMatch !== null;
86
+ const firstKeyToMainSchema = isInContentTypeView ? 'contentType' : 'component';
87
+ const currentUid = isInContentTypeView
88
+ ? get(contentTypeMatch, 'params.uid', null)
89
+ : get(componentMatch, 'params.componentUid', null);
90
+ const abortController = new AbortController();
91
+ const { signal } = abortController;
92
+ const getDataRef = useRef();
93
+ const endPoint = isInContentTypeView ? 'content-types' : 'components';
94
+
95
+ getDataRef.current = async () => {
96
+ try {
97
+ const [
98
+ { data: componentsArray },
99
+ { data: contentTypesArray },
100
+ reservedNames,
101
+ ] = await Promise.all(
102
+ ['components', 'content-types', 'reserved-names'].map(endPoint => {
103
+ return request(`/${pluginId}/${endPoint}`, {
104
+ method: 'GET',
105
+ signal,
106
+ });
107
+ })
108
+ );
109
+
110
+ const components = createDataObject(componentsArray);
111
+ const contentTypes = createDataObject(contentTypesArray);
112
+ const orderedComponents = orderAllDataAttributesWithImmutable({
113
+ components,
114
+ });
115
+ const orderedContenTypes = orderAllDataAttributesWithImmutable({
116
+ components: contentTypes,
117
+ });
118
+
119
+ dispatch({
120
+ type: GET_DATA_SUCCEEDED,
121
+ components: orderedComponents.get('components'),
122
+ contentTypes: orderedContenTypes.get('components'),
123
+ reservedNames,
124
+ });
125
+ } catch (err) {
126
+ console.error({ err });
127
+ strapi.notification.toggle({
128
+ type: 'warning',
129
+ message: { id: 'notification.error' },
130
+ });
131
+ }
132
+ };
133
+
134
+ useEffect(() => {
135
+ getDataRef.current();
136
+ }, []);
137
+
138
+ useEffect(() => {
139
+ // We need to set the modifiedData after the data has been retrieved
140
+ // and also on pathname change
141
+ if (!isLoading && currentUid) {
142
+ setModifiedData();
143
+ }
144
+ // eslint-disable-next-line react-hooks/exhaustive-deps
145
+ }, [isLoading, pathname, currentUid]);
146
+
147
+ useEffect(() => {
148
+ if (!autoReload) {
149
+ strapi.notification.toggle({
150
+ type: 'info',
151
+ message: { id: getTrad('notification.info.autoreaload-disable') },
152
+ });
153
+ }
154
+ }, [autoReload]);
155
+
156
+ const didModifiedComponents =
157
+ getCreatedAndModifiedComponents(modifiedData.components || {}, components).length > 0;
158
+
159
+ const addAttribute = (
160
+ attributeToSet,
161
+ forTarget,
162
+ targetUid,
163
+ isEditing = false,
164
+ initialAttribute,
165
+ shouldAddComponentToData = false
166
+ ) => {
167
+ const actionType = isEditing ? EDIT_ATTRIBUTE : ADD_ATTRIBUTE;
168
+
169
+ dispatch({
170
+ type: actionType,
171
+ attributeToSet,
172
+ forTarget,
173
+ targetUid,
174
+ initialAttribute,
175
+ shouldAddComponentToData,
176
+ });
177
+ };
178
+
179
+ const addCreatedComponentToDynamicZone = (dynamicZoneTarget, componentsToAdd) => {
180
+ dispatch({
181
+ type: ADD_CREATED_COMPONENT_TO_DYNAMIC_ZONE,
182
+ dynamicZoneTarget,
183
+ componentsToAdd,
184
+ });
185
+ };
186
+
187
+ const cancelChanges = () => {
188
+ toggleModalCancel();
189
+ dispatch({ type: CANCEL_CHANGES });
190
+ };
191
+
192
+ const createSchema = (
193
+ data,
194
+ schemaType,
195
+ uid,
196
+ componentCategory,
197
+ shouldAddComponentToData = false
198
+ ) => {
199
+ const type = schemaType === 'contentType' ? CREATE_SCHEMA : CREATE_COMPONENT_SCHEMA;
200
+
201
+ dispatch({
202
+ type,
203
+ data,
204
+ componentCategory,
205
+ schemaType,
206
+ uid,
207
+ shouldAddComponentToData,
208
+ });
209
+ };
210
+
211
+ const changeDynamicZoneComponents = (dynamicZoneTarget, newComponents) => {
212
+ dispatch({
213
+ type: CHANGE_DYNAMIC_ZONE_COMPONENTS,
214
+ dynamicZoneTarget,
215
+ newComponents,
216
+ });
217
+ };
218
+
219
+ const removeAttribute = (mainDataKey, attributeToRemoveName, componentUid = '') => {
220
+ const type =
221
+ mainDataKey === 'components' ? REMOVE_FIELD_FROM_DISPLAYED_COMPONENT : REMOVE_FIELD;
222
+
223
+ if (mainDataKey === 'contentType') {
224
+ emitEvent('willDeleteFieldOfContentType');
225
+ }
226
+
227
+ dispatch({
228
+ type,
229
+ mainDataKey,
230
+ attributeToRemoveName,
231
+ componentUid,
232
+ });
233
+ };
234
+
235
+ const deleteCategory = async categoryUid => {
236
+ try {
237
+ const requestURL = `/${pluginId}/component-categories/${categoryUid}`;
238
+ // eslint-disable-next-line no-alert
239
+ const userConfirm = window.confirm(
240
+ formatMessage({
241
+ id: getTrad('popUpWarning.bodyMessage.category.delete'),
242
+ })
243
+ );
244
+ // Close the modal
245
+ push({ search: '' });
246
+
247
+ if (userConfirm) {
248
+ strapi.lockApp();
249
+
250
+ await request(requestURL, { method: 'DELETE' }, true);
251
+
252
+ await updatePermissions();
253
+
254
+ // Reload the plugin so the cycle is new again
255
+ dispatch({ type: RELOAD_PLUGIN });
256
+ // Refetch all the data
257
+ getDataRef.current();
258
+ }
259
+ } catch (err) {
260
+ console.error({ err });
261
+ strapi.notification.toggle({
262
+ type: 'warning',
263
+ message: { id: 'notification.error' },
264
+ });
265
+ } finally {
266
+ strapi.unlockApp();
267
+ }
268
+ };
269
+
270
+ const deleteData = async () => {
271
+ try {
272
+ const requestURL = `/${pluginId}/${endPoint}/${currentUid}`;
273
+ const isTemporary = get(modifiedData, [firstKeyToMainSchema, 'isTemporary'], false);
274
+ // eslint-disable-next-line no-alert
275
+ const userConfirm = window.confirm(
276
+ formatMessage({
277
+ id: getTrad(
278
+ `popUpWarning.bodyMessage.${isInContentTypeView ? 'contentType' : 'component'}.delete`
279
+ ),
280
+ })
281
+ );
282
+
283
+ // Close the modal
284
+ push({ search: '' });
285
+
286
+ if (userConfirm) {
287
+ if (isTemporary) {
288
+ // Delete the not saved type
289
+ // Here we just need to reset the components to the initial ones and also the content types
290
+ // Doing so will trigging a url change since the type doesn't exist in either the contentTypes or the components
291
+ // so the modified and the initial data will also be reset in the useEffect...
292
+ dispatch({ type: DELETE_NOT_SAVED_TYPE });
293
+
294
+ return;
295
+ }
296
+
297
+ strapi.lockApp();
298
+
299
+ await request(requestURL, { method: 'DELETE' }, true);
300
+
301
+ // Reload the plugin so the cycle is new again
302
+ dispatch({ type: RELOAD_PLUGIN });
303
+
304
+ // Refetch the permissions
305
+ await updatePermissions();
306
+
307
+ // Refetch all the data
308
+ getDataRef.current();
309
+ }
310
+ } catch (err) {
311
+ console.error({ err });
312
+ strapi.notification.toggle({
313
+ type: 'warning',
314
+ message: { id: 'notification.error' },
315
+ });
316
+ } finally {
317
+ strapi.unlockApp();
318
+ }
319
+ };
320
+
321
+ const editCategory = async (categoryUid, body) => {
322
+ try {
323
+ const requestURL = `/${pluginId}/component-categories/${categoryUid}`;
324
+
325
+ // Close the modal
326
+ push({ search: '' });
327
+
328
+ // Lock the app
329
+ strapi.lockApp();
330
+
331
+ // Update the category
332
+ await request(requestURL, { method: 'PUT', body }, true);
333
+
334
+ await updatePermissions();
335
+
336
+ // Reload the plugin so the cycle is new again
337
+ dispatch({ type: RELOAD_PLUGIN });
338
+ // Refetch all the data
339
+ getDataRef.current();
340
+ } catch (err) {
341
+ console.error({ err });
342
+ strapi.notification.toggle({
343
+ type: 'warning',
344
+ message: { id: 'notification.error' },
345
+ });
346
+ } finally {
347
+ strapi.unlockApp();
348
+ }
349
+ };
350
+
351
+ const getAllComponentsThatHaveAComponentInTheirAttributes = () => {
352
+ // We need to create an object with all the non modified compos
353
+ // plus the ones that are created on the fly
354
+ const allCompos = Object.assign({}, components, modifiedData.components);
355
+
356
+ // Since we apply the modification of a specific component only in the modified data
357
+ // we need to update all compos with the modifications
358
+ if (!isInContentTypeView) {
359
+ const currentEditedCompo = get(modifiedData, 'component', {});
360
+
361
+ set(allCompos, get(currentEditedCompo, ['uid'], ''), currentEditedCompo);
362
+ }
363
+
364
+ const composWithCompos = retrieveComponentsThatHaveComponents(allCompos);
365
+
366
+ return makeUnique(composWithCompos);
367
+ };
368
+
369
+ const getAllNestedComponents = () => {
370
+ const appNestedCompo = retrieveNestedComponents(components);
371
+ const editingDataNestedCompos = retrieveNestedComponents(modifiedData.components || {});
372
+
373
+ return makeUnique([...editingDataNestedCompos, ...appNestedCompo]);
374
+ };
375
+
376
+ const removeComponentFromDynamicZone = (dzName, componentToRemoveIndex) => {
377
+ dispatch({
378
+ type: REMOVE_COMPONENT_FROM_DYNAMIC_ZONE,
379
+ dzName,
380
+ componentToRemoveIndex,
381
+ });
382
+ };
383
+
384
+ const setModifiedData = () => {
385
+ const currentSchemas = isInContentTypeView ? contentTypes : components;
386
+ const schemaToSet = get(currentSchemas, currentUid, {
387
+ schema: { attributes: {} },
388
+ });
389
+
390
+ const retrievedComponents = retrieveComponentsFromSchema(
391
+ schemaToSet.schema.attributes,
392
+ components
393
+ );
394
+ const newSchemaToSet = createModifiedDataSchema(
395
+ schemaToSet,
396
+ retrievedComponents,
397
+ components,
398
+ isInContentTypeView
399
+ );
400
+
401
+ const dataShape = orderAllDataAttributesWithImmutable(newSchemaToSet, isInContentTypeView);
402
+
403
+ const hasJustCreatedSchema =
404
+ get(schemaToSet, 'isTemporary', false) &&
405
+ size(get(schemaToSet, 'schema.attributes', {})) === 0;
406
+
407
+ dispatch({
408
+ type: SET_MODIFIED_DATA,
409
+ schemaToSet: dataShape,
410
+ hasJustCreatedSchema,
411
+ });
412
+ };
413
+
414
+ const shouldRedirect = useMemo(() => {
415
+ const dataSet = isInContentTypeView ? contentTypes : components;
416
+
417
+ return !Object.keys(dataSet).includes(currentUid) && !isLoading;
418
+ }, [components, contentTypes, currentUid, isInContentTypeView, isLoading]);
419
+
420
+ const redirectEndpoint = useMemo(() => {
421
+ const allowedEndpoints = Object.keys(contentTypes)
422
+ .filter(uid => get(contentTypes, [uid, 'schema', 'visible'], true))
423
+ .sort();
424
+
425
+ return get(allowedEndpoints, '0', '');
426
+ }, [contentTypes]);
427
+
428
+ if (shouldRedirect) {
429
+ return <Redirect to={`/plugins/${pluginId}/content-types/${redirectEndpoint}`} />;
430
+ }
431
+
432
+ const submitData = async additionalContentTypeData => {
433
+ try {
434
+ const isCreating = get(modifiedData, [firstKeyToMainSchema, 'isTemporary'], false);
435
+ const body = {
436
+ components: getComponentsToPost(
437
+ modifiedData.components,
438
+ components,
439
+ currentUid,
440
+ isCreating
441
+ ),
442
+ };
443
+
444
+ if (isInContentTypeView) {
445
+ const contentType = apis.forms.mutateContentTypeSchema(
446
+ {
447
+ ...formatMainDataType(modifiedData.contentType),
448
+ ...additionalContentTypeData,
449
+ },
450
+ initialData.contentType
451
+ );
452
+
453
+ body.contentType = contentType;
454
+
455
+ emitEvent('willSaveContentType');
456
+ } else {
457
+ body.component = formatMainDataType(modifiedData.component, true);
458
+
459
+ emitEvent('willSaveComponent');
460
+ }
461
+
462
+ const method = isCreating ? 'POST' : 'PUT';
463
+
464
+ const baseURL = `/${pluginId}/${endPoint}`;
465
+ const requestURL = isCreating ? baseURL : `${baseURL}/${currentUid}`;
466
+
467
+ // Lock the app
468
+ strapi.lockApp();
469
+
470
+ await request(requestURL, { method, body }, true);
471
+
472
+ await updatePermissions();
473
+
474
+ // Submit ct tracking success
475
+ if (isInContentTypeView) {
476
+ emitEvent('didSaveContentType');
477
+
478
+ const oldName = get(body, ['contentType', 'schema', 'name'], '');
479
+ const newName = get(initialData, ['contentType', 'schema', 'name'], '');
480
+
481
+ if (!isCreating && oldName !== newName) {
482
+ emitEvent('didEditNameOfContentType');
483
+ }
484
+ } else {
485
+ emitEvent('didSaveComponent');
486
+ }
487
+
488
+ // Reload the plugin so the cycle is new again
489
+ dispatch({ type: RELOAD_PLUGIN });
490
+ // Refetch all the data
491
+ getDataRef.current();
492
+ } catch (err) {
493
+ if (!isInContentTypeView) {
494
+ emitEvent('didNotSaveComponent');
495
+ }
496
+
497
+ console.error({ err: err.response });
498
+ strapi.notification.toggle({
499
+ type: 'warning',
500
+ message: { id: 'notification.error' },
501
+ });
502
+ } finally {
503
+ strapi.unlockApp();
504
+ }
505
+ };
506
+
507
+ // Open the modal warning cancel changes
508
+ const toggleModalCancel = () => {
509
+ toggleInfoModal(prev => ({ ...prev, cancel: !prev.cancel }));
510
+ };
511
+
512
+ const updatePermissions = async () => {
513
+ await fetchUserPermissions();
514
+ };
515
+
516
+ const updateSchema = (data, schemaType, componentUID) => {
517
+ dispatch({
518
+ type: UPDATE_SCHEMA,
519
+ data,
520
+ schemaType,
521
+ uid: componentUID,
522
+ });
523
+ };
524
+
525
+ return (
526
+ <DataManagerContext.Provider
527
+ value={{
528
+ addAttribute,
529
+ addCreatedComponentToDynamicZone,
530
+ allComponentsCategories: retrieveSpecificInfoFromComponents(components, ['category']),
531
+ allComponentsIconAlreadyTaken: retrieveSpecificInfoFromComponents(components, [
532
+ 'schema',
533
+ 'icon',
534
+ ]),
535
+ allIcons,
536
+ changeDynamicZoneComponents,
537
+ components,
538
+ componentsGroupedByCategory: groupBy(components, 'category'),
539
+ componentsThatHaveOtherComponentInTheirAttributes: getAllComponentsThatHaveAComponentInTheirAttributes(),
540
+ contentTypes,
541
+ createSchema,
542
+ deleteCategory,
543
+ deleteData,
544
+ editCategory,
545
+ isInDevelopmentMode,
546
+ initialData,
547
+ isInContentTypeView,
548
+ modifiedData,
549
+ nestedComponents: getAllNestedComponents(),
550
+ removeAttribute,
551
+ removeComponentFromDynamicZone,
552
+ reservedNames,
553
+ setModifiedData,
554
+ sortedContentTypesList: sortContentType(contentTypes),
555
+ submitData,
556
+ toggleModalCancel,
557
+ updateSchema,
558
+ }}
559
+ >
560
+ {isLoadingForDataToBeSet ? (
561
+ <LoadingIndicatorPage />
562
+ ) : (
563
+ <>
564
+ {children}
565
+ {isInDevelopmentMode && (
566
+ <>
567
+ <FormModal />
568
+ <PopUpWarning
569
+ isOpen={infoModals.cancel}
570
+ toggleModal={toggleModalCancel}
571
+ content={{
572
+ message: getTrad(
573
+ `popUpWarning.bodyMessage.cancel-modifications${
574
+ didModifiedComponents ? '.with-components' : ''
575
+ }`
576
+ ),
577
+ }}
578
+ popUpWarningType="danger"
579
+ onConfirm={() => {
580
+ cancelChanges();
581
+ }}
582
+ />
583
+ </>
584
+ )}
585
+ </>
586
+ )}
587
+ </DataManagerContext.Provider>
588
+ );
589
+ };
590
+
591
+ DataManagerProvider.defaultProps = {
592
+ components: {},
593
+ };
594
+
595
+ DataManagerProvider.propTypes = {
596
+ allIcons: PropTypes.array.isRequired,
597
+ children: PropTypes.node.isRequired,
598
+ components: PropTypes.object,
599
+ contentTypes: PropTypes.object.isRequired,
600
+ isLoading: PropTypes.bool.isRequired,
601
+ isLoadingForDataToBeSet: PropTypes.bool.isRequired,
602
+ initialData: PropTypes.object.isRequired,
603
+ modifiedData: PropTypes.object.isRequired,
604
+ reservedNames: PropTypes.object.isRequired,
605
+ };
606
+
607
+ const mapStateToProps = makeSelectDataManagerProvider();
608
+ const withConnect = connect(mapStateToProps, null);
609
+
610
+ export default compose(withConnect)(memo(DataManagerProvider));