mirror of
https://github.com/strapi/strapi.git
synced 2025-11-19 11:41:49 +00:00
Merge pull request #5664 from strapi/features/media-lib-upload-url
ML/ add url upload
This commit is contained in:
commit
2830cc817e
@ -28,6 +28,7 @@ const Card = ({
|
|||||||
type,
|
type,
|
||||||
url,
|
url,
|
||||||
withFileCaching,
|
withFileCaching,
|
||||||
|
withoutFileInfo,
|
||||||
}) => {
|
}) => {
|
||||||
const fileSize = formatBytes(size, 0);
|
const fileSize = formatBytes(size, 0);
|
||||||
const fileType = mime || type;
|
const fileType = mime || type;
|
||||||
@ -50,14 +51,22 @@ const Card = ({
|
|||||||
<Border color={hasError ? 'orange' : 'mediumBlue'} shown={checked || hasError} />
|
<Border color={hasError ? 'orange' : 'mediumBlue'} shown={checked || hasError} />
|
||||||
{children}
|
{children}
|
||||||
</CardImgWrapper>
|
</CardImgWrapper>
|
||||||
|
|
||||||
|
{!withoutFileInfo ? (
|
||||||
|
<>
|
||||||
<Flex>
|
<Flex>
|
||||||
<Title>{name}</Title>
|
<Title>{name}</Title>
|
||||||
<Tag label={getType(fileType)} />
|
<Tag label={getType(fileType)} />
|
||||||
</Flex>
|
</Flex>
|
||||||
<Text color="grey" fontSize="xs" ellipsis>
|
<Text color="grey" fontSize="xs" ellipsis>
|
||||||
{`${getExtension(fileType)} - ${fileSize}`}
|
{!withoutFileInfo && `${getExtension(fileType)} - ${fileSize}`}
|
||||||
</Text>
|
</Text>
|
||||||
{hasError && <ErrorMessage>{errorMessage}</ErrorMessage>}
|
</>
|
||||||
|
) : (
|
||||||
|
<Text lineHeight="13px" />
|
||||||
|
)}
|
||||||
|
|
||||||
|
{hasError && <ErrorMessage title={errorMessage}>{errorMessage}</ErrorMessage>}
|
||||||
</Wrapper>
|
</Wrapper>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -78,6 +87,7 @@ Card.defaultProps = {
|
|||||||
type: null,
|
type: null,
|
||||||
url: null,
|
url: null,
|
||||||
withFileCaching: true,
|
withFileCaching: true,
|
||||||
|
withoutFileInfo: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
Card.propTypes = {
|
Card.propTypes = {
|
||||||
@ -96,6 +106,7 @@ Card.propTypes = {
|
|||||||
type: PropTypes.string,
|
type: PropTypes.string,
|
||||||
url: PropTypes.string,
|
url: PropTypes.string,
|
||||||
withFileCaching: PropTypes.bool,
|
withFileCaching: PropTypes.bool,
|
||||||
|
withoutFileInfo: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default memo(Card);
|
export default memo(Card);
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
import styled from 'styled-components';
|
||||||
|
import ContainerFluid from '../ContainerFluid';
|
||||||
|
|
||||||
|
const Wrapper = styled(ContainerFluid)`
|
||||||
|
margin-bottom: 0.3rem;
|
||||||
|
padding-top: 2.3rem;
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
height: 10.1rem;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export default Wrapper;
|
||||||
@ -0,0 +1,42 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Inputs } from '@buffetjs/custom';
|
||||||
|
import { useGlobalContext } from 'strapi-helper-plugin';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Wrapper from './Wrapper';
|
||||||
|
import { getTrad } from '../../utils';
|
||||||
|
|
||||||
|
const InputUploadURL = ({ onChange, value }) => {
|
||||||
|
const { formatMessage } = useGlobalContext();
|
||||||
|
const label = formatMessage({ id: getTrad('input.url.label') });
|
||||||
|
const description = formatMessage({ id: getTrad('input.url.description') });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Wrapper>
|
||||||
|
<div className="row">
|
||||||
|
<div className="col-12">
|
||||||
|
<Inputs
|
||||||
|
autoFocus
|
||||||
|
type="textarea"
|
||||||
|
name="url"
|
||||||
|
onChange={onChange}
|
||||||
|
label={label}
|
||||||
|
description={description}
|
||||||
|
value={value.join('\n')}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Wrapper>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
InputUploadURL.defaultProps = {
|
||||||
|
onChange: () => {},
|
||||||
|
value: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
InputUploadURL.propTypes = {
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
value: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default InputUploadURL;
|
||||||
@ -13,6 +13,10 @@ const ModalNavWrapper = ({ children, links, renderRightContent, initialTab }) =>
|
|||||||
|
|
||||||
const handleGoTo = link => {
|
const handleGoTo = link => {
|
||||||
setTo(link.to);
|
setTo(link.to);
|
||||||
|
|
||||||
|
if (link.onClick) {
|
||||||
|
link.onClick(link.to);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@ -1,13 +1,30 @@
|
|||||||
import React from 'react';
|
import React, { useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import InputFileModal from '../InputFileModal';
|
import InputFileModal from '../InputFileModal';
|
||||||
|
import InputUploadURL from '../InputUploadURL';
|
||||||
import ModalNavWrapper from '../ModalNavWrapper';
|
import ModalNavWrapper from '../ModalNavWrapper';
|
||||||
import ModalSection from '../ModalSection';
|
import ModalSection from '../ModalSection';
|
||||||
|
|
||||||
const UploadForm = ({ addFilesToUpload }) => {
|
const UploadForm = ({
|
||||||
|
addFilesToUpload,
|
||||||
|
filesToDownload,
|
||||||
|
onChange,
|
||||||
|
setShouldDisplayNextButton,
|
||||||
|
}) => {
|
||||||
|
useEffect(() => {
|
||||||
|
return () => {
|
||||||
|
setShouldDisplayNextButton(false);
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const handleClick = to => {
|
||||||
|
setShouldDisplayNextButton(to === 'url');
|
||||||
|
};
|
||||||
|
|
||||||
const links = [
|
const links = [
|
||||||
{ to: 'computer', label: 'computer', isDisabled: false },
|
{ to: 'computer', label: 'computer', isDisabled: false, onClick: handleClick },
|
||||||
{ to: 'url', label: 'url', isDisabled: true },
|
{ to: 'url', label: 'url', isDisabled: false, onClick: handleClick },
|
||||||
];
|
];
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -15,7 +32,7 @@ const UploadForm = ({ addFilesToUpload }) => {
|
|||||||
{to => (
|
{to => (
|
||||||
<ModalSection>
|
<ModalSection>
|
||||||
{to === 'computer' && <InputFileModal onChange={addFilesToUpload} />}
|
{to === 'computer' && <InputFileModal onChange={addFilesToUpload} />}
|
||||||
{to === 'url' && <div>COMING SOON</div>}
|
{to === 'url' && <InputUploadURL onChange={onChange} value={filesToDownload} />}
|
||||||
</ModalSection>
|
</ModalSection>
|
||||||
)}
|
)}
|
||||||
</ModalNavWrapper>
|
</ModalNavWrapper>
|
||||||
@ -24,10 +41,16 @@ const UploadForm = ({ addFilesToUpload }) => {
|
|||||||
|
|
||||||
UploadForm.defaultProps = {
|
UploadForm.defaultProps = {
|
||||||
addFilesToUpload: () => {},
|
addFilesToUpload: () => {},
|
||||||
|
filesToDownload: [],
|
||||||
|
onChange: () => {},
|
||||||
|
setShouldDisplayNextButton: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
UploadForm.propTypes = {
|
UploadForm.propTypes = {
|
||||||
addFilesToUpload: PropTypes.func,
|
addFilesToUpload: PropTypes.func,
|
||||||
|
filesToDownload: PropTypes.arrayOf(PropTypes.string),
|
||||||
|
onChange: PropTypes.func,
|
||||||
|
setShouldDisplayNextButton: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UploadForm;
|
export default UploadForm;
|
||||||
|
|||||||
@ -11,13 +11,14 @@ const RowItem = ({
|
|||||||
fileInfo,
|
fileInfo,
|
||||||
hasError,
|
hasError,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
|
isDownloading,
|
||||||
isUploading,
|
isUploading,
|
||||||
onClick,
|
onClick,
|
||||||
onClickDeleteFileToUpload,
|
onClickDeleteFileToUpload,
|
||||||
onClickEdit,
|
onClickEdit,
|
||||||
originalIndex,
|
originalIndex,
|
||||||
}) => {
|
}) => {
|
||||||
const url = URL.createObjectURL(file);
|
const url = file ? URL.createObjectURL(file) : null;
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
onClick(originalIndex);
|
onClick(originalIndex);
|
||||||
@ -31,7 +32,14 @@ const RowItem = ({
|
|||||||
onClickEdit(originalIndex);
|
onClickEdit(originalIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
const fileSize = file.mime ? file.type : file.size / 1000;
|
let fileSize = null;
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
fileSize = file.mime ? file.type : file.size / 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
const shouldDisplayControls = !isUploading && !isDownloading && file !== null;
|
||||||
|
const shouldDisplayTrashIcon = file === null && hasError;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="col-xs-12 col-md-6 col-xl-3" key={originalIndex}>
|
<div className="col-xs-12 col-md-6 col-xl-3" key={originalIndex}>
|
||||||
@ -40,14 +48,20 @@ const RowItem = ({
|
|||||||
errorMessage={errorMessage}
|
errorMessage={errorMessage}
|
||||||
hasError={hasError}
|
hasError={hasError}
|
||||||
hasIcon
|
hasIcon
|
||||||
type={file.type}
|
type={file ? file.type : null}
|
||||||
size={fileSize}
|
size={fileSize}
|
||||||
url={url}
|
url={url}
|
||||||
{...fileInfo}
|
{...fileInfo}
|
||||||
withFileCaching={false}
|
withFileCaching={false}
|
||||||
|
withoutFileInfo={isDownloading || (file === null && hasError)}
|
||||||
>
|
>
|
||||||
{isUploading && <InfiniteLoadingIndicator onClick={handleClick} />}
|
{(isUploading || isDownloading) && <InfiniteLoadingIndicator onClick={handleClick} />}
|
||||||
{!isUploading && (
|
{shouldDisplayTrashIcon && (
|
||||||
|
<CardControlsWrapper className="card-control-wrapper">
|
||||||
|
<CardControl title="delete" onClick={handleClickDelete} type="trash-alt" small />
|
||||||
|
</CardControlsWrapper>
|
||||||
|
)}
|
||||||
|
{shouldDisplayControls && (
|
||||||
<CardControlsWrapper className="card-control-wrapper">
|
<CardControlsWrapper className="card-control-wrapper">
|
||||||
<CardControl title="delete" onClick={handleClickDelete} type="trash-alt" small />
|
<CardControl title="delete" onClick={handleClickDelete} type="trash-alt" small />
|
||||||
<CardControl title="edit" onClick={handleClickEdit} small />
|
<CardControl title="edit" onClick={handleClickEdit} small />
|
||||||
@ -59,16 +73,19 @@ const RowItem = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
RowItem.defaultProps = {
|
RowItem.defaultProps = {
|
||||||
|
file: null,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
|
isDownloading: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
RowItem.propTypes = {
|
RowItem.propTypes = {
|
||||||
file: PropTypes.object.isRequired,
|
file: PropTypes.object,
|
||||||
fileInfo: PropTypes.shape({
|
fileInfo: PropTypes.shape({
|
||||||
name: PropTypes.string.isRequired,
|
name: PropTypes.string.isRequired,
|
||||||
}).isRequired,
|
}).isRequired,
|
||||||
hasError: PropTypes.bool.isRequired,
|
hasError: PropTypes.bool.isRequired,
|
||||||
errorMessage: PropTypes.string,
|
errorMessage: PropTypes.string,
|
||||||
|
isDownloading: PropTypes.bool,
|
||||||
isUploading: PropTypes.bool.isRequired,
|
isUploading: PropTypes.bool.isRequired,
|
||||||
onClick: PropTypes.func.isRequired,
|
onClick: PropTypes.func.isRequired,
|
||||||
onClickDeleteFileToUpload: PropTypes.func.isRequired,
|
onClickDeleteFileToUpload: PropTypes.func.isRequired,
|
||||||
|
|||||||
@ -2,7 +2,7 @@ import React, { useEffect, useState, useRef, memo } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Modal, ModalFooter, PopUpWarning, useGlobalContext, request } from 'strapi-helper-plugin';
|
import { Modal, ModalFooter, PopUpWarning, useGlobalContext, request } from 'strapi-helper-plugin';
|
||||||
import { Button } from '@buffetjs/core';
|
import { Button } from '@buffetjs/core';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
import { getRequestUrl, getTrad } from '../../utils';
|
import { getRequestUrl, getTrad } from '../../utils';
|
||||||
import ModalHeader from '../../components/ModalHeader';
|
import ModalHeader from '../../components/ModalHeader';
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
@ -12,16 +12,20 @@ import useModalContext from '../../hooks/useModalContext';
|
|||||||
const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
||||||
const { formatMessage } = useGlobalContext();
|
const { formatMessage } = useGlobalContext();
|
||||||
const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
|
const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
|
||||||
|
const [displayNextButton, setDisplayNextButton] = useState(false);
|
||||||
const {
|
const {
|
||||||
addFilesToUpload,
|
addFilesToUpload,
|
||||||
currentStep,
|
currentStep,
|
||||||
|
downloadFiles,
|
||||||
fetchMediaLib,
|
fetchMediaLib,
|
||||||
|
filesToDownload,
|
||||||
filesToUpload,
|
filesToUpload,
|
||||||
fileToEdit,
|
fileToEdit,
|
||||||
goTo,
|
goTo,
|
||||||
handleAbortUpload,
|
handleAbortUpload,
|
||||||
handleCancelFileToUpload,
|
handleCancelFileToUpload,
|
||||||
handleCleanFilesError,
|
handleCleanFilesError,
|
||||||
|
handleClickNextButton,
|
||||||
handleClose,
|
handleClose,
|
||||||
handleEditExistingFile,
|
handleEditExistingFile,
|
||||||
handleFileSelection,
|
handleFileSelection,
|
||||||
@ -56,29 +60,43 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentStep === 'upload' && filesToUploadLength === 0) {
|
if (currentStep === 'upload') {
|
||||||
// Go to the modal list view when file uploading is over
|
// Go to the modal list view when file uploading is over
|
||||||
|
|
||||||
|
if (filesToUploadLength === 0) {
|
||||||
goToList();
|
goToList();
|
||||||
|
} else {
|
||||||
|
downloadFiles();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [filesToUploadLength, currentStep]);
|
}, [filesToUploadLength, currentStep]);
|
||||||
|
|
||||||
const goToList = () => {
|
|
||||||
fetchMediaLib();
|
|
||||||
goTo('list');
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleConfirmDeleteFile = () => {
|
|
||||||
setShouldDeleteFile(true);
|
|
||||||
toggleModalWarning();
|
|
||||||
};
|
|
||||||
|
|
||||||
const addFilesToUploadList = ({ target: { value } }) => {
|
const addFilesToUploadList = ({ target: { value } }) => {
|
||||||
addFilesToUpload({ target: { value } });
|
addFilesToUpload({ target: { value } });
|
||||||
|
|
||||||
goNext();
|
goNext();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const goBack = () => {
|
||||||
|
goTo(prev);
|
||||||
|
};
|
||||||
|
|
||||||
|
const goNext = () => {
|
||||||
|
if (next === null) {
|
||||||
|
onToggle();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
goTo(next);
|
||||||
|
};
|
||||||
|
|
||||||
|
const goToList = () => {
|
||||||
|
fetchMediaLib();
|
||||||
|
goTo('list');
|
||||||
|
};
|
||||||
|
|
||||||
const handleClickDeleteFile = async () => {
|
const handleClickDeleteFile = async () => {
|
||||||
toggleModalWarning();
|
toggleModalWarning();
|
||||||
};
|
};
|
||||||
@ -93,6 +111,16 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleCloseModal = () => {
|
||||||
|
setDisplayNextButton(false);
|
||||||
|
handleClose();
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleConfirmDeleteFile = () => {
|
||||||
|
setShouldDeleteFile(true);
|
||||||
|
toggleModalWarning();
|
||||||
|
};
|
||||||
|
|
||||||
const handleGoToAddBrowseFiles = () => {
|
const handleGoToAddBrowseFiles = () => {
|
||||||
handleCleanFilesError();
|
handleCleanFilesError();
|
||||||
|
|
||||||
@ -187,25 +215,12 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
|||||||
onToggle();
|
onToggle();
|
||||||
};
|
};
|
||||||
|
|
||||||
const goBack = () => {
|
const shouldDisplayNextButton = currentStep === 'browse' && displayNextButton;
|
||||||
goTo(prev);
|
const isFinishButtonDisabled = filesToUpload.some(file => file.isDownloading);
|
||||||
};
|
|
||||||
|
|
||||||
// FIXME: when back button needed
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const goNext = () => {
|
|
||||||
if (next === null) {
|
|
||||||
onToggle();
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
goTo(next);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal isOpen={isOpen} onToggle={handleToggle} onClosed={handleClose}>
|
<Modal isOpen={isOpen} onToggle={handleToggle} onClosed={handleCloseModal}>
|
||||||
{/* header title */}
|
{/* header title */}
|
||||||
<ModalHeader
|
<ModalHeader
|
||||||
goBack={goBack}
|
goBack={goBack}
|
||||||
@ -218,6 +233,7 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
|||||||
<Component
|
<Component
|
||||||
addFilesToUpload={addFilesToUploadList}
|
addFilesToUpload={addFilesToUploadList}
|
||||||
components={components}
|
components={components}
|
||||||
|
filesToDownload={filesToDownload}
|
||||||
filesToUpload={filesToUpload}
|
filesToUpload={filesToUpload}
|
||||||
fileToEdit={fileToEdit}
|
fileToEdit={fileToEdit}
|
||||||
isEditingUploadedFile={currentStep === 'edit'}
|
isEditingUploadedFile={currentStep === 'edit'}
|
||||||
@ -238,6 +254,7 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
|||||||
toggleDisableForm={handleFormDisabled}
|
toggleDisableForm={handleFormDisabled}
|
||||||
onToggle={handleToggle}
|
onToggle={handleToggle}
|
||||||
setCropResult={handleSetCropResult}
|
setCropResult={handleSetCropResult}
|
||||||
|
setShouldDisplayNextButton={setDisplayNextButton}
|
||||||
withBackButton={withBackButton}
|
withBackButton={withBackButton}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -248,7 +265,12 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
|||||||
{formatMessage({ id: 'app.components.Button.cancel' })}
|
{formatMessage({ id: 'app.components.Button.cancel' })}
|
||||||
</Button>
|
</Button>
|
||||||
{currentStep === 'upload' && (
|
{currentStep === 'upload' && (
|
||||||
<Button type="button" color="success" onClick={handleUploadFiles}>
|
<Button
|
||||||
|
type="button"
|
||||||
|
color="success"
|
||||||
|
onClick={handleUploadFiles}
|
||||||
|
disabled={isFinishButtonDisabled}
|
||||||
|
>
|
||||||
{formatMessage(
|
{formatMessage(
|
||||||
{
|
{
|
||||||
id: getTrad(
|
id: getTrad(
|
||||||
@ -261,6 +283,16 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
|
|||||||
)}
|
)}
|
||||||
</Button>
|
</Button>
|
||||||
)}
|
)}
|
||||||
|
{shouldDisplayNextButton && (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
color="primary"
|
||||||
|
onClick={handleClickNextButton}
|
||||||
|
disabled={isEmpty(filesToDownload)}
|
||||||
|
>
|
||||||
|
{formatMessage({ id: getTrad('button.next') })}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{currentStep === 'edit-new' && (
|
{currentStep === 'edit-new' && (
|
||||||
<Button color="success" type="button" onClick={handleSubmitEditNewFile}>
|
<Button color="success" type="button" onClick={handleSubmitEditNewFile}>
|
||||||
{formatMessage({ id: 'form.button.finish' })}
|
{formatMessage({ id: 'form.button.finish' })}
|
||||||
|
|||||||
@ -2,12 +2,20 @@ import React, { useReducer, useEffect } from 'react';
|
|||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { request, generateSearchFromFilters } from 'strapi-helper-plugin';
|
import { request, generateSearchFromFilters } from 'strapi-helper-plugin';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
|
import axios from 'axios';
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
import { getRequestUrl, compactParams, createNewFilesToUploadArray } from '../../utils';
|
import {
|
||||||
|
getFilesToDownload,
|
||||||
|
getRequestUrl,
|
||||||
|
compactParams,
|
||||||
|
createNewFilesToUploadArray,
|
||||||
|
} from '../../utils';
|
||||||
import InputModalStepperContext from '../../contexts/InputModal/InputModalDataManager';
|
import InputModalStepperContext from '../../contexts/InputModal/InputModalDataManager';
|
||||||
import init from './init';
|
import init from './init';
|
||||||
import reducer, { initialState } from './reducer';
|
import reducer, { initialState } from './reducer';
|
||||||
|
|
||||||
|
/* eslint-disable indent */
|
||||||
|
|
||||||
const InputModalStepperProvider = ({
|
const InputModalStepperProvider = ({
|
||||||
allowedTypes,
|
allowedTypes,
|
||||||
children,
|
children,
|
||||||
@ -47,6 +55,48 @@ const InputModalStepperProvider = ({
|
|||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [isOpen, params]);
|
}, [isOpen, params]);
|
||||||
|
|
||||||
|
const downloadFiles = async () => {
|
||||||
|
const files = getFilesToDownload(filesToUpload);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.all(
|
||||||
|
files.map(file => {
|
||||||
|
const { source } = file;
|
||||||
|
|
||||||
|
return axios
|
||||||
|
.get(file.fileURL, {
|
||||||
|
headers: new Headers({ Origin: window.location.origin, mode: 'cors' }),
|
||||||
|
responseType: 'blob',
|
||||||
|
cancelToken: source.token,
|
||||||
|
})
|
||||||
|
.then(({ data }) => {
|
||||||
|
const createdFile = new File([data], file.fileURL, {
|
||||||
|
type: data.type,
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: 'FILE_DOWNLOADED',
|
||||||
|
blob: createdFile,
|
||||||
|
originalIndex: file.originalIndex,
|
||||||
|
fileTempId: file.tempId,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('fetch file error', err);
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_FILE_TO_DOWNLOAD_ERROR',
|
||||||
|
originalIndex: file.originalIndex,
|
||||||
|
fileTempId: file.tempId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
// Silent
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleRemoveFileToUpload = fileIndex => {
|
const handleRemoveFileToUpload = fileIndex => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'REMOVE_FILE_TO_UPLOAD',
|
type: 'REMOVE_FILE_TO_UPLOAD',
|
||||||
@ -54,11 +104,26 @@ const InputModalStepperProvider = ({
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleFileToEditChange = ({ target: { name, value } }) => {
|
const handleClickNextButton = () => {
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ON_CHANGE',
|
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
|
||||||
|
nextStep: 'upload',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleFileToEditChange = ({ target: { name, value } }) => {
|
||||||
|
let val = value;
|
||||||
|
let type = 'ON_CHANGE';
|
||||||
|
|
||||||
|
if (name === 'url') {
|
||||||
|
val = value.split('\n');
|
||||||
|
type = 'ON_CHANGE_URLS_TO_DOWNLOAD';
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type,
|
||||||
keys: name,
|
keys: name,
|
||||||
value,
|
value: val,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -186,8 +251,16 @@ const InputModalStepperProvider = ({
|
|||||||
const handleCancelFileToUpload = fileIndex => {
|
const handleCancelFileToUpload = fileIndex => {
|
||||||
const fileToCancel = get(filesToUpload, fileIndex, {});
|
const fileToCancel = get(filesToUpload, fileIndex, {});
|
||||||
|
|
||||||
|
const { source } = fileToCancel;
|
||||||
|
|
||||||
// Cancel upload
|
// Cancel upload
|
||||||
|
if (source) {
|
||||||
|
// Cancel dowload file upload with axios
|
||||||
|
source.cancel('Operation canceled by the user.');
|
||||||
|
} else {
|
||||||
|
// Cancel uplodad file with fetch
|
||||||
fileToCancel.abortController.abort();
|
fileToCancel.abortController.abort();
|
||||||
|
}
|
||||||
|
|
||||||
handleRemoveFileToUpload(fileIndex);
|
handleRemoveFileToUpload(fileIndex);
|
||||||
};
|
};
|
||||||
@ -306,11 +379,13 @@ const InputModalStepperProvider = ({
|
|||||||
value={{
|
value={{
|
||||||
...reducerState,
|
...reducerState,
|
||||||
addFilesToUpload,
|
addFilesToUpload,
|
||||||
|
downloadFiles,
|
||||||
fetchMediaLib,
|
fetchMediaLib,
|
||||||
goTo,
|
goTo,
|
||||||
handleAbortUpload,
|
handleAbortUpload,
|
||||||
handleAllFilesSelection,
|
handleAllFilesSelection,
|
||||||
handleCancelFileToUpload,
|
handleCancelFileToUpload,
|
||||||
|
handleClickNextButton,
|
||||||
handleCleanFilesError,
|
handleCleanFilesError,
|
||||||
handleClose,
|
handleClose,
|
||||||
handleEditExistingFile,
|
handleEditExistingFile,
|
||||||
|
|||||||
@ -1,12 +1,17 @@
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { intersectionWith, differenceWith, unionWith, set } from 'lodash';
|
import { intersectionWith, differenceWith, unionWith, set } from 'lodash';
|
||||||
|
|
||||||
import { createNewFilesToUploadArray, formatFileForEditing } from '../../utils';
|
import {
|
||||||
|
createNewFilesToDownloadArray,
|
||||||
|
createNewFilesToUploadArray,
|
||||||
|
formatFileForEditing,
|
||||||
|
} from '../../utils';
|
||||||
|
|
||||||
const initialState = {
|
const initialState = {
|
||||||
selectedFiles: [],
|
selectedFiles: [],
|
||||||
files: [],
|
files: [],
|
||||||
filesToUpload: [],
|
filesToUpload: [],
|
||||||
|
filesToDownload: [],
|
||||||
fileToEdit: null,
|
fileToEdit: null,
|
||||||
currentTab: null,
|
currentTab: null,
|
||||||
params: {
|
params: {
|
||||||
@ -24,10 +29,38 @@ const reducer = (state, action) =>
|
|||||||
// eslint-disable-next-line consistent-return
|
// eslint-disable-next-line consistent-return
|
||||||
produce(state, draftState => {
|
produce(state, draftState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case 'ADD_URLS_TO_FILES_TO_UPLOAD': {
|
||||||
|
draftState.filesToUpload = [
|
||||||
|
...draftState.filesToUpload,
|
||||||
|
...createNewFilesToDownloadArray(draftState.filesToDownload, draftState.filesToUpload),
|
||||||
|
].map((fileToUpload, index) => ({
|
||||||
|
...fileToUpload,
|
||||||
|
originalIndex: index,
|
||||||
|
}));
|
||||||
|
draftState.currentStep = action.nextStep;
|
||||||
|
draftState.filesToDownload = [];
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'FILE_DOWNLOADED': {
|
||||||
|
const index = state.filesToUpload.findIndex(file => file.tempId === action.fileTempId);
|
||||||
|
|
||||||
|
draftState.filesToUpload[index] = {
|
||||||
|
...draftState.filesToUpload[index],
|
||||||
|
isDownloading: false,
|
||||||
|
file: action.blob,
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'ON_CHANGE': {
|
case 'ON_CHANGE': {
|
||||||
set(draftState.fileToEdit, action.keys.split('.'), action.value);
|
set(draftState.fileToEdit, action.keys.split('.'), action.value);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'ON_CHANGE_URLS_TO_DOWNLOAD': {
|
||||||
|
set(draftState, ['filesToDownload'], action.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'GET_DATA_SUCCEEDED': {
|
case 'GET_DATA_SUCCEEDED': {
|
||||||
draftState.files = action.files;
|
draftState.files = action.files;
|
||||||
draftState.count = action.countData.count;
|
draftState.count = action.countData.count;
|
||||||
@ -174,6 +207,18 @@ const reducer = (state, action) =>
|
|||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'SET_FILE_TO_DOWNLOAD_ERROR': {
|
||||||
|
const index = state.filesToUpload.findIndex(file => file.tempId === action.fileTempId);
|
||||||
|
|
||||||
|
draftState.filesToUpload[index] = {
|
||||||
|
...draftState.filesToUpload[index],
|
||||||
|
isDownloading: false,
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: draftState.filesToUpload[index].fileURL,
|
||||||
|
};
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'SET_FORM_DISABLED': {
|
case 'SET_FORM_DISABLED': {
|
||||||
draftState.isFormDisabled = action.isFormDisabled;
|
draftState.isFormDisabled = action.isFormDisabled;
|
||||||
break;
|
break;
|
||||||
|
|||||||
@ -30,6 +30,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@ -43,6 +44,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 1,
|
originalIndex: 1,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -74,6 +76,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -92,6 +95,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@ -105,6 +109,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 1,
|
originalIndex: 1,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@ -118,6 +123,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 2,
|
originalIndex: 2,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -141,6 +147,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -154,6 +161,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
@ -162,6 +170,188 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ADD_URLS_TO_FILES_TO_UPLOAD', () => {
|
||||||
|
it('should add the files to the empty filesToUpload array and update the current step', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
|
||||||
|
nextStep: 'test',
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToUpload: [],
|
||||||
|
filesToDownload: ['test', 'test1'],
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
currentStep: 'test',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
originalIndex: 0,
|
||||||
|
fileURL: 'test',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const received = reducer(state, action);
|
||||||
|
|
||||||
|
expect(received.currentStep).toEqual(expected.currentStep);
|
||||||
|
expect(received.filesToDownload).toEqual(expected.filesToDownload);
|
||||||
|
expect(received.filesToUpload).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining(expected.filesToUpload[0]),
|
||||||
|
expect.objectContaining(expected.filesToUpload[1]),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add the files to the (not empty) filesToUpload array and update the current step', () => {
|
||||||
|
const state = {
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: ['test2', 'test3'],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
const action = {
|
||||||
|
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
|
||||||
|
nextStep: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
currentStep: 'test',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test2',
|
||||||
|
},
|
||||||
|
originalIndex: 2,
|
||||||
|
fileURL: 'test2',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test3',
|
||||||
|
},
|
||||||
|
originalIndex: 3,
|
||||||
|
fileURL: 'test3',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const received = reducer(state, action);
|
||||||
|
|
||||||
|
expect(received.currentStep).toEqual(expected.currentStep);
|
||||||
|
expect(received.filesToDownload).toEqual(expected.filesToDownload);
|
||||||
|
expect(received.filesToUpload).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining(expected.filesToUpload[0]),
|
||||||
|
expect.objectContaining(expected.filesToUpload[1]),
|
||||||
|
expect.objectContaining(expected.filesToUpload[2]),
|
||||||
|
expect.objectContaining(expected.filesToUpload[3]),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('CLEAN_FILES_ERROR', () => {
|
describe('CLEAN_FILES_ERROR', () => {
|
||||||
it('should not change the filesToUpload property if it is empty', () => {
|
it('should not change the filesToUpload property if it is empty', () => {
|
||||||
const action = {
|
const action = {
|
||||||
@ -243,6 +433,219 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('FILE_DOWLOADED', () => {
|
||||||
|
it('should update the corresponding file', () => {
|
||||||
|
const state = {
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const action = {
|
||||||
|
type: 'FILE_DOWNLOADED',
|
||||||
|
fileTempId: 2,
|
||||||
|
blob: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'test',
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: false,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ON_CHANGE', () => {
|
||||||
|
it('should change the data correctly', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'ON_CHANGE',
|
||||||
|
keys: 'test',
|
||||||
|
value: 'test 1',
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
fileToEdit: {
|
||||||
|
test: 'test',
|
||||||
|
isUploading: true,
|
||||||
|
},
|
||||||
|
currentStep: 'test',
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
fileToEdit: {
|
||||||
|
test: 'test 1',
|
||||||
|
isUploading: true,
|
||||||
|
},
|
||||||
|
currentStep: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('ON_CHANGE_URLS_TO_DOWNLOAD', () => {
|
||||||
|
it('should change the data correctly', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'ON_CHANGE_URLS_TO_DOWNLOAD',
|
||||||
|
keys: 'test',
|
||||||
|
value: ['test 1', 'test 2'],
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
filesToDownload: [],
|
||||||
|
currentStep: 'test',
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
filesToDownload: ['test 1', 'test 2'],
|
||||||
|
currentStep: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('SET_FILE_TO_DOWNLOAD_ERROR', () => {
|
||||||
|
it('should update the specified file error', () => {
|
||||||
|
const state = {
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const action = {
|
||||||
|
type: 'SET_FILE_TO_DOWNLOAD_ERROR',
|
||||||
|
fileTempId: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = {
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: 'test1',
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: false,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('TOGGLE_SELECT_ALL', () => {
|
describe('TOGGLE_SELECT_ALL', () => {
|
||||||
it('should select all files', () => {
|
it('should select all files', () => {
|
||||||
const action = {
|
const action = {
|
||||||
@ -1100,6 +1503,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
const expected = {
|
const expected = {
|
||||||
selectedFiles: [],
|
selectedFiles: [],
|
||||||
files: [],
|
files: [],
|
||||||
|
filesToDownload: [],
|
||||||
filesToUpload: [],
|
filesToUpload: [],
|
||||||
fileToEdit: null,
|
fileToEdit: null,
|
||||||
currentTab: null,
|
currentTab: null,
|
||||||
|
|||||||
@ -1,10 +1,11 @@
|
|||||||
import React, { useEffect, useState, useReducer, useRef } from 'react';
|
import React, { useEffect, useState, useReducer, useRef } from 'react';
|
||||||
|
import axios from 'axios';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { isEqual, get } from 'lodash';
|
import { isEqual, isEmpty, get } from 'lodash';
|
||||||
import { Modal, ModalFooter, PopUpWarning, useGlobalContext, request } from 'strapi-helper-plugin';
|
import { Modal, ModalFooter, PopUpWarning, useGlobalContext, request } from 'strapi-helper-plugin';
|
||||||
import { Button } from '@buffetjs/core';
|
import { Button } from '@buffetjs/core';
|
||||||
import pluginId from '../../pluginId';
|
import pluginId from '../../pluginId';
|
||||||
import { getTrad } from '../../utils';
|
import { getFilesToDownload, getTrad } from '../../utils';
|
||||||
import ModalHeader from '../../components/ModalHeader';
|
import ModalHeader from '../../components/ModalHeader';
|
||||||
import stepper from './stepper';
|
import stepper from './stepper';
|
||||||
import init from './init';
|
import init from './init';
|
||||||
@ -22,20 +23,29 @@ const ModalStepper = ({
|
|||||||
const [isWarningDeleteOpen, setIsWarningDeleteOpen] = useState(false);
|
const [isWarningDeleteOpen, setIsWarningDeleteOpen] = useState(false);
|
||||||
const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
|
const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
|
||||||
const [isFormDisabled, setIsFormDisabled] = useState(false);
|
const [isFormDisabled, setIsFormDisabled] = useState(false);
|
||||||
|
const [displayNextButton, setDisplayNextButton] = useState(false);
|
||||||
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
|
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
|
||||||
const { currentStep, fileToEdit, filesToUpload } = reducerState.toJS();
|
const { currentStep, fileToEdit, filesToDownload, filesToUpload } = reducerState.toJS();
|
||||||
const { Component, components, headerBreadcrumbs, next, prev, withBackButton } = stepper[
|
const { Component, components, headerBreadcrumbs, next, prev, withBackButton } = stepper[
|
||||||
currentStep
|
currentStep
|
||||||
];
|
];
|
||||||
const filesToUploadLength = filesToUpload.length;
|
const filesToUploadLength = filesToUpload.length;
|
||||||
const toggleRef = useRef(onToggle);
|
const toggleRef = useRef(onToggle);
|
||||||
const editModalRef = useRef();
|
const editModalRef = useRef();
|
||||||
|
const downloadFilesRef = useRef();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (currentStep === 'upload' && filesToUploadLength === 0) {
|
if (currentStep === 'upload') {
|
||||||
|
// Close the modal
|
||||||
|
if (filesToUploadLength === 0) {
|
||||||
// Passing true to the onToggle prop will refetch the data when the modal closes
|
// Passing true to the onToggle prop will refetch the data when the modal closes
|
||||||
toggleRef.current(true);
|
toggleRef.current(true);
|
||||||
|
} else {
|
||||||
|
// Download files from url
|
||||||
|
downloadFilesRef.current();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [filesToUploadLength, currentStep]);
|
}, [filesToUploadLength, currentStep]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -63,6 +73,49 @@ const ModalStepper = ({
|
|||||||
goTo(next);
|
goTo(next);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
downloadFilesRef.current = async () => {
|
||||||
|
const files = getFilesToDownload(filesToUpload);
|
||||||
|
|
||||||
|
try {
|
||||||
|
await Promise.all(
|
||||||
|
files.map(file => {
|
||||||
|
const { source } = file;
|
||||||
|
|
||||||
|
return axios
|
||||||
|
.get(file.fileURL, {
|
||||||
|
headers: new Headers({ Origin: window.location.origin, mode: 'cors' }),
|
||||||
|
responseType: 'blob',
|
||||||
|
cancelToken: source.token,
|
||||||
|
// Should we add a timeout?
|
||||||
|
})
|
||||||
|
.then(({ data }) => {
|
||||||
|
const createdFile = new File([data], file.fileURL, {
|
||||||
|
type: data.type,
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: 'FILE_DOWNLOADED',
|
||||||
|
blob: createdFile,
|
||||||
|
originalIndex: file.originalIndex,
|
||||||
|
fileTempId: file.tempId,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch(err => {
|
||||||
|
console.error('fetch file error', err);
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: 'SET_FILE_TO_DOWNLOAD_ERROR',
|
||||||
|
originalIndex: file.originalIndex,
|
||||||
|
fileTempId: file.tempId,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
})
|
||||||
|
);
|
||||||
|
} catch (err) {
|
||||||
|
// Silent
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
const handleAbortUpload = () => {
|
const handleAbortUpload = () => {
|
||||||
const { abortController } = fileToEdit;
|
const { abortController } = fileToEdit;
|
||||||
|
|
||||||
@ -75,9 +128,16 @@ const ModalStepper = ({
|
|||||||
|
|
||||||
const handleCancelFileToUpload = fileOriginalIndex => {
|
const handleCancelFileToUpload = fileOriginalIndex => {
|
||||||
const fileToCancel = filesToUpload.find(file => file.originalIndex === fileOriginalIndex);
|
const fileToCancel = filesToUpload.find(file => file.originalIndex === fileOriginalIndex);
|
||||||
|
const { source } = fileToCancel;
|
||||||
|
|
||||||
// Cancel upload
|
// Cancel
|
||||||
|
if (source) {
|
||||||
|
// Cancel dowload file upload with axios
|
||||||
|
source.cancel('Operation canceled by the user.');
|
||||||
|
} else {
|
||||||
|
// Cancel upload with fetch
|
||||||
fileToCancel.abortController.abort();
|
fileToCancel.abortController.abort();
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'REMOVE_FILE_TO_UPLOAD',
|
type: 'REMOVE_FILE_TO_UPLOAD',
|
||||||
@ -86,10 +146,18 @@ const ModalStepper = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleChange = ({ target: { name, value } }) => {
|
const handleChange = ({ target: { name, value } }) => {
|
||||||
|
let val = value;
|
||||||
|
let type = 'ON_CHANGE';
|
||||||
|
|
||||||
|
if (name === 'url') {
|
||||||
|
val = value.split('\n');
|
||||||
|
type = 'ON_CHANGE_URLS_TO_DOWNLOAD';
|
||||||
|
}
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'ON_CHANGE',
|
type,
|
||||||
keys: name,
|
keys: name,
|
||||||
value,
|
value: val,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -98,6 +166,14 @@ const ModalStepper = ({
|
|||||||
toggleModalWarning();
|
toggleModalWarning();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleClickNextButton = () => {
|
||||||
|
// Navigate to next step
|
||||||
|
dispatch({
|
||||||
|
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
|
||||||
|
nextStep: next,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
const handleClickDeleteFile = async () => {
|
const handleClickDeleteFile = async () => {
|
||||||
toggleModalWarning();
|
toggleModalWarning();
|
||||||
};
|
};
|
||||||
@ -120,6 +196,7 @@ const ModalStepper = ({
|
|||||||
const handleClose = () => {
|
const handleClose = () => {
|
||||||
onClosed();
|
onClosed();
|
||||||
setIsFormDisabled(false);
|
setIsFormDisabled(false);
|
||||||
|
setDisplayNextButton(false);
|
||||||
|
|
||||||
dispatch({
|
dispatch({
|
||||||
type: 'RESET_PROPS',
|
type: 'RESET_PROPS',
|
||||||
@ -297,8 +374,6 @@ const ModalStepper = ({
|
|||||||
goTo(prev);
|
goTo(prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: when back button needed
|
|
||||||
// eslint-disable-next-line no-unused-vars
|
|
||||||
const goNext = () => {
|
const goNext = () => {
|
||||||
if (next === null) {
|
if (next === null) {
|
||||||
onToggle();
|
onToggle();
|
||||||
@ -320,6 +395,9 @@ const ModalStepper = ({
|
|||||||
setIsWarningDeleteOpen(prev => !prev);
|
setIsWarningDeleteOpen(prev => !prev);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const shouldDisplayNextButton = currentStep === 'browse' && displayNextButton;
|
||||||
|
const isFinishButtonDisabled = filesToUpload.some(file => file.isDownloading);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<Modal isOpen={isOpen} onToggle={handleToggle} onClosed={handleClose}>
|
<Modal isOpen={isOpen} onToggle={handleToggle} onClosed={handleClose}>
|
||||||
@ -336,6 +414,7 @@ const ModalStepper = ({
|
|||||||
onAbortUpload={handleAbortUpload}
|
onAbortUpload={handleAbortUpload}
|
||||||
addFilesToUpload={addFilesToUpload}
|
addFilesToUpload={addFilesToUpload}
|
||||||
fileToEdit={fileToEdit}
|
fileToEdit={fileToEdit}
|
||||||
|
filesToDownload={filesToDownload}
|
||||||
filesToUpload={filesToUpload}
|
filesToUpload={filesToUpload}
|
||||||
components={components}
|
components={components}
|
||||||
isEditingUploadedFile={currentStep === 'edit'}
|
isEditingUploadedFile={currentStep === 'edit'}
|
||||||
@ -354,6 +433,7 @@ const ModalStepper = ({
|
|||||||
toggleDisableForm={setIsFormDisabled}
|
toggleDisableForm={setIsFormDisabled}
|
||||||
ref={currentStep === 'edit' ? editModalRef : null}
|
ref={currentStep === 'edit' ? editModalRef : null}
|
||||||
setCropResult={handleSetCropResult}
|
setCropResult={handleSetCropResult}
|
||||||
|
setShouldDisplayNextButton={setDisplayNextButton}
|
||||||
withBackButton={withBackButton}
|
withBackButton={withBackButton}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@ -363,8 +443,23 @@ const ModalStepper = ({
|
|||||||
<Button type="button" color="cancel" onClick={handleToggle}>
|
<Button type="button" color="cancel" onClick={handleToggle}>
|
||||||
{formatMessage({ id: 'app.components.Button.cancel' })}
|
{formatMessage({ id: 'app.components.Button.cancel' })}
|
||||||
</Button>
|
</Button>
|
||||||
|
{shouldDisplayNextButton && (
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
color="primary"
|
||||||
|
onClick={handleClickNextButton}
|
||||||
|
disabled={isEmpty(filesToDownload)}
|
||||||
|
>
|
||||||
|
{formatMessage({ id: getTrad('button.next') })}
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
{currentStep === 'upload' && (
|
{currentStep === 'upload' && (
|
||||||
<Button type="button" color="success" onClick={handleUploadFiles}>
|
<Button
|
||||||
|
type="button"
|
||||||
|
color="success"
|
||||||
|
onClick={handleUploadFiles}
|
||||||
|
disabled={isFinishButtonDisabled}
|
||||||
|
>
|
||||||
{formatMessage(
|
{formatMessage(
|
||||||
{
|
{
|
||||||
id: getTrad(
|
id: getTrad(
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
import { fromJS } from 'immutable';
|
import { fromJS } from 'immutable';
|
||||||
import createNewFilesToUploadArray from '../../utils/createNewFilesToUploadArray';
|
|
||||||
|
import { createNewFilesToDownloadArray, createNewFilesToUploadArray } from '../../utils';
|
||||||
|
|
||||||
const initialState = fromJS({
|
const initialState = fromJS({
|
||||||
currentStep: 'browse',
|
currentStep: 'browse',
|
||||||
filesToUpload: [],
|
filesToUpload: [],
|
||||||
|
filesToDownload: [],
|
||||||
fileToEdit: null,
|
fileToEdit: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -17,18 +19,45 @@ const reducer = (state, action) => {
|
|||||||
.map((data, index) => data.set('originalIndex', index))
|
.map((data, index) => data.set('originalIndex', index))
|
||||||
)
|
)
|
||||||
.update('currentStep', () => action.nextStep);
|
.update('currentStep', () => action.nextStep);
|
||||||
|
case 'ADD_URLS_TO_FILES_TO_UPLOAD':
|
||||||
|
return state
|
||||||
|
.update('filesToUpload', list =>
|
||||||
|
list
|
||||||
|
.concat(
|
||||||
|
fromJS(createNewFilesToDownloadArray(state.get('filesToDownload'), list.toJS()))
|
||||||
|
)
|
||||||
|
.map((data, index) => data.set('originalIndex', index))
|
||||||
|
)
|
||||||
|
.update('currentStep', () => action.nextStep)
|
||||||
|
.update('filesToDownload', () => fromJS([]));
|
||||||
case 'CLEAN_FILES_ERROR':
|
case 'CLEAN_FILES_ERROR':
|
||||||
return state.update('filesToUpload', list =>
|
return state.update('filesToUpload', list =>
|
||||||
list.map(data => {
|
list.map(data => {
|
||||||
|
if (data.get('tempId')) {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
return data.set('hasError', false).set('errorMessage', null);
|
return data.set('hasError', false).set('errorMessage', null);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
case 'FILE_DOWNLOADED':
|
||||||
|
return state.updateIn(['filesToUpload'], list => {
|
||||||
|
return list.map(file => {
|
||||||
|
if (file.get('tempId') === action.fileTempId) {
|
||||||
|
return file.update('isDownloading', () => false).update('file', () => action.blob);
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
});
|
||||||
|
});
|
||||||
case 'GO_TO':
|
case 'GO_TO':
|
||||||
return state.update('currentStep', () => action.to);
|
return state.update('currentStep', () => action.to);
|
||||||
case 'INIT_FILE_TO_EDIT':
|
case 'INIT_FILE_TO_EDIT':
|
||||||
return state.update('fileToEdit', () => fromJS(action.fileToEdit));
|
return state.update('fileToEdit', () => fromJS(action.fileToEdit));
|
||||||
case 'ON_ABORT_UPLOAD':
|
case 'ON_ABORT_UPLOAD':
|
||||||
return state.updateIn(['fileToEdit', 'isUploading'], () => false);
|
return state.updateIn(['fileToEdit', 'isUploading'], () => false);
|
||||||
|
case 'ON_CHANGE_URLS_TO_DOWNLOAD':
|
||||||
|
return state.updateIn(['filesToDownload'], () => fromJS(action.value));
|
||||||
case 'ON_CHANGE':
|
case 'ON_CHANGE':
|
||||||
return state.updateIn(['fileToEdit', ...action.keys.split('.')], () => action.value);
|
return state.updateIn(['fileToEdit', ...action.keys.split('.')], () => action.value);
|
||||||
case 'ON_SUBMIT_EDIT_NEW_FILE': {
|
case 'ON_SUBMIT_EDIT_NEW_FILE': {
|
||||||
@ -64,6 +93,19 @@ const reducer = (state, action) => {
|
|||||||
return data;
|
return data;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
case 'SET_FILE_TO_DOWNLOAD_ERROR':
|
||||||
|
return state.update('filesToUpload', list => {
|
||||||
|
return list.map(file => {
|
||||||
|
if (file.get('tempId') === action.fileTempId) {
|
||||||
|
return file
|
||||||
|
.update('isDownloading', () => false)
|
||||||
|
.update('hasError', () => true)
|
||||||
|
.update('errorMessage', () => file.get('fileURL'));
|
||||||
|
}
|
||||||
|
|
||||||
|
return file;
|
||||||
|
});
|
||||||
|
});
|
||||||
case 'SET_FILE_TO_EDIT':
|
case 'SET_FILE_TO_EDIT':
|
||||||
return state.update('fileToEdit', () => state.getIn(['filesToUpload', action.fileIndex]));
|
return state.update('fileToEdit', () => state.getIn(['filesToUpload', action.fileIndex]));
|
||||||
case 'SET_FILES_UPLOADING_STATE':
|
case 'SET_FILES_UPLOADING_STATE':
|
||||||
|
|||||||
@ -44,6 +44,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@ -57,6 +58,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 1,
|
originalIndex: 1,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -88,6 +90,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -106,6 +109,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@ -119,6 +123,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 1,
|
originalIndex: 1,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
abortController: new AbortController(),
|
abortController: new AbortController(),
|
||||||
@ -132,6 +137,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 2,
|
originalIndex: 2,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -155,6 +161,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -168,6 +175,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
originalIndex: 0,
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
@ -176,6 +184,188 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ADD_URLS_TO_FILES_TO_UPLOAD', () => {
|
||||||
|
it('should add the files to the empty filesToUpload array and update the current step', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
|
||||||
|
nextStep: 'test',
|
||||||
|
};
|
||||||
|
const state = fromJS({
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToUpload: [],
|
||||||
|
filesToDownload: ['test', 'test1'],
|
||||||
|
});
|
||||||
|
const expected = fromJS({
|
||||||
|
currentStep: 'test',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
originalIndex: 0,
|
||||||
|
fileURL: 'test',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const received = reducer(state, action);
|
||||||
|
|
||||||
|
expect(received.get('currentStep')).toEqual(expected.get('currentStep'));
|
||||||
|
expect(received.get('filesToDownload')).toEqual(expected.get('filesToDownload'));
|
||||||
|
expect(received.get('filesToUpload').toJS()).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining(expected.getIn(['filesToUpload', '0']).toJS()),
|
||||||
|
expect.objectContaining(expected.getIn(['filesToUpload', '1']).toJS()),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add the files to the (not empty) filesToUpload array and update the current step', () => {
|
||||||
|
const state = fromJS({
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: ['test2', 'test3'],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
const action = {
|
||||||
|
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
|
||||||
|
nextStep: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = fromJS({
|
||||||
|
currentStep: 'test',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test2',
|
||||||
|
},
|
||||||
|
originalIndex: 2,
|
||||||
|
fileURL: 'test2',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 3,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test3',
|
||||||
|
},
|
||||||
|
originalIndex: 3,
|
||||||
|
fileURL: 'test3',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 4,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const received = reducer(state, action);
|
||||||
|
|
||||||
|
expect(received.get('currentStep')).toEqual(expected.get('currentStep'));
|
||||||
|
expect(received.get('filesToDownload')).toEqual(expected.get('filesToDownload'));
|
||||||
|
expect(received.get('filesToUpload').toJS()).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining(expected.getIn(['filesToUpload', '0']).toJS()),
|
||||||
|
expect.objectContaining(expected.getIn(['filesToUpload', '1']).toJS()),
|
||||||
|
expect.objectContaining(expected.getIn(['filesToUpload', '2']).toJS()),
|
||||||
|
expect.objectContaining(expected.getIn(['filesToUpload', '3']).toJS()),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('CLEAN_FILES_ERROR', () => {
|
describe('CLEAN_FILES_ERROR', () => {
|
||||||
it('should not change the filesToUpload property if it is empty', () => {
|
it('should not change the filesToUpload property if it is empty', () => {
|
||||||
const action = {
|
const action = {
|
||||||
@ -255,6 +445,159 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
|
|
||||||
expect(reducer(state, action)).toEqual(expected);
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should not change the data containing a defined tempId key', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'CLEAN_FILES_ERROR',
|
||||||
|
};
|
||||||
|
const state = fromJS({
|
||||||
|
currentStep: 'test',
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { ok: true },
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: 'error1',
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { test: true },
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: 'error2',
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 1,
|
||||||
|
tempId: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { test: false },
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: 'error3',
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const expected = fromJS({
|
||||||
|
currentStep: 'test',
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { ok: true },
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { test: true },
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: 'error2',
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 1,
|
||||||
|
tempId: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { test: false },
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('FILE_DOWLOADED', () => {
|
||||||
|
it('should update the corresponding file', () => {
|
||||||
|
const state = fromJS({
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const action = {
|
||||||
|
type: 'FILE_DOWNLOADED',
|
||||||
|
fileTempId: 2,
|
||||||
|
blob: 'test',
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = fromJS({
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: 'test',
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: false,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('GO_TO', () => {
|
describe('GO_TO', () => {
|
||||||
@ -347,6 +690,26 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('ON_CHANGE_URLS_TO_DOWNLOAD', () => {
|
||||||
|
it('should change the data correctly', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'ON_CHANGE_URLS_TO_DOWNLOAD',
|
||||||
|
keys: 'test',
|
||||||
|
value: ['test 1', 'test 2'],
|
||||||
|
};
|
||||||
|
const state = fromJS({
|
||||||
|
filesToDownload: [],
|
||||||
|
currentStep: 'test',
|
||||||
|
});
|
||||||
|
const expected = fromJS({
|
||||||
|
filesToDownload: ['test 1', 'test 2'],
|
||||||
|
currentStep: 'test',
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('ON_SUBMIT_EDIT_EXISTING_FILE', () => {
|
describe('ON_SUBMIT_EDIT_EXISTING_FILE', () => {
|
||||||
it('should set the isUploading key to false', () => {
|
it('should set the isUploading key to false', () => {
|
||||||
const action = {
|
const action = {
|
||||||
@ -521,6 +884,7 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
const expected = fromJS({
|
const expected = fromJS({
|
||||||
currentStep: 'browse',
|
currentStep: 'browse',
|
||||||
filesToUpload: [],
|
filesToUpload: [],
|
||||||
|
filesToDownload: [],
|
||||||
fileToEdit: null,
|
fileToEdit: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -555,6 +919,89 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('SET_FILE_TO_DOWNLOAD_ERROR', () => {
|
||||||
|
it('should update the specified file error', () => {
|
||||||
|
const state = fromJS({
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
const action = {
|
||||||
|
type: 'SET_FILE_TO_DOWNLOAD_ERROR',
|
||||||
|
fileTempId: 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
const expected = fromJS({
|
||||||
|
currentStep: 'browse',
|
||||||
|
filesToDownload: [],
|
||||||
|
filesToUpload: [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test1', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
originalIndex: 0,
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test1',
|
||||||
|
},
|
||||||
|
originalIndex: 1,
|
||||||
|
fileURL: 'test1',
|
||||||
|
hasError: true,
|
||||||
|
errorMessage: 'test1',
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: false,
|
||||||
|
tempId: 2,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('SET_FILE_ERROR', () => {
|
describe('SET_FILE_ERROR', () => {
|
||||||
it('should update the specified file error', () => {
|
it('should update the specified file error', () => {
|
||||||
const action = {
|
const action = {
|
||||||
|
|||||||
@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
|
"button.next": "Next",
|
||||||
"checkControl.crop-original": "Crop the original asset",
|
"checkControl.crop-original": "Crop the original asset",
|
||||||
"checkControl.crop-duplicate": "Duplicate & crop the asset",
|
"checkControl.crop-duplicate": "Duplicate & crop the asset",
|
||||||
"control-card.add": "Add",
|
"control-card.add": "Add",
|
||||||
@ -22,6 +23,8 @@
|
|||||||
"input.label-normal": "to upload or",
|
"input.label-normal": "to upload or",
|
||||||
"input.placeholder": "Click to select an asset or drag & drop a file in this area",
|
"input.placeholder": "Click to select an asset or drag & drop a file in this area",
|
||||||
"input.button.label": "Browse files",
|
"input.button.label": "Browse files",
|
||||||
|
"input.url.label": "URL",
|
||||||
|
"input.url.description": "Separate your URL links by a carriage return.",
|
||||||
"list.assets-empty.title": "There is no asset yet",
|
"list.assets-empty.title": "There is no asset yet",
|
||||||
"list.assets-empty.title-withSearch": "There is no asset with the applied filters",
|
"list.assets-empty.title-withSearch": "There is no asset with the applied filters",
|
||||||
"list.assets-empty.subtitle": "Add a first one to the list.",
|
"list.assets-empty.subtitle": "Add a first one to the list.",
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
import axios from 'axios';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
|
||||||
|
const getTempsIds = alreadyUploadedFiles => {
|
||||||
|
return [...new Set([0, ...alreadyUploadedFiles.map(file => file.tempId).filter(id => !!id)])];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getMax = arr => {
|
||||||
|
return Math.max.apply(Math, arr) + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
const createNewFilesToDownloadArray = (filesURLArray, alreadyUploadedFiles) => {
|
||||||
|
const tempIds = getTempsIds(alreadyUploadedFiles);
|
||||||
|
const max = getMax(tempIds);
|
||||||
|
|
||||||
|
const arrayToReturn = filesURLArray.reduce((acc, current, index) => {
|
||||||
|
if (isEmpty(current)) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
const CancelToken = axios.CancelToken;
|
||||||
|
const abortController = new AbortController();
|
||||||
|
const source = CancelToken.source();
|
||||||
|
|
||||||
|
acc.push({
|
||||||
|
abortController,
|
||||||
|
source,
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: current,
|
||||||
|
},
|
||||||
|
fileURL: current,
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: max + index,
|
||||||
|
});
|
||||||
|
|
||||||
|
return acc;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return arrayToReturn;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default createNewFilesToDownloadArray;
|
||||||
|
export { getMax, getTempsIds };
|
||||||
@ -14,6 +14,7 @@ const createNewFilesToUploadArray = filesObject => {
|
|||||||
hasError: false,
|
hasError: false,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
|
tempId: null,
|
||||||
});
|
});
|
||||||
|
|
||||||
return acc;
|
return acc;
|
||||||
|
|||||||
@ -0,0 +1,5 @@
|
|||||||
|
const getFilesToDownload = files => {
|
||||||
|
return files.filter(file => file.isDownloading === true);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default getFilesToDownload;
|
||||||
@ -2,12 +2,14 @@ export { default as canDownloadFile } from './canDownloadFile';
|
|||||||
export { default as compactParams } from './compactParams';
|
export { default as compactParams } from './compactParams';
|
||||||
export { default as createFileToDownloadName } from './createFileToDownloadName';
|
export { default as createFileToDownloadName } from './createFileToDownloadName';
|
||||||
export { default as createMatrix } from './createMatrix';
|
export { default as createMatrix } from './createMatrix';
|
||||||
|
export { default as createNewFilesToDownloadArray } from './createNewFilesToDownloadArray';
|
||||||
export { default as createNewFilesToUploadArray } from './createNewFilesToUploadArray';
|
export { default as createNewFilesToUploadArray } from './createNewFilesToUploadArray';
|
||||||
export { default as formatBytes } from './formatBytes';
|
export { default as formatBytes } from './formatBytes';
|
||||||
export { default as formatFileForEditing } from './formatFileForEditing';
|
export { default as formatFileForEditing } from './formatFileForEditing';
|
||||||
export { default as generatePageFromStart } from './generatePageFromStart';
|
export { default as generatePageFromStart } from './generatePageFromStart';
|
||||||
export { default as generateStartFromPage } from './generateStartFromPage';
|
export { default as generateStartFromPage } from './generateStartFromPage';
|
||||||
export { default as getExtension } from './getExtension';
|
export { default as getExtension } from './getExtension';
|
||||||
|
export { default as getFilesToDownload } from './getFilesToDownload';
|
||||||
export { default as getRequestUrl } from './getRequestUrl';
|
export { default as getRequestUrl } from './getRequestUrl';
|
||||||
export { default as getTrad } from './getTrad';
|
export { default as getTrad } from './getTrad';
|
||||||
export { default as getType } from './getType';
|
export { default as getType } from './getType';
|
||||||
|
|||||||
@ -0,0 +1,131 @@
|
|||||||
|
import createNewFilesToDownloadArray, {
|
||||||
|
getMax,
|
||||||
|
getTempsIds,
|
||||||
|
} from '../createNewFilesToDownloadArray';
|
||||||
|
|
||||||
|
describe('UPLOAD | utils', () => {
|
||||||
|
describe('createNewFilesToDownloadArray', () => {
|
||||||
|
it('should create an array containing the formatted data and filter the empty data', () => {
|
||||||
|
const dataURLArray = ['', 'un', undefined, 'deux', null, 'trois'];
|
||||||
|
const dataFilesArray = [
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
tempId: null,
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
abortController: new AbortController(),
|
||||||
|
file: { name: 'test', ok: true },
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'test',
|
||||||
|
},
|
||||||
|
tempId: 121,
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const received = createNewFilesToDownloadArray(dataURLArray, dataFilesArray);
|
||||||
|
|
||||||
|
expect(received).toEqual(
|
||||||
|
expect.arrayContaining([
|
||||||
|
expect.objectContaining({
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'un',
|
||||||
|
},
|
||||||
|
fileURL: 'un',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 123,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'deux',
|
||||||
|
},
|
||||||
|
fileURL: 'deux',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 125,
|
||||||
|
}),
|
||||||
|
expect.objectContaining({
|
||||||
|
file: null,
|
||||||
|
fileInfo: {
|
||||||
|
alternativeText: '',
|
||||||
|
caption: '',
|
||||||
|
name: 'trois',
|
||||||
|
},
|
||||||
|
fileURL: 'trois',
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
isUploading: false,
|
||||||
|
isDownloading: true,
|
||||||
|
tempId: 127,
|
||||||
|
}),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getMax', () => {
|
||||||
|
it('should return the max of an array + 1', () => {
|
||||||
|
const data = [0, 12, 1, 121];
|
||||||
|
|
||||||
|
const expected = 122;
|
||||||
|
|
||||||
|
expect(getMax(data)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('getTempsIds', () => {
|
||||||
|
it('should add 0 to the initial array', () => {
|
||||||
|
const data = [];
|
||||||
|
|
||||||
|
const expected = [0];
|
||||||
|
|
||||||
|
expect(getTempsIds(data)).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return a unique array of ids and remove the undefined and null values', () => {
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
tempId: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tempId: 'a',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
tempId: 0,
|
||||||
|
},
|
||||||
|
{},
|
||||||
|
{
|
||||||
|
tempId: 1,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const expected = [0, 'a', 1];
|
||||||
|
|
||||||
|
expect(getTempsIds(data)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -15,6 +15,7 @@ describe('UPLOAD | containers | ModalStepper | utils', () => {
|
|||||||
caption: '',
|
caption: '',
|
||||||
name: 'test',
|
name: 'test',
|
||||||
},
|
},
|
||||||
|
tempId: null,
|
||||||
hasError: false,
|
hasError: false,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
isUploading: false,
|
isUploading: false,
|
||||||
|
|||||||
@ -0,0 +1,36 @@
|
|||||||
|
import getFilesToDownload from '../getFilesToDownload';
|
||||||
|
|
||||||
|
describe('UPLOAD | utils | getFilesToDownload', () => {
|
||||||
|
it('should return an array containing only the files that have the isDownloading key to true', () => {
|
||||||
|
const data = [
|
||||||
|
{
|
||||||
|
fileURL: '1',
|
||||||
|
isDownloading: undefined,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileURL: '2',
|
||||||
|
isDownloading: null,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileURL: '3',
|
||||||
|
isDownloading: 'true',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileURL: '4',
|
||||||
|
isDownloading: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fileURL: '5',
|
||||||
|
isDownloading: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const expected = [
|
||||||
|
{
|
||||||
|
fileURL: '5',
|
||||||
|
isDownloading: true,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
expect(getFilesToDownload(data)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
Loading…
x
Reference in New Issue
Block a user