@strapi/admin 4.2.0-beta.3 → 4.3.0-beta.1

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 (177) hide show
  1. package/admin/src/components/ConfigurationsProvider/index.js +51 -0
  2. package/admin/src/components/ConfigurationsProvider/reducer.js +28 -0
  3. package/admin/src/components/LeftMenu/index.js +12 -2
  4. package/admin/src/components/Providers/index.js +8 -4
  5. package/admin/src/components/UnauthenticatedLogo/index.js +4 -2
  6. package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +3 -3
  7. package/admin/src/content-manager/components/SelectMany/index.js +2 -4
  8. package/admin/src/content-manager/components/SelectWrapper/index.js +1 -13
  9. package/admin/src/hooks/useFetchMarketplaceProviders/index.js +23 -0
  10. package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +11 -0
  11. package/admin/src/pages/App/index.js +7 -2
  12. package/admin/src/pages/MarketplacePage/components/{EmptyPluginSearch/EmptyPluginGrid.js → EmptyNpmPackageSearch/EmptyNpmPackageGrid.js} +1 -1
  13. package/admin/src/pages/MarketplacePage/components/{EmptyPluginSearch → EmptyNpmPackageSearch}/index.js +6 -4
  14. package/admin/src/pages/MarketplacePage/components/{PluginCard → NpmPackageCard}/InstallPluginButton.js +0 -0
  15. package/admin/src/pages/MarketplacePage/components/{PluginCard → NpmPackageCard}/index.js +22 -10
  16. package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +42 -0
  17. package/admin/src/pages/MarketplacePage/components/PageHeader/index.js +12 -5
  18. package/admin/src/pages/MarketplacePage/index.js +99 -37
  19. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/index.js +85 -0
  20. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/init.js +13 -0
  21. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/reducer.js +43 -0
  22. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/index.js +118 -0
  23. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/reducer.js +28 -0
  24. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/stepper.js +25 -0
  25. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/AddLogoDialog.js +67 -0
  26. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromComputerForm.js +176 -0
  27. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromUrlForm.js +86 -0
  28. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/ImageCardAsset.js +51 -0
  29. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js +97 -0
  30. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/index.js +85 -0
  31. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/reducer.js +28 -0
  32. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +153 -91
  33. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +16 -0
  34. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/constants.js +3 -0
  35. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/getFormData.js +17 -0
  36. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/parseFileMetadatas.js +76 -0
  37. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/prefixAllUrls.js +17 -0
  38. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/urlToFile.js +21 -0
  39. package/admin/src/translations/en.json +33 -3
  40. package/admin/src/translations/pl.json +264 -12
  41. package/admin/src/translations/vi.json +17 -17
  42. package/admin/src/tsconfig.json +1 -1
  43. package/build/1820.ca954075.chunk.js +503 -0
  44. package/build/1856.6a94980b.chunk.js +172 -0
  45. package/build/20.9e5a98b6.chunk.js +308 -0
  46. package/build/2077.5456ccd1.chunk.js +194 -0
  47. package/build/3531.231e0eb6.chunk.js +10 -0
  48. package/build/{4073.41ac1235.chunk.js → 4073.e144a91a.chunk.js} +1 -1
  49. package/build/413.d5986568.chunk.js +284 -0
  50. package/build/4715.4588fdf5.chunk.js +385 -0
  51. package/build/{210.014495c1.chunk.js → 472.d43be8bb.chunk.js} +58 -58
  52. package/build/4800.d3ebc81d.chunk.js +1 -0
  53. package/build/5250.24040688.chunk.js +11 -0
  54. package/build/6229.53b33cf0.chunk.js +194 -0
  55. package/build/7418.6db737ce.chunk.js +112 -0
  56. package/build/8773.54a26ded.chunk.js +327 -0
  57. package/build/9066.2847fdff.chunk.js +101 -0
  58. package/build/9262.25aa12a5.chunk.js +1 -0
  59. package/build/9420.ba035f29.chunk.js +508 -0
  60. package/build/Admin-authenticatedApp.52f3c150.chunk.js +80 -0
  61. package/build/{Admin_homePage.f157e33e.chunk.js → Admin_homePage.0ac648e8.chunk.js} +2 -2
  62. package/build/Admin_marketplace.71c66b49.chunk.js +11 -0
  63. package/build/{Admin_profilePage.62c203ad.chunk.js → Admin_profilePage.27191ed2.chunk.js} +1 -1
  64. package/build/Admin_settingsPage.021da806.chunk.js +178 -0
  65. package/build/{admin-edit-roles-page.94e1403b.chunk.js → admin-edit-roles-page.fb374555.chunk.js} +1 -1
  66. package/build/admin-edit-users.a360deaf.chunk.js +10 -0
  67. package/build/admin-users.47d06d24.chunk.js +11 -0
  68. package/build/api-tokens-create-page.698f132d.chunk.js +1 -0
  69. package/build/api-tokens-edit-page.afece2fe.chunk.js +1 -0
  70. package/build/{api-tokens-list-page.340750a6.chunk.js → api-tokens-list-page.46d96dee.chunk.js} +1 -1
  71. package/build/content-manager.afcc3624.chunk.js +1182 -0
  72. package/build/email-settings-page.8871dfe8.chunk.js +103 -0
  73. package/build/en-json.0a5ba154.chunk.js +1 -0
  74. package/build/i18n-settings-page.dfb4eb01.chunk.js +101 -0
  75. package/build/index.html +1 -1
  76. package/build/main.ca3856ed.js +8640 -0
  77. package/build/pl-json.f65302c2.chunk.js +1 -0
  78. package/build/{runtime~main.e7611418.js → runtime~main.48a46dd2.js} +1 -1
  79. package/build/{sso-settings-page.e9034e22.chunk.js → sso-settings-page.dfb0b917.chunk.js} +1 -1
  80. package/build/upload-settings.8d8c672a.chunk.js +101 -0
  81. package/build/upload-translation-de-json.745613c0.chunk.js +1 -0
  82. package/build/upload-translation-dk-json.cb25dcf0.chunk.js +1 -0
  83. package/build/upload-translation-en-json.e78688a0.chunk.js +1 -0
  84. package/build/upload-translation-es-json.1f344b53.chunk.js +1 -0
  85. package/build/upload-translation-fr-json.e21c0c7a.chunk.js +1 -0
  86. package/build/upload-translation-he-json.4ce77b7b.chunk.js +1 -0
  87. package/build/upload-translation-it-json.5ce11e0b.chunk.js +1 -0
  88. package/build/upload-translation-ja-json.22afae44.chunk.js +1 -0
  89. package/build/upload-translation-ko-json.9a2c21cb.chunk.js +1 -0
  90. package/build/upload-translation-ms-json.0605d6da.chunk.js +1 -0
  91. package/build/upload-translation-pl-json.e534b676.chunk.js +1 -0
  92. package/build/upload-translation-pt-BR-json.95686cfb.chunk.js +1 -0
  93. package/build/upload-translation-ru-json.37bd1546.chunk.js +1 -0
  94. package/build/upload-translation-sk-json.b03d4904.chunk.js +1 -0
  95. package/build/upload-translation-th-json.64dd70ce.chunk.js +1 -0
  96. package/build/upload-translation-uk-json.1328cb3e.chunk.js +1 -0
  97. package/build/{upload-translation-zh-Hans-json.c9622577.chunk.js → upload-translation-zh-Hans-json.6832ff81.chunk.js} +1 -1
  98. package/build/upload-translation-zh-json.ee8fba96.chunk.js +1 -0
  99. package/build/upload.5622b777.chunk.js +7 -0
  100. package/build/users-advanced-settings-page.4af9e241.chunk.js +101 -0
  101. package/build/users-email-settings-page.d69c0d87.chunk.js +101 -0
  102. package/build/users-providers-settings-page.fc1fda6d.chunk.js +101 -0
  103. package/build/vi-json.bf3424be.chunk.js +1 -0
  104. package/build/webhook-edit-page.a7ae6e3b.chunk.js +23 -0
  105. package/build/webhook-list-page.057f396c.chunk.js +133 -0
  106. package/index.js +2 -8
  107. package/package.json +10 -9
  108. package/scripts/build.js +3 -1
  109. package/server/config/admin-actions.js +14 -0
  110. package/server/controllers/admin.js +40 -2
  111. package/server/routes/admin.js +28 -1
  112. package/server/services/index.js +1 -0
  113. package/server/services/project-settings.js +173 -0
  114. package/server/utils/index.d.ts +2 -0
  115. package/server/validation/project-settings.js +39 -0
  116. package/utils/create-cache-dir.js +6 -36
  117. package/utils/get-custom-app-config-file.js +7 -2
  118. package/utils/get-plugins-path.js +1 -1
  119. package/admin/src/content-manager/components/SelectWrapper/ClearIndicator.js +0 -18
  120. package/admin/src/content-manager/components/SelectWrapper/DropdownIndicator.js +0 -24
  121. package/admin/src/content-manager/components/SelectWrapper/IconBox.js +0 -20
  122. package/admin/src/content-manager/components/SelectWrapper/IndicatorSeparator.js +0 -3
  123. package/admin/src/content-manager/components/SelectWrapper/utils/getSelectStyles.js +0 -92
  124. package/build/1709.ceed0e18.chunk.js +0 -503
  125. package/build/1856.521a99fd.chunk.js +0 -172
  126. package/build/20.cf744c35.chunk.js +0 -308
  127. package/build/2077.51485bfb.chunk.js +0 -194
  128. package/build/2135.95ee6de1.chunk.js +0 -162
  129. package/build/2524.688d0355.chunk.js +0 -1
  130. package/build/2912.79c2b3c8.chunk.js +0 -253
  131. package/build/4715.77e04177.chunk.js +0 -385
  132. package/build/4761.3eabdf46.chunk.js +0 -101
  133. package/build/6229.a5cca9f2.chunk.js +0 -194
  134. package/build/6281.f10a7e3a.chunk.js +0 -1
  135. package/build/7009.79fce86d.chunk.js +0 -164
  136. package/build/7191.3bde3cbf.chunk.js +0 -335
  137. package/build/7841.f0e7d629.chunk.js +0 -253
  138. package/build/7863.bc7a8f3a.chunk.js +0 -112
  139. package/build/9420.cb0b75e8.chunk.js +0 -508
  140. package/build/Admin-authenticatedApp.4ce8d292.chunk.js +0 -80
  141. package/build/Admin_marketplace.1e3393c9.chunk.js +0 -11
  142. package/build/Admin_settingsPage.924a7816.chunk.js +0 -170
  143. package/build/admin-edit-users.6c2bf718.chunk.js +0 -10
  144. package/build/admin-users.e03db115.chunk.js +0 -11
  145. package/build/api-tokens-create-page.787ab302.chunk.js +0 -1
  146. package/build/api-tokens-edit-page.e4010c0c.chunk.js +0 -1
  147. package/build/content-manager.6cdcfb6e.chunk.js +0 -1204
  148. package/build/email-settings-page.f67d13b2.chunk.js +0 -103
  149. package/build/en-json.3e1a222e.chunk.js +0 -1
  150. package/build/i18n-settings-page.6b67cb75.chunk.js +0 -101
  151. package/build/main.45472ea9.js +0 -8404
  152. package/build/pl-json.94f05d2c.chunk.js +0 -1
  153. package/build/upload-settings.3db55de0.chunk.js +0 -101
  154. package/build/upload-translation-de-json.b642da08.chunk.js +0 -1
  155. package/build/upload-translation-dk-json.fc61df13.chunk.js +0 -1
  156. package/build/upload-translation-en-json.59269508.chunk.js +0 -1
  157. package/build/upload-translation-es-json.8ec935ef.chunk.js +0 -1
  158. package/build/upload-translation-fr-json.eb9b4f84.chunk.js +0 -1
  159. package/build/upload-translation-he-json.c226f2dc.chunk.js +0 -1
  160. package/build/upload-translation-it-json.8e58456e.chunk.js +0 -1
  161. package/build/upload-translation-ja-json.1378a2e7.chunk.js +0 -1
  162. package/build/upload-translation-ko-json.5e06e112.chunk.js +0 -1
  163. package/build/upload-translation-ms-json.dc3bf0d7.chunk.js +0 -1
  164. package/build/upload-translation-pl-json.6071e38c.chunk.js +0 -1
  165. package/build/upload-translation-pt-BR-json.7e8d9550.chunk.js +0 -1
  166. package/build/upload-translation-ru-json.da2529f3.chunk.js +0 -1
  167. package/build/upload-translation-sk-json.bfdf4f09.chunk.js +0 -1
  168. package/build/upload-translation-th-json.6a48b826.chunk.js +0 -1
  169. package/build/upload-translation-uk-json.6fb09148.chunk.js +0 -1
  170. package/build/upload-translation-zh-json.711f804b.chunk.js +0 -1
  171. package/build/upload.070c189b.chunk.js +0 -105
  172. package/build/users-advanced-settings-page.a23cda17.chunk.js +0 -101
  173. package/build/users-email-settings-page.0a096388.chunk.js +0 -1
  174. package/build/users-providers-settings-page.bfe7755a.chunk.js +0 -1
  175. package/build/vi-json.3d14e91e.chunk.js +0 -1
  176. package/build/webhook-edit-page.2fa94db3.chunk.js +0 -23
  177. package/build/webhook-list-page.b594db49.chunk.js +0 -133
@@ -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,86 @@
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 () => {
22
+ try {
23
+ const file = await urlToFile(logoUrl);
24
+ const asset = await parseFileMetadatas(file);
25
+
26
+ setLocalImage(asset);
27
+ goTo(next);
28
+ } catch (err) {
29
+ if (err.displayMessage) {
30
+ setError(formatMessage(err.displayMessage, { size: SIZE, dimension: DIMENSION }));
31
+ } else {
32
+ throw err;
33
+ }
34
+ }
35
+ };
36
+
37
+ return (
38
+ <form
39
+ onSubmit={e => {
40
+ e.preventDefault();
41
+ handleSubmit();
42
+ }}
43
+ >
44
+ <Box paddingLeft={8} paddingRight={8} paddingTop={6} paddingBottom={6}>
45
+ <TextInput
46
+ label={formatMessage({
47
+ id: 'Settings.application.customization.modal.upload.from-url.input-label',
48
+ defaultMessage: 'URL',
49
+ })}
50
+ error={error}
51
+ onChange={handleChange}
52
+ value={logoUrl}
53
+ name="logo-url"
54
+ />
55
+ </Box>
56
+ <ModalFooter
57
+ startActions={
58
+ <Button onClick={onClose} variant="tertiary">
59
+ {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'Cancel' })}
60
+ </Button>
61
+ }
62
+ endActions={
63
+ <Button type="submit">
64
+ {formatMessage({
65
+ id: 'Settings.application.customization.modal.upload.next',
66
+ defaultMessage: 'Next',
67
+ })}
68
+ </Button>
69
+ }
70
+ />
71
+ </form>
72
+ );
73
+ };
74
+
75
+ FromUrlForm.defaultProps = {
76
+ next: null,
77
+ };
78
+
79
+ FromUrlForm.propTypes = {
80
+ goTo: PropTypes.func.isRequired,
81
+ next: PropTypes.string,
82
+ onClose: PropTypes.func.isRequired,
83
+ setLocalImage: PropTypes.func.isRequired,
84
+ };
85
+
86
+ 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 };