@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
@@ -1,26 +1,76 @@
1
- import React from 'react';
1
+ import React, { useRef } from 'react';
2
+ import { useQuery, useMutation, useQueryClient } from 'react-query';
2
3
  import { useIntl } from 'react-intl';
3
- import { useAppInfos, SettingsPageTitle, useFocusWhenNavigate } from '@strapi/helper-plugin';
4
+ import {
5
+ useAppInfos,
6
+ SettingsPageTitle,
7
+ useFocusWhenNavigate,
8
+ CheckPermissions,
9
+ useNotification,
10
+ useTracking,
11
+ } from '@strapi/helper-plugin';
4
12
  import { HeaderLayout, Layout, ContentLayout } from '@strapi/design-system/Layout';
5
13
  import { Main } from '@strapi/design-system/Main';
6
14
  import { Box } from '@strapi/design-system/Box';
7
15
  import { Grid, GridItem } from '@strapi/design-system/Grid';
8
16
  import { Typography } from '@strapi/design-system/Typography';
9
-
10
17
  import { Stack } from '@strapi/design-system/Stack';
11
- import { Link } from '@strapi/design-system/Link';
18
+ import { Button } from '@strapi/design-system/Button';
19
+ import { Link } from '@strapi/design-system/v2/Link';
12
20
  import ExternalLink from '@strapi/icons/ExternalLink';
21
+ import Check from '@strapi/icons/Check';
22
+ import { useConfigurations } from '../../../../hooks';
23
+ import Form from './components/Form';
24
+ import { fetchProjectSettings, postProjectSettings } from './utils/api';
25
+ import getFormData from './utils/getFormData';
26
+
27
+ const permissions = [{ action: 'admin::project-settings.update', subject: null }];
13
28
 
14
29
  const ApplicationInfosPage = () => {
30
+ const inputsRef = useRef();
31
+ const toggleNotification = useNotification();
32
+ const { trackUsage } = useTracking();
15
33
  const { formatMessage } = useIntl();
34
+ const queryClient = useQueryClient();
16
35
  useFocusWhenNavigate();
17
36
  const appInfos = useAppInfos();
18
37
  const { shouldUpdateStrapi, latestStrapiReleaseTag, strapiVersion } = appInfos;
38
+ const { updateProjectSettings } = useConfigurations();
39
+
40
+ const { data } = useQuery('project-settings', fetchProjectSettings);
19
41
 
20
42
  const currentPlan = appInfos.communityEdition
21
43
  ? 'app.components.UpgradePlanModal.text-ce'
22
44
  : 'app.components.UpgradePlanModal.text-ee';
23
45
 
46
+ const submitMutation = useMutation(body => postProjectSettings(body), {
47
+ onSuccess: async ({ menuLogo }) => {
48
+ await queryClient.invalidateQueries('project-settings', { refetchActive: true });
49
+ updateProjectSettings({ menuLogo: menuLogo?.url });
50
+ },
51
+ });
52
+
53
+ const handleSubmit = () => {
54
+ const inputValues = inputsRef.current.getValues();
55
+ const formData = getFormData(inputValues);
56
+
57
+ submitMutation.mutate(formData, {
58
+ onSuccess: () => {
59
+ const { menuLogo } = inputValues;
60
+
61
+ if (menuLogo.rawFile) {
62
+ trackUsage('didChangeLogo');
63
+ }
64
+ },
65
+ onError: () => {
66
+ toggleNotification({
67
+ type: 'warning',
68
+ message: { id: 'notification.error', defaultMessage: 'An error occurred' },
69
+ });
70
+ },
71
+ });
72
+ };
73
+
24
74
  return (
25
75
  <Layout>
26
76
  <SettingsPageTitle name="Application" />
@@ -31,101 +81,119 @@ const ApplicationInfosPage = () => {
31
81
  id: 'Settings.application.description',
32
82
  defaultMessage: 'Administration panel’s global information',
33
83
  })}
84
+ primaryAction={
85
+ <Button onClick={handleSubmit} startIcon={<Check />}>
86
+ {formatMessage({ id: 'global.save', defaultMessage: 'Save' })}
87
+ </Button>
88
+ }
34
89
  />
35
90
  <ContentLayout>
36
- <Box
37
- hasRadius
38
- background="neutral0"
39
- shadow="tableShadow"
40
- paddingTop={7}
41
- paddingBottom={7}
42
- paddingRight={6}
43
- paddingLeft={6}
44
- >
45
- <Stack spacing={5}>
46
- <Typography variant="delta" as="h3">
47
- {formatMessage({
48
- id: 'global.details',
49
- defaultMessage: 'Details',
50
- })}
51
- </Typography>
91
+ <Stack spacing={6}>
92
+ <Box
93
+ hasRadius
94
+ background="neutral0"
95
+ shadow="tableShadow"
96
+ paddingTop={6}
97
+ paddingBottom={6}
98
+ paddingRight={7}
99
+ paddingLeft={7}
100
+ >
101
+ <Stack spacing={5}>
102
+ <Typography variant="delta" as="h3">
103
+ {formatMessage({
104
+ id: 'global.details',
105
+ defaultMessage: 'Details',
106
+ })}
107
+ </Typography>
52
108
 
53
- <Grid paddingTop={1}>
54
- <GridItem col={6} s={12}>
55
- <Typography variant="sigma" textColor="neutral600">
56
- {formatMessage({
57
- id: 'Settings.application.strapiVersion',
58
- defaultMessage: 'strapi version',
59
- })}
60
- </Typography>
61
- <Typography as="p">v{strapiVersion}</Typography>
62
- <Link
63
- href={
64
- appInfos.communityEdition
65
- ? 'https://discord.strapi.io'
66
- : 'https://support.strapi.io/support/home'
67
- }
68
- endIcon={<ExternalLink />}
69
- >
70
- {formatMessage({
71
- id: 'Settings.application.get-help',
72
- defaultMessage: 'Get help',
73
- })}
74
- </Link>
75
- </GridItem>
76
- <GridItem col={6} s={12}>
77
- <Typography variant="sigma" textColor="neutral600">
78
- {formatMessage({
79
- id: 'Settings.application.edition-title',
80
- defaultMessage: 'current plan',
81
- })}
82
- </Typography>
83
- <Typography as="p">
84
- {formatMessage({
85
- id: currentPlan,
86
- defaultMessage: `${
87
- appInfos.communityEdition ? 'Community Edition' : 'Enterprise Edition'
88
- }`,
89
- })}
90
- </Typography>
91
- </GridItem>
92
- </Grid>
109
+ <Grid paddingTop={1}>
110
+ <GridItem col={6} s={12}>
111
+ <Typography variant="sigma" textColor="neutral600">
112
+ {formatMessage({
113
+ id: 'Settings.application.strapiVersion',
114
+ defaultMessage: 'strapi version',
115
+ })}
116
+ </Typography>
117
+ <Typography as="p">v{strapiVersion}</Typography>
118
+ <Link
119
+ href={
120
+ appInfos.communityEdition
121
+ ? 'https://discord.strapi.io'
122
+ : 'https://support.strapi.io/support/home'
123
+ }
124
+ isExternal
125
+ endIcon={<ExternalLink />}
126
+ >
127
+ {formatMessage({
128
+ id: 'Settings.application.get-help',
129
+ defaultMessage: 'Get help',
130
+ })}
131
+ </Link>
132
+ </GridItem>
133
+ <GridItem col={6} s={12}>
134
+ <Typography variant="sigma" textColor="neutral600">
135
+ {formatMessage({
136
+ id: 'Settings.application.edition-title',
137
+ defaultMessage: 'current plan',
138
+ })}
139
+ </Typography>
140
+ <Typography as="p">
141
+ {formatMessage({
142
+ id: currentPlan,
143
+ defaultMessage: `${
144
+ appInfos.communityEdition ? 'Community Edition' : 'Enterprise Edition'
145
+ }`,
146
+ })}
147
+ </Typography>
148
+ </GridItem>
149
+ </Grid>
93
150
 
94
- <Grid paddingTop={1}>
95
- <GridItem col={6} s={12}>
96
- {shouldUpdateStrapi && (
151
+ <Grid paddingTop={1}>
152
+ <GridItem col={6} s={12}>
153
+ {shouldUpdateStrapi && (
154
+ <Link
155
+ href={`https://github.com/strapi/strapi/releases/tag/${latestStrapiReleaseTag}`}
156
+ isExternal
157
+ endIcon={<ExternalLink />}
158
+ >
159
+ {formatMessage({
160
+ id: 'Settings.application.link-upgrade',
161
+ defaultMessage: 'Upgrade your admin panel',
162
+ })}
163
+ </Link>
164
+ )}
165
+ </GridItem>
166
+ <GridItem col={6} s={12}>
97
167
  <Link
98
- href={`https://github.com/strapi/strapi/releases/tag/${latestStrapiReleaseTag}`}
168
+ href="https://strapi.io/pricing-self-hosted"
169
+ isExternal
99
170
  endIcon={<ExternalLink />}
100
171
  >
101
172
  {formatMessage({
102
- id: 'Settings.application.link-upgrade',
103
- defaultMessage: 'Upgrade your admin panel',
173
+ id: 'Settings.application.link-pricing',
174
+ defaultMessage: 'See all pricing plans',
104
175
  })}
105
176
  </Link>
106
- )}
107
- </GridItem>
108
- <GridItem col={6} s={12}>
109
- <Link href="https://strapi.io/pricing-self-hosted" endIcon={<ExternalLink />}>
177
+ </GridItem>
178
+ </Grid>
179
+
180
+ <Box paddingTop={1}>
181
+ <Typography variant="sigma" textColor="neutral600">
110
182
  {formatMessage({
111
- id: 'Settings.application.link-pricing',
112
- defaultMessage: 'See all pricing plans',
183
+ id: 'Settings.application.node-version',
184
+ defaultMessage: 'node version',
113
185
  })}
114
- </Link>
115
- </GridItem>
116
- </Grid>
117
-
118
- <Box paddingTop={1}>
119
- <Typography variant="sigma" textColor="neutral600">
120
- {formatMessage({
121
- id: 'Settings.application.node-version',
122
- defaultMessage: 'node version',
123
- })}
124
- </Typography>
125
- <Typography as="p">{appInfos.nodeVersion}</Typography>
126
- </Box>
127
- </Stack>
128
- </Box>
186
+ </Typography>
187
+ <Typography as="p">{appInfos.nodeVersion}</Typography>
188
+ </Box>
189
+ </Stack>
190
+ </Box>
191
+ {data && (
192
+ <CheckPermissions permissions={permissions}>
193
+ <Form ref={inputsRef} projectSettingsStored={data} />
194
+ </CheckPermissions>
195
+ )}
196
+ </Stack>
129
197
  </ContentLayout>
130
198
  </Main>
131
199
  </Layout>
@@ -0,0 +1,16 @@
1
+ import { axiosInstance } from '../../../../../core/utils';
2
+ import prefixAllUrls from './prefixAllUrls';
3
+
4
+ const fetchProjectSettings = async () => {
5
+ const { data } = await axiosInstance.get('/admin/project-settings');
6
+
7
+ return prefixAllUrls(data);
8
+ };
9
+
10
+ const postProjectSettings = async body => {
11
+ const { data } = await axiosInstance.post('/admin/project-settings', body);
12
+
13
+ return prefixAllUrls(data);
14
+ };
15
+
16
+ export { fetchProjectSettings, postProjectSettings };
@@ -0,0 +1,3 @@
1
+ export const DIMENSION = 750;
2
+ export const SIZE = 100;
3
+ export const ACCEPTED_FORMAT = ['image/jpeg', 'image/png', 'image/svg+xml'];
@@ -0,0 +1,17 @@
1
+ const getFormData = data => {
2
+ const formData = new FormData();
3
+
4
+ Object.entries(data).forEach(([key, value]) => {
5
+ if (value && value.rawFile instanceof File) {
6
+ formData.append(key, value.rawFile);
7
+ }
8
+
9
+ if (value && value.isReset) {
10
+ formData.append(key, null);
11
+ }
12
+ });
13
+
14
+ return formData;
15
+ };
16
+
17
+ export default getFormData;
@@ -0,0 +1,76 @@
1
+ import { DIMENSION, SIZE, ACCEPTED_FORMAT } from './constants';
2
+
3
+ const FILE_FORMAT_ERROR_MESSAGE = {
4
+ id: 'Settings.application.customization.modal.upload.error-format',
5
+ defaultMessage: 'Wrong format uploaded (accepted formats only: jpeg, jpg, png, svg).',
6
+ };
7
+
8
+ const FILE_SIZING_ERROR_MESSAGE = {
9
+ id: 'Settings.application.customization.modal.upload.error-size',
10
+ defaultMessage:
11
+ 'The file uploaded is too large (max dimension: {dimension}x{dimension}, max file size: {size}KB)',
12
+ };
13
+
14
+ const getFileDimensions = file => {
15
+ return new Promise(resolve => {
16
+ const reader = new FileReader();
17
+ reader.onload = () => {
18
+ const img = new Image();
19
+ img.onload = function() {
20
+ resolve({ width: img.width, height: img.height });
21
+ };
22
+ img.src = reader.result;
23
+ };
24
+ reader.readAsDataURL(file);
25
+ });
26
+ };
27
+
28
+ const rawFileToAsset = (rawFile, fileDimensions) => {
29
+ return {
30
+ ext: rawFile.name.split('.').pop(),
31
+ size: rawFile.size / 1000,
32
+ name: rawFile.name,
33
+ url: URL.createObjectURL(rawFile),
34
+ rawFile,
35
+ width: fileDimensions.width,
36
+ height: fileDimensions.height,
37
+ };
38
+ };
39
+
40
+ export const parseFileMetadatas = async file => {
41
+ let error;
42
+
43
+ const isFormatAuthorized = ACCEPTED_FORMAT.includes(file.type);
44
+
45
+ if (!isFormatAuthorized) {
46
+ error = new Error('File format');
47
+ error.displayMessage = FILE_FORMAT_ERROR_MESSAGE;
48
+
49
+ throw error;
50
+ }
51
+
52
+ const fileDimensions = await getFileDimensions(file);
53
+
54
+ const areDimensionsAuthorized =
55
+ fileDimensions.width <= DIMENSION && fileDimensions.height <= DIMENSION;
56
+
57
+ if (!areDimensionsAuthorized) {
58
+ error = new Error('File sizing');
59
+ error.displayMessage = FILE_SIZING_ERROR_MESSAGE;
60
+
61
+ throw error;
62
+ }
63
+
64
+ const asset = rawFileToAsset(file, fileDimensions);
65
+
66
+ const isSizeAuthorized = asset.size <= SIZE;
67
+
68
+ if (!isSizeAuthorized) {
69
+ error = new Error('File sizing');
70
+ error.displayMessage = FILE_SIZING_ERROR_MESSAGE;
71
+
72
+ throw error;
73
+ }
74
+
75
+ return asset;
76
+ };
@@ -0,0 +1,17 @@
1
+ import transform from 'lodash/transform';
2
+ import { prefixFileUrlWithBackendUrl } from '@strapi/helper-plugin';
3
+
4
+ const prefixAllUrls = data =>
5
+ transform(
6
+ data,
7
+ (result, value, key) => {
8
+ if (value && value.url) {
9
+ result[key] = { ...value, url: prefixFileUrlWithBackendUrl(value.url) };
10
+ } else {
11
+ result[key] = value;
12
+ }
13
+ },
14
+ {}
15
+ );
16
+
17
+ export default prefixAllUrls;
@@ -0,0 +1,21 @@
1
+ import axios from 'axios';
2
+
3
+ const urlToFile = async url => {
4
+ try {
5
+ const res = await axios.get(url, { responseType: 'blob', timeout: 8000 });
6
+ const loadedFile = new File([res.data], res.config.url, {
7
+ type: res.headers['content-type'],
8
+ });
9
+
10
+ return loadedFile;
11
+ } catch (err) {
12
+ err.displayMessage = {
13
+ id: 'Settings.application.customization.modal.upload.error-network',
14
+ defaultMessage: 'Network error',
15
+ };
16
+
17
+ throw err;
18
+ }
19
+ };
20
+
21
+ export default urlToFile;
@@ -6,6 +6,7 @@ import {
6
6
  useTracking,
7
7
  LoadingIndicatorPage,
8
8
  SettingsPageTitle,
9
+ Link,
9
10
  } from '@strapi/helper-plugin';
10
11
  import { Box } from '@strapi/design-system/Box';
11
12
  import { Button } from '@strapi/design-system/Button';
@@ -13,7 +14,6 @@ import { ContentLayout, HeaderLayout } from '@strapi/design-system/Layout';
13
14
  import { Main } from '@strapi/design-system/Main';
14
15
  import { Stack } from '@strapi/design-system/Stack';
15
16
  import { Formik } from 'formik';
16
- import { Link } from '@strapi/design-system/Link';
17
17
  import ArrowLeft from '@strapi/icons/ArrowLeft';
18
18
  import get from 'lodash/get';
19
19
  import { useIntl } from 'react-intl';
@@ -15,6 +15,7 @@ import {
15
15
  useNotification,
16
16
  useOverlayBlocker,
17
17
  LoadingIndicatorPage,
18
+ Link,
18
19
  } from '@strapi/helper-plugin';
19
20
  import { useQuery } from 'react-query';
20
21
  import { Formik } from 'formik';
@@ -22,7 +23,6 @@ import { Box } from '@strapi/design-system/Box';
22
23
  import { Button } from '@strapi/design-system/Button';
23
24
  import { Grid, GridItem } from '@strapi/design-system/Grid';
24
25
  import { HeaderLayout, ContentLayout } from '@strapi/design-system/Layout';
25
- import { Link } from '@strapi/design-system/Link';
26
26
  import { Typography } from '@strapi/design-system/Typography';
27
27
  import { Main } from '@strapi/design-system/Main';
28
28
  import { Stack } from '@strapi/design-system/Stack';
@@ -1,13 +1,12 @@
1
1
  import React, { useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
- import { Form } from '@strapi/helper-plugin';
3
+ import { Form, Link } from '@strapi/helper-plugin';
4
4
  import ArrowLeft from '@strapi/icons/ArrowLeft';
5
5
  import Check from '@strapi/icons/Check';
6
6
  import Publish from '@strapi/icons/Play';
7
7
  import { ContentLayout, HeaderLayout } from '@strapi/design-system/Layout';
8
8
  import { Box } from '@strapi/design-system/Box';
9
9
  import { Button } from '@strapi/design-system/Button';
10
- import { Link } from '@strapi/design-system/Link';
11
10
  import { Stack } from '@strapi/design-system/Stack';
12
11
  import { TextInput } from '@strapi/design-system/TextInput';
13
12
  import { Grid, GridItem } from '@strapi/design-system/Grid';
@@ -17,6 +17,7 @@ import {
17
17
  ConfirmDialog,
18
18
  onRowClick,
19
19
  stopPropagation,
20
+ LinkButton,
20
21
  } from '@strapi/helper-plugin';
21
22
  import { HeaderLayout, Layout, ContentLayout, ActionLayout } from '@strapi/design-system/Layout';
22
23
  import { EmptyStateLayout } from '@strapi/design-system/EmptyStateLayout';
@@ -30,7 +31,6 @@ import { Button } from '@strapi/design-system/Button';
30
31
  import { VisuallyHidden } from '@strapi/design-system/VisuallyHidden';
31
32
  import { Switch } from '@strapi/design-system/Switch';
32
33
  import { Main } from '@strapi/design-system/Main';
33
- import { LinkButton } from '@strapi/design-system/LinkButton';
34
34
  import { useNotifyAT } from '@strapi/design-system/LiveRegions';
35
35
  import { Box } from '@strapi/design-system/Box';
36
36
  import Plus from '@strapi/icons/Plus';