@strapi/admin 4.10.1 → 4.10.2

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 (127) hide show
  1. package/admin/src/components/AuthenticatedApp/index.js +19 -24
  2. package/admin/src/components/DragLayer/DragLayer.js +53 -0
  3. package/admin/src/components/DragLayer/index.js +1 -0
  4. package/admin/src/components/LeftMenu/index.js +2 -2
  5. package/admin/src/components/Providers/index.js +11 -7
  6. package/admin/src/content-manager/contexts/index.js +0 -1
  7. package/admin/src/content-manager/hooks/index.js +0 -1
  8. package/admin/src/content-manager/hooks/useLazyComponents/index.js +7 -3
  9. package/admin/src/content-manager/hooks/useRelation/useRelation.js +1 -3
  10. package/admin/src/content-manager/pages/{ListSettingsView/components/CardPreview.js → App/components/CardDragPreview.js} +28 -28
  11. package/admin/src/content-manager/pages/App/components/ComponentDragPreview.js +75 -0
  12. package/admin/src/content-manager/{components/DragLayer → pages/App/components}/RelationDragPreview.js +7 -4
  13. package/admin/src/content-manager/pages/App/index.js +39 -2
  14. package/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.js +1 -1
  15. package/admin/src/content-manager/pages/EditSettingsView/components/DisplayedFieldButton.js +1 -1
  16. package/admin/src/content-manager/pages/EditSettingsView/components/DynamicZoneList.js +1 -1
  17. package/admin/src/content-manager/pages/EditSettingsView/components/FormModal.js +1 -1
  18. package/admin/src/content-manager/{components → pages/EditSettingsView/components}/LayoutDndProvider/index.js +3 -4
  19. package/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.js +1 -1
  20. package/admin/src/content-manager/pages/EditSettingsView/components/ModalForm.js +1 -1
  21. package/admin/src/content-manager/pages/EditSettingsView/components/RowItemsLayout.js +1 -1
  22. package/admin/src/content-manager/pages/EditSettingsView/hooks/useLayoutDnd.js +6 -0
  23. package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -1
  24. package/admin/src/content-manager/pages/ListSettingsView/components/DraggableCard.js +6 -6
  25. package/admin/src/hooks/useMenu/index.js +2 -2
  26. package/admin/src/hooks/useReleaseNotification/index.js +2 -2
  27. package/admin/src/hooks/useSettingsMenu/index.js +2 -2
  28. package/admin/src/pages/Admin/Onboarding/index.js +2 -2
  29. package/admin/src/pages/App/index.js +2 -2
  30. package/admin/src/pages/HomePage/SocialLinks.js +2 -2
  31. package/admin/src/pages/MarketplacePage/index.js +2 -2
  32. package/admin/src/pages/ProfilePage/index.js +2 -2
  33. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +2 -2
  34. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/components/Permissions/utils/updateValues.js +3 -3
  35. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +2 -2
  36. package/admin/src/translations/fr.json +1 -1
  37. package/build/{5563.905daa13.chunk.js → 5563.986609ed.chunk.js} +2 -2
  38. package/build/6858.56d4d528.chunk.js +50 -0
  39. package/build/{7259.b7d00cea.chunk.js → 7259.7a48aa2f.chunk.js} +1 -1
  40. package/build/7725.1633e06f.chunk.js +213 -0
  41. package/build/9703.e590889d.chunk.js +1 -0
  42. package/build/Admin-authenticatedApp.a8373103.chunk.js +79 -0
  43. package/build/{Admin_InternalErrorPage.15c6bf07.chunk.js → Admin_InternalErrorPage.96ceaae1.chunk.js} +1 -1
  44. package/build/{Admin_homePage.f9309c6d.chunk.js → Admin_homePage.9f7c0bb1.chunk.js} +5 -5
  45. package/build/{Admin_marketplace.56bc1008.chunk.js → Admin_marketplace.a60cde15.chunk.js} +5 -5
  46. package/build/{Admin_pluginsPage.f6b52ee9.chunk.js → Admin_pluginsPage.9e6fa51c.chunk.js} +1 -1
  47. package/build/{Admin_profilePage.9112cffc.chunk.js → Admin_profilePage.1b337b73.chunk.js} +2 -2
  48. package/build/{Admin_settingsPage.4604a16c.chunk.js → Admin_settingsPage.5e045f42.chunk.js} +2 -2
  49. package/build/{Upload_ConfigureTheView.eaaec495.chunk.js → Upload_ConfigureTheView.4fc648b5.chunk.js} +1 -1
  50. package/build/admin-app.9bfe4ec7.chunk.js +63 -0
  51. package/build/{admin-edit-roles-page.8a4063f7.chunk.js → admin-edit-roles-page.d0c9497b.chunk.js} +24 -24
  52. package/build/{admin-edit-users.7e14d85f.chunk.js → admin-edit-users.ba27c532.chunk.js} +2 -2
  53. package/build/{admin-roles-list.329c1f63.chunk.js → admin-roles-list.c759daa3.chunk.js} +1 -1
  54. package/build/{admin-users.d02de059.chunk.js → admin-users.ad5dd832.chunk.js} +2 -2
  55. package/build/{api-tokens-create-page.97595e12.chunk.js → api-tokens-create-page.973d2816.chunk.js} +1 -1
  56. package/build/{api-tokens-edit-page.cd36e30e.chunk.js → api-tokens-edit-page.29725c5e.chunk.js} +1 -1
  57. package/build/{api-tokens-list-page.6757c7b9.chunk.js → api-tokens-list-page.66c4fbdd.chunk.js} +2 -2
  58. package/build/{audit-logs-settings-page.19d90bda.chunk.js → audit-logs-settings-page.45cb4fb5.chunk.js} +1 -1
  59. package/build/content-manager.d28eb183.chunk.js +1111 -0
  60. package/build/{content-type-builder-list-view.9c2c020c.chunk.js → content-type-builder-list-view.5ff685ec.chunk.js} +1 -1
  61. package/build/{content-type-builder.68af11d2.chunk.js → content-type-builder.4737a30c.chunk.js} +3 -3
  62. package/build/{email-settings-page.1095e1ab.chunk.js → email-settings-page.dc07d518.chunk.js} +1 -1
  63. package/build/{fr-json.5947cf63.chunk.js → fr-json.73494bf5.chunk.js} +1 -1
  64. package/build/{i18n-settings-page.d95b32df.chunk.js → i18n-settings-page.8219dd99.chunk.js} +1 -1
  65. package/build/index.html +1 -1
  66. package/build/main.41970e4c.js +2597 -0
  67. package/build/review-workflows-settings.7c0b4e73.chunk.js +61 -0
  68. package/build/{runtime~main.d4c8d6a2.js → runtime~main.c20330f1.js} +1 -1
  69. package/build/{sso-settings-page.1dd4886e.chunk.js → sso-settings-page.f44d95d8.chunk.js} +1 -1
  70. package/build/{transfer-tokens-create-page.ec2ca215.chunk.js → transfer-tokens-create-page.170acee6.chunk.js} +1 -1
  71. package/build/{transfer-tokens-edit-page.22bf28e5.chunk.js → transfer-tokens-edit-page.6cf23295.chunk.js} +1 -1
  72. package/build/{transfer-tokens-list-page.cf8c77f2.chunk.js → transfer-tokens-list-page.c3fec4c1.chunk.js} +2 -2
  73. package/build/{upload-settings.945fdcfa.chunk.js → upload-settings.dd2d987c.chunk.js} +1 -1
  74. package/build/{upload.a86b1054.chunk.js → upload.c8479232.chunk.js} +1 -1
  75. package/build/{users-advanced-settings-page.5b5a9baa.chunk.js → users-advanced-settings-page.c36cfd59.chunk.js} +1 -1
  76. package/build/{users-email-settings-page.e5506eb4.chunk.js → users-email-settings-page.2716ce8e.chunk.js} +5 -5
  77. package/build/{users-providers-settings-page.e32089c2.chunk.js → users-providers-settings-page.0d6304a5.chunk.js} +1 -1
  78. package/build/{users-roles-settings-page.20656f92.chunk.js → users-roles-settings-page.eeb3a339.chunk.js} +1 -1
  79. package/build/{webhook-edit-page.a3b62049.chunk.js → webhook-edit-page.f4db86f3.chunk.js} +2 -2
  80. package/build/{webhook-list-page.ca38eeef.chunk.js → webhook-list-page.30d73114.chunk.js} +1 -1
  81. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/ReviewWorkflowsStageEE.js +11 -5
  82. package/ee/admin/content-manager/components/DynamicTable/CellContent/ReviewWorkflowsStage/getTableColumn.js +7 -3
  83. package/ee/admin/content-manager/pages/EditView/InformationBox/InformationBoxEE.js +16 -2
  84. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/ReviewWorkflows.js +34 -25
  85. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/actions/index.js +11 -0
  86. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/StageDragPreview/StageDragPreview.js +45 -0
  87. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/StageDragPreview/index.js +1 -0
  88. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/Stage.js +287 -63
  89. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/OptionColor/OptionColor.js +27 -0
  90. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/OptionColor/index.js +1 -0
  91. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/SingleValueColor/SingleValueColor.js +31 -0
  92. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stage/components/SingleValueColor/index.js +1 -0
  93. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/components/Stages/Stages.js +2 -1
  94. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/constants.js +26 -0
  95. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/reducer/index.js +36 -2
  96. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/colors.js +33 -0
  97. package/ee/admin/pages/SettingsPage/pages/ReviewWorkflows/utils/getWorkflowValidationSchema.js +9 -0
  98. package/ee/server/constants/workflows.js +1 -0
  99. package/ee/server/content-types/workflow-stage/index.js +7 -0
  100. package/ee/server/controllers/authentication/middlewares.js +1 -1
  101. package/ee/server/migrations/review-workflows-stages-color.js +20 -0
  102. package/ee/server/register.js +2 -0
  103. package/ee/server/services/review-workflows/review-workflows.js +1 -1
  104. package/ee/server/services/review-workflows/stages.js +1 -1
  105. package/ee/server/utils/persisted-tables.js +3 -0
  106. package/ee/server/validation/review-workflows.js +7 -1
  107. package/jest.config.front.js +1 -0
  108. package/package.json +10 -10
  109. package/admin/src/components/AutoReloadOverlayBlockerProvider/Blocker.js +0 -95
  110. package/admin/src/components/AutoReloadOverlayBlockerProvider/Overlay.js +0 -42
  111. package/admin/src/components/AutoReloadOverlayBlockerProvider/index.js +0 -99
  112. package/admin/src/components/Notifications/Notification/index.js +0 -159
  113. package/admin/src/components/Notifications/index.js +0 -46
  114. package/admin/src/components/Notifications/reducer.js +0 -47
  115. package/admin/src/components/OverlayBlocker/index.js +0 -67
  116. package/admin/src/content-manager/components/DragLayer/ComponentDragPreview.js +0 -83
  117. package/admin/src/content-manager/components/DragLayer/index.js +0 -85
  118. package/admin/src/content-manager/contexts/LayoutDnd.js +0 -5
  119. package/admin/src/content-manager/hooks/useCallbackRef.js +0 -23
  120. package/admin/src/content-manager/hooks/useLayoutDnd.js +0 -6
  121. package/admin/src/content-manager/pages/ListSettingsView/utils/ellipsisCardTitle.js +0 -7
  122. package/build/8694.6522968d.chunk.js +0 -247
  123. package/build/Admin-authenticatedApp.5562aedc.chunk.js +0 -79
  124. package/build/admin-app.014adc27.chunk.js +0 -110
  125. package/build/content-manager.84f81966.chunk.js +0 -1130
  126. package/build/main.841e0dcb.js +0 -2280
  127. package/build/review-workflows-settings.f7890c40.chunk.js +0 -106
@@ -94,7 +94,7 @@ function persistStagesJoinTables({ strapi }) {
94
94
  // Persist the stage join table
95
95
  const { attributes, tableName } = strapi.db.metadata.get(contentTypeUID);
96
96
  const joinTableName = attributes[ENTITY_STAGE_ATTRIBUTE].joinTable.name;
97
- return { name: joinTableName, dependsOn: { name: tableName } };
97
+ return { name: joinTableName, dependsOn: [{ name: tableName }] };
98
98
  };
99
99
 
100
100
  const joinTablesToPersist = pipe([
@@ -208,7 +208,7 @@ function getDiffBetweenStages(sourceStages, comparisonStages) {
208
208
 
209
209
  if (!srcStage) {
210
210
  acc.created.push(stageToCompare);
211
- } else if (srcStage.name !== stageToCompare.name) {
211
+ } else if (srcStage.name !== stageToCompare.name || srcStage.color !== stageToCompare.color) {
212
212
  acc.updated.push(stageToCompare);
213
213
  }
214
214
  return acc;
@@ -124,6 +124,9 @@ const persistTablesWithPrefix = async (tableNamePrefix) => {
124
124
  const removePersistedTablesWithSuffix = async (tableNameSuffix) => {
125
125
  const tableNameRegex = new RegExp(`.*${tableNameSuffix}$`);
126
126
  const tableNames = await findTables({ strapi }, tableNameRegex);
127
+ if (!tableNames.length) {
128
+ return;
129
+ }
127
130
  await removePersistedTables({ strapi }, tableNames);
128
131
  };
129
132
 
@@ -5,9 +5,15 @@ const { yup, validateYupSchema } = require('@strapi/utils');
5
5
  const stageObject = yup.object().shape({
6
6
  id: yup.number().integer().min(1),
7
7
  name: yup.string().max(255).required(),
8
+ color: yup.string().matches(/^#(?:[0-9a-fA-F]{3}){1,2}$/i), // hex color
8
9
  });
9
10
 
10
- const validateUpdateStagesSchema = yup.array().of(stageObject).required();
11
+ const validateUpdateStagesSchema = yup
12
+ .array()
13
+ .of(stageObject)
14
+ .required()
15
+ .max(200, 'You can not create more than 200 stages');
16
+
11
17
  const validateUpdateStageOnEntity = yup
12
18
  .object()
13
19
  .shape({
@@ -3,4 +3,5 @@
3
3
  module.exports = {
4
4
  preset: '../../../jest-preset.front.js',
5
5
  collectCoverageFrom: ['<rootDir>/packages/core/admin/admin/**/*.js'],
6
+ displayName: 'Core admin',
6
7
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@strapi/admin",
3
- "version": "4.10.1",
3
+ "version": "4.10.2",
4
4
  "description": "Strapi Admin",
5
5
  "repository": {
6
6
  "type": "git",
@@ -48,15 +48,15 @@
48
48
  "@casl/ability": "^5.4.3",
49
49
  "@fingerprintjs/fingerprintjs": "3.3.6",
50
50
  "@pmmmwh/react-refresh-webpack-plugin": "0.5.10",
51
- "@strapi/babel-plugin-switch-ee-ce": "4.10.1",
52
- "@strapi/data-transfer": "4.10.1",
51
+ "@strapi/babel-plugin-switch-ee-ce": "4.10.2",
52
+ "@strapi/data-transfer": "4.10.2",
53
53
  "@strapi/design-system": "1.6.6",
54
- "@strapi/helper-plugin": "4.10.1",
54
+ "@strapi/helper-plugin": "4.10.2",
55
55
  "@strapi/icons": "1.6.6",
56
- "@strapi/permissions": "4.10.1",
57
- "@strapi/provider-audit-logs-local": "4.10.1",
58
- "@strapi/typescript-utils": "4.10.1",
59
- "@strapi/utils": "4.10.1",
56
+ "@strapi/permissions": "4.10.2",
57
+ "@strapi/provider-audit-logs-local": "4.10.2",
58
+ "@strapi/typescript-utils": "4.10.2",
59
+ "@strapi/utils": "4.10.2",
60
60
  "axios": "1.3.4",
61
61
  "babel-loader": "^9.1.2",
62
62
  "babel-plugin-styled-components": "2.0.2",
@@ -117,7 +117,7 @@
117
117
  "react-error-boundary": "3.1.4",
118
118
  "react-fast-compare": "^3.2.0",
119
119
  "react-helmet": "^6.1.0",
120
- "react-intl": "6.3.2",
120
+ "react-intl": "6.4.1",
121
121
  "react-is": "^17.0.2",
122
122
  "react-query": "3.24.3",
123
123
  "react-redux": "8.0.5",
@@ -168,5 +168,5 @@
168
168
  }
169
169
  }
170
170
  },
171
- "gitHead": "23b531cef55c1583ea7d526b2baf2340a3129dad"
171
+ "gitHead": "a02b19866a3bcc1f30c2395698afae6e9c3e0515"
172
172
  }
@@ -1,95 +0,0 @@
1
- import React, { useEffect } from 'react';
2
- import ReactDOM from 'react-dom';
3
- import PropTypes from 'prop-types';
4
- import { useIntl } from 'react-intl';
5
- import styled, { keyframes } from 'styled-components';
6
- import { pxToRem } from '@strapi/helper-plugin';
7
- import { Clock, Refresh } from '@strapi/icons';
8
- import { Link } from '@strapi/design-system/v2';
9
- import { Box, Flex, Typography } from '@strapi/design-system';
10
- import { Content, IconBox, Overlay } from './Overlay';
11
-
12
- const overlayContainer = document.createElement('div');
13
- const ID = 'autoReloadOverlayBlocker';
14
- overlayContainer.setAttribute('id', ID);
15
-
16
- const rotation = keyframes`
17
- from {
18
- transform: rotate(0deg);
19
- }
20
- to {
21
- transform: rotate(359deg);
22
- }
23
- `;
24
-
25
- const LoaderReload = styled(Refresh)`
26
- animation: ${rotation} 1s infinite linear;
27
- `;
28
-
29
- const Blocker = ({ displayedIcon, description, title, isOpen }) => {
30
- const { formatMessage } = useIntl();
31
-
32
- useEffect(() => {
33
- document.body.appendChild(overlayContainer);
34
-
35
- return () => {
36
- document.body.removeChild(overlayContainer);
37
- };
38
- }, []);
39
-
40
- if (isOpen) {
41
- return ReactDOM.createPortal(
42
- <Overlay>
43
- <Content direction="column" alignItems="stretch" gap={6}>
44
- <Flex direction="column" alignItems="stretch" gap={2}>
45
- <Flex justifyContent="center">
46
- <Typography as="h1" variant="alpha">
47
- {formatMessage(title)}
48
- </Typography>
49
- </Flex>
50
- <Flex justifyContent="center">
51
- <Typography as="h2" textColor="neutral600" fontSize={4} fontWeight="regular">
52
- {formatMessage(description)}
53
- </Typography>
54
- </Flex>
55
- </Flex>
56
- <Flex justifyContent="center">
57
- {displayedIcon === 'reload' && (
58
- <IconBox padding={6} background="primary100" borderColor="primary200">
59
- <LoaderReload width={pxToRem(36)} height={pxToRem(36)} />
60
- </IconBox>
61
- )}
62
-
63
- {displayedIcon === 'time' && (
64
- <IconBox padding={6} background="primary100" borderColor="primary200">
65
- <Clock width={pxToRem(40)} height={pxToRem(40)} />
66
- </IconBox>
67
- )}
68
- </Flex>
69
- <Flex justifyContent="center">
70
- <Box paddingTop={2}>
71
- <Link href="https://docs.strapi.io" isExternal>
72
- {formatMessage({
73
- id: 'global.documentation',
74
- defaultMessage: 'Read the documentation',
75
- })}
76
- </Link>
77
- </Box>
78
- </Flex>
79
- </Content>
80
- </Overlay>,
81
- overlayContainer
82
- );
83
- }
84
-
85
- return null;
86
- };
87
-
88
- Blocker.propTypes = {
89
- displayedIcon: PropTypes.oneOfType([PropTypes.string, PropTypes.array]).isRequired,
90
- description: PropTypes.object.isRequired,
91
- isOpen: PropTypes.bool.isRequired,
92
- title: PropTypes.object.isRequired,
93
- };
94
-
95
- export default Blocker;
@@ -1,42 +0,0 @@
1
- import styled from 'styled-components';
2
- import { Box, Flex } from '@strapi/design-system';
3
- import { pxToRem } from '@strapi/helper-plugin';
4
-
5
- const Overlay = styled(Box)`
6
- position: fixed;
7
- top: 0;
8
- right: 0;
9
- bottom: 0;
10
- left: 0;
11
- z-index: 1140;
12
- &:before {
13
- content: '';
14
- position: fixed;
15
- top: 0;
16
- right: 0;
17
- bottom: 0;
18
- left: 0;
19
- background: ${({ theme }) => theme.colors.neutral0};
20
- opacity: 0.9;
21
- }
22
- `;
23
-
24
- const Content = styled(Flex)`
25
- position: fixed;
26
- top: 0;
27
- right: 0;
28
- bottom: 0;
29
- left: 0;
30
- padding-top: ${pxToRem(160)};
31
- `;
32
-
33
- const IconBox = styled(Box)`
34
- border-radius: 50%;
35
- svg {
36
- > path {
37
- fill: ${({ theme }) => theme.colors.primary600} !important;
38
- }
39
- }
40
- `;
41
-
42
- export { Content, IconBox, Overlay };
@@ -1,99 +0,0 @@
1
- import React, { useEffect, useMemo, useRef, useState } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { AutoReloadOverlayBockerContext } from '@strapi/helper-plugin';
4
- import Blocker from './Blocker';
5
-
6
- const ELAPSED = 30;
7
-
8
- const AutoReloadOverlayBlockerProvider = ({ children }) => {
9
- const [isOpen, setIsOpen] = useState(false);
10
- const [{ elapsed }, setState] = useState({ elapsed: 0, start: 0 });
11
- const [config, setConfig] = useState(undefined);
12
-
13
- const lockAppWithAutoreload = (config = undefined) => {
14
- setIsOpen(true);
15
- setConfig(config);
16
- setState((prev) => ({ ...prev, start: Date.now() }));
17
- };
18
-
19
- const unlockAppWithAutoreload = () => {
20
- setIsOpen(false);
21
- setState({ start: 0, elapsed: 0 });
22
- setConfig(undefined);
23
- };
24
-
25
- const lockApp = useRef(lockAppWithAutoreload);
26
- const unlockApp = useRef(unlockAppWithAutoreload);
27
-
28
- useEffect(() => {
29
- let timer = null;
30
-
31
- if (isOpen) {
32
- timer = setInterval(() => {
33
- if (elapsed > ELAPSED) {
34
- clearInterval(timer);
35
-
36
- return null;
37
- }
38
-
39
- setState((prev) => ({ ...prev, elapsed: Math.round(Date.now() - prev.start) / 1000 }));
40
-
41
- return null;
42
- }, 1000);
43
- } else {
44
- clearInterval(timer);
45
- }
46
-
47
- return () => {
48
- clearInterval(timer);
49
- };
50
- }, [isOpen, elapsed]);
51
-
52
- let displayedIcon = config?.icon || 'reload';
53
-
54
- let description = {
55
- id: config?.description || 'components.OverlayBlocker.description',
56
- defaultMessage:
57
- "You're using a feature that needs the server to restart. Please wait until the server is up.",
58
- };
59
- let title = {
60
- id: config?.title || 'components.OverlayBlocker.title',
61
- defaultMessage: 'Waiting for restart',
62
- };
63
-
64
- if (elapsed > ELAPSED) {
65
- displayedIcon = 'time';
66
-
67
- description = {
68
- id: 'components.OverlayBlocker.description.serverError',
69
- defaultMessage: 'The server should have restarted, please check your logs in the terminal.',
70
- };
71
-
72
- title = {
73
- id: 'components.OverlayBlocker.title.serverError',
74
- defaultMessage: 'The restart is taking longer than expected',
75
- };
76
- }
77
-
78
- const autoReloadValue = useMemo(() => {
79
- return { lockApp: lockApp.current, unlockApp: unlockApp.current };
80
- }, [lockApp, unlockApp]);
81
-
82
- return (
83
- <AutoReloadOverlayBockerContext.Provider value={autoReloadValue}>
84
- <Blocker
85
- displayedIcon={displayedIcon}
86
- isOpen={isOpen}
87
- description={description}
88
- title={title}
89
- />
90
- {children}
91
- </AutoReloadOverlayBockerContext.Provider>
92
- );
93
- };
94
-
95
- AutoReloadOverlayBlockerProvider.propTypes = {
96
- children: PropTypes.element.isRequired,
97
- };
98
-
99
- export default AutoReloadOverlayBlockerProvider;
@@ -1,159 +0,0 @@
1
- import React, { useEffect, useCallback } from 'react';
2
- import PropTypes from 'prop-types';
3
- import { useIntl } from 'react-intl';
4
- import { Alert } from '@strapi/design-system';
5
- import { Link } from '@strapi/design-system/v2';
6
-
7
- const Notification = ({ dispatch, notification }) => {
8
- const { formatMessage } = useIntl();
9
- const { message, link, type, id, onClose, timeout, blockTransition, title } = notification;
10
-
11
- const formattedMessage = (msg) =>
12
- typeof msg === 'string' ? msg : formatMessage(msg, msg.values);
13
- const handleClose = useCallback(() => {
14
- if (onClose) {
15
- onClose();
16
- }
17
-
18
- dispatch({
19
- type: 'HIDE_NOTIFICATION',
20
- id,
21
- });
22
- // eslint-disable-next-line react-hooks/exhaustive-deps
23
- }, [id]);
24
-
25
- useEffect(() => {
26
- let timeoutToClear;
27
-
28
- if (!blockTransition) {
29
- timeoutToClear = setTimeout(() => {
30
- handleClose();
31
- }, timeout || 2500);
32
- }
33
-
34
- return () => clearTimeout(timeoutToClear);
35
- }, [blockTransition, handleClose, timeout]);
36
-
37
- let variant;
38
- let alertTitle;
39
-
40
- // TODO break out this logic into separate file
41
- if (type === 'info') {
42
- variant = 'default';
43
- alertTitle = formatMessage({
44
- id: 'notification.default.title',
45
- defaultMessage: 'Information:',
46
- });
47
- } else if (type === 'warning') {
48
- // type should be renamed to danger in the future, but it might introduce changes if done now
49
- variant = 'danger';
50
- alertTitle = formatMessage({
51
- id: 'notification.warning.title',
52
- defaultMessage: 'Warning:',
53
- });
54
- } else if (type === 'softWarning') {
55
- // type should be renamed to just warning in the future
56
- variant = 'warning';
57
- alertTitle = formatMessage({
58
- id: 'notification.warning.title',
59
- defaultMessage: 'Warning:',
60
- });
61
- } else {
62
- variant = 'success';
63
- alertTitle = formatMessage({
64
- id: 'notification.success.title',
65
- defaultMessage: 'Success:',
66
- });
67
- }
68
-
69
- if (title) {
70
- alertTitle =
71
- typeof title === 'string'
72
- ? title
73
- : formattedMessage({
74
- id: title?.id || title,
75
- defaultMessage: title?.defaultMessage || title?.id || title,
76
- values: title?.values,
77
- });
78
- }
79
-
80
- return (
81
- <Alert
82
- action={
83
- link ? (
84
- <Link href={link.url} isExternal>
85
- {formatMessage({
86
- id: link.label?.id || link.label,
87
- defaultMessage: link.label?.defaultMessage || link.label?.id || link.label,
88
- })}
89
- </Link>
90
- ) : undefined
91
- }
92
- onClose={handleClose}
93
- closeLabel="Close"
94
- title={alertTitle}
95
- variant={variant}
96
- >
97
- {formattedMessage({
98
- id: message?.id || message,
99
- defaultMessage: message?.defaultMessage || message?.id || message,
100
- values: message?.values,
101
- })}
102
- </Alert>
103
- );
104
- };
105
-
106
- Notification.defaultProps = {
107
- notification: {
108
- id: 1,
109
- type: 'success',
110
- message: {
111
- id: 'notification.success.saved',
112
- defaultMessage: 'Saved',
113
- },
114
- onClose: () => null,
115
- timeout: 2500,
116
- blockTransition: false,
117
- },
118
- };
119
-
120
- Notification.propTypes = {
121
- dispatch: PropTypes.func.isRequired,
122
- notification: PropTypes.shape({
123
- id: PropTypes.number,
124
- message: PropTypes.oneOfType([
125
- PropTypes.string,
126
- PropTypes.shape({
127
- id: PropTypes.string.isRequired,
128
- defaultMessage: PropTypes.string,
129
- values: PropTypes.object,
130
- }),
131
- ]),
132
- link: PropTypes.shape({
133
- target: PropTypes.string,
134
- url: PropTypes.string.isRequired,
135
- label: PropTypes.oneOfType([
136
- PropTypes.string,
137
- PropTypes.shape({
138
- id: PropTypes.string.isRequired,
139
- defaultMessage: PropTypes.string,
140
- values: PropTypes.object,
141
- }),
142
- ]).isRequired,
143
- }),
144
- type: PropTypes.string,
145
- onClose: PropTypes.func,
146
- timeout: PropTypes.number,
147
- blockTransition: PropTypes.bool,
148
- title: PropTypes.oneOfType([
149
- PropTypes.string,
150
- PropTypes.shape({
151
- id: PropTypes.string.isRequired,
152
- defaultMessage: PropTypes.string,
153
- values: PropTypes.object,
154
- }),
155
- ]),
156
- }),
157
- };
158
-
159
- export default Notification;
@@ -1,46 +0,0 @@
1
- import { NotificationsProvider } from '@strapi/helper-plugin';
2
- import React, { useReducer } from 'react';
3
- import PropTypes from 'prop-types';
4
- import { Flex } from '@strapi/design-system';
5
- import Notification from './Notification';
6
- import reducer, { initialState } from './reducer';
7
-
8
- const Notifications = ({ children }) => {
9
- const [{ notifications }, dispatch] = useReducer(reducer, initialState);
10
-
11
- const displayNotification = (config) => {
12
- dispatch({
13
- type: 'SHOW_NOTIFICATION',
14
- config,
15
- });
16
- };
17
-
18
- return (
19
- <NotificationsProvider toggleNotification={displayNotification}>
20
- <Flex
21
- left="50%"
22
- marginLeft="-250px"
23
- position="fixed"
24
- direction="column"
25
- alignItems="stretch"
26
- gap={2}
27
- top={`${46 / 16}rem`}
28
- width={`${500 / 16}rem`}
29
- zIndex={10}
30
- >
31
- {notifications.map((notification) => {
32
- return (
33
- <Notification key={notification.id} dispatch={dispatch} notification={notification} />
34
- );
35
- })}
36
- </Flex>
37
- {children}
38
- </NotificationsProvider>
39
- );
40
- };
41
-
42
- Notifications.propTypes = {
43
- children: PropTypes.element.isRequired,
44
- };
45
-
46
- export default Notifications;
@@ -1,47 +0,0 @@
1
- import produce from 'immer';
2
- import get from 'lodash/get';
3
-
4
- const initialState = {
5
- notifId: 0,
6
- notifications: [],
7
- };
8
-
9
- const notificationReducer = (state = initialState, action) =>
10
- // eslint-disable-next-line consistent-return
11
- produce(state, (draftState) => {
12
- switch (action.type) {
13
- case 'SHOW_NOTIFICATION': {
14
- draftState.notifications.push({
15
- // No action.config spread to limit the notification API and avoid customization
16
- id: state.notifId,
17
- type: get(action, ['config', 'type'], 'success'),
18
- message: get(action, ['config', 'message'], {
19
- id: 'notification.success.saved',
20
- defaultMessage: 'Saved',
21
- }),
22
- link: get(action, ['config', 'link'], null),
23
- timeout: get(action, ['config', 'timeout'], 2500),
24
- blockTransition: get(action, ['config', 'blockTransition'], false),
25
- onClose: get(action, ['config', 'onClose'], null),
26
- title: get(action, ['config', 'title'], null),
27
- });
28
- draftState.notifId = state.notifId + 1;
29
- break;
30
- }
31
- case 'HIDE_NOTIFICATION': {
32
- const indexToRemove = state.notifications.findIndex((notif) => notif.id === action.id);
33
-
34
- if (indexToRemove !== -1) {
35
- draftState.notifications.splice(indexToRemove, 1);
36
- }
37
- break;
38
- }
39
-
40
- default: {
41
- return draftState;
42
- }
43
- }
44
- });
45
-
46
- export default notificationReducer;
47
- export { initialState };
@@ -1,67 +0,0 @@
1
- /**
2
- *
3
- * OverlayBlockerProvider
4
- *
5
- */
6
- import React, { useEffect, useState } from 'react';
7
- import ReactDOM from 'react-dom';
8
- import PropTypes from 'prop-types';
9
- import styled from 'styled-components';
10
- import { OverlayBlockerContext } from '@strapi/helper-plugin';
11
-
12
- const overlayContainer = document.createElement('div');
13
- overlayContainer.setAttribute('id', 'overlayBlocker');
14
-
15
- const Overlay = styled.div`
16
- position: fixed;
17
- top: 0;
18
- right: 0;
19
- bottom: 0;
20
- left: 0;
21
- z-index: 1140;
22
- `;
23
-
24
- const Portal = ({ isOpen }) => {
25
- useEffect(() => {
26
- document.body.appendChild(overlayContainer);
27
-
28
- return () => {
29
- document.body.removeChild(overlayContainer);
30
- };
31
- }, []);
32
-
33
- if (isOpen) {
34
- return ReactDOM.createPortal(<Overlay />, overlayContainer);
35
- }
36
-
37
- return null;
38
- };
39
-
40
- Portal.propTypes = {
41
- isOpen: PropTypes.bool.isRequired,
42
- };
43
-
44
- const OverlayBlockerProvider = ({ children }) => {
45
- const [isOpen, setIsOpen] = useState(false);
46
-
47
- const lockApp = () => {
48
- setIsOpen(true);
49
- };
50
-
51
- const unlockApp = () => {
52
- setIsOpen(false);
53
- };
54
-
55
- return (
56
- <OverlayBlockerContext.Provider value={{ lockApp, unlockApp }}>
57
- {children}
58
- <Portal isOpen={isOpen} />
59
- </OverlayBlockerContext.Provider>
60
- );
61
- };
62
-
63
- OverlayBlockerProvider.propTypes = {
64
- children: PropTypes.node.isRequired,
65
- };
66
-
67
- export default OverlayBlockerProvider;