diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/FromComputerForm.js b/packages/core/upload/admin/src/components/UploadAssetDialog/FromComputerForm.js
new file mode 100644
index 0000000000..f999c49b9f
--- /dev/null
+++ b/packages/core/upload/admin/src/components/UploadAssetDialog/FromComputerForm.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import { Box } from '@strapi/parts/Box';
+
+export const FromComputerForm = () => {
+ return (
+
+ From computer form
+
+ );
+};
diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/FromUrlForm.js b/packages/core/upload/admin/src/components/UploadAssetDialog/FromUrlForm.js
new file mode 100644
index 0000000000..7c8b12d9dd
--- /dev/null
+++ b/packages/core/upload/admin/src/components/UploadAssetDialog/FromUrlForm.js
@@ -0,0 +1,10 @@
+import React from 'react';
+import { Box } from '@strapi/parts/Box';
+
+export const FromUrlForm = () => {
+ return (
+
+ From URL form
+
+ );
+};
diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/UploadAssetDialog.js b/packages/core/upload/admin/src/components/UploadAssetDialog/UploadAssetDialog.js
new file mode 100644
index 0000000000..0980b58ea9
--- /dev/null
+++ b/packages/core/upload/admin/src/components/UploadAssetDialog/UploadAssetDialog.js
@@ -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 (
+
+
+
+ {formatMessage({
+ id: getTrad('header.actions.upload-assets'),
+ defaultMessage: 'Upload assets',
+ })}
+
+
+
+
+
+
+ {formatMessage({
+ id: getTrad('modal.nav.computer'),
+ defaultMessage: 'From computer',
+ })}
+
+
+ {formatMessage({
+ id: getTrad('modal.nav.url'),
+ defaultMessage: 'From URL',
+ })}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {formatMessage({ id: 'app.components.Button.cancel', defaultMessage: 'cancel' })}
+
+ }
+ endActions={
+ <>
+
+ >
+ }
+ />
+
+ );
+};
+
+UploadAssetDialog.propTypes = {
+ onSuccess: PropTypes.func.isRequired,
+ onClose: PropTypes.func.isRequired,
+};
diff --git a/packages/core/upload/admin/src/components/UploadAssetDialog/tests/UploadAssetDialog.test.js b/packages/core/upload/admin/src/components/UploadAssetDialog/tests/UploadAssetDialog.test.js
new file mode 100644
index 0000000000..65b1428eb5
--- /dev/null
+++ b/packages/core/upload/admin/src/components/UploadAssetDialog/tests/UploadAssetDialog.test.js
@@ -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(
+
+
+ ,
+ { 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;
+ }
+
+
+
+
+
+
+
+
+
+
+ Upload assets
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ `);
+ });
+});
diff --git a/packages/core/upload/admin/src/pages/App/index.js b/packages/core/upload/admin/src/pages/App/index.js
index 480c071664..322a597325 100644
--- a/packages/core/upload/admin/src/pages/App/index.js
+++ b/packages/core/upload/admin/src/pages/App/index.js
@@ -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={
- }>
+ } onClick={toggleUploadAssetDialog}>
{formatMessage({
id: getTrad('header.actions.upload-assets'),
defaultMessage: 'Upload new assets',
@@ -110,7 +113,11 @@ const App = () => {
{canRead && data && data.length === 0 && (
}>
+ }
+ onClick={toggleUploadAssetDialog}
+ >
{formatMessage({
id: getTrad('modal.header.browse'),
defaultMessage: 'Upload assets',
@@ -126,6 +133,10 @@ const App = () => {
{canRead && data && data.length > 0 && }
+
+ {showUploadAssetDialog && (
+ {}} />
+ )}
);
};
diff --git a/packages/core/upload/admin/src/translations/en.json b/packages/core/upload/admin/src/translations/en.json
index 63352e9ef0..58a9cb094f 100644
--- a/packages/core/upload/admin/src/translations/en.json
+++ b/packages/core/upload/admin/src/translations/en.json
@@ -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."
}