mirror of
https://github.com/strapi/strapi.git
synced 2025-09-15 19:39:06 +00:00
go to pending modal on successfully drop file
This commit is contained in:
parent
a6fecbb914
commit
d5c74ba1ae
@ -58,7 +58,7 @@ const LogoInput = ({ customLogo, defaultLogo }) => {
|
|||||||
</CarouselInput>
|
</CarouselInput>
|
||||||
<LogoModalStepper
|
<LogoModalStepper
|
||||||
onClose={() => setIsDialogOpen(false)}
|
onClose={() => setIsDialogOpen(false)}
|
||||||
initialStep={customLogo ? 'pending' : 'add'}
|
initialStep={customLogo ? 'pending' : 'upload'}
|
||||||
isOpen={isDialogOpen}
|
isOpen={isDialogOpen}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
|
@ -1,23 +1,37 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { Tabs, Tab, TabGroup, TabPanels, TabPanel } from '@strapi/design-system/Tabs';
|
import { Tabs, Tab, TabGroup, TabPanels, TabPanel } from '@strapi/design-system/Tabs';
|
||||||
import { Box } from '@strapi/design-system/Box';
|
import { Box } from '@strapi/design-system/Box';
|
||||||
import { Divider } from '@strapi/design-system/Divider';
|
import { Divider } from '@strapi/design-system/Divider';
|
||||||
import FromComputerForm from './FromComputerForm';
|
import FromComputerForm from './FromComputerForm';
|
||||||
|
|
||||||
const AddLogoDialog = () => {
|
const AddLogoDialog = ({ setLocalImage, goTo, next }) => {
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<TabGroup label="How do you want to upload your assets?" variant="simple">
|
<TabGroup label="How do you want to upload your assets?" variant="simple">
|
||||||
<Box paddingLeft={2} paddingRight={2}>
|
<Box paddingLeft={2} paddingRight={2}>
|
||||||
<Tabs>
|
<Tabs>
|
||||||
<Tab>From computer</Tab>
|
<Tab>
|
||||||
<Tab>From URL</Tab>
|
{formatMessage({
|
||||||
|
id: 'Settings.application.customization.modal.upload.from-computer',
|
||||||
|
defaultMessage: 'From computer',
|
||||||
|
})}
|
||||||
|
</Tab>
|
||||||
|
<Tab>
|
||||||
|
{formatMessage({
|
||||||
|
id: 'Settings.application.customization.modal.upload.from-url',
|
||||||
|
defaultMessage: 'From URL',
|
||||||
|
})}
|
||||||
|
</Tab>
|
||||||
</Tabs>
|
</Tabs>
|
||||||
|
|
||||||
<Divider />
|
<Divider />
|
||||||
</Box>
|
</Box>
|
||||||
<TabPanels>
|
<TabPanels>
|
||||||
<TabPanel>
|
<TabPanel>
|
||||||
<FromComputerForm />
|
<FromComputerForm setLocalImage={setLocalImage} goTo={goTo} next={next} />
|
||||||
</TabPanel>
|
</TabPanel>
|
||||||
<TabPanel>TO DO</TabPanel>
|
<TabPanel>TO DO</TabPanel>
|
||||||
</TabPanels>
|
</TabPanels>
|
||||||
@ -25,4 +39,14 @@ const AddLogoDialog = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AddLogoDialog.defaultProps = {
|
||||||
|
next: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
AddLogoDialog.propTypes = {
|
||||||
|
setLocalImage: PropTypes.func.isRequired,
|
||||||
|
goTo: PropTypes.func.isRequired,
|
||||||
|
next: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
export default AddLogoDialog;
|
export default AddLogoDialog;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import React, { useState, useRef } from 'react';
|
import React, { useState, useRef } from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import { useIntl } from 'react-intl';
|
import { useIntl } from 'react-intl';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
import { Box } from '@strapi/design-system/Box';
|
import { Box } from '@strapi/design-system/Box';
|
||||||
@ -14,7 +15,7 @@ const FileInput = styled(Box)`
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const FromComputerForm = () => {
|
const FromComputerForm = ({ setLocalImage, goTo, next }) => {
|
||||||
const { formatMessage } = useIntl();
|
const { formatMessage } = useIntl();
|
||||||
const [dragOver, setDragOver] = useState(false);
|
const [dragOver, setDragOver] = useState(false);
|
||||||
const [fileError, setFileError] = useState(false);
|
const [fileError, setFileError] = useState(false);
|
||||||
@ -37,8 +38,9 @@ const FromComputerForm = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const fileToAsset = await parseFileMetadatas(file);
|
const asset = await parseFileMetadatas(file);
|
||||||
console.log(fileToAsset);
|
setLocalImage(asset);
|
||||||
|
goTo(next);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err.displayMessage) {
|
if (err.displayMessage) {
|
||||||
setFileError(formatMessage(err.displayMessage));
|
setFileError(formatMessage(err.displayMessage));
|
||||||
@ -77,47 +79,52 @@ const FromComputerForm = () => {
|
|||||||
onDragEnter={handleDragEnter}
|
onDragEnter={handleDragEnter}
|
||||||
onDragLeave={handleDragLeave}
|
onDragLeave={handleDragLeave}
|
||||||
>
|
>
|
||||||
<Flex justifyContent="center">
|
<Flex justifyContent="center" direction="column">
|
||||||
<Flex direction="column">
|
<Icon
|
||||||
<Icon
|
color="primary600"
|
||||||
color="primary600"
|
width={`${60 / 16}rem`}
|
||||||
width={`${60 / 16}rem`}
|
height={`${60 / 16}rem`}
|
||||||
height={`${60 / 16}rem`}
|
as={PicturePlus}
|
||||||
as={PicturePlus}
|
aria-hidden
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Box paddingTop={3} paddingBottom={5}>
|
<Box paddingTop={3} paddingBottom={5}>
|
||||||
<Typography variant="delta">Drag & Drop here or</Typography>
|
<Typography variant="delta" as="span">
|
||||||
</Box>
|
Drag and Drop here or
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
|
||||||
<FileInput
|
<FileInput
|
||||||
accept={ACCEPTED_FORMAT.map(format => `.${format}`)}
|
accept={ACCEPTED_FORMAT.map(format => `.${format}`)}
|
||||||
cursor="pointer"
|
cursor="pointer"
|
||||||
as="input"
|
as="input"
|
||||||
position="absolute"
|
position="absolute"
|
||||||
left={0}
|
left={0}
|
||||||
right={0}
|
right={0}
|
||||||
bottom={0}
|
bottom={0}
|
||||||
top={0}
|
top={0}
|
||||||
width="100%"
|
width="100%"
|
||||||
type="file"
|
type="file"
|
||||||
name="files"
|
name="files"
|
||||||
tabIndex={-1}
|
tabIndex={-1}
|
||||||
zIndex={1}
|
zIndex={1}
|
||||||
onChange={handleChange}
|
onChange={handleChange}
|
||||||
ref={inputRef}
|
ref={inputRef}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Button type="button" onClick={handleClick}>
|
<Button type="button" onClick={handleClick}>
|
||||||
Browse files
|
{formatMessage({
|
||||||
</Button>
|
id: 'Settings.application.customization.modal.upload.cta.browse',
|
||||||
|
defaultMessage: 'Browse files',
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
|
||||||
<Box paddingTop={6}>
|
<Box paddingTop={6}>
|
||||||
<Typography variant="pi" textColor="neutral600">
|
<Typography variant="pi" textColor="neutral600">
|
||||||
Max dimension: 750*750, Max size: TBC
|
{/* Add translation once we know more about max size */}
|
||||||
</Typography>
|
Max dimension: 750*750, Max size: TBC
|
||||||
</Box>
|
</Typography>
|
||||||
</Flex>
|
</Box>
|
||||||
</Flex>
|
</Flex>
|
||||||
</Box>
|
</Box>
|
||||||
{fileError && (
|
{fileError && (
|
||||||
@ -133,4 +140,14 @@ const FromComputerForm = () => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FromComputerForm.defaultProps = {
|
||||||
|
next: null,
|
||||||
|
};
|
||||||
|
|
||||||
|
FromComputerForm.propTypes = {
|
||||||
|
setLocalImage: PropTypes.func.isRequired,
|
||||||
|
goTo: PropTypes.func.isRequired,
|
||||||
|
next: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
export default FromComputerForm;
|
export default FromComputerForm;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
|
||||||
const PendingLogoDialog = () => {
|
const PendingLogoDialog = () => {
|
||||||
return <div>PendingLogoDialog</div>;
|
return <div>PENDING DIALOG - TO DO</div>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export default PendingLogoDialog;
|
export default PendingLogoDialog;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import React, { useReducer, useEffect } from 'react';
|
import React, { useReducer, useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
import {
|
import {
|
||||||
ModalLayout,
|
ModalLayout,
|
||||||
ModalBody,
|
ModalBody,
|
||||||
@ -11,15 +12,16 @@ import reducer, { initialState } from './reducer';
|
|||||||
import stepper from './stepper';
|
import stepper from './stepper';
|
||||||
|
|
||||||
const LogoModalStepper = ({ initialStep, isOpen, onClose }) => {
|
const LogoModalStepper = ({ initialStep, isOpen, onClose }) => {
|
||||||
const [{ currentStep }, dispatch] = useReducer(reducer, initialState);
|
const [{ currentStep, localImage }, dispatch] = useReducer(reducer, initialState);
|
||||||
const { Component, modalTitle } = stepper[currentStep];
|
const { Component, modalTitle, next } = stepper[currentStep];
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (isOpen) {
|
if (isOpen) {
|
||||||
goTo(initialStep);
|
goTo(initialStep);
|
||||||
}
|
}
|
||||||
// Disabling the rule because we just want to let the ability to open the modal
|
// Disabling the rule because we just want to open the modal at a specific step
|
||||||
// at a specific step then we will let the stepper handle the navigation
|
// then we let the stepper handle the navigation
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isOpen]);
|
}, [isOpen]);
|
||||||
|
|
||||||
@ -30,6 +32,13 @@ const LogoModalStepper = ({ initialStep, isOpen, onClose }) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const setLocalImage = asset => {
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_LOCAL_IMAGE',
|
||||||
|
value: asset,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
if (!isOpen) {
|
if (!isOpen) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@ -37,12 +46,12 @@ const LogoModalStepper = ({ initialStep, isOpen, onClose }) => {
|
|||||||
return (
|
return (
|
||||||
<ModalLayout labelledBy="modal" onClose={onClose}>
|
<ModalLayout labelledBy="modal" onClose={onClose}>
|
||||||
<ModalHeader>
|
<ModalHeader>
|
||||||
<Typography fontWeight="bold" as="h2" id="title">
|
<Typography fontWeight="bold" as="h2" id="modal">
|
||||||
{modalTitle}
|
{formatMessage(modalTitle)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</ModalHeader>
|
</ModalHeader>
|
||||||
<ModalBody>
|
<ModalBody>
|
||||||
<Component />
|
<Component setLocalImage={setLocalImage} localImage={localImage} goTo={goTo} next={next} />
|
||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter />
|
<ModalFooter />
|
||||||
</ModalLayout>
|
</ModalLayout>
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
currentStep: 'add',
|
currentStep: 'upload',
|
||||||
|
localImage: undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
const reducer = (state = initialState, action) =>
|
const reducer = (state = initialState, action) =>
|
||||||
@ -18,6 +19,10 @@ const reducer = (state = initialState, action) =>
|
|||||||
draftState.currentStep = action.to;
|
draftState.currentStep = action.to;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'SET_LOCAL_IMAGE': {
|
||||||
|
draftState.localImage = action.value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default: {
|
default: {
|
||||||
return draftState;
|
return draftState;
|
||||||
}
|
}
|
||||||
|
@ -2,17 +2,23 @@ import AddLogoDialog from './AddLogoDialog';
|
|||||||
import PendingLogoDialog from './PendingLogoDialog';
|
import PendingLogoDialog from './PendingLogoDialog';
|
||||||
|
|
||||||
const stepper = {
|
const stepper = {
|
||||||
add: {
|
upload: {
|
||||||
Component: AddLogoDialog,
|
Component: AddLogoDialog,
|
||||||
modalTitle: 'Upload logo',
|
modalTitle: {
|
||||||
|
id: 'Settings.application.customization.modal.upload',
|
||||||
|
defaultMessage: 'Upload logo',
|
||||||
|
},
|
||||||
next: 'pending',
|
next: 'pending',
|
||||||
prev: null,
|
prev: null,
|
||||||
},
|
},
|
||||||
pending: {
|
pending: {
|
||||||
Component: PendingLogoDialog,
|
Component: PendingLogoDialog,
|
||||||
modalTitle: 'Pending logo',
|
modalTitle: {
|
||||||
|
id: 'Settings.application.customization.modal.pending',
|
||||||
|
defaultMessage: 'Pending logo',
|
||||||
|
},
|
||||||
next: null,
|
next: null,
|
||||||
prev: 'add',
|
prev: 'upload',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -34,9 +34,10 @@ const rawFileToAsset = rawFile => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const parseFileMetadatas = async file => {
|
export const parseFileMetadatas = async file => {
|
||||||
const isFormatAuthorized = ACCEPTED_FORMAT.some(format => file.type.includes(format));
|
|
||||||
let error;
|
let error;
|
||||||
|
|
||||||
|
const isFormatAuthorized = ACCEPTED_FORMAT.some(format => file.type.includes(format));
|
||||||
|
|
||||||
if (!isFormatAuthorized) {
|
if (!isFormatAuthorized) {
|
||||||
error = new Error('File format');
|
error = new Error('File format');
|
||||||
error.displayMessage = FILE_FORMAT_ERROR_MESSAGE;
|
error.displayMessage = FILE_FORMAT_ERROR_MESSAGE;
|
||||||
|
@ -103,6 +103,11 @@
|
|||||||
"Settings.application.customization.carousel.title": "Logo",
|
"Settings.application.customization.carousel.title": "Logo",
|
||||||
"Settings.application.customization.carousel.change-action": "Change logo",
|
"Settings.application.customization.carousel.change-action": "Change logo",
|
||||||
"Settings.application.customization.carousel-slide.label": "Logo slide",
|
"Settings.application.customization.carousel-slide.label": "Logo slide",
|
||||||
|
"Settings.application.customization.modal.upload": "Upload logo",
|
||||||
|
"Settings.application.customization.modal.upload.from-computer": "From computer",
|
||||||
|
"Settings.application.customization.modal.upload.cta.browse": "Browse files",
|
||||||
|
"Settings.application.customization.modal.upload.from-url": "From URL",
|
||||||
|
"Settings.application.customization.modal.pending": "Pending logo",
|
||||||
"Settings.error": "Error",
|
"Settings.error": "Error",
|
||||||
"Settings.global": "Global Settings",
|
"Settings.global": "Global Settings",
|
||||||
"Settings.permissions": "Administration panel",
|
"Settings.permissions": "Administration panel",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user