@strapi/admin 4.4.0-rc.1 → 4.5.0-alpha.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 (203) hide show
  1. package/admin/src/StrapiApp.js +12 -4
  2. package/admin/src/components/Providers/index.js +10 -14
  3. package/admin/src/content-manager/components/CollectionTypeFormWrapper/index.js +11 -1
  4. package/admin/src/content-manager/components/DynamicTable/CellContent/RelationMultiple/index.js +11 -7
  5. package/admin/src/content-manager/components/DynamicTable/CellContent/index.js +6 -5
  6. package/admin/src/content-manager/components/DynamicTable/TableRows/index.js +5 -0
  7. package/admin/src/content-manager/components/DynamicTable/index.js +1 -1
  8. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +23 -17
  9. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +123 -24
  10. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/cleanData.js +17 -1
  11. package/admin/src/content-manager/components/FieldTypeIcon/index.js +1 -31
  12. package/admin/src/content-manager/components/Inputs/index.js +22 -36
  13. package/admin/src/content-manager/components/RelationInput/RelationInput.js +364 -0
  14. package/admin/src/content-manager/components/{SelectWrapper → RelationInput/components}/Option.js +15 -25
  15. package/admin/src/content-manager/components/RelationInput/components/Relation.js +48 -0
  16. package/admin/src/content-manager/components/RelationInput/components/RelationItem.js +52 -0
  17. package/admin/src/content-manager/components/RelationInput/components/RelationList.js +52 -0
  18. package/admin/src/content-manager/components/RelationInput/constants.js +1 -0
  19. package/admin/src/content-manager/components/RelationInput/index.js +1 -0
  20. package/admin/src/content-manager/components/RelationInputDataManager/RelationInputDataManager.js +250 -0
  21. package/admin/src/content-manager/components/RelationInputDataManager/constants.js +8 -0
  22. package/admin/src/content-manager/components/RelationInputDataManager/index.js +1 -0
  23. package/admin/src/content-manager/components/{SelectWrapper → RelationInputDataManager}/utils/connect.js +0 -1
  24. package/admin/src/content-manager/components/RelationInputDataManager/utils/getRelationLink.js +5 -0
  25. package/admin/src/content-manager/components/{SelectWrapper → RelationInputDataManager}/utils/index.js +1 -0
  26. package/admin/src/content-manager/components/RelationInputDataManager/utils/normalizeRelations.js +58 -0
  27. package/admin/src/content-manager/components/{SelectWrapper → RelationInputDataManager}/utils/select.js +31 -1
  28. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +19 -2
  29. package/admin/src/content-manager/hooks/useFetchContentTypeLayout/utils/formatLayouts.js +7 -69
  30. package/admin/src/content-manager/hooks/useRelation/index.js +1 -0
  31. package/admin/src/content-manager/hooks/useRelation/useRelation.js +73 -0
  32. package/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFields.js +4 -4
  33. package/admin/src/content-manager/pages/EditSettingsView/components/FormModal.js +2 -7
  34. package/admin/src/content-manager/pages/EditSettingsView/index.js +22 -51
  35. package/admin/src/content-manager/pages/EditSettingsView/reducer.js +0 -25
  36. package/admin/src/content-manager/pages/EditView/Header/index.js +3 -90
  37. package/admin/src/content-manager/pages/EditView/Header/utils/index.js +0 -1
  38. package/admin/src/content-manager/pages/EditView/Header/utils/select.js +0 -2
  39. package/admin/src/content-manager/pages/EditView/index.js +93 -155
  40. package/admin/src/content-manager/pages/ListView/FieldPicker/index.js +0 -1
  41. package/admin/src/content-manager/pages/ListView/index.js +0 -1
  42. package/admin/src/content-manager/pages/ListViewLayoutManager/index.js +0 -1
  43. package/admin/src/content-manager/utils/formatLayoutToApi.js +1 -3
  44. package/admin/src/core/apis/index.js +0 -1
  45. package/admin/src/hooks/index.js +0 -1
  46. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +197 -215
  47. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/schema.js +1 -2
  48. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DeleteButton/index.js +0 -1
  49. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js +36 -3
  50. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/index.js +11 -13
  51. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +2 -3
  52. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/utils/tableHeaders.js +8 -8
  53. package/admin/src/pages/SettingsPage/pages/ApiTokens/ProtectedEditView/index.js +1 -1
  54. package/admin/src/permissions/defaultPermissions.js +6 -2
  55. package/admin/src/translations/ar.json +0 -1
  56. package/admin/src/translations/ca.json +0 -9
  57. package/admin/src/translations/cs.json +0 -2
  58. package/admin/src/translations/de.json +0 -11
  59. package/admin/src/translations/dk.json +0 -11
  60. package/admin/src/translations/en.json +0 -28
  61. package/admin/src/translations/es.json +0 -11
  62. package/admin/src/translations/fr.json +0 -11
  63. package/admin/src/translations/gu.json +0 -11
  64. package/admin/src/translations/hi.json +0 -11
  65. package/admin/src/translations/hu.json +0 -10
  66. package/admin/src/translations/id.json +0 -10
  67. package/admin/src/translations/it.json +0 -10
  68. package/admin/src/translations/ja.json +0 -11
  69. package/admin/src/translations/ko.json +0 -11
  70. package/admin/src/translations/ml.json +0 -11
  71. package/admin/src/translations/ms.json +0 -2
  72. package/admin/src/translations/nl.json +0 -11
  73. package/admin/src/translations/pl.json +0 -11
  74. package/admin/src/translations/pt-BR.json +0 -11
  75. package/admin/src/translations/pt.json +0 -1
  76. package/admin/src/translations/ru.json +0 -10
  77. package/admin/src/translations/sa.json +0 -11
  78. package/admin/src/translations/sk.json +0 -10
  79. package/admin/src/translations/sv.json +0 -9
  80. package/admin/src/translations/th.json +0 -2
  81. package/admin/src/translations/tr.json +0 -1
  82. package/admin/src/translations/uk.json +0 -2
  83. package/admin/src/translations/vi.json +0 -1
  84. package/admin/src/translations/zh-Hans.json +0 -12
  85. package/admin/src/translations/zh.json +0 -11
  86. package/build/7098.40dcd7bf.chunk.js +1 -0
  87. package/build/8851.e4ac62f2.chunk.js +158 -0
  88. package/build/{8773.c06c24c0.chunk.js → 9311.7cc03f29.chunk.js} +291 -108
  89. package/build/{Admin-authenticatedApp.99b4868f.chunk.js → Admin-authenticatedApp.e39f36c9.chunk.js} +3 -3
  90. package/build/{Admin_homePage.6d5e3236.chunk.js → Admin_homePage.118926e0.chunk.js} +1 -1
  91. package/build/{Admin_profilePage.da32abbc.chunk.js → Admin_profilePage.9d50ac44.chunk.js} +1 -1
  92. package/build/{Admin_settingsPage.98e2a62b.chunk.js → Admin_settingsPage.98a711e5.chunk.js} +16 -16
  93. package/build/admin-app.4f7618a9.chunk.js +112 -0
  94. package/build/admin-edit-roles-page.554ba3fa.chunk.js +1 -0
  95. package/build/api-tokens-create-page.4c262d6e.chunk.js +1 -0
  96. package/build/api-tokens-edit-page.10a9d368.chunk.js +1 -0
  97. package/build/api-tokens-list-page.442c9f3c.chunk.js +15 -0
  98. package/build/{ar-json.d4cb26d9.chunk.js → ar-json.3489463d.chunk.js} +1 -1
  99. package/build/{ca-json.d16c1d28.chunk.js → ca-json.a16899ae.chunk.js} +1 -1
  100. package/build/content-manager.7d57c9d1.chunk.js +1200 -0
  101. package/build/content-type-builder-list-view.8cc534e0.chunk.js +194 -0
  102. package/build/content-type-builder-translation-en-json.201bfb78.chunk.js +1 -0
  103. package/build/content-type-builder.684df7a4.chunk.js +142 -0
  104. package/build/{cs-json.c8f28ba8.chunk.js → cs-json.ce49da5c.chunk.js} +1 -1
  105. package/build/{de-json.a9b514dc.chunk.js → de-json.aa6026b3.chunk.js} +1 -1
  106. package/build/{dk-json.09e8d145.chunk.js → dk-json.fac2bcfb.chunk.js} +1 -1
  107. package/build/en-json.0c69c7d7.chunk.js +1 -0
  108. package/build/{es-json.3a9c7c09.chunk.js → es-json.d672e181.chunk.js} +1 -1
  109. package/build/{fr-json.4ed1fc2c.chunk.js → fr-json.71a16175.chunk.js} +1 -1
  110. package/build/{gu-json.d8311297.chunk.js → gu-json.ca345cd1.chunk.js} +1 -1
  111. package/build/{hi-json.0edb8d29.chunk.js → hi-json.50c7e6d4.chunk.js} +1 -1
  112. package/build/{hu-json.7855529a.chunk.js → hu-json.e0521dcc.chunk.js} +1 -1
  113. package/build/{id-json.df9618f2.chunk.js → id-json.4b1ff8d6.chunk.js} +1 -1
  114. package/build/index.html +1 -1
  115. package/build/{it-json.a21bf078.chunk.js → it-json.86bac220.chunk.js} +1 -1
  116. package/build/{ja-json.7b0d9067.chunk.js → ja-json.4e44e36b.chunk.js} +1 -1
  117. package/build/{ko-json.983c1f8f.chunk.js → ko-json.1003756e.chunk.js} +1 -1
  118. package/build/main.b47db1a3.js +9337 -0
  119. package/build/{ml-json.8dd021c8.chunk.js → ml-json.c7774425.chunk.js} +1 -1
  120. package/build/{ms-json.836ed013.chunk.js → ms-json.ed51e902.chunk.js} +1 -1
  121. package/build/{nl-json.29d2eb37.chunk.js → nl-json.f58ea235.chunk.js} +1 -1
  122. package/build/{pl-json.1f04f00c.chunk.js → pl-json.fed96aba.chunk.js} +1 -1
  123. package/build/{pt-BR-json.b4bc8efe.chunk.js → pt-BR-json.073799ab.chunk.js} +1 -1
  124. package/build/{pt-json.c23020ab.chunk.js → pt-json.3161ca22.chunk.js} +1 -1
  125. package/build/{ru-json.7ab40ccf.chunk.js → ru-json.7ad2cbbf.chunk.js} +1 -1
  126. package/build/{runtime~main.4ee06902.js → runtime~main.feeac6d3.js} +1 -1
  127. package/build/{sa-json.c5a9f4ea.chunk.js → sa-json.f0f704f0.chunk.js} +1 -1
  128. package/build/{sk-json.e4c24c4e.chunk.js → sk-json.a848961b.chunk.js} +1 -1
  129. package/build/sso-settings-page.445184e0.chunk.js +1 -0
  130. package/build/{sv-json.c3f471ae.chunk.js → sv-json.b038acbe.chunk.js} +1 -1
  131. package/build/{th-json.a59ffb32.chunk.js → th-json.72e8de3d.chunk.js} +1 -1
  132. package/build/{tr-json.276e59fe.chunk.js → tr-json.9c44ea0c.chunk.js} +1 -1
  133. package/build/{uk-json.5b5b9c27.chunk.js → uk-json.c4cd2e24.chunk.js} +1 -1
  134. package/build/{vi-json.bf3424be.chunk.js → vi-json.f7890025.chunk.js} +1 -1
  135. package/build/{webhook-edit-page.9e46fc3f.chunk.js → webhook-edit-page.d2ea3351.chunk.js} +1 -1
  136. package/build/{zh-Hans-json.9c99f8d4.chunk.js → zh-Hans-json.03d2bda1.chunk.js} +1 -1
  137. package/build/{zh-json.451a0271.chunk.js → zh-json.3d0cc664.chunk.js} +1 -1
  138. package/package.json +7 -8
  139. package/server/bootstrap.js +1 -19
  140. package/server/config/admin-actions.js +0 -20
  141. package/server/content-types/api-token.js +1 -25
  142. package/server/content-types/index.js +0 -1
  143. package/server/controllers/api-token.js +1 -24
  144. package/server/controllers/index.js +0 -1
  145. package/server/routes/api-tokens.js +0 -11
  146. package/server/routes/index.js +0 -2
  147. package/server/services/api-token.js +29 -310
  148. package/server/services/constants.js +0 -10
  149. package/server/services/permission/engine-hooks.js +82 -0
  150. package/server/services/permission/engine.js +226 -36
  151. package/server/services/permission.js +1 -4
  152. package/server/strategies/admin.js +1 -7
  153. package/server/strategies/api-token.js +11 -71
  154. package/server/validation/api-tokens.js +2 -12
  155. package/admin/src/content-manager/components/SelectMany/ListItem.js +0 -102
  156. package/admin/src/content-manager/components/SelectMany/index.js +0 -148
  157. package/admin/src/content-manager/components/SelectOne/SingleValue.js +0 -67
  158. package/admin/src/content-manager/components/SelectOne/index.js +0 -97
  159. package/admin/src/content-manager/components/SelectWrapper/Label.js +0 -60
  160. package/admin/src/content-manager/components/SelectWrapper/index.js +0 -356
  161. package/admin/src/content-manager/pages/EditSettingsView/components/RelationalFieldButton.js +0 -135
  162. package/admin/src/content-manager/pages/EditSettingsView/components/RelationalFields.js +0 -103
  163. package/admin/src/content-manager/pages/EditView/Header/utils/getDraftRelations.js +0 -62
  164. package/admin/src/contexts/ApiTokenPermissions/index.js +0 -24
  165. package/admin/src/core/apis/CustomFields.js +0 -80
  166. package/admin/src/hooks/useRegenerate/index.js +0 -34
  167. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ActionBoundRoutes/index.js +0 -56
  168. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/getMethodColor.js +0 -41
  169. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/BoundRoute/index.js +0 -72
  170. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/CheckBoxWrapper.js +0 -30
  171. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/CollapsableContentType/index.js +0 -150
  172. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/ContenTypesSection/index.js +0 -37
  173. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormApiTokenContainer/index.js +0 -254
  174. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormBody/index.js +0 -77
  175. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/FormHead/index.js +0 -85
  176. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Permissions/index.js +0 -40
  177. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/components/Regenerate/index.js +0 -68
  178. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/init.js +0 -13
  179. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/reducer.js +0 -72
  180. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/getDateOfExpiration.js +0 -16
  181. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/index.js +0 -5
  182. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/utils/transformPermissionsData.js +0 -36
  183. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/DefaultButton/index.js +0 -63
  184. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/ReadButton/index.js +0 -19
  185. package/build/1669.d1b29c28.chunk.js +0 -1
  186. package/build/4318.7d167b58.chunk.js +0 -30
  187. package/build/524.40377968.chunk.js +0 -644
  188. package/build/7379.d246dd38.chunk.js +0 -1
  189. package/build/admin-app.a61d5c2e.chunk.js +0 -112
  190. package/build/admin-edit-roles-page.4dd6bcb9.chunk.js +0 -1
  191. package/build/api-tokens-create-page.93dd0689.chunk.js +0 -1
  192. package/build/api-tokens-edit-page.b0adac81.chunk.js +0 -1
  193. package/build/api-tokens-list-page.bb36535f.chunk.js +0 -16
  194. package/build/content-manager.feb0d540.chunk.js +0 -1178
  195. package/build/content-type-builder-list-view.5b3cd768.chunk.js +0 -194
  196. package/build/content-type-builder-translation-en-json.f985c9c4.chunk.js +0 -1
  197. package/build/content-type-builder.a684b2e8.chunk.js +0 -145
  198. package/build/en-json.a9918c93.chunk.js +0 -1
  199. package/build/main.e4065f58.js +0 -9337
  200. package/build/sso-settings-page.9ceb0140.chunk.js +0 -1
  201. package/server/content-types/api-token-permission.js +0 -36
  202. package/server/controllers/content-api.js +0 -15
  203. package/server/routes/content-api.js +0 -20
@@ -1,356 +0,0 @@
1
- import React, { useCallback, useState, useEffect, useMemo, memo } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { useIntl } from 'react-intl';
4
- import { useLocation } from 'react-router-dom';
5
- import { Stack } from '@strapi/design-system/Stack';
6
- import findIndex from 'lodash/findIndex';
7
- import get from 'lodash/get';
8
- import isArray from 'lodash/isArray';
9
- import isEmpty from 'lodash/isEmpty';
10
- import set from 'lodash/set';
11
- import {
12
- NotAllowedInput,
13
- useCMEditViewDataManager,
14
- useQueryParams,
15
- Link,
16
- } from '@strapi/helper-plugin';
17
- import { stringify } from 'qs';
18
- import axios from 'axios';
19
- import { axiosInstance } from '../../../core/utils';
20
- import { getTrad } from '../../utils';
21
- import Label from './Label';
22
- import SelectOne from '../SelectOne';
23
- import SelectMany from '../SelectMany';
24
- import Option from './Option';
25
- import { connect, select } from './utils';
26
-
27
- const initialPaginationState = {
28
- contains: '',
29
- limit: 20,
30
- start: 0,
31
- };
32
-
33
- const buildParams = (query, paramsToKeep) => {
34
- if (!paramsToKeep) {
35
- return {};
36
- }
37
-
38
- return paramsToKeep.reduce((acc, current) => {
39
- const value = get(query, current, null);
40
-
41
- if (value) {
42
- set(acc, current, value);
43
- }
44
-
45
- return acc;
46
- }, {});
47
- };
48
- function SelectWrapper({
49
- description,
50
- editable,
51
- labelAction,
52
- intlLabel,
53
- isCreatingEntry,
54
- isFieldAllowed,
55
- isFieldReadable,
56
- mainField,
57
- name,
58
- relationType,
59
- targetModel,
60
- placeholder,
61
- queryInfos,
62
- }) {
63
- const { formatMessage } = useIntl();
64
- const [{ query }] = useQueryParams();
65
- // Disable the input in case of a polymorphic relation
66
- const isMorph = useMemo(() => relationType.toLowerCase().includes('morph'), [relationType]);
67
- const { addRelation, modifiedData, moveRelation, onChange, onRemoveRelation } =
68
- useCMEditViewDataManager();
69
- const { pathname } = useLocation();
70
-
71
- const value = get(modifiedData, name, null);
72
- const [state, setState] = useState(initialPaginationState);
73
- const [options, setOptions] = useState([]);
74
- const [isLoading, setIsLoading] = useState(false);
75
- const [isOpen, setIsOpen] = useState(false);
76
-
77
- const filteredOptions = useMemo(() => {
78
- return options.filter((option) => {
79
- if (!isEmpty(value)) {
80
- // SelectMany
81
- if (Array.isArray(value)) {
82
- return findIndex(value, (o) => o.id === option.value.id) === -1;
83
- }
84
-
85
- // SelectOne
86
- return get(value, 'id', '') !== option.value.id;
87
- }
88
-
89
- return true;
90
- });
91
- }, [options, value]);
92
-
93
- const { endPoint, containsKey, defaultParams, shouldDisplayRelationLink, paramsToKeep } =
94
- queryInfos;
95
-
96
- const isSingle = ['oneWay', 'oneToOne', 'manyToOne', 'oneToManyMorph', 'oneToOneMorph'].includes(
97
- relationType
98
- );
99
-
100
- const idsToOmit = useMemo(() => {
101
- if (!value) {
102
- return [];
103
- }
104
-
105
- if (isSingle) {
106
- return [value.id];
107
- }
108
-
109
- return value.map((val) => val.id);
110
- }, [isSingle, value]);
111
-
112
- const getData = useCallback(
113
- async (source) => {
114
- // Currently polymorphic relations are not handled
115
- if (isMorph) {
116
- setIsLoading(false);
117
-
118
- return;
119
- }
120
-
121
- if (!isFieldAllowed) {
122
- setIsLoading(false);
123
-
124
- return;
125
- }
126
-
127
- setIsLoading(true);
128
-
129
- const params = { limit: state.limit, ...defaultParams, start: state.start };
130
-
131
- if (state.contains) {
132
- params[`filters[${containsKey}][$contains]`] = state.contains;
133
- }
134
-
135
- try {
136
- const { data } = await axiosInstance.post(
137
- endPoint,
138
- { idsToOmit },
139
- { params, cancelToken: source.token }
140
- );
141
-
142
- const formattedData = data.map((obj) => {
143
- return { value: obj, label: obj[mainField.name] };
144
- });
145
-
146
- setOptions((prevState) =>
147
- prevState.concat(formattedData).filter((obj, index) => {
148
- const objIndex = prevState.findIndex((el) => el.value.id === obj.value.id);
149
-
150
- if (objIndex === -1) {
151
- return true;
152
- }
153
-
154
- return prevState.findIndex((el) => el.value.id === obj.value.id) === index;
155
- })
156
- );
157
- setIsLoading(false);
158
- } catch (err) {
159
- // Silent
160
- setIsLoading(false);
161
- }
162
- },
163
- [
164
- containsKey,
165
- defaultParams,
166
- endPoint,
167
- idsToOmit,
168
- isFieldAllowed,
169
- isMorph,
170
- mainField.name,
171
- state.contains,
172
- state.limit,
173
- state.start,
174
- ]
175
- );
176
-
177
- useEffect(() => {
178
- const CancelToken = axios.CancelToken;
179
- const source = CancelToken.source();
180
-
181
- if (isOpen) {
182
- getData(source);
183
- }
184
-
185
- return () => source.cancel('Operation canceled by the user.');
186
- }, [getData, isOpen]);
187
-
188
- const handleInputChange = (inputValue, { action }) => {
189
- if (action === 'input-change') {
190
- setState((prevState) => {
191
- if (prevState.contains === inputValue) {
192
- return prevState;
193
- }
194
-
195
- return { ...prevState, contains: inputValue, start: 0 };
196
- });
197
- }
198
-
199
- return inputValue;
200
- };
201
-
202
- const handleMenuScrollToBottom = () => {
203
- setState((prevState) => ({
204
- ...prevState,
205
- start: prevState.start + 20,
206
- }));
207
- };
208
-
209
- const handleMenuClose = () => {
210
- setState(initialPaginationState);
211
- setIsOpen(false);
212
- };
213
-
214
- const handleChange = (value) => {
215
- onChange({ target: { name, value: value ? value.value : value } });
216
- };
217
-
218
- const handleAddRelation = (value) => {
219
- if (!isEmpty(value)) {
220
- addRelation({ target: { name, value } });
221
- }
222
- };
223
-
224
- const handleMenuOpen = () => {
225
- setIsOpen(true);
226
- };
227
-
228
- const to = `/content-manager/collectionType/${targetModel}/${value ? value.id : null}`;
229
-
230
- const searchToPersist = stringify(buildParams(query, paramsToKeep), { encode: false });
231
-
232
- let link = null;
233
-
234
- if (isSingle && value && shouldDisplayRelationLink) {
235
- link = (
236
- <Link to={{ pathname: to, state: { from: pathname }, search: searchToPersist }}>
237
- {formatMessage({ id: getTrad('containers.Edit.seeDetails'), defaultMessage: 'Details' })}
238
- </Link>
239
- );
240
- }
241
-
242
- const Component = isSingle ? SelectOne : SelectMany;
243
- const associationsLength = isArray(value) ? value.length : 0;
244
-
245
- const isDisabled = useMemo(() => {
246
- if (isMorph) {
247
- return true;
248
- }
249
-
250
- if (!isCreatingEntry) {
251
- return (!isFieldAllowed && isFieldReadable) || !editable;
252
- }
253
-
254
- return !editable;
255
- }, [isMorph, isCreatingEntry, editable, isFieldAllowed, isFieldReadable]);
256
-
257
- if (!isFieldAllowed && isCreatingEntry) {
258
- return <NotAllowedInput intlLabel={intlLabel} labelAction={labelAction} />;
259
- }
260
-
261
- if (!isCreatingEntry && !isFieldAllowed && !isFieldReadable) {
262
- return <NotAllowedInput intlLabel={intlLabel} labelAction={labelAction} />;
263
- }
264
-
265
- return (
266
- <Stack spacing={1}>
267
- <Label
268
- intlLabel={intlLabel}
269
- isSingle={isSingle}
270
- labelAction={labelAction}
271
- link={link}
272
- name={name}
273
- numberOfEntries={associationsLength}
274
- />
275
- <Component
276
- addRelation={handleAddRelation}
277
- components={{
278
- Option,
279
- }}
280
- displayNavigationLink={shouldDisplayRelationLink}
281
- id={name}
282
- isDisabled={isDisabled}
283
- isLoading={isLoading}
284
- isClearable
285
- loadingMessage={() =>
286
- formatMessage({
287
- id: getTrad('DynamicTable.relation-loading'),
288
- defaultMessage: 'Relations are loading',
289
- })
290
- }
291
- mainField={mainField}
292
- move={moveRelation}
293
- name={name}
294
- options={filteredOptions}
295
- onChange={handleChange}
296
- onInputChange={handleInputChange}
297
- onMenuClose={handleMenuClose}
298
- onMenuOpen={handleMenuOpen}
299
- onMenuScrollToBottom={handleMenuScrollToBottom}
300
- onRemove={onRemoveRelation}
301
- placeholder={placeholder}
302
- searchToPersist={searchToPersist}
303
- targetModel={targetModel}
304
- value={value}
305
- description={description}
306
- />
307
- </Stack>
308
- );
309
- }
310
-
311
- SelectWrapper.defaultProps = {
312
- editable: true,
313
- description: '',
314
- labelAction: null,
315
- isFieldAllowed: true,
316
- placeholder: null,
317
- };
318
-
319
- SelectWrapper.propTypes = {
320
- editable: PropTypes.bool,
321
- description: PropTypes.string,
322
- intlLabel: PropTypes.shape({
323
- id: PropTypes.string.isRequired,
324
- defaultMessage: PropTypes.string.isRequired,
325
- values: PropTypes.object,
326
- }).isRequired,
327
- labelAction: PropTypes.element,
328
- isCreatingEntry: PropTypes.bool.isRequired,
329
- isFieldAllowed: PropTypes.bool,
330
- isFieldReadable: PropTypes.bool.isRequired,
331
- mainField: PropTypes.shape({
332
- name: PropTypes.string.isRequired,
333
- schema: PropTypes.shape({
334
- type: PropTypes.string.isRequired,
335
- }).isRequired,
336
- }).isRequired,
337
- name: PropTypes.string.isRequired,
338
- placeholder: PropTypes.shape({
339
- id: PropTypes.string.isRequired,
340
- defaultMessage: PropTypes.string.isRequired,
341
- values: PropTypes.object,
342
- }),
343
- relationType: PropTypes.string.isRequired,
344
- targetModel: PropTypes.string.isRequired,
345
- queryInfos: PropTypes.shape({
346
- containsKey: PropTypes.string.isRequired,
347
- defaultParams: PropTypes.object,
348
- endPoint: PropTypes.string.isRequired,
349
- shouldDisplayRelationLink: PropTypes.bool.isRequired,
350
- paramsToKeep: PropTypes.array,
351
- }).isRequired,
352
- };
353
-
354
- const Memoized = memo(SelectWrapper);
355
-
356
- export default connect(Memoized, select);
@@ -1,135 +0,0 @@
1
- import React, { useRef, useEffect } from 'react';
2
- import styled from 'styled-components';
3
- import PropTypes from 'prop-types';
4
- import { useDrop, useDrag } from 'react-dnd';
5
- import { getEmptyImage } from 'react-dnd-html5-backend';
6
- import { Flex } from '@strapi/design-system/Flex';
7
- import Drag from '@strapi/icons/Drag';
8
- import { ItemTypes } from '../../../utils';
9
- import FieldButtonContent from './FieldButtonContent';
10
-
11
- const CustomDragIcon = styled(Drag)`
12
- height: ${12 / 16}rem;
13
- width: ${12 / 16}rem;
14
- path {
15
- fill: ${({ theme }) => theme.colors.neutral600};
16
- }
17
- `;
18
- const CustomFlex = styled(Flex)`
19
- opacity: ${({ isDragging }) => (isDragging ? 0 : 1)};
20
- `;
21
- const DragButton = styled(Flex)`
22
- cursor: all-scroll;
23
- border-right: 1px solid ${({ theme }) => theme.colors.neutral200};
24
- `;
25
-
26
- const RelationalFieldButton = ({
27
- attribute,
28
- onEditField,
29
- onDeleteField,
30
- children,
31
- index,
32
- name,
33
- onMoveField,
34
- }) => {
35
- const dragButtonRef = useRef();
36
-
37
- const [, drop] = useDrop({
38
- accept: ItemTypes.EDIT_RELATION,
39
- hover(item) {
40
- if (!dragButtonRef.current) {
41
- return;
42
- }
43
- const dragIndex = item.index;
44
- const hoverIndex = index;
45
-
46
- // Don't replace items with themselves
47
- if (dragIndex === hoverIndex) {
48
- return;
49
- }
50
-
51
- onMoveField(dragIndex, hoverIndex);
52
-
53
- item.index = hoverIndex;
54
- },
55
- });
56
-
57
- const [{ isDragging }, drag, dragPreview] = useDrag({
58
- type: ItemTypes.EDIT_RELATION,
59
- item() {
60
- return { index, labelField: children, name };
61
- },
62
- collect: (monitor) => ({
63
- isDragging: monitor.isDragging(),
64
- }),
65
- });
66
-
67
- useEffect(() => {
68
- dragPreview(getEmptyImage(), { captureDraggingState: true });
69
- }, [dragPreview]);
70
-
71
- drag(drop(dragButtonRef));
72
-
73
- const getHeight = () => {
74
- const higherFields = ['json', 'text', 'file', 'media', 'component', 'richtext', 'dynamiczone'];
75
-
76
- if (attribute && higherFields.includes(attribute.type)) {
77
- return `${74 / 16}rem`;
78
- }
79
-
80
- return `${32 / 16}rem`;
81
- };
82
-
83
- return (
84
- <CustomFlex
85
- width="100%"
86
- borderColor="neutral150"
87
- hasRadius
88
- background="neutral100"
89
- minHeight={getHeight()}
90
- alignItems="stretch"
91
- isDragging={isDragging}
92
- >
93
- <DragButton
94
- as="span"
95
- type="button"
96
- ref={dragButtonRef}
97
- onClick={(e) => e.stopPropagation()}
98
- alignItems="center"
99
- paddingLeft={3}
100
- paddingRight={3}
101
- // Disable the keyboard navigation since the drag n drop isn't accessible with the keyboard for the moment
102
- tabIndex={-1}
103
- >
104
- <CustomDragIcon />
105
- </DragButton>
106
- <FieldButtonContent
107
- attribute={attribute}
108
- onEditField={onEditField}
109
- onDeleteField={onDeleteField}
110
- >
111
- {children}
112
- </FieldButtonContent>
113
- </CustomFlex>
114
- );
115
- };
116
-
117
- RelationalFieldButton.defaultProps = {
118
- attribute: undefined,
119
- };
120
-
121
- RelationalFieldButton.propTypes = {
122
- attribute: PropTypes.shape({
123
- components: PropTypes.array,
124
- component: PropTypes.string,
125
- type: PropTypes.string,
126
- }),
127
- onEditField: PropTypes.func.isRequired,
128
- onDeleteField: PropTypes.func.isRequired,
129
- children: PropTypes.string.isRequired,
130
- index: PropTypes.number.isRequired,
131
- name: PropTypes.string.isRequired,
132
- onMoveField: PropTypes.func.isRequired,
133
- };
134
-
135
- export default RelationalFieldButton;
@@ -1,103 +0,0 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import get from 'lodash/get';
4
- import { useIntl } from 'react-intl';
5
- import { Button } from '@strapi/design-system/Button';
6
- import { Box } from '@strapi/design-system/Box';
7
- import { Typography } from '@strapi/design-system/Typography';
8
- import { Stack } from '@strapi/design-system/Stack';
9
- import { SimpleMenu, MenuItem } from '@strapi/design-system/SimpleMenu';
10
- import Plus from '@strapi/icons/Plus';
11
- import { getTrad } from '../../../utils';
12
- import { useLayoutDnd } from '../../../hooks';
13
- import RelationalFieldButton from './RelationalFieldButton';
14
-
15
- const RelationalFields = ({
16
- relationsLayout,
17
- editRelationsLayoutRemainingFields,
18
- onRemoveField,
19
- onAddField,
20
- }) => {
21
- const { formatMessage } = useIntl();
22
- const { setEditFieldToSelect, modifiedData, onMoveRelation } = useLayoutDnd();
23
-
24
- return (
25
- <Stack spacing={4}>
26
- <div>
27
- <Box>
28
- <Typography fontWeight="bold">
29
- {formatMessage({
30
- id: getTrad('containers.SettingPage.relations'),
31
- defaultMessage: 'Relational fields',
32
- })}
33
- </Typography>
34
- </Box>
35
- <Box>
36
- <Typography variant="pi" textColor="neutral600">
37
- {formatMessage({
38
- id: 'containers.SettingPage.editSettings.description',
39
- defaultMessage: 'Drag & drop the fields to build the layout',
40
- })}
41
- </Typography>
42
- </Box>
43
- </div>
44
- <Box padding={4} hasRadius borderStyle="dashed" borderWidth="1px" borderColor="neutral300">
45
- <Stack spacing={2}>
46
- {relationsLayout.map((relationName, index) => {
47
- const relationLabel = get(
48
- modifiedData,
49
- ['metadatas', relationName, 'edit', 'label'],
50
- ''
51
- );
52
-
53
- return (
54
- <RelationalFieldButton
55
- onEditField={() => setEditFieldToSelect(relationName)}
56
- onDeleteField={() => onRemoveField(index)}
57
- key={relationName}
58
- index={index}
59
- name={relationName}
60
- onMoveField={onMoveRelation}
61
- >
62
- {relationLabel || relationName}
63
- </RelationalFieldButton>
64
- );
65
- })}
66
- <SimpleMenu
67
- id="label"
68
- label={formatMessage({
69
- id: 'containers.SettingPage.add.relational-field',
70
- defaultMessage: 'Insert another relational field',
71
- })}
72
- data-testid="add-relation"
73
- as={Button}
74
- fullWidth
75
- startIcon={<Plus />}
76
- endIcon={null}
77
- variant="secondary"
78
- disabled={editRelationsLayoutRemainingFields.length === 0}
79
- >
80
- {editRelationsLayoutRemainingFields.map((remainingRelation) => (
81
- <MenuItem
82
- id={`menuItem-${remainingRelation}`}
83
- key={`menuItem-${remainingRelation}`}
84
- onClick={() => onAddField(remainingRelation)}
85
- >
86
- {remainingRelation}
87
- </MenuItem>
88
- ))}
89
- </SimpleMenu>
90
- </Stack>
91
- </Box>
92
- </Stack>
93
- );
94
- };
95
-
96
- RelationalFields.propTypes = {
97
- relationsLayout: PropTypes.array.isRequired,
98
- editRelationsLayoutRemainingFields: PropTypes.array.isRequired,
99
- onRemoveField: PropTypes.func.isRequired,
100
- onAddField: PropTypes.func.isRequired,
101
- };
102
-
103
- export default RelationalFields;
@@ -1,62 +0,0 @@
1
- import { get, has, isEmpty, isNil } from 'lodash';
2
-
3
- const getDraftRelations = (data, ctSchema, components) => {
4
- const getDraftRelationsCount = (data, schema) =>
5
- Object.keys(data).reduce((acc, current) => {
6
- const type = get(schema, ['attributes', current, 'type'], 'string');
7
- const relationType = get(schema, ['attributes', current, 'relationType'], '');
8
- const isMorph = relationType.toLowerCase().includes('morph');
9
- const oneWayTypes = ['oneWay', 'oneToOne', 'manyToOne'];
10
- const currentData = data[current];
11
-
12
- if (isNil(currentData)) {
13
- return acc;
14
- }
15
-
16
- if (type === 'dynamiczone') {
17
- currentData.forEach((curr) => {
18
- const compoSchema = get(components, curr.__component, {});
19
-
20
- acc += getDraftRelationsCount(curr, compoSchema);
21
- });
22
- }
23
-
24
- if (type === 'component') {
25
- const isRepeatable = get(schema, ['attributes', current, 'repeatable'], false);
26
- const compoUID = get(schema, ['attributes', current, 'component'], '');
27
- const compoSchema = get(components, compoUID, {});
28
-
29
- if (isRepeatable) {
30
- currentData.forEach((curr) => {
31
- acc += getDraftRelationsCount(curr, compoSchema);
32
- });
33
- } else {
34
- acc += getDraftRelationsCount(currentData, compoSchema);
35
- }
36
- }
37
-
38
- if (type === 'relation' && !isMorph) {
39
- if (oneWayTypes.includes(relationType)) {
40
- const hasDraftAndPublish = has(currentData, 'publishedAt');
41
-
42
- if (hasDraftAndPublish && isEmpty(currentData.publishedAt)) {
43
- acc += 1;
44
- }
45
- } else {
46
- currentData.forEach((value) => {
47
- if (has(value, 'publishedAt') && isEmpty(value.publishedAt)) {
48
- acc += 1;
49
- }
50
- });
51
- }
52
- }
53
-
54
- return acc;
55
- }, 0);
56
-
57
- const count = getDraftRelationsCount(data, ctSchema, components);
58
-
59
- return count;
60
- };
61
-
62
- export default getDraftRelations;
@@ -1,24 +0,0 @@
1
- import React, { createContext, useContext } from 'react';
2
- import PropTypes from 'prop-types';
3
-
4
- const ApiTokenPermissionsContext = createContext({});
5
-
6
- const ApiTokenPermissionsContextProvider = ({ children, ...rest }) => {
7
- return (
8
- <ApiTokenPermissionsContext.Provider value={rest}>
9
- {children}
10
- </ApiTokenPermissionsContext.Provider>
11
- );
12
- };
13
-
14
- const useApiTokenPermissionsContext = () => useContext(ApiTokenPermissionsContext);
15
-
16
- ApiTokenPermissionsContextProvider.propTypes = {
17
- children: PropTypes.node.isRequired,
18
- };
19
-
20
- export {
21
- ApiTokenPermissionsContext,
22
- ApiTokenPermissionsContextProvider,
23
- useApiTokenPermissionsContext,
24
- };