@strapi/admin 4.2.0-beta.1 → 4.2.0-beta.4

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 (166) hide show
  1. package/admin/src/assets/images/homepage-logo.png +0 -0
  2. package/admin/src/components/AutoReloadOverlayBlockerProvider/Blocker.js +2 -6
  3. package/admin/src/components/ConfigurationsProvider/index.js +51 -0
  4. package/admin/src/components/ConfigurationsProvider/reducer.js +28 -0
  5. package/admin/src/components/GuidedTour/Homepage/index.js +1 -2
  6. package/admin/src/components/GuidedTour/Modal/components/Stepper.js +1 -2
  7. package/admin/src/components/LeftMenu/index.js +19 -7
  8. package/admin/src/components/Notifications/Notification/index.js +2 -2
  9. package/admin/src/components/Providers/index.js +8 -4
  10. package/admin/src/components/UnauthenticatedLogo/index.js +4 -2
  11. package/admin/src/components/UpgradePlanModal/index.js +6 -2
  12. package/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js +1 -1
  13. package/admin/src/content-manager/components/SelectMany/ListItem.js +1 -2
  14. package/admin/src/content-manager/components/SelectWrapper/index.js +8 -7
  15. package/admin/src/content-manager/components/SelectWrapper/utils/getSelectStyles.js +1 -1
  16. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +2 -2
  17. package/admin/src/content-manager/components/Wysiwyg/Editor.js +2 -0
  18. package/admin/src/content-manager/pages/App/LeftMenu/index.js +8 -7
  19. package/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.js +1 -1
  20. package/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.js +1 -2
  21. package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -2
  22. package/admin/src/content-manager/pages/EditView/Header/index.js +3 -3
  23. package/admin/src/content-manager/pages/EditView/index.js +1 -4
  24. package/admin/src/content-manager/pages/ListSettingsView/index.js +1 -2
  25. package/admin/src/content-manager/pages/ListView/index.js +1 -1
  26. package/admin/src/content-manager/pages/NoContentType/index.js +1 -2
  27. package/admin/src/pages/App/index.js +7 -2
  28. package/admin/src/pages/AuthPage/components/ForgotPassword/index.js +1 -2
  29. package/admin/src/pages/AuthPage/components/ForgotPasswordSuccess/index.js +1 -1
  30. package/admin/src/pages/AuthPage/components/Login/BaseLogin.js +1 -2
  31. package/admin/src/pages/AuthPage/components/Oops/index.js +1 -2
  32. package/admin/src/pages/AuthPage/components/Register/index.js +12 -12
  33. package/admin/src/pages/AuthPage/components/ResetPassword/index.js +3 -4
  34. package/admin/src/pages/HomePage/ContentBlocks.js +15 -2
  35. package/admin/src/pages/HomePage/HomeHeader.js +2 -2
  36. package/admin/src/pages/HomePage/SocialLinks.js +4 -3
  37. package/admin/src/pages/InternalErrorPage/index.js +1 -2
  38. package/admin/src/pages/MarketplacePage/components/PageHeader/index.js +2 -1
  39. package/admin/src/pages/MarketplacePage/components/PluginCard/index.js +4 -3
  40. package/admin/src/pages/NotFoundPage/index.js +1 -2
  41. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +5 -4
  42. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
  43. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js +1 -1
  44. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +1 -1
  45. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/index.js +85 -0
  46. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/init.js +13 -0
  47. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/reducer.js +43 -0
  48. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/index.js +118 -0
  49. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/reducer.js +28 -0
  50. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/stepper.js +25 -0
  51. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/AddLogoDialog.js +67 -0
  52. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromComputerForm.js +176 -0
  53. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromUrlForm.js +82 -0
  54. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/ImageCardAsset.js +51 -0
  55. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js +97 -0
  56. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/index.js +85 -0
  57. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/reducer.js +28 -0
  58. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +155 -87
  59. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +16 -0
  60. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/constants.js +3 -0
  61. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/getFormData.js +17 -0
  62. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/parseFileMetadatas.js +76 -0
  63. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/prefixAllUrls.js +17 -0
  64. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/urlToFile.js +21 -0
  65. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +1 -1
  66. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -1
  67. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/index.js +1 -2
  68. package/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js +1 -1
  69. package/admin/src/translations/ca.json +699 -0
  70. package/admin/src/translations/en.json +26 -0
  71. package/admin/src/translations/languageNativeNames.js +1 -0
  72. package/admin/src/translations/ru.json +34 -0
  73. package/build/1541.6c1c96f9.chunk.js +307 -0
  74. package/build/1856.521a99fd.chunk.js +172 -0
  75. package/build/2077.51485bfb.chunk.js +194 -0
  76. package/build/2912.79c2b3c8.chunk.js +253 -0
  77. package/build/3214.9196aeff.chunk.js +235 -0
  78. package/build/3865.21cec9de.chunk.js +310 -0
  79. package/build/4073.e144a91a.chunk.js +1 -0
  80. package/build/4715.77e04177.chunk.js +385 -0
  81. package/build/{272.d442e5ca.chunk.js → 472.0350a5bd.chunk.js} +91 -102
  82. package/build/4982.f53b78a4.chunk.js +308 -0
  83. package/build/6229.a5cca9f2.chunk.js +194 -0
  84. package/build/7351.b95e65ae.chunk.js +428 -0
  85. package/build/7418.6db737ce.chunk.js +112 -0
  86. package/build/7841.f0e7d629.chunk.js +253 -0
  87. package/build/8826.58e236d4.chunk.js +1057 -0
  88. package/build/9066.118ecccd.chunk.js +101 -0
  89. package/build/{9298.dab64a1b.chunk.js → 9298.aff28744.chunk.js} +80 -91
  90. package/build/9420.cb0b75e8.chunk.js +508 -0
  91. package/build/{9988.9b6e1d79.chunk.js → 9988.f84412d9.chunk.js} +15 -14
  92. package/build/Admin-authenticatedApp.162a5805.chunk.js +80 -0
  93. package/build/Admin_homePage.0ac648e8.chunk.js +71 -0
  94. package/build/Admin_marketplace.0bb91ec8.chunk.js +11 -0
  95. package/build/Admin_settingsPage.23e873f0.chunk.js +178 -0
  96. package/build/admin-edit-roles-page.fb374555.chunk.js +1 -0
  97. package/build/admin-edit-users.a360deaf.chunk.js +10 -0
  98. package/build/api-tokens-create-page.698f132d.chunk.js +1 -0
  99. package/build/api-tokens-edit-page.afece2fe.chunk.js +1 -0
  100. package/build/api-tokens-list-page.46d96dee.chunk.js +15 -0
  101. package/build/ca-json.0097e443.chunk.js +1 -0
  102. package/build/content-manager.7cd28f84.chunk.js +1204 -0
  103. package/build/content-type-builder.7456cabe.chunk.js +141 -0
  104. package/build/{email-settings-page.d807edfd.chunk.js → email-settings-page.f67d13b2.chunk.js} +5 -5
  105. package/build/en-json.40ee00aa.chunk.js +1 -0
  106. package/build/fb376b132d18bf4522ca.png +0 -0
  107. package/build/{i18n-settings-page.c8f3b78b.chunk.js → i18n-settings-page.6b67cb75.chunk.js} +5 -5
  108. package/build/index.html +1 -1
  109. package/build/main.b632a0d6.js +11625 -0
  110. package/build/ru-json.28147733.chunk.js +1 -0
  111. package/build/runtime~main.38d418e9.js +2 -0
  112. package/build/{upload-settings.17202e3b.chunk.js → upload-settings.3db55de0.chunk.js} +5 -5
  113. package/build/upload-translation-ca-json.79159984.chunk.js +1 -0
  114. package/build/{upload.d647d59d.chunk.js → upload.070c189b.chunk.js} +5 -5
  115. package/build/{users-advanced-settings-page.22690469.chunk.js → users-advanced-settings-page.a23cda17.chunk.js} +5 -5
  116. package/build/users-roles-settings-page.988ebc3b.chunk.js +30 -0
  117. package/build/{webhook-edit-page.043fe03f.chunk.js → webhook-edit-page.a7ae6e3b.chunk.js} +3 -3
  118. package/build/webhook-list-page.83297d98.chunk.js +133 -0
  119. package/ee/admin/pages/AuthPage/components/Providers/index.js +1 -1
  120. package/ee/admin/pages/SettingsPage/pages/Roles/CreatePage/index.js +1 -1
  121. package/ee/server/controllers/user.js +4 -0
  122. package/package.json +9 -9
  123. package/server/config/admin-actions.js +14 -0
  124. package/server/controllers/admin.js +33 -1
  125. package/server/controllers/user.js +4 -0
  126. package/server/routes/admin.js +28 -0
  127. package/server/services/index.js +1 -0
  128. package/server/services/permission/permissions-manager/sanitize.js +22 -0
  129. package/server/services/project-settings.js +173 -0
  130. package/server/services/user.js +1 -1
  131. package/server/utils/index.d.ts +2 -0
  132. package/server/validation/project-settings.js +39 -0
  133. package/utils/create-cache-dir.js +2 -5
  134. package/webpack.config.js +2 -2
  135. package/admin/src/content-manager/components/DynamicComponentCard/index.js +0 -43
  136. package/build/1856.e2bce2e8.chunk.js +0 -171
  137. package/build/2481.5fe150c7.chunk.js +0 -184
  138. package/build/2912.5a7b0406.chunk.js +0 -252
  139. package/build/2a9e9ef5c4c775bb7c7b.png +0 -0
  140. package/build/306.28d21ab8.chunk.js +0 -896
  141. package/build/4073.4765687b.chunk.js +0 -1
  142. package/build/4715.7f616cf6.chunk.js +0 -387
  143. package/build/497.2ba35e90.chunk.js +0 -284
  144. package/build/4982.91235074.chunk.js +0 -310
  145. package/build/6229.f558fd19.chunk.js +0 -194
  146. package/build/6404.25d0f0d8.chunk.js +0 -508
  147. package/build/7841.0d73dde1.chunk.js +0 -252
  148. package/build/7863.996e70df.chunk.js +0 -112
  149. package/build/9853.6cc1043a.chunk.js +0 -354
  150. package/build/Admin-authenticatedApp.d26b3032.chunk.js +0 -80
  151. package/build/Admin_homePage.fc4a8408.chunk.js +0 -71
  152. package/build/Admin_marketplace.c406a140.chunk.js +0 -11
  153. package/build/Admin_settingsPage.c40fdef1.chunk.js +0 -170
  154. package/build/admin-edit-roles-page.c69fe8ab.chunk.js +0 -1
  155. package/build/admin-edit-users.be232f6b.chunk.js +0 -10
  156. package/build/api-tokens-create-page.9774f0fe.chunk.js +0 -1
  157. package/build/api-tokens-edit-page.8f03c9a1.chunk.js +0 -1
  158. package/build/api-tokens-list-page.126fbca6.chunk.js +0 -15
  159. package/build/content-manager.ca66b566.chunk.js +0 -1204
  160. package/build/content-type-builder.d12fd5cd.chunk.js +0 -141
  161. package/build/en-json.3e1a222e.chunk.js +0 -1
  162. package/build/main.36da7eeb.js +0 -7918
  163. package/build/ru-json.4560906c.chunk.js +0 -1
  164. package/build/runtime~main.251e9cca.js +0 -2
  165. package/build/users-roles-settings-page.487f3346.chunk.js +0 -30
  166. package/build/webhook-list-page.2d2d71a1.chunk.js +0 -132
@@ -0,0 +1,67 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import PropTypes from 'prop-types';
4
+ import { Tabs, Tab, TabGroup, TabPanels, TabPanel } from '@strapi/design-system/Tabs';
5
+ import { Box } from '@strapi/design-system/Box';
6
+ import { Divider } from '@strapi/design-system/Divider';
7
+ import FromComputerForm from './FromComputerForm';
8
+ import FromUrlForm from './FromUrlForm';
9
+
10
+ const AddLogoDialog = ({ setLocalImage, goTo, next, onClose }) => {
11
+ const { formatMessage } = useIntl();
12
+
13
+ return (
14
+ <TabGroup
15
+ label={formatMessage({
16
+ id: 'Settings.application.customization.modal.tab.label',
17
+ defaultMessage: 'How do you want to upload your assets?',
18
+ })}
19
+ variant="simple"
20
+ >
21
+ <Box paddingLeft={8} paddingRight={8}>
22
+ <Tabs>
23
+ <Tab>
24
+ {formatMessage({
25
+ id: 'Settings.application.customization.modal.upload.from-computer',
26
+ defaultMessage: 'From computer',
27
+ })}
28
+ </Tab>
29
+ <Tab>
30
+ {formatMessage({
31
+ id: 'Settings.application.customization.modal.upload.from-url',
32
+ defaultMessage: 'From url',
33
+ })}
34
+ </Tab>
35
+ </Tabs>
36
+
37
+ <Divider />
38
+ </Box>
39
+ <TabPanels>
40
+ <TabPanel>
41
+ <FromComputerForm
42
+ onClose={onClose}
43
+ setLocalImage={setLocalImage}
44
+ goTo={goTo}
45
+ next={next}
46
+ />
47
+ </TabPanel>
48
+ <TabPanel>
49
+ <FromUrlForm onClose={onClose} setLocalImage={setLocalImage} goTo={goTo} next={next} />
50
+ </TabPanel>
51
+ </TabPanels>
52
+ </TabGroup>
53
+ );
54
+ };
55
+
56
+ AddLogoDialog.defaultProps = {
57
+ next: null,
58
+ };
59
+
60
+ AddLogoDialog.propTypes = {
61
+ goTo: PropTypes.func.isRequired,
62
+ next: PropTypes.string,
63
+ onClose: PropTypes.func.isRequired,
64
+ setLocalImage: PropTypes.func.isRequired,
65
+ };
66
+
67
+ export default AddLogoDialog;
@@ -0,0 +1,176 @@
1
+ import React, { useState, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import styled from 'styled-components';
5
+ import { Box } from '@strapi/design-system/Box';
6
+ import { Stack } from '@strapi/design-system/Stack';
7
+ import { Flex } from '@strapi/design-system/Flex';
8
+ import { Icon } from '@strapi/design-system/Icon';
9
+ import { Typography } from '@strapi/design-system/Typography';
10
+ import { ModalFooter } from '@strapi/design-system/ModalLayout';
11
+ import { Button } from '@strapi/design-system/Button';
12
+ import { Field, FieldError, FieldInput } from '@strapi/design-system/Field';
13
+ import PicturePlus from '@strapi/icons/PicturePlus';
14
+ import { parseFileMetadatas } from '../../utils/parseFileMetadatas';
15
+ import { ACCEPTED_FORMAT, SIZE, DIMENSION } from '../../utils/constants';
16
+
17
+ const FileInput = styled(FieldInput)`
18
+ opacity: 0;
19
+ position: absolute;
20
+ top: 0;
21
+ bottom: 0;
22
+ left: 0;
23
+ right: 0;
24
+ z-index: 1;
25
+ `;
26
+
27
+ const FromComputerForm = ({ setLocalImage, goTo, next, onClose }) => {
28
+ const { formatMessage } = useIntl();
29
+ const [dragOver, setDragOver] = useState(false);
30
+ const [fileError, setFileError] = useState(undefined);
31
+ const inputRef = useRef(null);
32
+
33
+ const handleDragEnter = () => setDragOver(true);
34
+ const handleDragLeave = () => setDragOver(false);
35
+
36
+ const handleClick = e => {
37
+ e.preventDefault();
38
+ inputRef.current.click();
39
+ };
40
+
41
+ const handleChange = async () => {
42
+ handleDragLeave();
43
+ const file = inputRef.current.files[0];
44
+
45
+ if (!file) {
46
+ return;
47
+ }
48
+
49
+ try {
50
+ const asset = await parseFileMetadatas(file);
51
+ setLocalImage(asset);
52
+ goTo(next);
53
+ } catch (err) {
54
+ if (err.displayMessage) {
55
+ setFileError(formatMessage(err.displayMessage, { size: SIZE, dimension: DIMENSION }));
56
+ inputRef.current.focus();
57
+ } else {
58
+ throw err;
59
+ }
60
+ }
61
+ };
62
+
63
+ const getBorderColor = () => {
64
+ if (dragOver) {
65
+ return 'primary500';
66
+ }
67
+ if (fileError) {
68
+ return 'danger600';
69
+ }
70
+
71
+ return 'neutral300';
72
+ };
73
+
74
+ return (
75
+ <>
76
+ <form>
77
+ <Box paddingLeft={8} paddingRight={8} paddingTop={6} paddingBottom={6}>
78
+ <Field name="logo-upload" error={fileError}>
79
+ <label htmlFor="logo-upload">
80
+ <Stack spacing={2}>
81
+ <Flex
82
+ paddingTop={9}
83
+ paddingBottom={7}
84
+ hasRadius
85
+ justifyContent="center"
86
+ direction="column"
87
+ background={dragOver ? 'primary100' : 'neutral100'}
88
+ borderColor={getBorderColor()}
89
+ borderStyle="dashed"
90
+ borderWidth="1px"
91
+ position="relative"
92
+ onDragEnter={handleDragEnter}
93
+ onDragLeave={handleDragLeave}
94
+ >
95
+ <Icon
96
+ color="primary600"
97
+ width={`${60 / 16}rem`}
98
+ height={`${60 / 16}rem`}
99
+ as={PicturePlus}
100
+ aria-hidden
101
+ />
102
+
103
+ <Box paddingTop={3} paddingBottom={5}>
104
+ <Typography variant="delta" as="span">
105
+ {formatMessage({
106
+ id: 'Settings.application.customization.modal.upload.drag-drop',
107
+ defaultMessage: 'Drag and Drop here or',
108
+ })}
109
+ </Typography>
110
+ </Box>
111
+
112
+ <FileInput
113
+ accept={ACCEPTED_FORMAT}
114
+ cursor="pointer"
115
+ as="input"
116
+ type="file"
117
+ name="files"
118
+ tabIndex={-1}
119
+ zIndex={1}
120
+ onChange={handleChange}
121
+ ref={inputRef}
122
+ id="logo-upload"
123
+ />
124
+
125
+ <Button type="button" onClick={handleClick}>
126
+ {formatMessage({
127
+ id: 'Settings.application.customization.modal.upload.cta.browse',
128
+ defaultMessage: 'Browse files',
129
+ })}
130
+ </Button>
131
+
132
+ <Box paddingTop={6}>
133
+ <Typography variant="pi" textColor="neutral600">
134
+ {formatMessage(
135
+ {
136
+ id: 'Settings.application.customization.modal.upload.file-validation',
137
+ defaultMessage:
138
+ 'Max dimension: {dimension}x{dimension}, Max size: {size}KB',
139
+ },
140
+ { size: SIZE, dimension: DIMENSION }
141
+ )}
142
+ </Typography>
143
+ </Box>
144
+ </Flex>
145
+ <FieldError />
146
+ </Stack>
147
+ </label>
148
+ </Field>
149
+ </Box>
150
+ </form>
151
+ <ModalFooter
152
+ startActions={
153
+ <Button onClick={onClose} variant="tertiary">
154
+ {formatMessage({
155
+ id: 'Settings.application.customization.modal.cancel',
156
+ defaultMessage: 'Cancel',
157
+ })}
158
+ </Button>
159
+ }
160
+ />
161
+ </>
162
+ );
163
+ };
164
+
165
+ FromComputerForm.defaultProps = {
166
+ next: null,
167
+ };
168
+
169
+ FromComputerForm.propTypes = {
170
+ goTo: PropTypes.func.isRequired,
171
+ next: PropTypes.string,
172
+ onClose: PropTypes.func.isRequired,
173
+ setLocalImage: PropTypes.func.isRequired,
174
+ };
175
+
176
+ export default FromComputerForm;
@@ -0,0 +1,82 @@
1
+ import React, { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { Box } from '@strapi/design-system/Box';
5
+ import { Button } from '@strapi/design-system/Button';
6
+ import { TextInput } from '@strapi/design-system/TextInput';
7
+ import { ModalFooter } from '@strapi/design-system/ModalLayout';
8
+ import urlToFile from '../../utils/urlToFile';
9
+ import { parseFileMetadatas } from '../../utils/parseFileMetadatas';
10
+ import { SIZE, DIMENSION } from '../../utils/constants';
11
+
12
+ const FromUrlForm = ({ goTo, next, onClose, setLocalImage }) => {
13
+ const { formatMessage } = useIntl();
14
+ const [logoUrl, setLogoUrl] = useState('');
15
+ const [error, setError] = useState(null);
16
+
17
+ const handleChange = e => {
18
+ setLogoUrl(e.target.value);
19
+ };
20
+
21
+ const handleSubmit = async e => {
22
+ e.preventDefault();
23
+ try {
24
+ const file = await urlToFile(logoUrl);
25
+ const asset = await parseFileMetadatas(file);
26
+
27
+ setLocalImage(asset);
28
+ goTo(next);
29
+ } catch (err) {
30
+ if (err.displayMessage) {
31
+ setError(formatMessage(err.displayMessage, { size: SIZE, dimension: DIMENSION }));
32
+ } else {
33
+ throw err;
34
+ }
35
+ }
36
+ };
37
+
38
+ return (
39
+ <form onSubmit={handleSubmit}>
40
+ <Box paddingLeft={8} paddingRight={8} paddingTop={6} paddingBottom={6}>
41
+ <TextInput
42
+ label={formatMessage({
43
+ id: 'Settings.application.customization.modal.upload.from-url.input-label',
44
+ defaultMessage: 'URL',
45
+ })}
46
+ error={error}
47
+ onChange={handleChange}
48
+ value={logoUrl}
49
+ name="logo-url"
50
+ />
51
+ </Box>
52
+ <ModalFooter
53
+ startActions={
54
+ <Button onClick={onClose} variant="tertiary">
55
+ {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}
56
+ </Button>
57
+ }
58
+ endActions={
59
+ <Button type="submit">
60
+ {formatMessage({
61
+ id: 'Settings.application.customization.modal.upload.next',
62
+ defaultMessage: 'Next',
63
+ })}
64
+ </Button>
65
+ }
66
+ />
67
+ </form>
68
+ );
69
+ };
70
+
71
+ FromUrlForm.defaultProps = {
72
+ next: null,
73
+ };
74
+
75
+ FromUrlForm.propTypes = {
76
+ goTo: PropTypes.func.isRequired,
77
+ next: PropTypes.string,
78
+ onClose: PropTypes.func.isRequired,
79
+ setLocalImage: PropTypes.func.isRequired,
80
+ };
81
+
82
+ export default FromUrlForm;
@@ -0,0 +1,51 @@
1
+ import React from 'react';
2
+ import { useIntl } from 'react-intl';
3
+ import PropTypes from 'prop-types';
4
+ import {
5
+ Card,
6
+ CardAsset,
7
+ CardBadge,
8
+ CardBody,
9
+ CardContent,
10
+ CardHeader,
11
+ CardTitle,
12
+ CardSubtitle,
13
+ } from '@strapi/design-system/Card';
14
+
15
+ const ImageCardAsset = ({ asset }) => {
16
+ const { formatMessage } = useIntl();
17
+
18
+ return (
19
+ <Card>
20
+ <CardHeader>
21
+ <CardAsset size="S" src={asset.url} />
22
+ </CardHeader>
23
+ <CardBody>
24
+ <CardContent>
25
+ <CardTitle>{asset.name}</CardTitle>
26
+ <CardSubtitle>
27
+ {`${asset.ext.toUpperCase()} - ${asset.width}✕${asset.height}`}
28
+ </CardSubtitle>
29
+ </CardContent>
30
+ <CardBadge>
31
+ {formatMessage({
32
+ id: 'Settings.application.customization.modal.pending.card-badge',
33
+ defaultMessage: 'image',
34
+ })}
35
+ </CardBadge>
36
+ </CardBody>
37
+ </Card>
38
+ );
39
+ };
40
+
41
+ ImageCardAsset.propTypes = {
42
+ asset: PropTypes.shape({
43
+ name: PropTypes.string,
44
+ url: PropTypes.string,
45
+ width: PropTypes.number,
46
+ height: PropTypes.number,
47
+ ext: PropTypes.string,
48
+ }).isRequired,
49
+ };
50
+
51
+ export default ImageCardAsset;
@@ -0,0 +1,97 @@
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { pxToRem } from '@strapi/helper-plugin';
5
+ import { Box } from '@strapi/design-system/Box';
6
+ import { Flex } from '@strapi/design-system/Flex';
7
+ import { Button } from '@strapi/design-system/Button';
8
+ import { ModalFooter } from '@strapi/design-system/ModalLayout';
9
+ import { Typography } from '@strapi/design-system/Typography';
10
+ import ImageCardAsset from './ImageCardAsset';
11
+
12
+ const PendingLogoDialog = ({ onClose, asset, prev, next, goTo, setLocalImage, onChangeLogo }) => {
13
+ const { formatMessage } = useIntl();
14
+
15
+ const handleGoBack = () => {
16
+ setLocalImage(undefined);
17
+ goTo(prev);
18
+ };
19
+
20
+ const handleUpload = () => {
21
+ onChangeLogo(asset);
22
+ goTo(next);
23
+ };
24
+
25
+ return (
26
+ <>
27
+ <Box paddingLeft={8} paddingRight={8} paddingTop={6} paddingBottom={6}>
28
+ <Flex justifyContent="space-between" paddingBottom={6}>
29
+ <Flex direction="column" alignItems="flex-start">
30
+ <Typography variant="pi" fontWeight="bold">
31
+ {formatMessage({
32
+ id: 'Settings.application.customization.modal.pending.title',
33
+ defaultMessage: 'Logo ready to upload',
34
+ })}
35
+ </Typography>
36
+ <Typography variant="pi" textColor="neutral500">
37
+ {formatMessage({
38
+ id: 'Settings.application.customization.modal.pending.subtitle',
39
+ defaultMessage: 'Manage the chosen logo before uploading it',
40
+ })}
41
+ </Typography>
42
+ </Flex>
43
+ <Button onClick={handleGoBack} variant="secondary">
44
+ {formatMessage({
45
+ id: 'Settings.application.customization.modal.pending.choose-another',
46
+ defaultMessage: 'Choose another logo',
47
+ })}
48
+ </Button>
49
+ </Flex>
50
+ <Box maxWidth={pxToRem(180)}>
51
+ <ImageCardAsset asset={asset} />
52
+ </Box>
53
+ </Box>
54
+ <ModalFooter
55
+ startActions={
56
+ <Button onClick={onClose} variant="tertiary">
57
+ {formatMessage({
58
+ id: 'Settings.application.customization.modal.cancel',
59
+ defaultMessage: 'Cancel',
60
+ })}
61
+ </Button>
62
+ }
63
+ endActions={
64
+ <Button onClick={handleUpload}>
65
+ {formatMessage({
66
+ id: 'Settings.application.customization.modal.pending.upload',
67
+ defaultMessage: 'Upload logo',
68
+ })}
69
+ </Button>
70
+ }
71
+ />
72
+ </>
73
+ );
74
+ };
75
+
76
+ PendingLogoDialog.defaultProps = {
77
+ next: null,
78
+ prev: null,
79
+ };
80
+
81
+ PendingLogoDialog.propTypes = {
82
+ goTo: PropTypes.func.isRequired,
83
+ asset: PropTypes.shape({
84
+ name: PropTypes.string,
85
+ url: PropTypes.string,
86
+ width: PropTypes.number,
87
+ height: PropTypes.number,
88
+ ext: PropTypes.string,
89
+ }).isRequired,
90
+ next: PropTypes.string,
91
+ onClose: PropTypes.func.isRequired,
92
+ onChangeLogo: PropTypes.func.isRequired,
93
+ prev: PropTypes.string,
94
+ setLocalImage: PropTypes.func.isRequired,
95
+ };
96
+
97
+ export default PendingLogoDialog;
@@ -0,0 +1,85 @@
1
+ import React, { useReducer } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { useIntl } from 'react-intl';
4
+ import { ModalLayout, ModalHeader } from '@strapi/design-system/ModalLayout';
5
+ import { Typography } from '@strapi/design-system/Typography';
6
+ import reducer, { initialState } from './reducer';
7
+
8
+ const LogoModalStepper = ({
9
+ onChangeLogo,
10
+ customLogo,
11
+ goTo,
12
+ Component,
13
+ modalTitle,
14
+ next,
15
+ prev,
16
+ currentStep,
17
+ }) => {
18
+ const [{ localImage }, dispatch] = useReducer(reducer, initialState);
19
+ const { formatMessage } = useIntl();
20
+
21
+ const setLocalImage = asset => {
22
+ dispatch({
23
+ type: 'SET_LOCAL_IMAGE',
24
+ value: asset,
25
+ });
26
+ };
27
+
28
+ const handleCloseModal = () => {
29
+ goTo(null);
30
+ };
31
+
32
+ if (!currentStep) {
33
+ return null;
34
+ }
35
+
36
+ return (
37
+ <ModalLayout labelledBy="modal" onClose={handleCloseModal}>
38
+ <ModalHeader>
39
+ <Typography fontWeight="bold" as="h2" id="modal">
40
+ {formatMessage(modalTitle)}
41
+ </Typography>
42
+ </ModalHeader>
43
+ <Component
44
+ setLocalImage={setLocalImage}
45
+ goTo={goTo}
46
+ next={next}
47
+ prev={prev}
48
+ onClose={handleCloseModal}
49
+ asset={localImage || customLogo}
50
+ onChangeLogo={onChangeLogo}
51
+ />
52
+ </ModalLayout>
53
+ );
54
+ };
55
+
56
+ LogoModalStepper.defaultProps = {
57
+ Component: undefined,
58
+ currentStep: undefined,
59
+ customLogo: undefined,
60
+ modalTitle: undefined,
61
+ next: null,
62
+ prev: null,
63
+ };
64
+
65
+ LogoModalStepper.propTypes = {
66
+ Component: PropTypes.elementType,
67
+ currentStep: PropTypes.string,
68
+ customLogo: PropTypes.shape({
69
+ name: PropTypes.string,
70
+ url: PropTypes.string,
71
+ width: PropTypes.number,
72
+ height: PropTypes.number,
73
+ ext: PropTypes.string,
74
+ }),
75
+ goTo: PropTypes.func.isRequired,
76
+ modalTitle: PropTypes.shape({
77
+ id: PropTypes.string,
78
+ defaultMessage: PropTypes.string,
79
+ }),
80
+ next: PropTypes.string,
81
+ onChangeLogo: PropTypes.func.isRequired,
82
+ prev: PropTypes.string,
83
+ };
84
+
85
+ export default LogoModalStepper;
@@ -0,0 +1,28 @@
1
+ /* eslint-disable consistent-return */
2
+ /*
3
+ *
4
+ * LogoModalStepper reducer
5
+ *
6
+ */
7
+
8
+ import produce from 'immer';
9
+
10
+ const initialState = {
11
+ localImage: undefined,
12
+ };
13
+
14
+ const reducer = (state = initialState, action) =>
15
+ produce(state, draftState => {
16
+ switch (action.type) {
17
+ case 'SET_LOCAL_IMAGE': {
18
+ draftState.localImage = action.value;
19
+ break;
20
+ }
21
+ default: {
22
+ return draftState;
23
+ }
24
+ }
25
+ });
26
+
27
+ export default reducer;
28
+ export { initialState };