@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.
- package/admin/src/components/ConfigurationsProvider/index.js +51 -0
- package/admin/src/components/ConfigurationsProvider/reducer.js +28 -0
- package/admin/src/components/LeftMenu/index.js +12 -2
- package/admin/src/components/Providers/index.js +8 -4
- package/admin/src/components/UnauthenticatedLogo/index.js +4 -2
- package/admin/src/content-manager/components/EditViewDataManagerProvider/index.js +3 -3
- package/admin/src/content-manager/components/SelectMany/index.js +2 -4
- package/admin/src/content-manager/components/SelectWrapper/index.js +1 -13
- package/admin/src/hooks/useFetchMarketplaceProviders/index.js +23 -0
- package/admin/src/hooks/useFetchMarketplaceProviders/utils/api.js +11 -0
- package/admin/src/pages/App/index.js +7 -2
- package/admin/src/pages/MarketplacePage/components/{EmptyPluginSearch/EmptyPluginGrid.js → EmptyNpmPackageSearch/EmptyNpmPackageGrid.js} +1 -1
- package/admin/src/pages/MarketplacePage/components/{EmptyPluginSearch → EmptyNpmPackageSearch}/index.js +6 -4
- package/admin/src/pages/MarketplacePage/components/{PluginCard → NpmPackageCard}/InstallPluginButton.js +0 -0
- package/admin/src/pages/MarketplacePage/components/{PluginCard → NpmPackageCard}/index.js +22 -10
- package/admin/src/pages/MarketplacePage/components/NpmPackagesGrid/index.js +42 -0
- package/admin/src/pages/MarketplacePage/components/PageHeader/index.js +12 -5
- package/admin/src/pages/MarketplacePage/index.js +99 -37
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/index.js +85 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/init.js +13 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/reducer.js +43 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/index.js +118 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/reducer.js +28 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/stepper.js +25 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/AddLogoDialog.js +67 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromComputerForm.js +176 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromUrlForm.js +86 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/ImageCardAsset.js +51 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js +97 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/index.js +85 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/reducer.js +28 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +153 -91
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +16 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/constants.js +3 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/getFormData.js +17 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/parseFileMetadatas.js +76 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/prefixAllUrls.js +17 -0
- package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/urlToFile.js +21 -0
- package/admin/src/translations/en.json +33 -3
- package/admin/src/translations/pl.json +264 -12
- package/admin/src/translations/vi.json +17 -17
- package/admin/src/tsconfig.json +1 -1
- package/build/1820.ca954075.chunk.js +503 -0
- package/build/1856.6a94980b.chunk.js +172 -0
- package/build/20.9e5a98b6.chunk.js +308 -0
- package/build/2077.5456ccd1.chunk.js +194 -0
- package/build/3531.231e0eb6.chunk.js +10 -0
- package/build/{4073.41ac1235.chunk.js → 4073.e144a91a.chunk.js} +1 -1
- package/build/413.d5986568.chunk.js +284 -0
- package/build/4715.4588fdf5.chunk.js +385 -0
- package/build/{210.014495c1.chunk.js → 472.d43be8bb.chunk.js} +58 -58
- package/build/4800.d3ebc81d.chunk.js +1 -0
- package/build/5250.24040688.chunk.js +11 -0
- package/build/6229.53b33cf0.chunk.js +194 -0
- package/build/7418.6db737ce.chunk.js +112 -0
- package/build/8773.54a26ded.chunk.js +327 -0
- package/build/9066.2847fdff.chunk.js +101 -0
- package/build/9262.25aa12a5.chunk.js +1 -0
- package/build/9420.ba035f29.chunk.js +508 -0
- package/build/Admin-authenticatedApp.52f3c150.chunk.js +80 -0
- package/build/{Admin_homePage.f157e33e.chunk.js → Admin_homePage.0ac648e8.chunk.js} +2 -2
- package/build/Admin_marketplace.71c66b49.chunk.js +11 -0
- package/build/{Admin_profilePage.62c203ad.chunk.js → Admin_profilePage.27191ed2.chunk.js} +1 -1
- package/build/Admin_settingsPage.021da806.chunk.js +178 -0
- package/build/{admin-edit-roles-page.94e1403b.chunk.js → admin-edit-roles-page.fb374555.chunk.js} +1 -1
- package/build/admin-edit-users.a360deaf.chunk.js +10 -0
- package/build/admin-users.47d06d24.chunk.js +11 -0
- package/build/api-tokens-create-page.698f132d.chunk.js +1 -0
- package/build/api-tokens-edit-page.afece2fe.chunk.js +1 -0
- package/build/{api-tokens-list-page.340750a6.chunk.js → api-tokens-list-page.46d96dee.chunk.js} +1 -1
- package/build/content-manager.afcc3624.chunk.js +1182 -0
- package/build/email-settings-page.8871dfe8.chunk.js +103 -0
- package/build/en-json.0a5ba154.chunk.js +1 -0
- package/build/i18n-settings-page.dfb4eb01.chunk.js +101 -0
- package/build/index.html +1 -1
- package/build/main.ca3856ed.js +8640 -0
- package/build/pl-json.f65302c2.chunk.js +1 -0
- package/build/{runtime~main.e7611418.js → runtime~main.48a46dd2.js} +1 -1
- package/build/{sso-settings-page.e9034e22.chunk.js → sso-settings-page.dfb0b917.chunk.js} +1 -1
- package/build/upload-settings.8d8c672a.chunk.js +101 -0
- package/build/upload-translation-de-json.745613c0.chunk.js +1 -0
- package/build/upload-translation-dk-json.cb25dcf0.chunk.js +1 -0
- package/build/upload-translation-en-json.e78688a0.chunk.js +1 -0
- package/build/upload-translation-es-json.1f344b53.chunk.js +1 -0
- package/build/upload-translation-fr-json.e21c0c7a.chunk.js +1 -0
- package/build/upload-translation-he-json.4ce77b7b.chunk.js +1 -0
- package/build/upload-translation-it-json.5ce11e0b.chunk.js +1 -0
- package/build/upload-translation-ja-json.22afae44.chunk.js +1 -0
- package/build/upload-translation-ko-json.9a2c21cb.chunk.js +1 -0
- package/build/upload-translation-ms-json.0605d6da.chunk.js +1 -0
- package/build/upload-translation-pl-json.e534b676.chunk.js +1 -0
- package/build/upload-translation-pt-BR-json.95686cfb.chunk.js +1 -0
- package/build/upload-translation-ru-json.37bd1546.chunk.js +1 -0
- package/build/upload-translation-sk-json.b03d4904.chunk.js +1 -0
- package/build/upload-translation-th-json.64dd70ce.chunk.js +1 -0
- package/build/upload-translation-uk-json.1328cb3e.chunk.js +1 -0
- package/build/{upload-translation-zh-Hans-json.c9622577.chunk.js → upload-translation-zh-Hans-json.6832ff81.chunk.js} +1 -1
- package/build/upload-translation-zh-json.ee8fba96.chunk.js +1 -0
- package/build/upload.5622b777.chunk.js +7 -0
- package/build/users-advanced-settings-page.4af9e241.chunk.js +101 -0
- package/build/users-email-settings-page.d69c0d87.chunk.js +101 -0
- package/build/users-providers-settings-page.fc1fda6d.chunk.js +101 -0
- package/build/vi-json.bf3424be.chunk.js +1 -0
- package/build/webhook-edit-page.a7ae6e3b.chunk.js +23 -0
- package/build/webhook-list-page.057f396c.chunk.js +133 -0
- package/index.js +2 -8
- package/package.json +10 -9
- package/scripts/build.js +3 -1
- package/server/config/admin-actions.js +14 -0
- package/server/controllers/admin.js +40 -2
- package/server/routes/admin.js +28 -1
- package/server/services/index.js +1 -0
- package/server/services/project-settings.js +173 -0
- package/server/utils/index.d.ts +2 -0
- package/server/validation/project-settings.js +39 -0
- package/utils/create-cache-dir.js +6 -36
- package/utils/get-custom-app-config-file.js +7 -2
- package/utils/get-plugins-path.js +1 -1
- package/admin/src/content-manager/components/SelectWrapper/ClearIndicator.js +0 -18
- package/admin/src/content-manager/components/SelectWrapper/DropdownIndicator.js +0 -24
- package/admin/src/content-manager/components/SelectWrapper/IconBox.js +0 -20
- package/admin/src/content-manager/components/SelectWrapper/IndicatorSeparator.js +0 -3
- package/admin/src/content-manager/components/SelectWrapper/utils/getSelectStyles.js +0 -92
- package/build/1709.ceed0e18.chunk.js +0 -503
- package/build/1856.521a99fd.chunk.js +0 -172
- package/build/20.cf744c35.chunk.js +0 -308
- package/build/2077.51485bfb.chunk.js +0 -194
- package/build/2135.95ee6de1.chunk.js +0 -162
- package/build/2524.688d0355.chunk.js +0 -1
- package/build/2912.79c2b3c8.chunk.js +0 -253
- package/build/4715.77e04177.chunk.js +0 -385
- package/build/4761.3eabdf46.chunk.js +0 -101
- package/build/6229.a5cca9f2.chunk.js +0 -194
- package/build/6281.f10a7e3a.chunk.js +0 -1
- package/build/7009.79fce86d.chunk.js +0 -164
- package/build/7191.3bde3cbf.chunk.js +0 -335
- package/build/7841.f0e7d629.chunk.js +0 -253
- package/build/7863.bc7a8f3a.chunk.js +0 -112
- package/build/9420.cb0b75e8.chunk.js +0 -508
- package/build/Admin-authenticatedApp.4ce8d292.chunk.js +0 -80
- package/build/Admin_marketplace.1e3393c9.chunk.js +0 -11
- package/build/Admin_settingsPage.924a7816.chunk.js +0 -170
- package/build/admin-edit-users.6c2bf718.chunk.js +0 -10
- package/build/admin-users.e03db115.chunk.js +0 -11
- package/build/api-tokens-create-page.787ab302.chunk.js +0 -1
- package/build/api-tokens-edit-page.e4010c0c.chunk.js +0 -1
- package/build/content-manager.6cdcfb6e.chunk.js +0 -1204
- package/build/email-settings-page.f67d13b2.chunk.js +0 -103
- package/build/en-json.3e1a222e.chunk.js +0 -1
- package/build/i18n-settings-page.6b67cb75.chunk.js +0 -101
- package/build/main.45472ea9.js +0 -8404
- package/build/pl-json.94f05d2c.chunk.js +0 -1
- package/build/upload-settings.3db55de0.chunk.js +0 -101
- package/build/upload-translation-de-json.b642da08.chunk.js +0 -1
- package/build/upload-translation-dk-json.fc61df13.chunk.js +0 -1
- package/build/upload-translation-en-json.59269508.chunk.js +0 -1
- package/build/upload-translation-es-json.8ec935ef.chunk.js +0 -1
- package/build/upload-translation-fr-json.eb9b4f84.chunk.js +0 -1
- package/build/upload-translation-he-json.c226f2dc.chunk.js +0 -1
- package/build/upload-translation-it-json.8e58456e.chunk.js +0 -1
- package/build/upload-translation-ja-json.1378a2e7.chunk.js +0 -1
- package/build/upload-translation-ko-json.5e06e112.chunk.js +0 -1
- package/build/upload-translation-ms-json.dc3bf0d7.chunk.js +0 -1
- package/build/upload-translation-pl-json.6071e38c.chunk.js +0 -1
- package/build/upload-translation-pt-BR-json.7e8d9550.chunk.js +0 -1
- package/build/upload-translation-ru-json.da2529f3.chunk.js +0 -1
- package/build/upload-translation-sk-json.bfdf4f09.chunk.js +0 -1
- package/build/upload-translation-th-json.6a48b826.chunk.js +0 -1
- package/build/upload-translation-uk-json.6fb09148.chunk.js +0 -1
- package/build/upload-translation-zh-json.711f804b.chunk.js +0 -1
- package/build/upload.070c189b.chunk.js +0 -105
- package/build/users-advanced-settings-page.a23cda17.chunk.js +0 -101
- package/build/users-email-settings-page.0a096388.chunk.js +0 -1
- package/build/users-providers-settings-page.bfe7755a.chunk.js +0 -1
- package/build/vi-json.3d14e91e.chunk.js +0 -1
- package/build/webhook-edit-page.2fa94db3.chunk.js +0 -23
- package/build/webhook-list-page.b594db49.chunk.js +0 -133
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
useNotification,
|
|
13
13
|
useAppInfos,
|
|
14
14
|
} from '@strapi/helper-plugin';
|
|
15
|
-
import { Grid, GridItem } from '@strapi/design-system/Grid';
|
|
16
15
|
import { Layout, ContentLayout } from '@strapi/design-system/Layout';
|
|
17
16
|
import { Main } from '@strapi/design-system/Main';
|
|
18
17
|
import { Searchbar } from '@strapi/design-system/Searchbar';
|
|
@@ -20,20 +19,22 @@ import { Box } from '@strapi/design-system/Box';
|
|
|
20
19
|
import { useNotifyAT } from '@strapi/design-system/LiveRegions';
|
|
21
20
|
import { Typography } from '@strapi/design-system/Typography';
|
|
22
21
|
import { Flex } from '@strapi/design-system/Flex';
|
|
22
|
+
import { Tabs, Tab, TabGroup, TabPanels, TabPanel } from '@strapi/design-system/Tabs';
|
|
23
23
|
|
|
24
|
-
import
|
|
25
|
-
import { EmptyPluginSearch } from './components/EmptyPluginSearch';
|
|
24
|
+
import EmptyNpmPackageSearch from './components/EmptyNpmPackageSearch';
|
|
26
25
|
import PageHeader from './components/PageHeader';
|
|
27
26
|
import { fetchAppInformation } from './utils/api';
|
|
28
27
|
import useFetchInstalledPlugins from '../../hooks/useFetchInstalledPlugins';
|
|
28
|
+
import useFetchMarketplaceProviders from '../../hooks/useFetchMarketplaceProviders';
|
|
29
29
|
import useFetchMarketplacePlugins from '../../hooks/useFetchMarketplacePlugins';
|
|
30
30
|
import adminPermissions from '../../permissions';
|
|
31
31
|
import offlineCloud from '../../assets/images/icon_offline-cloud.svg';
|
|
32
32
|
import useNavigatorOnLine from '../../hooks/useNavigatorOnLine';
|
|
33
33
|
import MissingPluginBanner from './components/MissingPluginBanner';
|
|
34
|
+
import NpmPackagesGrid from './components/NpmPackagesGrid';
|
|
34
35
|
|
|
35
|
-
const matchSearch = (
|
|
36
|
-
return matchSorter(
|
|
36
|
+
const matchSearch = (npmPackages, search) => {
|
|
37
|
+
return matchSorter(npmPackages, search, {
|
|
37
38
|
keys: [
|
|
38
39
|
{
|
|
39
40
|
threshold: matchSorter.rankings.WORD_STARTS_WITH,
|
|
@@ -51,6 +52,7 @@ const MarketPlacePage = () => {
|
|
|
51
52
|
const trackUsageRef = useRef(trackUsage);
|
|
52
53
|
const toggleNotification = useNotification();
|
|
53
54
|
const [searchQuery, setSearchQuery] = useState('');
|
|
55
|
+
const [npmPackageType, setNpmPackageType] = useState('plugin');
|
|
54
56
|
const { autoReload: isInDevelopmentMode } = useAppInfos();
|
|
55
57
|
const isOnline = useNavigatorOnLine();
|
|
56
58
|
|
|
@@ -78,6 +80,11 @@ const MarketPlacePage = () => {
|
|
|
78
80
|
data: marketplacePluginsResponse,
|
|
79
81
|
} = useFetchMarketplacePlugins(notifyMarketplaceLoad);
|
|
80
82
|
|
|
83
|
+
const {
|
|
84
|
+
status: marketplaceProvidersStatus,
|
|
85
|
+
data: marketplaceProvidersResponse,
|
|
86
|
+
} = useFetchMarketplaceProviders(notifyMarketplaceLoad);
|
|
87
|
+
|
|
81
88
|
const {
|
|
82
89
|
status: installedPluginsStatus,
|
|
83
90
|
data: installedPluginsResponse,
|
|
@@ -96,13 +103,19 @@ const MarketPlacePage = () => {
|
|
|
96
103
|
}
|
|
97
104
|
);
|
|
98
105
|
|
|
99
|
-
const isLoading = [
|
|
100
|
-
|
|
101
|
-
|
|
106
|
+
const isLoading = [
|
|
107
|
+
marketplacePluginsStatus,
|
|
108
|
+
marketplaceProvidersStatus,
|
|
109
|
+
installedPluginsStatus,
|
|
110
|
+
appInfoStatus,
|
|
111
|
+
].includes('loading');
|
|
102
112
|
|
|
103
|
-
const hasFailed = [
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
const hasFailed = [
|
|
114
|
+
marketplacePluginsStatus,
|
|
115
|
+
marketplaceProvidersStatus,
|
|
116
|
+
installedPluginsStatus,
|
|
117
|
+
appInfoStatus,
|
|
118
|
+
].includes('error');
|
|
106
119
|
|
|
107
120
|
useEffect(() => {
|
|
108
121
|
trackUsageRef.current('didGoToMarketplace');
|
|
@@ -179,7 +192,23 @@ const MarketPlacePage = () => {
|
|
|
179
192
|
);
|
|
180
193
|
}
|
|
181
194
|
|
|
182
|
-
|
|
195
|
+
// Search for plugins and providers that match the search query
|
|
196
|
+
const pluginSearchResults = matchSearch(marketplacePluginsResponse.data, searchQuery);
|
|
197
|
+
const providerSearchResults = matchSearch(marketplaceProvidersResponse.data, searchQuery);
|
|
198
|
+
const emptySearchMessage = formatMessage(
|
|
199
|
+
{
|
|
200
|
+
id: 'admin.pages.MarketPlacePage.search.empty',
|
|
201
|
+
defaultMessage: 'No result for "{target}"',
|
|
202
|
+
},
|
|
203
|
+
{ target: searchQuery }
|
|
204
|
+
);
|
|
205
|
+
|
|
206
|
+
const handleTabChange = selected => {
|
|
207
|
+
const packageType = selected === 0 ? 'plugin' : 'provider';
|
|
208
|
+
setNpmPackageType(packageType);
|
|
209
|
+
};
|
|
210
|
+
|
|
211
|
+
// Check if plugins are installed already
|
|
183
212
|
const installedPluginNames = installedPluginsResponse.plugins.map(plugin => plugin.packageName);
|
|
184
213
|
|
|
185
214
|
return (
|
|
@@ -191,7 +220,7 @@ const MarketPlacePage = () => {
|
|
|
191
220
|
defaultMessage: 'Marketplace - Plugins',
|
|
192
221
|
})}
|
|
193
222
|
/>
|
|
194
|
-
<PageHeader isOnline={isOnline} />
|
|
223
|
+
<PageHeader isOnline={isOnline} npmPackageType={npmPackageType} />
|
|
195
224
|
<ContentLayout>
|
|
196
225
|
<Box width="25%" paddingBottom={4}>
|
|
197
226
|
<Searchbar
|
|
@@ -201,43 +230,76 @@ const MarketPlacePage = () => {
|
|
|
201
230
|
onChange={e => setSearchQuery(e.target.value)}
|
|
202
231
|
clearLabel={formatMessage({
|
|
203
232
|
id: 'admin.pages.MarketPlacePage.search.clear',
|
|
204
|
-
defaultMessage: 'Clear the
|
|
233
|
+
defaultMessage: 'Clear the search',
|
|
205
234
|
})}
|
|
206
235
|
placeholder={formatMessage({
|
|
207
236
|
id: 'admin.pages.MarketPlacePage.search.placeholder',
|
|
208
|
-
defaultMessage: 'Search
|
|
237
|
+
defaultMessage: 'Search',
|
|
209
238
|
})}
|
|
210
239
|
>
|
|
211
240
|
{formatMessage({
|
|
212
241
|
id: 'admin.pages.MarketPlacePage.search.placeholder',
|
|
213
|
-
defaultMessage: 'Search
|
|
242
|
+
defaultMessage: 'Search',
|
|
214
243
|
})}
|
|
215
244
|
</Searchbar>
|
|
216
245
|
</Box>
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
246
|
+
<TabGroup
|
|
247
|
+
label={formatMessage({
|
|
248
|
+
id: 'admin.pages.MarketPlacePage.tab-group.label',
|
|
249
|
+
defaultMessage: 'Plugins and Providers for Strapi',
|
|
250
|
+
})}
|
|
251
|
+
id="tabs"
|
|
252
|
+
variant="simple"
|
|
253
|
+
onTabChange={handleTabChange}
|
|
254
|
+
>
|
|
255
|
+
<Box paddingBottom={4}>
|
|
256
|
+
<Tabs>
|
|
257
|
+
<Tab>
|
|
258
|
+
{formatMessage({
|
|
259
|
+
id: 'admin.pages.MarketPlacePage.plugins',
|
|
260
|
+
defaultMessage: 'Plugins',
|
|
261
|
+
})}{' '}
|
|
262
|
+
({pluginSearchResults.length})
|
|
263
|
+
</Tab>
|
|
264
|
+
<Tab>
|
|
265
|
+
{formatMessage({
|
|
266
|
+
id: 'admin.pages.MarketPlacePage.providers',
|
|
267
|
+
defaultMessage: 'Providers',
|
|
268
|
+
})}{' '}
|
|
269
|
+
({providerSearchResults.length})
|
|
270
|
+
</Tab>
|
|
271
|
+
</Tabs>
|
|
272
|
+
</Box>
|
|
273
|
+
<TabPanels>
|
|
274
|
+
{/* Plugins panel */}
|
|
275
|
+
<TabPanel>
|
|
276
|
+
{searchQuery.length > 0 && !pluginSearchResults.length ? (
|
|
277
|
+
<EmptyNpmPackageSearch content={emptySearchMessage} />
|
|
278
|
+
) : (
|
|
279
|
+
<NpmPackagesGrid
|
|
280
|
+
npmPackages={pluginSearchResults}
|
|
281
|
+
installedPackageNames={installedPluginNames}
|
|
282
|
+
useYarn={appInfoResponse.data.useYarn}
|
|
283
|
+
isInDevelopmentMode={isInDevelopmentMode}
|
|
284
|
+
npmPackageType="plugin"
|
|
285
|
+
/>
|
|
286
|
+
)}
|
|
287
|
+
</TabPanel>
|
|
288
|
+
{/* Providers panel */}
|
|
289
|
+
<TabPanel>
|
|
290
|
+
{searchQuery.length > 0 && !providerSearchResults.length ? (
|
|
291
|
+
<EmptyNpmPackageSearch content={emptySearchMessage} />
|
|
292
|
+
) : (
|
|
293
|
+
<NpmPackagesGrid
|
|
294
|
+
npmPackages={providerSearchResults}
|
|
234
295
|
useYarn={appInfoResponse.data.useYarn}
|
|
235
296
|
isInDevelopmentMode={isInDevelopmentMode}
|
|
297
|
+
npmPackageType="provider"
|
|
236
298
|
/>
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
</
|
|
240
|
-
|
|
299
|
+
)}
|
|
300
|
+
</TabPanel>
|
|
301
|
+
</TabPanels>
|
|
302
|
+
</TabGroup>
|
|
241
303
|
<Box paddingTop={7}>
|
|
242
304
|
<MissingPluginBanner />
|
|
243
305
|
</Box>
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import React, { useReducer, forwardRef, useImperativeHandle } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { useIntl } from 'react-intl';
|
|
4
|
+
import { useTracking } from '@strapi/helper-plugin';
|
|
5
|
+
import { Grid, GridItem } from '@strapi/design-system/Grid';
|
|
6
|
+
import { Box } from '@strapi/design-system/Box';
|
|
7
|
+
import { Typography } from '@strapi/design-system/Typography';
|
|
8
|
+
import LogoInput from '../LogoInput';
|
|
9
|
+
import { useConfigurations } from '../../../../../../hooks';
|
|
10
|
+
import reducer, { initialState } from './reducer';
|
|
11
|
+
import init from './init';
|
|
12
|
+
|
|
13
|
+
const Form = forwardRef(({ projectSettingsStored }, ref) => {
|
|
14
|
+
const { formatMessage } = useIntl();
|
|
15
|
+
const { trackUsage } = useTracking();
|
|
16
|
+
const {
|
|
17
|
+
logos: { menu },
|
|
18
|
+
} = useConfigurations();
|
|
19
|
+
const [{ menuLogo }, dispatch] = useReducer(reducer, initialState, () =>
|
|
20
|
+
init(initialState, projectSettingsStored)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
const handleChangeMenuLogo = asset => {
|
|
24
|
+
dispatch({
|
|
25
|
+
type: 'SET_CUSTOM_MENU_LOGO',
|
|
26
|
+
value: asset,
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const handleResetMenuLogo = () => {
|
|
31
|
+
trackUsage('didClickResetLogo');
|
|
32
|
+
|
|
33
|
+
dispatch({
|
|
34
|
+
type: 'RESET_CUSTOM_MENU_LOGO',
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
useImperativeHandle(ref, () => ({
|
|
39
|
+
getValues: () => ({ menuLogo: menuLogo.submit }),
|
|
40
|
+
}));
|
|
41
|
+
|
|
42
|
+
return (
|
|
43
|
+
<Box
|
|
44
|
+
hasRadius
|
|
45
|
+
background="neutral0"
|
|
46
|
+
shadow="tableShadow"
|
|
47
|
+
paddingTop={6}
|
|
48
|
+
paddingBottom={6}
|
|
49
|
+
paddingRight={7}
|
|
50
|
+
paddingLeft={7}
|
|
51
|
+
>
|
|
52
|
+
<Typography variant="delta" as="h3">
|
|
53
|
+
{formatMessage({
|
|
54
|
+
id: 'Settings.application.customization',
|
|
55
|
+
defaultMessage: 'Customization',
|
|
56
|
+
})}
|
|
57
|
+
</Typography>
|
|
58
|
+
<Grid paddingTop={4}>
|
|
59
|
+
<GridItem col={6} s={12}>
|
|
60
|
+
<LogoInput
|
|
61
|
+
onChangeLogo={handleChangeMenuLogo}
|
|
62
|
+
customLogo={menuLogo.display}
|
|
63
|
+
defaultLogo={menu.default}
|
|
64
|
+
onResetMenuLogo={handleResetMenuLogo}
|
|
65
|
+
/>
|
|
66
|
+
</GridItem>
|
|
67
|
+
</Grid>
|
|
68
|
+
</Box>
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
Form.defaultProps = {
|
|
73
|
+
projectSettingsStored: null,
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
Form.propTypes = {
|
|
77
|
+
projectSettingsStored: PropTypes.shape({
|
|
78
|
+
menuLogo: PropTypes.shape({
|
|
79
|
+
url: PropTypes.string,
|
|
80
|
+
name: PropTypes.string,
|
|
81
|
+
}),
|
|
82
|
+
}),
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export default Form;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import merge from 'lodash/merge';
|
|
2
|
+
|
|
3
|
+
const init = (initialState, projectSettingsStored) => {
|
|
4
|
+
const copyInitialState = merge(initialState, {
|
|
5
|
+
menuLogo: {
|
|
6
|
+
display: projectSettingsStored.menuLogo,
|
|
7
|
+
},
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
return copyInitialState;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
export default init;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
/*
|
|
3
|
+
*
|
|
4
|
+
* ApplicationInfosPage Form reducer
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import produce from 'immer';
|
|
9
|
+
|
|
10
|
+
const initialState = {
|
|
11
|
+
menuLogo: {
|
|
12
|
+
display: null,
|
|
13
|
+
submit: {
|
|
14
|
+
rawFile: null,
|
|
15
|
+
isReset: false,
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
const reducer = (state = initialState, action) =>
|
|
21
|
+
produce(state, draftState => {
|
|
22
|
+
switch (action.type) {
|
|
23
|
+
case 'SET_CUSTOM_MENU_LOGO': {
|
|
24
|
+
draftState.menuLogo.display = action.value;
|
|
25
|
+
draftState.menuLogo.submit.rawFile = action.value.rawFile;
|
|
26
|
+
break;
|
|
27
|
+
}
|
|
28
|
+
case 'RESET_CUSTOM_MENU_LOGO': {
|
|
29
|
+
draftState.menuLogo.display = null;
|
|
30
|
+
draftState.menuLogo.submit = {
|
|
31
|
+
rawFile: null,
|
|
32
|
+
isReset: true,
|
|
33
|
+
};
|
|
34
|
+
break;
|
|
35
|
+
}
|
|
36
|
+
default: {
|
|
37
|
+
return draftState;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
export default reducer;
|
|
43
|
+
export { initialState };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import React, { useReducer } from 'react';
|
|
2
|
+
import { useIntl } from 'react-intl';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import { CarouselInput, CarouselSlide, CarouselActions } from '@strapi/design-system/CarouselInput';
|
|
5
|
+
import { IconButton } from '@strapi/design-system/IconButton';
|
|
6
|
+
import { Box } from '@strapi/design-system/Box';
|
|
7
|
+
import Plus from '@strapi/icons/Plus';
|
|
8
|
+
import Refresh from '@strapi/icons/Refresh';
|
|
9
|
+
import reducer, { initialState } from './reducer';
|
|
10
|
+
import LogoModalStepper from '../LogoModalStepper';
|
|
11
|
+
import { SIZE, DIMENSION } from '../../utils/constants';
|
|
12
|
+
import stepper from './stepper';
|
|
13
|
+
|
|
14
|
+
const LogoInput = ({ customLogo, defaultLogo, onChangeLogo, onResetMenuLogo }) => {
|
|
15
|
+
const [{ currentStep }, dispatch] = useReducer(reducer, initialState);
|
|
16
|
+
const { Component, next, prev, modalTitle } = stepper[currentStep] || {};
|
|
17
|
+
const { formatMessage } = useIntl();
|
|
18
|
+
|
|
19
|
+
const goTo = to => {
|
|
20
|
+
dispatch({
|
|
21
|
+
type: 'GO_TO',
|
|
22
|
+
to,
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<>
|
|
28
|
+
<CarouselInput
|
|
29
|
+
label={formatMessage({
|
|
30
|
+
id: 'Settings.application.customization.carousel.title',
|
|
31
|
+
defaultMessage: 'Logo',
|
|
32
|
+
})}
|
|
33
|
+
selectedSlide={0}
|
|
34
|
+
hint={formatMessage(
|
|
35
|
+
{
|
|
36
|
+
id: 'Settings.application.customization.carousel-hint',
|
|
37
|
+
defaultMessage:
|
|
38
|
+
'Change the admin panel logo (Max dimension: {dimension}x{dimension}, Max file size: {size}KB)',
|
|
39
|
+
},
|
|
40
|
+
{ size: SIZE, dimension: DIMENSION }
|
|
41
|
+
)}
|
|
42
|
+
// Carousel is used here for a single media,
|
|
43
|
+
// we don't need previous and next labels but these props are required
|
|
44
|
+
previousLabel=""
|
|
45
|
+
nextLabel=""
|
|
46
|
+
onNext={() => {}}
|
|
47
|
+
onPrevious={() => {}}
|
|
48
|
+
secondaryLabel={customLogo?.name || 'logo.png'}
|
|
49
|
+
actions={
|
|
50
|
+
<CarouselActions>
|
|
51
|
+
<IconButton
|
|
52
|
+
onClick={() => goTo(customLogo ? 'pending' : 'upload')}
|
|
53
|
+
label={formatMessage({
|
|
54
|
+
id: 'Settings.application.customization.carousel.change-action',
|
|
55
|
+
defaultMessage: 'Change logo',
|
|
56
|
+
})}
|
|
57
|
+
icon={<Plus />}
|
|
58
|
+
/>
|
|
59
|
+
{customLogo && (
|
|
60
|
+
<IconButton
|
|
61
|
+
onClick={onResetMenuLogo}
|
|
62
|
+
label={formatMessage({
|
|
63
|
+
id: 'Settings.application.customization.carousel.reset-action',
|
|
64
|
+
defaultMessage: 'Reset logo',
|
|
65
|
+
})}
|
|
66
|
+
icon={<Refresh />}
|
|
67
|
+
/>
|
|
68
|
+
)}
|
|
69
|
+
</CarouselActions>
|
|
70
|
+
}
|
|
71
|
+
>
|
|
72
|
+
<CarouselSlide
|
|
73
|
+
label={formatMessage({
|
|
74
|
+
id: 'Settings.application.customization.carousel-slide.label',
|
|
75
|
+
defaultMessage: 'Logo slide',
|
|
76
|
+
})}
|
|
77
|
+
>
|
|
78
|
+
<Box
|
|
79
|
+
maxHeight="40%"
|
|
80
|
+
maxWidth="40%"
|
|
81
|
+
as="img"
|
|
82
|
+
src={customLogo?.url || defaultLogo}
|
|
83
|
+
alt={formatMessage({
|
|
84
|
+
id: 'Settings.application.customization.carousel.title',
|
|
85
|
+
defaultMessage: 'Logo',
|
|
86
|
+
})}
|
|
87
|
+
/>
|
|
88
|
+
</CarouselSlide>
|
|
89
|
+
</CarouselInput>
|
|
90
|
+
<LogoModalStepper
|
|
91
|
+
Component={Component}
|
|
92
|
+
currentStep={currentStep}
|
|
93
|
+
onChangeLogo={onChangeLogo}
|
|
94
|
+
customLogo={customLogo}
|
|
95
|
+
goTo={goTo}
|
|
96
|
+
next={next}
|
|
97
|
+
prev={prev}
|
|
98
|
+
modalTitle={modalTitle}
|
|
99
|
+
/>
|
|
100
|
+
</>
|
|
101
|
+
);
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
LogoInput.defaultProps = {
|
|
105
|
+
customLogo: null,
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
LogoInput.propTypes = {
|
|
109
|
+
customLogo: PropTypes.shape({
|
|
110
|
+
url: PropTypes.string,
|
|
111
|
+
name: PropTypes.string,
|
|
112
|
+
}),
|
|
113
|
+
defaultLogo: PropTypes.string.isRequired,
|
|
114
|
+
onChangeLogo: PropTypes.func.isRequired,
|
|
115
|
+
onResetMenuLogo: PropTypes.func.isRequired,
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
export default LogoInput;
|
package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/reducer.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* eslint-disable consistent-return */
|
|
2
|
+
/*
|
|
3
|
+
*
|
|
4
|
+
* LogoInput reducer
|
|
5
|
+
*
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import produce from 'immer';
|
|
9
|
+
|
|
10
|
+
const initialState = {
|
|
11
|
+
currentStep: undefined,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
const reducer = (state = initialState, action) =>
|
|
15
|
+
produce(state, draftState => {
|
|
16
|
+
switch (action.type) {
|
|
17
|
+
case 'GO_TO': {
|
|
18
|
+
draftState.currentStep = action.to;
|
|
19
|
+
break;
|
|
20
|
+
}
|
|
21
|
+
default: {
|
|
22
|
+
return draftState;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
export default reducer;
|
|
28
|
+
export { initialState };
|
package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/stepper.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import AddLogoDialog from '../LogoModalStepper/AddLogoDialog';
|
|
2
|
+
import PendingLogoDialog from '../LogoModalStepper/PendingLogoDialog';
|
|
3
|
+
|
|
4
|
+
const stepper = {
|
|
5
|
+
upload: {
|
|
6
|
+
Component: AddLogoDialog,
|
|
7
|
+
modalTitle: {
|
|
8
|
+
id: 'Settings.application.customization.modal.upload',
|
|
9
|
+
defaultMessage: 'Upload logo',
|
|
10
|
+
},
|
|
11
|
+
next: 'pending',
|
|
12
|
+
prev: null,
|
|
13
|
+
},
|
|
14
|
+
pending: {
|
|
15
|
+
Component: PendingLogoDialog,
|
|
16
|
+
modalTitle: {
|
|
17
|
+
id: 'Settings.application.customization.modal.pending',
|
|
18
|
+
defaultMessage: 'Pending logo',
|
|
19
|
+
},
|
|
20
|
+
next: null,
|
|
21
|
+
prev: 'upload',
|
|
22
|
+
},
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export default stepper;
|
|
@@ -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;
|