mirror of
https://github.com/strapi/strapi.git
synced 2025-11-02 02:44:55 +00:00
Add Upload from computer step
This commit is contained in:
parent
0ee4d32aae
commit
389166481f
@ -51,7 +51,7 @@ export const AddAssetStep = ({ onClose, onAddAsset }) => {
|
||||
</Box>
|
||||
<TabPanels>
|
||||
<TabPanel>
|
||||
<FromComputerForm />
|
||||
<FromComputerForm onClose={onClose} onAddAsset={onAddAsset} />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<FromUrlForm onClose={onClose} onAddAsset={onAddAsset} />
|
||||
|
||||
@ -1,10 +1,130 @@
|
||||
import React from 'react';
|
||||
/* eslint-disable jsx-a11y/label-has-associated-control */
|
||||
import React, { useRef } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import styled from 'styled-components';
|
||||
import { Box } from '@strapi/parts/Box';
|
||||
import { Row } from '@strapi/parts/Row';
|
||||
import { VisuallyHidden } from '@strapi/parts/VisuallyHidden';
|
||||
import { H3 } from '@strapi/parts/Text';
|
||||
import { ModalFooter } from '@strapi/parts/ModalLayout';
|
||||
import { Button } from '@strapi/parts/Button';
|
||||
import AddAssetIcon from '@strapi/icons/AddAsset';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { getTrad } from '../../../utils';
|
||||
import { typeFromMime } from '../../../utils/typeFromMime';
|
||||
import { AssetSource } from '../../../constants';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
`;
|
||||
|
||||
const IconWrapper = styled.div`
|
||||
font-size: ${60 / 16}rem;
|
||||
|
||||
svg path {
|
||||
fill: ${({ theme }) => theme.colors.primary600};
|
||||
}
|
||||
`;
|
||||
|
||||
const MediaBox = styled(Box)`
|
||||
border-style: dashed;
|
||||
`;
|
||||
|
||||
export const FromComputerForm = ({ onClose, onAddAsset }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
const inputRef = useRef(null);
|
||||
|
||||
const handleClick = e => {
|
||||
e.preventDefault();
|
||||
inputRef.current.click();
|
||||
};
|
||||
|
||||
const handleChange = () => {
|
||||
const files = inputRef.current.files;
|
||||
const assets = [];
|
||||
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = files.item(i);
|
||||
|
||||
assets.push({
|
||||
source: AssetSource.Computer,
|
||||
type: typeFromMime(file.type),
|
||||
url: URL.createObjectURL(file),
|
||||
ext: file.name.split('.').pop(),
|
||||
mime: file.type,
|
||||
});
|
||||
}
|
||||
|
||||
onAddAsset(assets);
|
||||
};
|
||||
|
||||
export const FromComputerForm = () => {
|
||||
return (
|
||||
<Box paddingTop={4} paddingBottom={4}>
|
||||
From computer form
|
||||
</Box>
|
||||
<form>
|
||||
<Box paddingLeft={8} paddingRight={8} paddingTop={6} paddingBottom={6}>
|
||||
<label>
|
||||
<MediaBox
|
||||
paddingTop={11}
|
||||
paddingBottom={11}
|
||||
hasRadius
|
||||
justifyContent="center"
|
||||
borderColor="neutral300"
|
||||
background="neutral100"
|
||||
>
|
||||
<Row justifyContent="center">
|
||||
<Wrapper>
|
||||
<IconWrapper>
|
||||
<AddAssetIcon aria-hidden />
|
||||
</IconWrapper>
|
||||
|
||||
<Box paddingTop={3} paddingBottom={5}>
|
||||
<H3 textColor="neutral600" as="span">
|
||||
{formatMessage({
|
||||
id: getTrad('input.label'),
|
||||
defaultMessage: 'Drag & Drop here or',
|
||||
})}
|
||||
</H3>
|
||||
</Box>
|
||||
|
||||
<Button type="button" onClick={handleClick}>
|
||||
{formatMessage({
|
||||
id: getTrad('input.button.label'),
|
||||
defaultMessage: 'Browse files',
|
||||
})}
|
||||
</Button>
|
||||
|
||||
<VisuallyHidden>
|
||||
<input
|
||||
type="file"
|
||||
multiple
|
||||
name="files"
|
||||
tabIndex={-1}
|
||||
ref={inputRef}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
</VisuallyHidden>
|
||||
</Wrapper>
|
||||
</Row>
|
||||
</MediaBox>
|
||||
</label>
|
||||
</Box>
|
||||
|
||||
<ModalFooter
|
||||
startActions={
|
||||
<Button onClick={onClose} variant="tertiary">
|
||||
{formatMessage({
|
||||
id: 'app.components.Button.cancel',
|
||||
defaultMessage: 'cancel',
|
||||
})}
|
||||
</Button>
|
||||
}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
FromComputerForm.propTypes = {
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onAddAsset: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
@ -56,12 +56,12 @@ export const FromUrlForm = ({ onClose, onAddAsset }) => {
|
||||
|
||||
<ModalFooter
|
||||
startActions={
|
||||
<Button onClick={onClose} variant="tertiary" loading={loading}>
|
||||
<Button onClick={onClose} variant="tertiary">
|
||||
{formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'cancel' })}
|
||||
</Button>
|
||||
}
|
||||
endActions={
|
||||
<Button type="submit">
|
||||
<Button type="submit" loading={loading}>
|
||||
{formatMessage({
|
||||
id: getTrad('button.next'),
|
||||
defaultMessage: 'Next',
|
||||
|
||||
@ -0,0 +1,431 @@
|
||||
import React from 'react';
|
||||
import { ThemeProvider, lightTheme } from '@strapi/parts';
|
||||
import { render as renderTL } from '@testing-library/react';
|
||||
import { FromComputerForm } from '../FromComputerForm';
|
||||
import en from '../../../../translations/en.json';
|
||||
|
||||
jest.mock('../../../../utils', () => ({
|
||||
...jest.requireActual('../../../../utils'),
|
||||
getTrad: x => x,
|
||||
}));
|
||||
|
||||
jest.mock('react-intl', () => ({
|
||||
useIntl: () => ({ formatMessage: jest.fn(({ id }) => en[id] || 'App level translation') }),
|
||||
}));
|
||||
|
||||
describe('FromComputerForm', () => {
|
||||
it('snapshots the component with 4 URLs: 3 valid and one in failure', async () => {
|
||||
const { container } = renderTL(
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<FromComputerForm onClose={jest.fn()} onAddAsset={jest.fn()} />
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
expect(container).toMatchInlineSnapshot(`
|
||||
.c19 {
|
||||
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;
|
||||
}
|
||||
|
||||
.c0 {
|
||||
padding-top: 24px;
|
||||
padding-right: 40px;
|
||||
padding-bottom: 24px;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.c1 {
|
||||
background: #f6f6f9;
|
||||
padding-top: 64px;
|
||||
padding-bottom: 64px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #c0c0cf;
|
||||
}
|
||||
|
||||
.c6 {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.c3 {
|
||||
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: center;
|
||||
-webkit-justify-content: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c12 {
|
||||
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;
|
||||
}
|
||||
|
||||
.c7 {
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25;
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c13 {
|
||||
background: #f6f6f9;
|
||||
padding-top: 16px;
|
||||
padding-right: 20px;
|
||||
padding-bottom: 16px;
|
||||
padding-left: 20px;
|
||||
}
|
||||
|
||||
.c15 {
|
||||
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;
|
||||
}
|
||||
|
||||
.c16 {
|
||||
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;
|
||||
}
|
||||
|
||||
.c14 {
|
||||
border-top: 1px solid #eaeaef;
|
||||
}
|
||||
|
||||
.c17 > * + * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.c11 {
|
||||
font-weight: 500;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.33;
|
||||
color: #32324d;
|
||||
}
|
||||
|
||||
.c8 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #dcdce4;
|
||||
}
|
||||
|
||||
.c8 svg {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.c8 svg > g,
|
||||
.c8 svg path {
|
||||
fill: #ffffff;
|
||||
}
|
||||
|
||||
.c8[aria-disabled='true'] {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
padding: 8px 16px;
|
||||
background: #4945ff;
|
||||
border: none;
|
||||
border: 1px solid #4945ff;
|
||||
background: #4945ff;
|
||||
}
|
||||
|
||||
.c9 .c10 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.c9[aria-disabled='true'] {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c9[aria-disabled='true'] .c10 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c9[aria-disabled='true'] svg > g,
|
||||
.c9[aria-disabled='true'] svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c9[aria-disabled='true']:active {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c9[aria-disabled='true']:active .c10 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c9[aria-disabled='true']:active svg > g,
|
||||
.c9[aria-disabled='true']:active svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c9:hover {
|
||||
border: 1px solid #7b79ff;
|
||||
background: #7b79ff;
|
||||
}
|
||||
|
||||
.c9:active {
|
||||
border: 1px solid #4945ff;
|
||||
background: #4945ff;
|
||||
}
|
||||
|
||||
.c18 {
|
||||
padding: 8px 16px;
|
||||
background: #4945ff;
|
||||
border: none;
|
||||
border: 1px solid #dcdce4;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.c18 .c10 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.c18[aria-disabled='true'] {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c18[aria-disabled='true'] .c10 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c18[aria-disabled='true'] svg > g,
|
||||
.c18[aria-disabled='true'] svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c18[aria-disabled='true']:active {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c18[aria-disabled='true']:active .c10 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c18[aria-disabled='true']:active svg > g,
|
||||
.c18[aria-disabled='true']:active svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c18:hover {
|
||||
background-color: #f6f6f9;
|
||||
}
|
||||
|
||||
.c18:active {
|
||||
background-color: #eaeaef;
|
||||
}
|
||||
|
||||
.c18 .c10 {
|
||||
color: #32324d;
|
||||
}
|
||||
|
||||
.c18 svg > g,
|
||||
.c18 svg path {
|
||||
fill: #32324d;
|
||||
}
|
||||
|
||||
.c4 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c5 {
|
||||
font-size: 3.75rem;
|
||||
}
|
||||
|
||||
.c5 svg path {
|
||||
fill: #4945ff;
|
||||
}
|
||||
|
||||
.c2 {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
<div>
|
||||
<form>
|
||||
<div
|
||||
class="c0"
|
||||
>
|
||||
<label>
|
||||
<div
|
||||
class="c1 c2"
|
||||
>
|
||||
<div
|
||||
class="c3"
|
||||
>
|
||||
<div
|
||||
class="c4"
|
||||
>
|
||||
<div
|
||||
class="c5"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
height="1em"
|
||||
viewBox="0 0 24 20"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M21.569 2.398H7.829v1.586h13.74c.47 0 .826.5.826 1.094v9.853l-2.791-3.17a2.13 2.13 0 00-.74-.55 2.211 2.211 0 00-.912-.196 2.213 2.213 0 00-.912.191 2.13 2.13 0 00-.74.546l-2.93 3.385-2.974-3.36a2.146 2.146 0 00-.74-.545 2.23 2.23 0 00-.911-.193c-.316.002-.628.07-.913.2-.286.13-.538.319-.739.553l-2.931 3.432V7.653H2.51v9.894c.023.153.06.304.108.452v.127l.041.095c.057.142.126.28.207.412l.099.15c.074.107.157.207.247.302l.124.119c.13.118.275.222.43.309h.024c.36.214.775.327 1.198.325h16.515c.36-.004.716-.085 1.039-.24.323-.153.606-.375.827-.648a2.78 2.78 0 00.504-.888c.066-.217.108-.44.124-.666V5.078a2.497 2.497 0 00-.652-1.81 2.706 2.706 0 00-1.776-.87z"
|
||||
fill="#32324D"
|
||||
/>
|
||||
<path
|
||||
d="M12.552 9.199c.912 0 1.651-.71 1.651-1.586 0-.875-.74-1.585-1.651-1.585-.912 0-1.652.71-1.652 1.585 0 .876.74 1.586 1.652 1.586zM3.303 6.408h.826V3.997h2.477v-.793-.793H4.129V0h-.826c-.219 0-.85.002-.826 0v2.411H0v1.586h2.477v2.41h.826z"
|
||||
fill="#32324D"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="c6"
|
||||
>
|
||||
<span
|
||||
class="c7"
|
||||
>
|
||||
Drag & Drop here or
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
class="c8 c9"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="c10 c11"
|
||||
>
|
||||
Browse files
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="c12"
|
||||
>
|
||||
<input
|
||||
multiple=""
|
||||
name="files"
|
||||
tabindex="-1"
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="c13 c14"
|
||||
>
|
||||
<div
|
||||
class="c15"
|
||||
>
|
||||
<div
|
||||
class="c16 c17"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
class="c8 c18"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="c10 c11"
|
||||
>
|
||||
App level translation
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="c16 c17"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<div
|
||||
class="c19"
|
||||
>
|
||||
<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>
|
||||
`);
|
||||
});
|
||||
});
|
||||
@ -15,7 +15,7 @@ import { UnknownAssetCard } from '../../AssetCard/UnknownAssetCard';
|
||||
import { getTrad } from '../../../utils';
|
||||
import { AssetType, AssetSource } from '../../../constants';
|
||||
|
||||
export const PendingAssetStep = ({ onClose, assets }) => {
|
||||
export const PendingAssetStep = ({ onClose, assets, onClickAddAsset }) => {
|
||||
const { formatMessage } = useIntl();
|
||||
|
||||
return (
|
||||
@ -49,7 +49,7 @@ export const PendingAssetStep = ({ onClose, assets }) => {
|
||||
})}
|
||||
</Text>
|
||||
</Stack>
|
||||
<Button size="S">
|
||||
<Button size="S" onClick={onClickAddAsset}>
|
||||
{formatMessage({
|
||||
id: getTrad('header.actions.upload-new-asset'),
|
||||
defaultMessage: 'Upload new asset',
|
||||
@ -142,4 +142,5 @@ PendingAssetStep.propTypes = {
|
||||
})
|
||||
).isRequired,
|
||||
onClose: PropTypes.func.isRequired,
|
||||
onClickAddAsset: PropTypes.func.isRequired,
|
||||
};
|
||||
|
||||
@ -47,7 +47,12 @@ describe('AddAssetTest', () => {
|
||||
|
||||
const { container } = renderTL(
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<PendingAssetStep assets={assets} onClose={jest.fn()} onAddAsset={jest.fn()} />
|
||||
<PendingAssetStep
|
||||
assets={assets}
|
||||
onClose={jest.fn()}
|
||||
onAddAsset={jest.fn()}
|
||||
onClickAddAsset={jest.fn()}
|
||||
/>
|
||||
</ThemeProvider>
|
||||
);
|
||||
|
||||
|
||||
@ -19,12 +19,18 @@ export const UploadAssetDialog = ({ onSuccess, onClose }) => {
|
||||
onSuccess();
|
||||
};
|
||||
|
||||
const moveToAddAsset = () => {
|
||||
setStep(Steps.AddAsset);
|
||||
};
|
||||
|
||||
return (
|
||||
<ModalLayout onClose={onClose} labelledBy="title">
|
||||
{step === Steps.AddAsset && (
|
||||
<AddAssetStep onClose={onClose} onAddAsset={handleAddToPendingAssets} />
|
||||
)}
|
||||
{step === Steps.PendingAsset && <PendingAssetStep onClose={onClose} assets={assets} />}
|
||||
{step === Steps.PendingAsset && (
|
||||
<PendingAssetStep onClose={onClose} assets={assets} onClickAddAsset={moveToAddAsset} />
|
||||
)}
|
||||
</ModalLayout>
|
||||
);
|
||||
};
|
||||
|
||||
@ -94,6 +94,20 @@ describe('', () => {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c35 {
|
||||
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;
|
||||
}
|
||||
|
||||
.c9 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
@ -147,6 +161,21 @@ describe('', () => {
|
||||
border-bottom: 1px solid #eaeaef;
|
||||
}
|
||||
|
||||
.c34 {
|
||||
border-top: 1px solid #eaeaef;
|
||||
}
|
||||
|
||||
.c36 > * + * {
|
||||
margin-left: 8px;
|
||||
}
|
||||
|
||||
.c28 {
|
||||
font-weight: 500;
|
||||
font-size: 1rem;
|
||||
line-height: 1.25;
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c7 {
|
||||
font-weight: 400;
|
||||
font-size: 0.875rem;
|
||||
@ -176,8 +205,23 @@ describe('', () => {
|
||||
}
|
||||
|
||||
.c21 {
|
||||
padding-top: 16px;
|
||||
padding-bottom: 16px;
|
||||
padding-top: 24px;
|
||||
padding-right: 40px;
|
||||
padding-bottom: 24px;
|
||||
padding-left: 40px;
|
||||
}
|
||||
|
||||
.c22 {
|
||||
background: #f6f6f9;
|
||||
padding-top: 64px;
|
||||
padding-bottom: 64px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #c0c0cf;
|
||||
}
|
||||
|
||||
.c27 {
|
||||
padding-top: 12px;
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
|
||||
.c14 {
|
||||
@ -218,6 +262,202 @@ describe('', () => {
|
||||
border-bottom: 2px solid transparent;
|
||||
}
|
||||
|
||||
.c32 {
|
||||
font-weight: 500;
|
||||
font-size: 0.75rem;
|
||||
line-height: 1.33;
|
||||
color: #32324d;
|
||||
}
|
||||
|
||||
.c29 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
padding: 8px;
|
||||
border-radius: 4px;
|
||||
background: #ffffff;
|
||||
border: 1px solid #dcdce4;
|
||||
}
|
||||
|
||||
.c29 svg {
|
||||
height: 12px;
|
||||
width: 12px;
|
||||
}
|
||||
|
||||
.c29 svg > g,
|
||||
.c29 svg path {
|
||||
fill: #ffffff;
|
||||
}
|
||||
|
||||
.c29[aria-disabled='true'] {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.c30 {
|
||||
padding: 8px 16px;
|
||||
background: #4945ff;
|
||||
border: none;
|
||||
border: 1px solid #4945ff;
|
||||
background: #4945ff;
|
||||
}
|
||||
|
||||
.c30 .c31 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.c30[aria-disabled='true'] {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c30[aria-disabled='true'] .c31 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c30[aria-disabled='true'] svg > g,
|
||||
.c30[aria-disabled='true'] svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c30[aria-disabled='true']:active {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c30[aria-disabled='true']:active .c31 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c30[aria-disabled='true']:active svg > g,
|
||||
.c30[aria-disabled='true']:active svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c30:hover {
|
||||
border: 1px solid #7b79ff;
|
||||
background: #7b79ff;
|
||||
}
|
||||
|
||||
.c30:active {
|
||||
border: 1px solid #4945ff;
|
||||
background: #4945ff;
|
||||
}
|
||||
|
||||
.c37 {
|
||||
padding: 8px 16px;
|
||||
background: #4945ff;
|
||||
border: none;
|
||||
border: 1px solid #dcdce4;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.c37 .c31 {
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.c37[aria-disabled='true'] {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c37[aria-disabled='true'] .c31 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c37[aria-disabled='true'] svg > g,
|
||||
.c37[aria-disabled='true'] svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c37[aria-disabled='true']:active {
|
||||
border: 1px solid #dcdce4;
|
||||
background: #eaeaef;
|
||||
}
|
||||
|
||||
.c37[aria-disabled='true']:active .c31 {
|
||||
color: #666687;
|
||||
}
|
||||
|
||||
.c37[aria-disabled='true']:active svg > g,
|
||||
.c37[aria-disabled='true']:active svg path {
|
||||
fill: #666687;
|
||||
}
|
||||
|
||||
.c37:hover {
|
||||
background-color: #f6f6f9;
|
||||
}
|
||||
|
||||
.c37:active {
|
||||
background-color: #eaeaef;
|
||||
}
|
||||
|
||||
.c37 .c31 {
|
||||
color: #32324d;
|
||||
}
|
||||
|
||||
.c37 svg > g,
|
||||
.c37 svg path {
|
||||
fill: #32324d;
|
||||
}
|
||||
|
||||
.c24 {
|
||||
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: center;
|
||||
-webkit-justify-content: center;
|
||||
-ms-flex-pack: center;
|
||||
justify-content: center;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c33 {
|
||||
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;
|
||||
}
|
||||
|
||||
.c25 {
|
||||
display: -webkit-box;
|
||||
display: -webkit-flex;
|
||||
display: -ms-flexbox;
|
||||
display: flex;
|
||||
-webkit-flex-direction: column;
|
||||
-ms-flex-direction: column;
|
||||
flex-direction: column;
|
||||
-webkit-align-items: center;
|
||||
-webkit-box-align: center;
|
||||
-ms-flex-align: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.c26 {
|
||||
font-size: 3.75rem;
|
||||
}
|
||||
|
||||
.c26 svg path {
|
||||
fill: #4945ff;
|
||||
}
|
||||
|
||||
.c23 {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
<body
|
||||
class="lock-body-scroll"
|
||||
>
|
||||
@ -344,11 +584,101 @@ describe('', () => {
|
||||
role="tabpanel"
|
||||
tabindex="0"
|
||||
>
|
||||
<div
|
||||
class="c21"
|
||||
>
|
||||
From computer form
|
||||
</div>
|
||||
<form>
|
||||
<div
|
||||
class="c21"
|
||||
>
|
||||
<label>
|
||||
<div
|
||||
class="c22 c23"
|
||||
>
|
||||
<div
|
||||
class="c24"
|
||||
>
|
||||
<div
|
||||
class="c25"
|
||||
>
|
||||
<div
|
||||
class="c26"
|
||||
>
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
fill="none"
|
||||
height="1em"
|
||||
viewBox="0 0 24 20"
|
||||
width="1em"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M21.569 2.398H7.829v1.586h13.74c.47 0 .826.5.826 1.094v9.853l-2.791-3.17a2.13 2.13 0 00-.74-.55 2.211 2.211 0 00-.912-.196 2.213 2.213 0 00-.912.191 2.13 2.13 0 00-.74.546l-2.93 3.385-2.974-3.36a2.146 2.146 0 00-.74-.545 2.23 2.23 0 00-.911-.193c-.316.002-.628.07-.913.2-.286.13-.538.319-.739.553l-2.931 3.432V7.653H2.51v9.894c.023.153.06.304.108.452v.127l.041.095c.057.142.126.28.207.412l.099.15c.074.107.157.207.247.302l.124.119c.13.118.275.222.43.309h.024c.36.214.775.327 1.198.325h16.515c.36-.004.716-.085 1.039-.24.323-.153.606-.375.827-.648a2.78 2.78 0 00.504-.888c.066-.217.108-.44.124-.666V5.078a2.497 2.497 0 00-.652-1.81 2.706 2.706 0 00-1.776-.87z"
|
||||
fill="#32324D"
|
||||
/>
|
||||
<path
|
||||
d="M12.552 9.199c.912 0 1.651-.71 1.651-1.586 0-.875-.74-1.585-1.651-1.585-.912 0-1.652.71-1.652 1.585 0 .876.74 1.586 1.652 1.586zM3.303 6.408h.826V3.997h2.477v-.793-.793H4.129V0h-.826c-.219 0-.85.002-.826 0v2.411H0v1.586h2.477v2.41h.826z"
|
||||
fill="#32324D"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<div
|
||||
class="c27"
|
||||
>
|
||||
<span
|
||||
class="c28"
|
||||
>
|
||||
Drag & Drop here or
|
||||
</span>
|
||||
</div>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
class="c29 c30"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="c31 c32"
|
||||
>
|
||||
Browse files
|
||||
</span>
|
||||
</button>
|
||||
<div
|
||||
class="c33"
|
||||
>
|
||||
<input
|
||||
multiple=""
|
||||
name="files"
|
||||
tabindex="-1"
|
||||
type="file"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</label>
|
||||
</div>
|
||||
<div
|
||||
class="c4 c34"
|
||||
>
|
||||
<div
|
||||
class="c6"
|
||||
>
|
||||
<div
|
||||
class="c35 c36"
|
||||
>
|
||||
<button
|
||||
aria-disabled="false"
|
||||
class="c29 c37"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
class="c31 c32"
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
<div
|
||||
class="c35 c36"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -27,6 +27,7 @@
|
||||
"header.content.assets-single": "1 asset",
|
||||
"input.button.label": "Browse files",
|
||||
"input.label-bold": "Drag & drop",
|
||||
"input.label": "Drag & Drop here or",
|
||||
"input.label-normal": "to upload or",
|
||||
"input.placeholder": "Click to select an asset or drag & drop a file in this area",
|
||||
"input.placeholder.icon": "Drop the asset in this zone",
|
||||
|
||||
@ -0,0 +1,22 @@
|
||||
import { AssetType } from '../../constants';
|
||||
import { typeFromMime } from '../typeFromMime';
|
||||
|
||||
describe('typeFromMime', () => {
|
||||
it('gives a type of image when the mime contains "image"', () => {
|
||||
const type = typeFromMime('image/png');
|
||||
|
||||
expect(type).toBe(AssetType.Image);
|
||||
});
|
||||
|
||||
it('gives a type of video when the mime contains "video"', () => {
|
||||
const type = typeFromMime('video/mp4');
|
||||
|
||||
expect(type).toBe(AssetType.Video);
|
||||
});
|
||||
|
||||
it('gives a type of document when the mime is neither video nor image', () => {
|
||||
const type = typeFromMime('application/pdf');
|
||||
|
||||
expect(type).toBe(AssetType.Document);
|
||||
});
|
||||
});
|
||||
12
packages/core/upload/admin/src/utils/typeFromMime.js
Normal file
12
packages/core/upload/admin/src/utils/typeFromMime.js
Normal file
@ -0,0 +1,12 @@
|
||||
import { AssetType } from '../constants';
|
||||
|
||||
export const typeFromMime = mime => {
|
||||
if (mime.includes(AssetType.Image)) {
|
||||
return AssetType.Image;
|
||||
}
|
||||
if (mime.includes(AssetType.Video)) {
|
||||
return AssetType.Video;
|
||||
}
|
||||
|
||||
return AssetType.Document;
|
||||
};
|
||||
@ -1,5 +1,6 @@
|
||||
import axios from 'axios';
|
||||
import { AssetType, AssetSource } from '../constants';
|
||||
import { typeFromMime } from './typeFromMime';
|
||||
|
||||
export const urlsToAssets = async urls => {
|
||||
const assetPromises = urls.map(url =>
|
||||
@ -19,25 +20,13 @@ export const urlsToAssets = async urls => {
|
||||
const fullFilledAssets = assetsResults.filter(asset => asset.status === 'fulfilled');
|
||||
const rejectedAssets = assetsResults.filter(asset => asset.status === 'rejected');
|
||||
|
||||
const assets = fullFilledAssets.map(fullFilledAsset => {
|
||||
let assetType;
|
||||
|
||||
if (fullFilledAsset.value.mime.includes(AssetType.Image)) {
|
||||
assetType = AssetType.Image;
|
||||
} else if (fullFilledAsset.value.mime.includes(AssetType.Video)) {
|
||||
assetType = AssetType.Video;
|
||||
} else {
|
||||
assetType = AssetType.Document;
|
||||
}
|
||||
|
||||
return {
|
||||
source: AssetSource.Url,
|
||||
type: assetType,
|
||||
url: fullFilledAsset.value.url,
|
||||
ext: fullFilledAsset.value.url.split('.').pop(),
|
||||
mime: fullFilledAsset.value.mime,
|
||||
};
|
||||
});
|
||||
const assets = fullFilledAssets.map(fullFilledAsset => ({
|
||||
source: AssetSource.Url,
|
||||
type: typeFromMime(fullFilledAsset.value.mime),
|
||||
url: fullFilledAsset.value.url,
|
||||
ext: fullFilledAsset.value.url.split('.').pop(),
|
||||
mime: fullFilledAsset.value.mime,
|
||||
}));
|
||||
|
||||
const unknownAssets = rejectedAssets.map(unknownAsset => ({
|
||||
source: AssetSource.Url,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user