@strapi/admin 4.9.0 → 4.10.0-beta.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 (184) hide show
  1. package/admin/src/content-manager/components/DynamicTable/CellContent/PublicationState/PublicationState.js +26 -0
  2. package/admin/src/content-manager/components/DynamicTable/CellContent/PublicationState/index.js +1 -0
  3. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/ReviewWorkflowsStage.js +15 -0
  4. package/admin/src/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/index.js +1 -0
  5. package/admin/src/content-manager/components/DynamicTable/index.js +43 -49
  6. package/admin/src/content-manager/components/DynamicZone/components/DynamicComponent.js +2 -0
  7. package/admin/src/content-manager/components/EditViewDataManagerProvider/reducer.js +1 -3
  8. package/admin/src/content-manager/components/EditViewDataManagerProvider/utils/findAllAndReplace.js +3 -10
  9. package/admin/src/content-manager/components/InputUID/endActionStyle.js +13 -4
  10. package/admin/src/content-manager/components/InputUID/index.js +71 -94
  11. package/admin/src/content-manager/pages/EditView/Information/index.js +77 -53
  12. package/admin/src/content-manager/pages/EditView/InformationBox/InformationBoxCE.js +13 -0
  13. package/admin/src/content-manager/pages/EditView/InformationBox/index.js +3 -0
  14. package/admin/src/content-manager/pages/EditView/index.js +3 -4
  15. package/admin/src/content-manager/pages/ListView/index.js +6 -9
  16. package/admin/src/hooks/useRegenerate/index.js +7 -12
  17. package/admin/src/index.js +1 -0
  18. package/admin/src/pages/AuthPage/components/Register/index.js +38 -46
  19. package/admin/src/pages/SettingsPage/components/Tokens/FormHead/index.js +0 -4
  20. package/admin/src/pages/SettingsPage/components/Tokens/Regenerate/index.js +3 -5
  21. package/admin/src/pages/SettingsPage/components/Tokens/TokenTypeSelect/index.js +5 -7
  22. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/components/FormTransferTokenContainer/index.js +0 -41
  23. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/index.js +9 -53
  24. package/admin/src/pages/SettingsPage/pages/TransferTokens/EditView/utils/schema.js +0 -1
  25. package/admin/src/pages/SettingsPage/pages/TransferTokens/ListView/index.js +5 -27
  26. package/admin/src/translations/en.json +6 -1
  27. package/build/2263.4c5916f9.chunk.js +98 -0
  28. package/build/4049.64715f20.chunk.js +1 -0
  29. package/build/4649.213b8a3b.chunk.js +30 -0
  30. package/build/6985.66cca29c.chunk.js +1 -0
  31. package/build/7259.aefb51e8.chunk.js +1 -0
  32. package/build/8469.853c822b.chunk.js +1 -0
  33. package/build/9505.dbe702ab.chunk.js +14 -0
  34. package/build/9816.01ee964f.chunk.js +2 -0
  35. package/build/Admin-authenticatedApp.f50ad423.chunk.js +79 -0
  36. package/build/Admin_InternalErrorPage.4ad8b0df.chunk.js +1 -0
  37. package/build/Admin_homePage.1411fb7c.chunk.js +68 -0
  38. package/build/Admin_marketplace.02608d56.chunk.js +22 -0
  39. package/build/Admin_pluginsPage.15e3b0fd.chunk.js +1 -0
  40. package/build/Admin_profilePage.76afeca0.chunk.js +15 -0
  41. package/build/Admin_settingsPage.147755cd.chunk.js +9 -0
  42. package/build/Upload_ConfigureTheView.34dde278.chunk.js +1 -0
  43. package/build/admin-app.55dd7921.chunk.js +112 -0
  44. package/build/admin-edit-roles-page.cf543488.chunk.js +216 -0
  45. package/build/admin-edit-users.31c20712.chunk.js +10 -0
  46. package/build/admin-roles-list.489c501f.chunk.js +2 -0
  47. package/build/admin-users.3e111a7d.chunk.js +11 -0
  48. package/build/api-tokens-create-page.4328b852.chunk.js +1 -0
  49. package/build/api-tokens-edit-page.bce5050f.chunk.js +1 -0
  50. package/build/api-tokens-list-page.93f24348.chunk.js +16 -0
  51. package/build/audit-logs-settings-page.7be97e82.chunk.js +1 -0
  52. package/build/content-manager.4480ae88.chunk.js +1137 -0
  53. package/build/content-type-builder-list-view.cf38fe2f.chunk.js +191 -0
  54. package/build/content-type-builder-translation-en-json.7961593e.chunk.js +1 -0
  55. package/build/content-type-builder.af9abf1e.chunk.js +126 -0
  56. package/build/email-settings-page.4bdbef9a.chunk.js +3 -0
  57. package/build/en-json.697b4bcf.chunk.js +1 -0
  58. package/build/{highlight.js.28a1547e.chunk.js → highlight.js.26ef649f.chunk.js} +2 -2
  59. package/build/i18n-settings-page.2bb5be96.chunk.js +1 -0
  60. package/build/index.html +1 -1
  61. package/build/main.af8c0f31.js +3790 -0
  62. package/build/review-workflows-settings.7a7dc773.chunk.js +57 -0
  63. package/build/runtime~main.5a95bee6.js +2 -0
  64. package/build/sso-settings-page.272b87c8.chunk.js +1 -0
  65. package/build/transfer-tokens-create-page.a1f14bb1.chunk.js +1 -0
  66. package/build/transfer-tokens-edit-page.00ee1c74.chunk.js +1 -0
  67. package/build/transfer-tokens-list-page.ce37354b.chunk.js +16 -0
  68. package/build/upload-settings.0875e973.chunk.js +1 -0
  69. package/build/{upload-translation-th-json.98d35574.chunk.js → upload-translation-th-json.3847dae0.chunk.js} +1 -1
  70. package/build/upload.c7da1611.chunk.js +13 -0
  71. package/build/users-advanced-settings-page.1d3c14c7.chunk.js +1 -0
  72. package/build/users-email-settings-page.e8db68c4.chunk.js +1 -0
  73. package/build/users-providers-settings-page.14cac425.chunk.js +1 -0
  74. package/build/users-roles-settings-page.2ea4de84.chunk.js +30 -0
  75. package/build/webhook-edit-page.329141a5.chunk.js +23 -0
  76. package/build/webhook-list-page.029957a4.chunk.js +1 -0
  77. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +92 -0
  78. package/ee/admin/content-manager/pages/EditView/InformationBox/index.js +3 -0
  79. package/ee/admin/hooks/useSettingsMenu/utils/customAdminLinks.js +12 -12
  80. package/ee/admin/hooks/useSettingsMenu/utils/customGlobalLinks.js +21 -13
  81. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +195 -0
  82. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +42 -0
  83. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/AddStage.js +87 -0
  84. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/AddStage/index.js +1 -0
  85. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +90 -0
  86. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/index.js +1 -0
  87. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +92 -0
  88. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/index.js +1 -0
  89. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +6 -0
  90. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/hooks/useReviewWorkflows.js +35 -0
  91. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/index.js +3 -0
  92. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +121 -0
  93. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +25 -0
  94. package/ee/admin/pages/SettingsPage/utils/customRoutes.js +16 -2
  95. package/ee/admin/permissions/customPermissions.js +3 -0
  96. package/ee/server/bootstrap.js +13 -0
  97. package/ee/server/config/admin-actions.js +10 -0
  98. package/ee/server/constants/default-stages.json +14 -0
  99. package/ee/server/constants/default-workflow.json +1 -0
  100. package/ee/server/constants/workflows.js +8 -0
  101. package/ee/server/content-types/index.js +9 -0
  102. package/ee/server/content-types/workflow/index.js +34 -0
  103. package/ee/server/content-types/workflow-stage/index.js +41 -0
  104. package/ee/server/controllers/index.js +2 -0
  105. package/ee/server/controllers/workflows/index.js +36 -0
  106. package/ee/server/controllers/workflows/stages/index.js +95 -0
  107. package/ee/server/index.js +1 -0
  108. package/ee/server/middlewares/review-workflows.js +40 -0
  109. package/ee/server/migrations/review-workflows.js +39 -0
  110. package/ee/server/register.js +9 -3
  111. package/ee/server/routes/index.js +104 -0
  112. package/ee/server/services/audit-logs.js +16 -75
  113. package/ee/server/services/index.js +4 -0
  114. package/ee/server/services/review-workflows/entity-service-decorator.js +42 -0
  115. package/ee/server/services/review-workflows/review-workflows.js +175 -0
  116. package/ee/server/services/review-workflows/stages.js +148 -0
  117. package/ee/server/services/review-workflows/workflows.js +25 -0
  118. package/ee/server/utils/index.js +8 -0
  119. package/ee/server/utils/review-workflows.js +25 -0
  120. package/ee/server/utils/test.js +11 -0
  121. package/ee/server/validation/review-workflows.js +24 -0
  122. package/jest.config.front.js +6 -1
  123. package/package.json +15 -17
  124. package/server/controllers/transfer/runner.js +2 -4
  125. package/server/middlewares/data-transfer.js +1 -4
  126. package/server/routes/transfer.js +4 -13
  127. package/server/services/constants.js +0 -4
  128. package/server/services/transfer/permission.js +1 -1
  129. package/server/services/transfer/token.js +31 -33
  130. package/server/validation/transfer/token.js +2 -10
  131. package/webpack.config.js +1 -1
  132. package/.eslintignore +0 -4
  133. package/.eslintrc.js +0 -14
  134. package/admin/src/components/LocalesProvider/__mocks__/useLocalesProvider.js +0 -7
  135. package/admin/src/hooks/useConfigurations/__mocks__/index.js +0 -7
  136. package/build/1387.84b454d3.chunk.js +0 -1
  137. package/build/1657.45231968.chunk.js +0 -168
  138. package/build/3081.bcf9a12f.chunk.js +0 -108
  139. package/build/462.8fff7f3b.chunk.js +0 -71
  140. package/build/4628.20631dd1.chunk.js +0 -1
  141. package/build/5542.b8240e3f.chunk.js +0 -70
  142. package/build/5563.905daa13.chunk.js +0 -79
  143. package/build/6404.68405699.chunk.js +0 -100
  144. package/build/7259.b7d00cea.chunk.js +0 -1
  145. package/build/8694.6522968d.chunk.js +0 -247
  146. package/build/9347.058ddb22.chunk.js +0 -1
  147. package/build/Admin-authenticatedApp.31bf88ef.chunk.js +0 -79
  148. package/build/Admin_InternalErrorPage.15c6bf07.chunk.js +0 -1
  149. package/build/Admin_homePage.da2181fe.chunk.js +0 -73
  150. package/build/Admin_marketplace.d99044eb.chunk.js +0 -31
  151. package/build/Admin_pluginsPage.f6b52ee9.chunk.js +0 -6
  152. package/build/Admin_profilePage.9112cffc.chunk.js +0 -15
  153. package/build/Admin_settingsPage.cb63220f.chunk.js +0 -79
  154. package/build/Upload_ConfigureTheView.eaaec495.chunk.js +0 -1
  155. package/build/admin-app.8cde5b22.chunk.js +0 -110
  156. package/build/admin-edit-roles-page.4f1858e9.chunk.js +0 -280
  157. package/build/admin-edit-users.7e14d85f.chunk.js +0 -10
  158. package/build/admin-roles-list.97e198f9.chunk.js +0 -31
  159. package/build/admin-users.d02de059.chunk.js +0 -34
  160. package/build/api-tokens-create-page.97595e12.chunk.js +0 -1
  161. package/build/api-tokens-edit-page.cd36e30e.chunk.js +0 -1
  162. package/build/api-tokens-list-page.6757c7b9.chunk.js +0 -16
  163. package/build/audit-logs-settings-page.ca9a3c46.chunk.js +0 -76
  164. package/build/content-manager.de0ee3e5.chunk.js +0 -1132
  165. package/build/content-type-builder-list-view.9c2c020c.chunk.js +0 -214
  166. package/build/content-type-builder-translation-en-json.e577d595.chunk.js +0 -1
  167. package/build/content-type-builder.ec5ac7ab.chunk.js +0 -126
  168. package/build/email-settings-page.1095e1ab.chunk.js +0 -10
  169. package/build/en-json.b052667a.chunk.js +0 -1
  170. package/build/i18n-settings-page.7d80aae0.chunk.js +0 -60
  171. package/build/main.d40f9ca1.js +0 -2280
  172. package/build/runtime~main.7cdc9956.js +0 -2
  173. package/build/sso-settings-page.1dd4886e.chunk.js +0 -1
  174. package/build/transfer-tokens-create-page.ec2ca215.chunk.js +0 -1
  175. package/build/transfer-tokens-edit-page.22bf28e5.chunk.js +0 -1
  176. package/build/transfer-tokens-list-page.cf8c77f2.chunk.js +0 -16
  177. package/build/upload-settings.945fdcfa.chunk.js +0 -13
  178. package/build/upload.a86b1054.chunk.js +0 -33
  179. package/build/users-advanced-settings-page.5b5a9baa.chunk.js +0 -8
  180. package/build/users-email-settings-page.e5506eb4.chunk.js +0 -23
  181. package/build/users-providers-settings-page.e32089c2.chunk.js +0 -28
  182. package/build/users-roles-settings-page.a5c5b0df.chunk.js +0 -30
  183. package/build/webhook-edit-page.213f0075.chunk.js +0 -75
  184. package/build/webhook-list-page.5beb2a5c.chunk.js +0 -71
@@ -0,0 +1,26 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Status, Typography } from '@strapi/design-system';
5
+
6
+ import { getTrad } from '../../../../utils';
7
+
8
+ export function PublicationState({ isPublished }) {
9
+ const { formatMessage } = useIntl();
10
+ const variant = isPublished ? 'success' : 'secondary';
11
+
12
+ return (
13
+ <Status showBullet={false} variant={variant} size="S" width="min-content">
14
+ <Typography fontWeight="bold" textColor={`${variant}700`}>
15
+ {formatMessage({
16
+ id: getTrad(`containers.List.${isPublished ? 'published' : 'draft'}`),
17
+ defaultMessage: isPublished ? 'Published' : 'Draft',
18
+ })}
19
+ </Typography>
20
+ </Status>
21
+ );
22
+ }
23
+
24
+ PublicationState.propTypes = {
25
+ isPublished: PropTypes.bool.isRequired,
26
+ };
@@ -0,0 +1 @@
1
+ export * from './PublicationState';
@@ -0,0 +1,15 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { Typography } from '@strapi/design-system';
4
+
5
+ export function ReviewWorkflowsStage({ name }) {
6
+ return (
7
+ <Typography fontWeight="regular" textColor="neutral700">
8
+ {name}
9
+ </Typography>
10
+ );
11
+ }
12
+
13
+ ReviewWorkflowsStage.propTypes = {
14
+ name: PropTypes.string.isRequired,
15
+ };
@@ -0,0 +1 @@
1
+ export * from './ReviewWorkflowsStage';
@@ -3,9 +3,6 @@ import PropTypes from 'prop-types';
3
3
  import { useIntl } from 'react-intl';
4
4
  import { DynamicTable as Table, useStrapiApp } from '@strapi/helper-plugin';
5
5
  import { useSelector } from 'react-redux';
6
- import styled from 'styled-components';
7
-
8
- import { Status, Typography } from '@strapi/design-system';
9
6
 
10
7
  import { INJECT_COLUMN_IN_TABLE } from '../../../exposedHooks';
11
8
  import { selectDisplayedHeaders } from '../../pages/ListView/selectors';
@@ -13,10 +10,8 @@ import { getTrad } from '../../utils';
13
10
  import TableRows from './TableRows';
14
11
  import ConfirmDialogDeleteAll from './ConfirmDialogDeleteAll';
15
12
  import ConfirmDialogDelete from './ConfirmDialogDelete';
16
-
17
- const StyledStatus = styled(Status)`
18
- width: min-content;
19
- `;
13
+ import { PublicationState } from './CellContent/PublicationState/PublicationState';
14
+ import { ReviewWorkflowsStage } from './CellContent/ReviewWorkflowsStage';
20
15
 
21
16
  const DynamicTable = ({
22
17
  canCreate,
@@ -31,7 +26,8 @@ const DynamicTable = ({
31
26
  rows,
32
27
  }) => {
33
28
  const { runHookWaterfall } = useStrapiApp();
34
- const hasDraftAndPublish = layout.contentType.options.draftAndPublish || false;
29
+ const hasDraftAndPublish = layout.contentType.options?.draftAndPublish ?? false;
30
+ const hasReviewWorkflows = layout.contentType.options?.reviewWorkflows ?? false;
35
31
  const { formatMessage } = useIntl();
36
32
  const displayedHeaders = useSelector(selectDisplayedHeaders);
37
33
 
@@ -42,43 +38,23 @@ const DynamicTable = ({
42
38
  });
43
39
 
44
40
  const formattedHeaders = headers.displayedHeaders.map((header) => {
45
- const { metadatas } = header;
46
-
47
- if (header.fieldSchema.type === 'relation') {
48
- const sortFieldValue = `${header.name}.${header.metadatas.mainField.name}`;
49
-
50
- return {
51
- ...header,
52
- metadatas: {
53
- ...metadatas,
54
- label: formatMessage({
55
- id: getTrad(`containers.ListPage.table-headers.${header.name}`),
56
- defaultMessage: metadatas.label,
57
- }),
58
- },
59
- name: sortFieldValue,
60
- };
61
- }
41
+ const { fieldSchema, metadatas, name } = header;
62
42
 
63
43
  return {
64
44
  ...header,
65
45
  metadatas: {
66
46
  ...metadatas,
67
47
  label: formatMessage({
68
- id: getTrad(`containers.ListPage.table-headers.${header.name}`),
48
+ id: getTrad(`containers.ListPage.table-headers.${name}`),
69
49
  defaultMessage: metadatas.label,
70
50
  }),
71
51
  },
52
+ name: fieldSchema.type === 'relation' ? `${name}.${metadatas.mainField.name}` : name,
72
53
  };
73
54
  });
74
55
 
75
- if (!hasDraftAndPublish) {
76
- return formattedHeaders;
77
- }
78
-
79
- return [
80
- ...formattedHeaders,
81
- {
56
+ if (hasDraftAndPublish) {
57
+ formattedHeaders.push({
82
58
  key: '__published_at_temp_key__',
83
59
  name: 'publishedAt',
84
60
  fieldSchema: {
@@ -92,24 +68,42 @@ const DynamicTable = ({
92
68
  searchable: false,
93
69
  sortable: true,
94
70
  },
95
- cellFormatter(cellData) {
96
- const isPublished = cellData.publishedAt;
97
- const variant = isPublished ? 'success' : 'secondary';
71
+ cellFormatter({ publishedAt }) {
72
+ return <PublicationState isPublished={!!publishedAt} />;
73
+ },
74
+ });
75
+ }
98
76
 
99
- return (
100
- <StyledStatus showBullet={false} variant={variant} size="S">
101
- <Typography fontWeight="bold" textColor={`${variant}700`}>
102
- {formatMessage({
103
- id: getTrad(`containers.List.${isPublished ? 'published' : 'draft'}`),
104
- defaultMessage: isPublished ? 'Published' : 'Draft',
105
- })}
106
- </Typography>
107
- </StyledStatus>
108
- );
77
+ if (hasReviewWorkflows) {
78
+ formattedHeaders.push({
79
+ key: '__strapi_reviewWorkflows_stage_temp_key__',
80
+ name: 'strapi_reviewWorkflows_stage',
81
+ fieldSchema: {
82
+ type: 'custom',
109
83
  },
110
- },
111
- ];
112
- }, [runHookWaterfall, displayedHeaders, layout, hasDraftAndPublish, formatMessage]);
84
+ metadatas: {
85
+ label: formatMessage({
86
+ id: getTrad(`containers.ListPage.table-headers.reviewWorkflows.stage`),
87
+ defaultMessage: 'Review stage',
88
+ }),
89
+ searchable: false,
90
+ sortable: false,
91
+ },
92
+ cellFormatter({ strapi_reviewWorkflows_stage }) {
93
+ return <ReviewWorkflowsStage name={strapi_reviewWorkflows_stage.name} />;
94
+ },
95
+ });
96
+ }
97
+
98
+ return formattedHeaders;
99
+ }, [
100
+ runHookWaterfall,
101
+ displayedHeaders,
102
+ layout,
103
+ hasDraftAndPublish,
104
+ hasReviewWorkflows,
105
+ formatMessage,
106
+ ]);
113
107
 
114
108
  return (
115
109
  <Table
@@ -41,6 +41,8 @@ const IconButtonCustom = styled(IconButton)`
41
41
  }
42
42
  `;
43
43
 
44
+ // TODO: Delete once https://github.com/strapi/design-system/pull/858
45
+ // is merged and released.
44
46
  const StyledBox = styled(Box)`
45
47
  > div:first-child {
46
48
  box-shadow: ${({ theme }) => theme.shadows.tableShadow};
@@ -220,9 +220,7 @@ const reducer = (state, action) =>
220
220
 
221
221
  const findAllRelationsAndReplaceWithEmptyArray = findAllAndReplace(
222
222
  components,
223
- (value) => {
224
- return value.type === 'relation';
225
- },
223
+ (value) => value.type === 'relation',
226
224
  (_, { path }) => {
227
225
  if (state.modifiedData?.id === data.id && get(state.modifiedData, path)) {
228
226
  return get(state.modifiedData, path);
@@ -26,11 +26,7 @@ const findAllAndReplaceSetup = (components, predicate = () => false, replacement
26
26
  /**
27
27
  * @type {<TData extends object = object>(data: TData, attributes: Attributes, options?: { ignoreFalseyValues?: boolean}) => TData}
28
28
  */
29
- const findAllAndReplace = (
30
- data,
31
- attributes,
32
- { ignoreFalseyValues = false, path = [], parent = attributes } = {}
33
- ) => {
29
+ const findAllAndReplace = (data, attributes, { ignoreFalseyValues = false, path = [] } = {}) => {
34
30
  return Object.entries(attributes).reduce(
35
31
  (acc, [key, value]) => {
36
32
  if (
@@ -40,7 +36,7 @@ const findAllAndReplaceSetup = (components, predicate = () => false, replacement
40
36
  return acc;
41
37
  }
42
38
 
43
- if (predicate(value, { path: [...path, key], parent })) {
39
+ if (predicate(value, { path: [...path, key], parent: acc })) {
44
40
  acc[key] =
45
41
  typeof replacement === 'function'
46
42
  ? replacement(acc[key], { path: [...path, key], parent: acc })
@@ -50,18 +46,16 @@ const findAllAndReplaceSetup = (components, predicate = () => false, replacement
50
46
  if (value.type === 'component') {
51
47
  const componentAttributes = components[value.component].attributes;
52
48
 
53
- if (!value.repeatable && acc[key] && typeof acc[key] === 'object') {
49
+ if (!value.repeatable) {
54
50
  acc[key] = findAllAndReplace(acc[key], componentAttributes, {
55
51
  ignoreFalseyValues,
56
52
  path: [...path, key],
57
- parent: attributes[key],
58
53
  });
59
54
  } else if (value.repeatable && Array.isArray(acc[key])) {
60
55
  acc[key] = acc[key].map((datum, index) => {
61
56
  const data = findAllAndReplace(datum, componentAttributes, {
62
57
  ignoreFalseyValues,
63
58
  path: [...path, key, index],
64
- parent: attributes[key],
65
59
  });
66
60
 
67
61
  return data;
@@ -73,7 +67,6 @@ const findAllAndReplaceSetup = (components, predicate = () => false, replacement
73
67
  const data = findAllAndReplace(datum, componentAttributes, {
74
68
  ignoreFalseyValues,
75
69
  path: [...path, key, index],
76
- parent: attributes[key],
77
70
  });
78
71
 
79
72
  return data;
@@ -1,5 +1,9 @@
1
1
  import styled, { keyframes } from 'styled-components';
2
- import { Flex, FieldAction } from '@strapi/design-system';
2
+ import { Box, Flex, FieldAction } from '@strapi/design-system';
3
+
4
+ export const EndActionWrapper = styled(Box)`
5
+ position: relative;
6
+ `;
3
7
 
4
8
  export const FieldActionWrapper = styled(FieldAction)`
5
9
  svg {
@@ -18,13 +22,18 @@ export const FieldActionWrapper = styled(FieldAction)`
18
22
  `;
19
23
 
20
24
  export const TextValidation = styled(Flex)`
25
+ position: absolute;
26
+ right: ${({ theme }) => theme.spaces[6]};
27
+ width: 100px;
28
+ pointer-events: none;
29
+
21
30
  svg {
31
+ margin-right: ${({ theme }) => theme.spaces[1]};
22
32
  height: ${12 / 16}rem;
23
33
  width: ${12 / 16}rem;
24
-
25
34
  path {
26
- fill: ${({ theme, available }) =>
27
- available ? theme.colors.success600 : theme.colors.danger600};
35
+ fill: ${({ theme, notAvailable }) =>
36
+ !notAvailable ? theme.colors.success600 : theme.colors.danger600};
28
37
  }
29
38
  }
30
39
  `;
@@ -1,19 +1,19 @@
1
1
  import React, { useEffect, useState, useRef } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import {
4
- useCMEditViewDataManager,
5
- useFetchClient,
6
- useNotification,
7
- useAPIErrorHandler,
8
- } from '@strapi/helper-plugin';
3
+ import { useCMEditViewDataManager, useFetchClient } from '@strapi/helper-plugin';
9
4
  import { useIntl } from 'react-intl';
10
- import { Flex, TextInput, Typography } from '@strapi/design-system';
5
+ import get from 'lodash/get';
6
+ import { TextInput, Typography } from '@strapi/design-system';
11
7
  import { Refresh, CheckCircle, ExclamationMarkCircle, Loader } from '@strapi/icons';
12
-
13
8
  import { getRequestUrl } from '../../utils';
14
9
  import useDebounce from './useDebounce';
15
10
  import UID_REGEX from './regex';
16
- import { FieldActionWrapper, TextValidation, LoadingWrapper } from './endActionStyle';
11
+ import {
12
+ EndActionWrapper,
13
+ FieldActionWrapper,
14
+ TextValidation,
15
+ LoadingWrapper,
16
+ } from './endActionStyle';
17
17
 
18
18
  const InputUID = ({
19
19
  attribute,
@@ -34,11 +34,9 @@ const InputUID = ({
34
34
  const [availability, setAvailability] = useState(null);
35
35
  const debouncedValue = useDebounce(value, 300);
36
36
  const generateUid = useRef();
37
- const toggleNotification = useNotification();
38
- const { formatAPIError } = useAPIErrorHandler();
39
37
  const initialValue = initialData[name];
40
38
  const { formatMessage } = useIntl();
41
- const createdAtName = layout?.options?.timestamps ?? 0;
39
+ const createdAtName = get(layout, ['options', 'timestamps', 0]);
42
40
  const isCreation = !initialData[createdAtName];
43
41
  const debouncedTargetFieldValue = useDebounce(modifiedData[attribute.targetField], 300);
44
42
  const [isCustomized, setIsCustomized] = useState(false);
@@ -61,74 +59,72 @@ const InputUID = ({
61
59
 
62
60
  generateUid.current = async (shouldSetInitialValue = false) => {
63
61
  setIsLoading(true);
64
-
62
+ const requestURL = getRequestUrl('uid/generate');
65
63
  try {
66
64
  const {
67
65
  data: { data },
68
- } = await post(getRequestUrl('uid/generate'), {
66
+ } = await post(requestURL, {
69
67
  contentTypeUID,
70
68
  field: name,
71
69
  data: modifiedData,
72
70
  });
73
-
74
71
  onChange({ target: { name, value: data, type: 'text' } }, shouldSetInitialValue);
75
72
  setIsLoading(false);
76
- } catch (error) {
73
+ } catch (err) {
77
74
  setIsLoading(false);
78
- toggleNotification({
79
- type: 'warning',
80
- message: formatAPIError(error),
81
- });
82
75
  }
83
76
  };
84
77
 
85
78
  const checkAvailability = async () => {
79
+ setIsLoading(true);
80
+
81
+ const requestURL = getRequestUrl('uid/check-availability');
82
+
86
83
  if (!value) {
87
84
  return;
88
85
  }
89
86
 
90
- setIsLoading(true);
91
-
92
87
  try {
93
- const { data } = await post(getRequestUrl('uid/check-availability'), {
88
+ const { data } = await post(requestURL, {
94
89
  contentTypeUID,
95
90
  field: name,
96
91
  value: value ? value.trim() : '',
97
92
  });
98
93
 
99
- setIsLoading(false);
100
94
  setAvailability(data);
101
- } catch (error) {
95
+
96
+ setIsLoading(false);
97
+ } catch (err) {
102
98
  setIsLoading(false);
103
- toggleNotification({
104
- type: 'warning',
105
- message: formatAPIError(error),
106
- });
107
99
  }
108
100
  };
109
101
 
110
- // FIXME: we need to find a better way to autofill the input when it is required.
102
+ // // FIXME: we need to find a better way to autofill the input when it is required.
111
103
  useEffect(() => {
112
104
  if (!value && attribute.required) {
113
105
  generateUid.current(true);
114
106
  }
115
- }, [attribute.required, generateUid, value]);
107
+ // eslint-disable-next-line react-hooks/exhaustive-deps
108
+ }, []);
116
109
 
117
110
  useEffect(() => {
118
- if (debouncedValue?.trim().match(UID_REGEX) && debouncedValue !== initialValue) {
111
+ if (
112
+ debouncedValue &&
113
+ debouncedValue.trim().match(UID_REGEX) &&
114
+ debouncedValue !== initialValue
115
+ ) {
119
116
  checkAvailability();
120
117
  }
121
-
122
118
  if (!debouncedValue) {
123
119
  setAvailability(null);
124
120
  }
125
121
  // eslint-disable-next-line react-hooks/exhaustive-deps
126
- }, [initialValue, debouncedValue]);
122
+ }, [debouncedValue, initialValue]);
127
123
 
128
124
  useEffect(() => {
129
125
  let timer;
130
126
 
131
- if (availability?.isAvailable) {
127
+ if (availability && availability.isAvailable) {
132
128
  timer = setTimeout(() => {
133
129
  setAvailability(null);
134
130
  }, 4000);
@@ -180,70 +176,51 @@ const InputUID = ({
180
176
  disabled={disabled}
181
177
  error={error}
182
178
  endAction={
183
- <Flex position="relative" gap={1}>
184
- {availability && !regenerateLabel && (
185
- <TextValidation
186
- alignItems="center"
187
- gap={1}
188
- justifyContent="flex-end"
189
- available={!!availability?.isAvailable}
190
- data-not-here-outer
191
- position="absolute"
192
- pointerEvents="none"
193
- right={6}
194
- width="100px"
195
- >
196
- {availability?.isAvailable ? <CheckCircle /> : <ExclamationMarkCircle />}
197
-
198
- <Typography
199
- textColor={availability.isAvailable ? 'success600' : 'danger600'}
200
- variant="pi"
201
- >
202
- {formatMessage(
203
- availability.isAvailable
204
- ? {
205
- id: 'content-manager.components.uid.available',
206
- defaultMessage: 'Available',
207
- }
208
- : {
209
- id: 'content-manager.components.uid.unavailable',
210
- defaultMessage: 'Unavailable',
211
- }
212
- )}
179
+ <EndActionWrapper>
180
+ {availability && availability.isAvailable && !regenerateLabel && (
181
+ <TextValidation alignItems="center" justifyContent="flex-end">
182
+ <CheckCircle />
183
+ <Typography textColor="success600" variant="pi">
184
+ {formatMessage({
185
+ id: 'content-manager.components.uid.available',
186
+ defaultMessage: 'Available',
187
+ })}
213
188
  </Typography>
214
189
  </TextValidation>
215
190
  )}
216
-
217
- {!disabled && (
218
- <>
219
- {regenerateLabel && (
220
- <TextValidation alignItems="center" justifyContent="flex-end" gap={1}>
221
- <Typography textColor="primary600" variant="pi">
222
- {regenerateLabel}
223
- </Typography>
224
- </TextValidation>
225
- )}
226
-
227
- <FieldActionWrapper
228
- onClick={() => generateUid.current()}
229
- label={formatMessage({
230
- id: 'content-manager.components.uid.regenerate',
231
- defaultMessage: 'Regenerate',
191
+ {availability && !availability.isAvailable && !regenerateLabel && (
192
+ <TextValidation notAvailable alignItems="center" justifyContent="flex-end">
193
+ <ExclamationMarkCircle />
194
+ <Typography textColor="danger600" variant="pi">
195
+ {formatMessage({
196
+ id: 'content-manager.components.uid.unavailable',
197
+ defaultMessage: 'Unavailable',
232
198
  })}
233
- onMouseEnter={handleGenerateMouseEnter}
234
- onMouseLeave={handleGenerateMouseLeave}
235
- >
236
- {isLoading ? (
237
- <LoadingWrapper data-testid="loading-wrapper">
238
- <Loader />
239
- </LoadingWrapper>
240
- ) : (
241
- <Refresh />
242
- )}
243
- </FieldActionWrapper>
244
- </>
199
+ </Typography>
200
+ </TextValidation>
201
+ )}
202
+ {regenerateLabel && (
203
+ <TextValidation alignItems="center" justifyContent="flex-end">
204
+ <Typography textColor="primary600" variant="pi">
205
+ {regenerateLabel}
206
+ </Typography>
207
+ </TextValidation>
245
208
  )}
246
- </Flex>
209
+ <FieldActionWrapper
210
+ onClick={() => generateUid.current()}
211
+ label="regenerate"
212
+ onMouseEnter={handleGenerateMouseEnter}
213
+ onMouseLeave={handleGenerateMouseLeave}
214
+ >
215
+ {isLoading ? (
216
+ <LoadingWrapper>
217
+ <Loader />
218
+ </LoadingWrapper>
219
+ ) : (
220
+ <Refresh />
221
+ )}
222
+ </FieldActionWrapper>
223
+ </EndActionWrapper>
247
224
  }
248
225
  hint={hint}
249
226
  label={label}