@strapi/admin 4.2.0-beta.2 → 4.2.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 (217) hide show
  1. package/admin/src/app.js +4 -7
  2. package/admin/src/assets/images/homepage-logo.png +0 -0
  3. package/admin/src/components/AutoReloadOverlayBlockerProvider/Blocker.js +2 -6
  4. package/admin/src/components/ConfigurationsProvider/index.js +51 -0
  5. package/admin/src/components/ConfigurationsProvider/reducer.js +28 -0
  6. package/admin/src/components/GuidedTour/Homepage/index.js +1 -2
  7. package/admin/src/components/GuidedTour/Modal/components/Stepper.js +1 -2
  8. package/admin/src/components/LeftMenu/index.js +19 -7
  9. package/admin/src/components/Notifications/Notification/index.js +2 -2
  10. package/admin/src/components/Providers/index.js +8 -4
  11. package/admin/src/components/UnauthenticatedLogo/index.js +4 -2
  12. package/admin/src/components/UpgradePlanModal/index.js +6 -2
  13. package/admin/src/content-manager/components/DynamicZone/components/ComponentPicker/Category/ComponentCard/index.js +1 -1
  14. package/admin/src/content-manager/components/SelectMany/ListItem.js +1 -2
  15. package/admin/src/content-manager/components/SelectWrapper/index.js +8 -7
  16. package/admin/src/content-manager/components/SelectWrapper/utils/getSelectStyles.js +1 -1
  17. package/admin/src/content-manager/components/SingleTypeFormWrapper/index.js +2 -2
  18. package/admin/src/content-manager/components/Wysiwyg/Editor.js +2 -0
  19. package/admin/src/content-manager/pages/App/LeftMenu/index.js +8 -7
  20. package/admin/src/content-manager/pages/EditSettingsView/components/ComponentFieldList.js +1 -1
  21. package/admin/src/content-manager/pages/EditSettingsView/components/LinkToCTB.js +1 -2
  22. package/admin/src/content-manager/pages/EditSettingsView/index.js +1 -2
  23. package/admin/src/content-manager/pages/EditView/Header/index.js +3 -3
  24. package/admin/src/content-manager/pages/EditView/index.js +1 -4
  25. package/admin/src/content-manager/pages/ListSettingsView/index.js +1 -2
  26. package/admin/src/content-manager/pages/ListView/index.js +1 -1
  27. package/admin/src/content-manager/pages/NoContentType/index.js +1 -2
  28. package/admin/src/hooks/useFetchMarketplaceProviders/index.js +23 -0
  29. package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +11 -0
  30. package/admin/src/pages/Admin/index.js +5 -15
  31. package/admin/src/pages/App/index.js +9 -18
  32. package/admin/src/pages/AuthPage/components/ForgotPassword/index.js +1 -2
  33. package/admin/src/pages/AuthPage/components/ForgotPasswordSuccess/index.js +1 -1
  34. package/admin/src/pages/AuthPage/components/Login/BaseLogin.js +1 -2
  35. package/admin/src/pages/AuthPage/components/Oops/index.js +1 -2
  36. package/admin/src/pages/AuthPage/components/Register/index.js +12 -12
  37. package/admin/src/pages/AuthPage/components/ResetPassword/index.js +3 -4
  38. package/admin/src/pages/HomePage/ContentBlocks.js +15 -2
  39. package/admin/src/pages/HomePage/HomeHeader.js +2 -2
  40. package/admin/src/pages/HomePage/SocialLinks.js +4 -3
  41. package/admin/src/pages/InternalErrorPage/index.js +1 -2
  42. package/admin/src/pages/MarketplacePage/components/{EmptyPluginSearch/EmptyPluginGrid.js → EmptyNpmPackageSearch/EmptyNpmPackageGrid.js} +1 -1
  43. package/admin/src/pages/MarketplacePage/components/{EmptyPluginSearch → EmptyNpmPackageSearch}/index.js +6 -4
  44. package/admin/src/pages/MarketplacePage/components/{PluginCard → NpmPackageCard}/InstallPluginButton.js +0 -0
  45. package/admin/src/pages/MarketplacePage/components/{PluginCard → NpmPackageCard}/index.js +26 -13
  46. package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +42 -0
  47. package/admin/src/pages/MarketplacePage/components/PageHeader/index.js +14 -6
  48. package/admin/src/pages/MarketplacePage/index.js +99 -37
  49. package/admin/src/pages/NotFoundPage/index.js +1 -2
  50. package/admin/src/pages/SettingsPage/components/SettingsNav/index.js +5 -4
  51. package/admin/src/pages/SettingsPage/pages/ApiTokens/EditView/index.js +1 -1
  52. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/DynamicTable/UpdateButton/index.js +1 -1
  53. package/admin/src/pages/SettingsPage/pages/ApiTokens/ListView/index.js +1 -1
  54. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/index.js +85 -0
  55. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/init.js +13 -0
  56. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/reducer.js +43 -0
  57. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/index.js +118 -0
  58. package/admin/src/pages/{App → SettingsPage/pages/ApplicationInfosPage/components/LogoInput}/reducer.js +13 -7
  59. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/stepper.js +25 -0
  60. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/AddLogoDialog.js +67 -0
  61. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromComputerForm.js +176 -0
  62. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromUrlForm.js +82 -0
  63. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/ImageCardAsset.js +51 -0
  64. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js +97 -0
  65. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/index.js +85 -0
  66. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/reducer.js +28 -0
  67. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +155 -87
  68. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +16 -0
  69. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/constants.js +3 -0
  70. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/getFormData.js +17 -0
  71. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/parseFileMetadatas.js +76 -0
  72. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/prefixAllUrls.js +17 -0
  73. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/urlToFile.js +21 -0
  74. package/admin/src/pages/SettingsPage/pages/Roles/EditPage/index.js +1 -1
  75. package/admin/src/pages/SettingsPage/pages/Users/EditPage/index.js +1 -1
  76. package/admin/src/pages/SettingsPage/pages/Webhooks/EditView/components/WebhookForm/index.js +1 -2
  77. package/admin/src/pages/SettingsPage/pages/Webhooks/ListView/index.js +1 -1
  78. package/admin/src/reducers.js +2 -4
  79. package/admin/src/translations/en.json +33 -3
  80. package/admin/src/translations/pl.json +264 -12
  81. package/admin/src/translations/vi.json +17 -17
  82. package/build/1856.6a94980b.chunk.js +172 -0
  83. package/build/2077.5456ccd1.chunk.js +194 -0
  84. package/build/2758.9475712b.chunk.js +162 -0
  85. package/build/2912.dd031292.chunk.js +253 -0
  86. package/build/4715.4588fdf5.chunk.js +385 -0
  87. package/build/4800.d3ebc81d.chunk.js +1 -0
  88. package/build/4982.c57c5675.chunk.js +308 -0
  89. package/build/7197.ed8d6752.chunk.js +113 -0
  90. package/build/7589.577cf729.chunk.js +194 -0
  91. package/build/{7393.8ae60738.chunk.js → 7757.f6eb5e92.chunk.js} +89 -87
  92. package/build/7841.9e9cf739.chunk.js +253 -0
  93. package/build/8681.aec05472.chunk.js +163 -0
  94. package/build/9066.2847fdff.chunk.js +101 -0
  95. package/build/9115.abdf4e3b.chunk.js +1 -0
  96. package/build/9158.e48d88af.chunk.js +503 -0
  97. package/build/{7191.3bde3cbf.chunk.js → 9298.cb3b6bc1.chunk.js} +112 -113
  98. package/build/9420.ba035f29.chunk.js +508 -0
  99. package/build/948.d64fb515.chunk.js +2 -0
  100. package/build/Admin-authenticatedApp.e7ed0550.chunk.js +80 -0
  101. package/build/Admin_homePage.8c00145e.chunk.js +71 -0
  102. package/build/Admin_marketplace.a88d5bda.chunk.js +11 -0
  103. package/build/Admin_pluginsPage.e895d79f.chunk.js +1 -0
  104. package/build/{Admin_profilePage.62c203ad.chunk.js → Admin_profilePage.33cfed9b.chunk.js} +2 -2
  105. package/build/Admin_settingsPage.fe33e0a2.chunk.js +180 -0
  106. package/build/admin-edit-roles-page.e77a2acc.chunk.js +1 -0
  107. package/build/admin-edit-users.4c49fe98.chunk.js +11 -0
  108. package/build/admin-users.b89adf82.chunk.js +12 -0
  109. package/build/api-tokens-create-page.618b3e40.chunk.js +1 -0
  110. package/build/api-tokens-edit-page.8d19dfe1.chunk.js +1 -0
  111. package/build/api-tokens-list-page.274e1c80.chunk.js +15 -0
  112. package/build/{codemirror-css.b467b1de.chunk.js → codemirror-css.98490df3.chunk.js} +2 -2
  113. package/build/{codemirror-javacript.41bdefda.chunk.js → codemirror-javacript.cafbda9c.chunk.js} +1 -1
  114. package/build/codemirror-theme.b3c64617.chunk.js +34 -0
  115. package/build/content-manager.04b93497.chunk.js +1204 -0
  116. package/build/content-type-builder.b3139cb1.chunk.js +141 -0
  117. package/build/{cropper-css.ecc0d670.chunk.js → cropper-css.0055cd53.chunk.js} +2 -2
  118. package/build/email-settings-page.4ae595f6.chunk.js +103 -0
  119. package/build/en-json.0a5ba154.chunk.js +1 -0
  120. package/build/fb376b132d18bf4522ca.png +0 -0
  121. package/build/{fontawesome-css-all.04f33619.chunk.js → fontawesome-css-all.b88d464e.chunk.js} +3 -3
  122. package/build/{fontawesome-css.477ba714.chunk.js → fontawesome-css.59dc4459.chunk.js} +2 -2
  123. package/build/highlight.js.9d8ef460.chunk.js +86 -0
  124. package/build/i18n-settings-page.bdac3c7b.chunk.js +101 -0
  125. package/build/index.html +1 -1
  126. package/build/main.3257934a.js +8404 -0
  127. package/build/pl-json.f65302c2.chunk.js +1 -0
  128. package/build/{runtime~main.a32b12c8.js → runtime~main.de49adfd.js} +1 -1
  129. package/build/sso-settings-page.0b4d2106.chunk.js +1 -0
  130. package/build/upload-settings.cadfd452.chunk.js +101 -0
  131. package/build/upload-translation-ca-json.79159984.chunk.js +1 -0
  132. package/build/upload.fbc65439.chunk.js +105 -0
  133. package/build/users-advanced-settings-page.646b6f29.chunk.js +101 -0
  134. package/build/users-email-settings-page.8b561ea3.chunk.js +1 -0
  135. package/build/users-providers-settings-page.82141ace.chunk.js +1 -0
  136. package/build/users-roles-settings-page.28bf6bdc.chunk.js +30 -0
  137. package/build/vi-json.bf3424be.chunk.js +1 -0
  138. package/build/webhook-edit-page.ca670f8d.chunk.js +23 -0
  139. package/build/webhook-list-page.7057f1e8.chunk.js +133 -0
  140. package/ee/admin/pages/AuthPage/components/Providers/index.js +1 -1
  141. package/ee/admin/pages/SettingsPage/pages/Roles/CreatePage/index.js +1 -1
  142. package/ee/server/controllers/user.js +4 -0
  143. package/index.js +239 -53
  144. package/package.json +8 -12
  145. package/scripts/build.js +3 -17
  146. package/server/config/admin-actions.js +14 -0
  147. package/server/controllers/admin.js +29 -12
  148. package/server/controllers/user.js +4 -0
  149. package/server/policies/index.js +0 -1
  150. package/server/routes/admin.js +28 -9
  151. package/server/routes/serve-admin-panel.js +1 -1
  152. package/server/services/index.js +1 -0
  153. package/server/services/permission/permissions-manager/sanitize.js +22 -0
  154. package/server/services/project-settings.js +173 -0
  155. package/server/services/user.js +1 -1
  156. package/server/utils/index.d.ts +2 -0
  157. package/server/validation/project-settings.js +39 -0
  158. package/webpack.config.js +5 -28
  159. package/admin/src/content-manager/components/DynamicComponentCard/index.js +0 -43
  160. package/admin/src/pages/App/constants.js +0 -1
  161. package/admin/src/tsconfig.json +0 -10
  162. package/build/1856.521a99fd.chunk.js +0 -172
  163. package/build/20.cf744c35.chunk.js +0 -308
  164. package/build/2077.51485bfb.chunk.js +0 -194
  165. package/build/2135.95ee6de1.chunk.js +0 -162
  166. package/build/2524.688d0355.chunk.js +0 -1
  167. package/build/2897.8e7d5853.chunk.js +0 -184
  168. package/build/2912.79c2b3c8.chunk.js +0 -253
  169. package/build/2a9e9ef5c4c775bb7c7b.png +0 -0
  170. package/build/4073.f3936352.chunk.js +0 -1
  171. package/build/4715.77e04177.chunk.js +0 -385
  172. package/build/5232.928fea74.chunk.js +0 -989
  173. package/build/6229.26d93336.chunk.js +0 -194
  174. package/build/6281.f10a7e3a.chunk.js +0 -1
  175. package/build/6404.80bf5858.chunk.js +0 -506
  176. package/build/7009.79fce86d.chunk.js +0 -164
  177. package/build/7841.f0e7d629.chunk.js +0 -253
  178. package/build/7863.c1938f3f.chunk.js +0 -112
  179. package/build/9066.118ecccd.chunk.js +0 -101
  180. package/build/Admin-authenticatedApp.1f76af8f.chunk.js +0 -80
  181. package/build/Admin_homePage.8b391120.chunk.js +0 -71
  182. package/build/Admin_marketplace.21730109.chunk.js +0 -11
  183. package/build/Admin_pluginsPage.788fb2f6.chunk.js +0 -1
  184. package/build/Admin_settingsPage.9ce20f16.chunk.js +0 -170
  185. package/build/admin-edit-roles-page.75380ed4.chunk.js +0 -1
  186. package/build/admin-edit-users.05f7f389.chunk.js +0 -10
  187. package/build/admin-users.e03db115.chunk.js +0 -11
  188. package/build/api-tokens-create-page.c44e0c62.chunk.js +0 -1
  189. package/build/api-tokens-edit-page.30d0924d.chunk.js +0 -1
  190. package/build/api-tokens-list-page.6049cd23.chunk.js +0 -15
  191. package/build/codemirror-theme.cf9f9eb6.chunk.js +0 -34
  192. package/build/content-manager.2f0f9b15.chunk.js +0 -1204
  193. package/build/content-type-builder.ce7b7f42.chunk.js +0 -141
  194. package/build/email-settings-page.f67d13b2.chunk.js +0 -103
  195. package/build/en-json.3e1a222e.chunk.js +0 -1
  196. package/build/highlight.js.3381ffc3.chunk.js +0 -86
  197. package/build/i18n-settings-page.6b67cb75.chunk.js +0 -101
  198. package/build/main.e6045245.js +0 -7909
  199. package/build/pl-json.94f05d2c.chunk.js +0 -1
  200. package/build/sso-settings-page.e9034e22.chunk.js +0 -1
  201. package/build/upload-settings.3db55de0.chunk.js +0 -101
  202. package/build/upload.070c189b.chunk.js +0 -105
  203. package/build/users-advanced-settings-page.a23cda17.chunk.js +0 -101
  204. package/build/users-email-settings-page.0a096388.chunk.js +0 -1
  205. package/build/users-providers-settings-page.bfe7755a.chunk.js +0 -1
  206. package/build/users-roles-settings-page.c01bec1d.chunk.js +0 -30
  207. package/build/vi-json.3d14e91e.chunk.js +0 -1
  208. package/build/webhook-edit-page.d457087d.chunk.js +0 -23
  209. package/build/webhook-list-page.a4217ff2.chunk.js +0 -133
  210. package/server/policies/isTelemetryEnabled.js +0 -16
  211. package/utils/create-cache-dir.js +0 -161
  212. package/utils/get-custom-app-config-file.js +0 -23
  213. package/utils/get-custom-webpack-config.js +0 -38
  214. package/utils/get-plugins-path.js +0 -26
  215. package/utils/index.js +0 -13
  216. package/utils/should-build-admin.js +0 -52
  217. package/utils/watch-admin-files.js +0 -59
@@ -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 };