Init the upload asset dialog

This commit is contained in:
mfrachet 2021-09-15 10:56:26 +02:00
parent bab10b0ef2
commit c5ddd9a039
6 changed files with 733 additions and 5 deletions

View File

@ -0,0 +1,10 @@
import React from 'react';
import { Box } from '@strapi/parts/Box';
export const FromComputerForm = () => {
return (
<Box paddingTop={4} paddingBottom={4}>
From computer form
</Box>
);
};

View File

@ -0,0 +1,10 @@
import React from 'react';
import { Box } from '@strapi/parts/Box';
export const FromUrlForm = () => {
return (
<Box paddingTop={4} paddingBottom={4}>
From URL form
</Box>
);
};

View File

@ -0,0 +1,90 @@
import React from 'react';
import PropTypes from 'prop-types';
import { ModalLayout, ModalHeader, ModalFooter, ModalBody } from '@strapi/parts/ModalLayout';
import { ButtonText } from '@strapi/parts/Text';
import { Button } from '@strapi/parts/Button';
import { Divider } from '@strapi/parts/Divider';
import { useIntl } from 'react-intl';
import { Tabs, Tab, TabGroup, TabPanels, TabPanel } from '@strapi/parts/Tabs';
import { FromUrlForm } from './FromUrlForm';
import { FromComputerForm } from './FromComputerForm';
import { getTrad } from '../../utils';
export const UploadAssetDialog = ({ onSuccess, onClose }) => {
const { formatMessage } = useIntl();
const handleSaveAssets = () => {
onSuccess();
};
return (
<ModalLayout onClose={onClose} labelledBy="title">
<ModalHeader>
<ButtonText textColor="neutral800" as="h2" id="title">
{formatMessage({
id: getTrad('header.actions.upload-assets'),
defaultMessage: 'Upload assets',
})}
</ButtonText>
</ModalHeader>
<ModalBody>
<TabGroup
label={formatMessage({
id: getTrad('tabs.title'),
defaultMessage: 'How do you want to upload your assets?',
})}
variant="simple"
>
<Tabs>
<Tab>
{formatMessage({
id: getTrad('modal.nav.computer'),
defaultMessage: 'From computer',
})}
</Tab>
<Tab>
{formatMessage({
id: getTrad('modal.nav.url'),
defaultMessage: 'From URL',
})}
</Tab>
</Tabs>
<Divider />
<TabPanels>
<TabPanel>
<FromUrlForm />
</TabPanel>
<TabPanel>
<FromComputerForm />
</TabPanel>
</TabPanels>
</TabGroup>
</ModalBody>
<ModalFooter
startActions={
<Button onClick={onClose} variant="tertiary">
{formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'cancel' })}
</Button>
}
endActions={
<>
<Button onClick={handleSaveAssets}>
{formatMessage(
{
id: getTrad('modal.upload-list.footer.button.singular'),
defaultMessage: 'Upload assets',
},
{ number: 0 }
)}
</Button>
</>
}
/>
</ModalLayout>
);
};
UploadAssetDialog.propTypes = {
onSuccess: PropTypes.func.isRequired,
onClose: PropTypes.func.isRequired,
};

View File

@ -0,0 +1,606 @@
import React from 'react';
import { render as renderTL } from '@testing-library/react';
import { ThemeProvider, lightTheme } from '@strapi/parts';
import en from '../../../translations/en.json';
import { UploadAssetDialog } from '../UploadAssetDialog';
jest.mock('../../../utils', () => ({
...jest.requireActual('../../../utils'),
getTrad: x => x,
}));
jest.mock('react-intl', () => ({
useIntl: () => ({ formatMessage: jest.fn(({ id }) => en[id]) }),
}));
const render = (props = { onSucces: () => {}, onError: () => {} }) =>
renderTL(
<ThemeProvider theme={lightTheme}>
<UploadAssetDialog {...props} />
</ThemeProvider>,
{ container: document.body }
);
describe('', () => {
it('snapshots the component', () => {
const { container } = render();
expect(container).toMatchInlineSnapshot(`
.c0 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.c2 {
background: #ffffff;
border-radius: 4px;
box-shadow: 0px 2px 15px rgba(33,33,52,0.1);
}
.c4 {
background: #f6f6f9;
padding-top: 16px;
padding-right: 20px;
padding-bottom: 16px;
padding-left: 20px;
}
.c11 {
padding-top: 24px;
padding-right: 40px;
padding-bottom: 24px;
padding-left: 40px;
}
.c30 {
background: #212134;
padding: 8px;
border-radius: 4px;
}
.c1 {
position: absolute;
z-index: 3;
inset: 0;
background: rgb(220,220,228,0.8);
padding: 0 40px;
}
.c3 {
max-width: 51.875rem;
margin: 0 auto;
overflow: hidden;
margin-top: 10%;
}
.c6 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-box-pack: justify;
-webkit-justify-content: space-between;
-ms-flex-pack: justify;
justify-content: space-between;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c23 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
-webkit-flex-direction: row;
-ms-flex-direction: row;
flex-direction: row;
-webkit-align-items: center;
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
}
.c33 {
font-weight: 500;
font-size: 0.75rem;
line-height: 1.33;
color: #ffffff;
}
.c32 {
border: 0;
-webkit-clip: rect(0 0 0 0);
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.c31 {
position: absolute;
z-index: 3;
display: revert;
}
.c9 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
cursor: pointer;
padding: 8px;
border-radius: 4px;
background: #ffffff;
border: 1px solid #dcdce4;
}
.c9 svg {
height: 12px;
width: 12px;
}
.c9 svg > g,
.c9 svg path {
fill: #ffffff;
}
.c9[aria-disabled='true'] {
pointer-events: none;
}
.c10 svg > g,
.c10 svg path {
fill: #8e8ea9;
}
.c10:hover svg > g,
.c10:hover svg path {
fill: #666687;
}
.c10:active svg > g,
.c10:active svg path {
fill: #a5a5ba;
}
.c10[aria-disabled='true'] {
background-color: #eaeaef;
}
.c10[aria-disabled='true'] svg path {
fill: #666687;
}
.c5 {
border-bottom: 1px solid #eaeaef;
}
.c22 {
border-top: 1px solid #eaeaef;
}
.c24 > * + * {
margin-left: 8px;
}
.c7 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #32324d;
}
.c8 {
font-weight: 600;
line-height: 1.14;
}
.c28 {
font-weight: 500;
font-size: 0.75rem;
line-height: 1.33;
color: #32324d;
}
.c25 {
display: -webkit-box;
display: -webkit-flex;
display: -ms-flexbox;
display: flex;
cursor: pointer;
padding: 8px;
border-radius: 4px;
background: #ffffff;
border: 1px solid #dcdce4;
}
.c25 svg {
height: 12px;
width: 12px;
}
.c25 svg > g,
.c25 svg path {
fill: #ffffff;
}
.c25[aria-disabled='true'] {
pointer-events: none;
}
.c26 {
padding: 8px 16px;
background: #4945ff;
border: none;
border: 1px solid #dcdce4;
background: #ffffff;
}
.c26 .c27 {
color: #ffffff;
}
.c26[aria-disabled='true'] {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c26[aria-disabled='true'] .c27 {
color: #666687;
}
.c26[aria-disabled='true'] svg > g,
.c26[aria-disabled='true'] svg path {
fill: #666687;
}
.c26[aria-disabled='true']:active {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c26[aria-disabled='true']:active .c27 {
color: #666687;
}
.c26[aria-disabled='true']:active svg > g,
.c26[aria-disabled='true']:active svg path {
fill: #666687;
}
.c26:hover {
background-color: #f6f6f9;
}
.c26:active {
background-color: #eaeaef;
}
.c26 .c27 {
color: #32324d;
}
.c26 svg > g,
.c26 svg path {
fill: #32324d;
}
.c29 {
padding: 8px 16px;
background: #4945ff;
border: none;
border: 1px solid #4945ff;
background: #4945ff;
}
.c29 .c27 {
color: #ffffff;
}
.c29[aria-disabled='true'] {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c29[aria-disabled='true'] .c27 {
color: #666687;
}
.c29[aria-disabled='true'] svg > g,
.c29[aria-disabled='true'] svg path {
fill: #666687;
}
.c29[aria-disabled='true']:active {
border: 1px solid #dcdce4;
background: #eaeaef;
}
.c29[aria-disabled='true']:active .c27 {
color: #666687;
}
.c29[aria-disabled='true']:active svg > g,
.c29[aria-disabled='true']:active svg path {
fill: #666687;
}
.c29:hover {
border: 1px solid #7b79ff;
background: #7b79ff;
}
.c29:active {
border: 1px solid #4945ff;
background: #4945ff;
}
.c19 {
background: #eaeaef;
}
.c20 {
height: 1px;
border: none;
margin: 0;
}
.c14 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #4945ff;
}
.c18 {
font-weight: 400;
font-size: 0.875rem;
line-height: 1.43;
color: #666687;
}
.c15 {
font-weight: 600;
line-height: 1.14;
}
.c16 {
font-weight: 600;
font-size: 0.6875rem;
line-height: 1.45;
text-transform: uppercase;
}
.c12 {
padding: 16px;
}
.c13 {
border-bottom: 2px solid #4945ff;
}
.c17 {
border-bottom: 2px solid transparent;
}
.c21 {
padding-top: 16px;
padding-bottom: 16px;
}
<body
class="lock-body-scroll"
>
<div
class="c0"
>
<p
aria-live="polite"
aria-relevant="all"
id="live-region-log"
role="log"
/>
<p
aria-live="polite"
aria-relevant="all"
id="live-region-status"
role="status"
/>
<p
aria-live="assertive"
aria-relevant="all"
id="live-region-alert"
role="alert"
/>
</div>
<div
data-react-portal="true"
>
<div
class="c1"
>
<div>
<div
aria-labelledby="title"
aria-modal="true"
class="c2 c3"
role="dialog"
>
<div
class="c4 c5"
>
<div
class="c6"
>
<h2
class="c7 c8"
id="title"
>
Upload assets
</h2>
<span>
<button
aria-disabled="false"
aria-labelledby="tooltip-1"
class="c9 c10"
tabindex="0"
type="button"
>
<svg
fill="none"
height="1em"
viewBox="0 0 24 24"
width="1em"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M24 2.417L21.583 0 12 9.583 2.417 0 0 2.417 9.583 12 0 21.583 2.417 24 12 14.417 21.583 24 24 21.583 14.417 12 24 2.417z"
fill="#212134"
/>
</svg>
</button>
</span>
</div>
</div>
<div
class="c11"
>
<div>
<div
aria-label="How do you want to upload your assets?"
role="tablist"
>
<button
aria-controls="tabgroup-1-0-tabpanel"
aria-selected="true"
id="tabgroup-1-0-tab"
role="tab"
tabindex="0"
type="button"
>
<div
class="c12 c13"
>
<span
class="c14 c15 c16"
>
From computer
</span>
</div>
</button>
<button
aria-selected="false"
id="tabgroup-1-1-tab"
role="tab"
tabindex="-1"
type="button"
>
<div
class="c12 c17"
>
<span
class="c18 c15 c16"
>
From url
</span>
</div>
</button>
</div>
<hr
class="c19 c20"
/>
<div>
<div
aria-labelledby="tabgroup-1-0-tab"
id="tabgroup-1-0-tabpanel"
role="tabpanel"
tabindex="0"
>
<div
class="c21"
>
From URL form
</div>
</div>
</div>
</div>
</div>
<div
class="c4 c22"
>
<div
class="c6"
>
<div
class="c23 c24"
>
<button
aria-disabled="false"
class="c25 c26"
type="button"
>
<span
class="c27 c28"
/>
</button>
</div>
<div
class="c23 c24"
>
<button
aria-disabled="false"
class="c25 c29"
type="button"
>
<span
class="c27 c28"
>
Upload {number} asset to the library
</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div
data-react-portal="true"
>
<div
class="c30 c31"
id="tooltip-1"
role="tooltip"
style="left: 0px; top: -8px;"
>
<div
class="c32"
id="description-2"
/>
<p
class="c33"
>
Close the modal
</p>
</div>
</div>
</body>
`);
});
});

View File

@ -1,4 +1,4 @@
import React from 'react';
import React, { useState } from 'react';
import { Redirect } from 'react-router-dom';
import { useIntl } from 'react-intl';
import styled from 'styled-components';
@ -17,6 +17,7 @@ import { Button } from '@strapi/parts/Button';
import AddIcon from '@strapi/icons/AddIcon';
import { Box } from '@strapi/parts/Box';
import { BaseCheckbox } from '@strapi/parts/BaseCheckbox';
import { UploadAssetDialog } from '../../components/UploadAssetDialog/UploadAssetDialog';
import { ListView } from './components/ListView';
import { useAssets } from '../../hooks/useAssets';
import { getTrad } from '../../utils';
@ -34,6 +35,8 @@ const App = () => {
const { data, isLoading, error } = useAssets({
skipWhen: !state.allowedActions.canMain,
});
const [showUploadAssetDialog, setShowUploadAssetDialog] = useState(false);
const toggleUploadAssetDialog = () => setShowUploadAssetDialog(prev => !prev);
useFocusWhenNavigate();
@ -64,7 +67,7 @@ const App = () => {
{ number: data?.length || 0 }
)}
primaryAction={
<Button startIcon={<AddIcon />}>
<Button startIcon={<AddIcon />} onClick={toggleUploadAssetDialog}>
{formatMessage({
id: getTrad('header.actions.upload-assets'),
defaultMessage: 'Upload new assets',
@ -110,7 +113,11 @@ const App = () => {
{canRead && data && data.length === 0 && (
<NoMedia
action={
<Button variant="secondary" startIcon={<AddIcon />}>
<Button
variant="secondary"
startIcon={<AddIcon />}
onClick={toggleUploadAssetDialog}
>
{formatMessage({
id: getTrad('modal.header.browse'),
defaultMessage: 'Upload assets',
@ -126,6 +133,10 @@ const App = () => {
{canRead && data && data.length > 0 && <ListView assets={data} />}
</ContentLayout>
</Main>
{showUploadAssetDialog && (
<UploadAssetDialog onClose={toggleUploadAssetDialog} onSuccess={() => {}} />
)}
</Layout>
);
};

View File

@ -51,9 +51,9 @@
"modal.header.pending-assets": "Pending assets",
"modal.header.select-files": "Selected files",
"modal.nav.browse": "browse",
"modal.nav.computer": "from computer",
"modal.nav.computer": "From computer",
"modal.nav.selected": "selected",
"modal.nav.url": "from url",
"modal.nav.url": "From url",
"modal.selected-list.sub-header-subtitle": "Drag & drop to reorder the assets in the field",
"modal.upload-list.footer.button.plural": "Upload {number} assets to the library",
"modal.upload-list.footer.button.singular": "Upload {number} asset to the library",
@ -86,6 +86,7 @@
"sort.name_desc": "Reverse alphabetical order (Z to A)",
"sort.updated_at_asc": "Oldest updates",
"sort.updated_at_desc": "Most recent updates",
"tabs.title": "How do you want to upload your assets?",
"window.confirm.close-modal.file": "Are you sure? Your changes will be lost.",
"window.confirm.close-modal.files": "Are you sure? You have some files that have not been uploaded yet."
}