@strapi/admin 4.1.9 → 4.1.10-beta.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 (47) hide show
  1. package/admin/src/components/ConfigurationsProvider/index.js +51 -0
  2. package/admin/src/components/ConfigurationsProvider/reducer.js +28 -0
  3. package/admin/src/components/LeftMenu/index.js +4 -2
  4. package/admin/src/components/Providers/index.js +8 -4
  5. package/admin/src/components/UnauthenticatedLogo/index.js +4 -2
  6. package/admin/src/pages/App/index.js +7 -2
  7. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/index.js +85 -0
  8. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/init.js +13 -0
  9. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/Form/reducer.js +43 -0
  10. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/index.js +116 -0
  11. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/reducer.js +28 -0
  12. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoInput/stepper.js +25 -0
  13. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/AddLogoDialog.js +67 -0
  14. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromComputerForm.js +176 -0
  15. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/FromUrlForm.js +82 -0
  16. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/ImageCardAsset.js +51 -0
  17. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/PendingLogoDialog.js +97 -0
  18. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/index.js +85 -0
  19. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/components/LogoModalStepper/reducer.js +28 -0
  20. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/index.js +149 -87
  21. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/api.js +16 -0
  22. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/constants.js +3 -0
  23. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/getFormData.js +17 -0
  24. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/parseFileMetadatas.js +76 -0
  25. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/prefixAllUrls.js +17 -0
  26. package/admin/src/pages/SettingsPage/pages/ApplicationInfosPage/utils/urlToFile.js +21 -0
  27. package/admin/src/translations/en.json +25 -0
  28. package/build/7197.959bbe97.chunk.js +113 -0
  29. package/build/{9298.5b5c6ea1.chunk.js → 9298.f97fcef0.chunk.js} +2 -2
  30. package/build/Admin-authenticatedApp.d8767873.chunk.js +80 -0
  31. package/build/Admin_settingsPage.0d94a598.chunk.js +180 -0
  32. package/build/en-json.ca572384.chunk.js +1 -0
  33. package/build/index.html +1 -1
  34. package/build/{main.25315363.js → main.06f66609.js} +1 -1
  35. package/build/{runtime~main.1ecd9f7d.js → runtime~main.dc1c7ef6.js} +1 -1
  36. package/package.json +5 -5
  37. package/server/config/admin-actions.js +14 -0
  38. package/server/controllers/admin.js +33 -1
  39. package/server/routes/admin.js +28 -0
  40. package/server/services/index.js +1 -0
  41. package/server/services/project-settings.js +173 -0
  42. package/server/utils/index.d.ts +2 -0
  43. package/server/validation/project-settings.js +39 -0
  44. package/build/6706.b0b5124d.chunk.js +0 -113
  45. package/build/Admin-authenticatedApp.72cf6aa3.chunk.js +0 -80
  46. package/build/Admin_settingsPage.f83a7c21.chunk.js +0 -172
  47. package/build/en-json.3e1a222e.chunk.js +0 -1
@@ -0,0 +1,51 @@
1
+ import React, { useReducer, useRef } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { ConfigurationsContext } from '../../contexts';
4
+ import reducer, { initialState } from './reducer';
5
+
6
+ const ConfigurationsProvider = ({
7
+ children,
8
+ authLogo,
9
+ menuLogo: defaultMenuLogo,
10
+ showReleaseNotification,
11
+ showTutorials,
12
+ }) => {
13
+ const [{ menuLogo }, dispatch] = useReducer(reducer, initialState);
14
+
15
+ const updateProjectSettings = ({ menuLogo }) => {
16
+ return dispatch({
17
+ type: 'UPDATE_PROJECT_SETTINGS',
18
+ values: {
19
+ menuLogo: menuLogo || defaultMenuLogo,
20
+ },
21
+ });
22
+ };
23
+
24
+ const updateProjectSettingsRef = useRef(updateProjectSettings);
25
+
26
+ return (
27
+ <ConfigurationsContext.Provider
28
+ value={{
29
+ logos: {
30
+ menu: { custom: menuLogo, default: defaultMenuLogo },
31
+ auth: { custom: null, default: authLogo },
32
+ },
33
+ updateProjectSettings: updateProjectSettingsRef.current,
34
+ showReleaseNotification,
35
+ showTutorials,
36
+ }}
37
+ >
38
+ {children}
39
+ </ConfigurationsContext.Provider>
40
+ );
41
+ };
42
+
43
+ ConfigurationsProvider.propTypes = {
44
+ authLogo: PropTypes.string.isRequired,
45
+ children: PropTypes.element.isRequired,
46
+ menuLogo: PropTypes.string.isRequired,
47
+ showReleaseNotification: PropTypes.bool.isRequired,
48
+ showTutorials: PropTypes.bool.isRequired,
49
+ };
50
+
51
+ export default ConfigurationsProvider;
@@ -0,0 +1,28 @@
1
+ /* eslint-disable consistent-return */
2
+ /*
3
+ *
4
+ * ConfigurationsProvider reducer
5
+ *
6
+ */
7
+
8
+ import produce from 'immer';
9
+
10
+ const initialState = {
11
+ menuLogo: null,
12
+ };
13
+
14
+ const reducer = (state = initialState, action) =>
15
+ produce(state, draftState => {
16
+ switch (action.type) {
17
+ case 'UPDATE_PROJECT_SETTINGS': {
18
+ Object.assign(draftState, action.values);
19
+ break;
20
+ }
21
+ default: {
22
+ return draftState;
23
+ }
24
+ }
25
+ });
26
+
27
+ export default reducer;
28
+ export { initialState };
@@ -53,7 +53,9 @@ const LinkUser = styled(Link)`
53
53
  const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
54
54
  const buttonRef = useRef();
55
55
  const [userLinksVisible, setUserLinksVisible] = useState(false);
56
- const { menuLogo } = useConfigurations();
56
+ const {
57
+ logos: { menu },
58
+ } = useConfigurations();
57
59
  const [condensed, setCondensed] = usePersistentState('navbar-condensed', false);
58
60
  const { userDisplayName } = useAppInfos();
59
61
  const { formatMessage } = useIntl();
@@ -93,7 +95,7 @@ const LeftMenu = ({ generalSectionLinks, pluginsSectionLinks }) => {
93
95
  defaultMessage: 'Workplace',
94
96
  })}
95
97
  title={menuTitle}
96
- icon={<img src={menuLogo} alt={menuTitle} />}
98
+ icon={<img src={menu.custom || menu.default} alt={menuTitle} />}
97
99
  />
98
100
 
99
101
  <Divider />
@@ -3,7 +3,8 @@ import PropTypes from 'prop-types';
3
3
  import { QueryClientProvider, QueryClient } from 'react-query';
4
4
  import { LibraryProvider, StrapiAppProvider } from '@strapi/helper-plugin';
5
5
  import { Provider } from 'react-redux';
6
- import { AdminContext, ConfigurationsContext } from '../../contexts';
6
+ import { AdminContext } from '../../contexts';
7
+ import ConfigurationsProvider from '../ConfigurationsProvider';
7
8
  import LanguageProvider from '../LanguageProvider';
8
9
  import GuidedTour from '../GuidedTour';
9
10
  import AutoReloadOverlayBlockerProvider from '../AutoReloadOverlayBlockerProvider';
@@ -47,8 +48,11 @@ const Providers = ({
47
48
  <QueryClientProvider client={queryClient}>
48
49
  <Provider store={store}>
49
50
  <AdminContext.Provider value={{ getAdminInjectedComponents }}>
50
- <ConfigurationsContext.Provider
51
- value={{ authLogo, menuLogo, showReleaseNotification, showTutorials }}
51
+ <ConfigurationsProvider
52
+ authLogo={authLogo}
53
+ menuLogo={menuLogo}
54
+ showReleaseNotification={showReleaseNotification}
55
+ showTutorials={showTutorials}
52
56
  >
53
57
  <StrapiAppProvider
54
58
  getPlugin={getPlugin}
@@ -71,7 +75,7 @@ const Providers = ({
71
75
  </LanguageProvider>
72
76
  </LibraryProvider>
73
77
  </StrapiAppProvider>
74
- </ConfigurationsContext.Provider>
78
+ </ConfigurationsProvider>
75
79
  </AdminContext.Provider>
76
80
  </Provider>
77
81
  </QueryClientProvider>
@@ -7,9 +7,11 @@ const Img = styled.img`
7
7
  `;
8
8
 
9
9
  const Logo = () => {
10
- const { authLogo } = useConfigurations();
10
+ const {
11
+ logos: { auth },
12
+ } = useConfigurations();
11
13
 
12
- return <Img src={authLogo} aria-hidden alt="" />;
14
+ return <Img src={auth.default} aria-hidden alt="" />;
13
15
  };
14
16
 
15
17
  export default Logo;
@@ -12,6 +12,7 @@ import {
12
12
  request,
13
13
  useNotification,
14
14
  TrackingContext,
15
+ prefixFileUrlWithBackendUrl,
15
16
  } from '@strapi/helper-plugin';
16
17
  import { SkipToContent } from '@strapi/design-system/Main';
17
18
  import { useIntl } from 'react-intl';
@@ -22,6 +23,7 @@ import NotFoundPage from '../NotFoundPage';
22
23
  import UseCasePage from '../UseCasePage';
23
24
  import { getUID } from './utils';
24
25
  import routes from './utils/routes';
26
+ import { useConfigurations } from '../../hooks';
25
27
 
26
28
  const AuthenticatedApp = lazy(() =>
27
29
  import(/* webpackChunkName: "Admin-authenticatedApp" */ '../../components/AuthenticatedApp')
@@ -29,6 +31,7 @@ const AuthenticatedApp = lazy(() =>
29
31
 
30
32
  function App() {
31
33
  const toggleNotification = useNotification();
34
+ const { updateProjectSettings } = useConfigurations();
32
35
  const { formatMessage } = useIntl();
33
36
  const [{ isLoading, hasAdmin, uuid }, setState] = useState({ isLoading: true, hasAdmin: false });
34
37
 
@@ -66,9 +69,11 @@ function App() {
66
69
  const getData = async () => {
67
70
  try {
68
71
  const {
69
- data: { hasAdmin, uuid },
72
+ data: { hasAdmin, uuid, menuLogo },
70
73
  } = await request('/admin/init', { method: 'GET' });
71
74
 
75
+ updateProjectSettings({ menuLogo: prefixFileUrlWithBackendUrl(menuLogo) });
76
+
72
77
  if (uuid) {
73
78
  try {
74
79
  const deviceId = await getUID();
@@ -99,7 +104,7 @@ function App() {
99
104
  };
100
105
 
101
106
  getData();
102
- }, [toggleNotification]);
107
+ }, [toggleNotification, updateProjectSettings]);
103
108
 
104
109
  const setHasAdmin = hasAdmin => setState(prev => ({ ...prev, hasAdmin }));
105
110
 
@@ -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,116 @@
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
+ previousLabel=""
43
+ nextLabel=""
44
+ onNext={() => {}}
45
+ onPrevious={() => {}}
46
+ secondaryLabel={customLogo?.name || 'logo.png'}
47
+ actions={
48
+ <CarouselActions>
49
+ <IconButton
50
+ onClick={() => goTo(customLogo ? 'pending' : 'upload')}
51
+ label={formatMessage({
52
+ id: 'Settings.application.customization.carousel.change-action',
53
+ defaultMessage: 'Change logo',
54
+ })}
55
+ icon={<Plus />}
56
+ />
57
+ {customLogo && (
58
+ <IconButton
59
+ onClick={onResetMenuLogo}
60
+ label={formatMessage({
61
+ id: 'Settings.application.customization.carousel.reset-action',
62
+ defaultMessage: 'Reset logo',
63
+ })}
64
+ icon={<Refresh />}
65
+ />
66
+ )}
67
+ </CarouselActions>
68
+ }
69
+ >
70
+ <CarouselSlide
71
+ label={formatMessage({
72
+ id: 'Settings.application.customization.carousel-slide.label',
73
+ defaultMessage: 'Logo slide',
74
+ })}
75
+ >
76
+ <Box
77
+ maxHeight="40%"
78
+ maxWidth="40%"
79
+ as="img"
80
+ src={customLogo?.url || defaultLogo}
81
+ alt={formatMessage({
82
+ id: 'Settings.application.customization.carousel.title',
83
+ defaultMessage: 'Logo',
84
+ })}
85
+ />
86
+ </CarouselSlide>
87
+ </CarouselInput>
88
+ <LogoModalStepper
89
+ Component={Component}
90
+ currentStep={currentStep}
91
+ onChangeLogo={onChangeLogo}
92
+ customLogo={customLogo}
93
+ goTo={goTo}
94
+ next={next}
95
+ prev={prev}
96
+ modalTitle={modalTitle}
97
+ />
98
+ </>
99
+ );
100
+ };
101
+
102
+ LogoInput.defaultProps = {
103
+ customLogo: null,
104
+ };
105
+
106
+ LogoInput.propTypes = {
107
+ customLogo: PropTypes.shape({
108
+ url: PropTypes.string,
109
+ name: PropTypes.string,
110
+ }),
111
+ defaultLogo: PropTypes.string.isRequired,
112
+ onChangeLogo: PropTypes.func.isRequired,
113
+ onResetMenuLogo: PropTypes.func.isRequired,
114
+ };
115
+
116
+ export default LogoInput;
@@ -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 };
@@ -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;