Merge pull request #5676 from strapi/fix/upload-url-error

Add url validation
This commit is contained in:
cyril lopez 2020-04-01 14:04:45 +02:00 committed by GitHub
commit 01a5bd4fb4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 126 additions and 17 deletions

View File

@ -5,10 +5,11 @@ import PropTypes from 'prop-types';
import Wrapper from './Wrapper';
import { getTrad } from '../../utils';
const InputUploadURL = ({ onChange, value }) => {
const InputUploadURL = ({ errors, onChange, value }) => {
const { formatMessage } = useGlobalContext();
const label = formatMessage({ id: getTrad('input.url.label') });
const description = formatMessage({ id: getTrad('input.url.description') });
const error = errors ? formatMessage({ id: errors.id }, { number: errors.number }) : null;
return (
<Wrapper>
@ -16,6 +17,7 @@ const InputUploadURL = ({ onChange, value }) => {
<div className="col-12">
<Inputs
autoFocus
error={error}
type="textarea"
name="url"
onChange={onChange}
@ -30,11 +32,13 @@ const InputUploadURL = ({ onChange, value }) => {
};
InputUploadURL.defaultProps = {
errors: null,
onChange: () => {},
value: [],
};
InputUploadURL.propTypes = {
errors: PropTypes.object,
onChange: PropTypes.func,
value: PropTypes.arrayOf(PropTypes.string),
};

View File

@ -8,6 +8,7 @@ import ModalSection from '../ModalSection';
const UploadForm = ({
addFilesToUpload,
filesToDownload,
formErrors,
onChange,
setShouldDisplayNextButton,
}) => {
@ -32,7 +33,9 @@ const UploadForm = ({
{to => (
<ModalSection>
{to === 'computer' && <InputFileModal onChange={addFilesToUpload} />}
{to === 'url' && <InputUploadURL onChange={onChange} value={filesToDownload} />}
{to === 'url' && (
<InputUploadURL errors={formErrors} onChange={onChange} value={filesToDownload} />
)}
</ModalSection>
)}
</ModalNavWrapper>
@ -42,6 +45,7 @@ const UploadForm = ({
UploadForm.defaultProps = {
addFilesToUpload: () => {},
filesToDownload: [],
formErrors: null,
onChange: () => {},
setShouldDisplayNextButton: () => {},
};
@ -49,6 +53,7 @@ UploadForm.defaultProps = {
UploadForm.propTypes = {
addFilesToUpload: PropTypes.func,
filesToDownload: PropTypes.arrayOf(PropTypes.string),
formErrors: PropTypes.object,
onChange: PropTypes.func,
setShouldDisplayNextButton: PropTypes.func,
};

View File

@ -21,6 +21,7 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
filesToDownload,
filesToUpload,
fileToEdit,
formErrors,
goTo,
handleAbortUpload,
handleCancelFileToUpload,
@ -236,6 +237,7 @@ const InputModalStepper = ({ isOpen, onToggle, onInputMediaChange }) => {
filesToDownload={filesToDownload}
filesToUpload={filesToUpload}
fileToEdit={fileToEdit}
formErrors={formErrors}
isEditingUploadedFile={currentStep === 'edit'}
isFormDisabled={isFormDisabled}
onAbortUpload={handleAbortUpload}

View File

@ -1,14 +1,16 @@
import React, { useReducer, useEffect } from 'react';
import React, { useReducer, useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { request, generateSearchFromFilters } from 'strapi-helper-plugin';
import { get } from 'lodash';
import { get, isEmpty } from 'lodash';
import axios from 'axios';
import pluginId from '../../pluginId';
import {
getFilesToDownload,
getRequestUrl,
getYupError,
compactParams,
createNewFilesToUploadArray,
urlSchema,
} from '../../utils';
import InputModalStepperContext from '../../contexts/InputModal/InputModalDataManager';
import init from './init';
@ -28,6 +30,7 @@ const InputModalStepperProvider = ({
selectedFiles,
step,
}) => {
const [formErrors, setFormErrors] = useState(null);
const [reducerState, dispatch] = useReducer(reducer, initialState, state =>
init({
...state,
@ -46,7 +49,7 @@ const InputModalStepperProvider = ({
},
})
);
const { params, filesToUpload, fileToEdit } = reducerState;
const { params, filesToDownload, filesToUpload, fileToEdit } = reducerState;
useEffect(() => {
if (isOpen) {
@ -104,11 +107,24 @@ const InputModalStepperProvider = ({
});
};
const handleClickNextButton = () => {
dispatch({
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
nextStep: 'upload',
});
const handleClickNextButton = async () => {
try {
await urlSchema.validate(
{ filesToDownload: filesToDownload.filter(url => !isEmpty(url)) },
{ abortEarly: false }
);
setFormErrors(null);
// Navigate to next step
dispatch({
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
nextStep: 'upload',
});
} catch (err) {
const formattedErrors = getYupError(err);
setFormErrors(formattedErrors.filesToDownload);
}
};
const handleFileToEditChange = ({ target: { name, value } }) => {
@ -116,6 +132,8 @@ const InputModalStepperProvider = ({
let type = 'ON_CHANGE';
if (name === 'url') {
setFormErrors(null);
val = value.split('\n');
type = 'ON_CHANGE_URLS_TO_DOWNLOAD';
}
@ -381,6 +399,7 @@ const InputModalStepperProvider = ({
addFilesToUpload,
downloadFiles,
fetchMediaLib,
formErrors,
goTo,
handleAbortUpload,
handleAllFilesSelection,

View File

@ -5,7 +5,7 @@ import { isEqual, isEmpty, get } from 'lodash';
import { Modal, ModalFooter, PopUpWarning, useGlobalContext, request } from 'strapi-helper-plugin';
import { Button } from '@buffetjs/core';
import pluginId from '../../pluginId';
import { getFilesToDownload, getTrad } from '../../utils';
import { getFilesToDownload, getTrad, getYupError, urlSchema } from '../../utils';
import ModalHeader from '../../components/ModalHeader';
import stepper from './stepper';
import init from './init';
@ -23,6 +23,7 @@ const ModalStepper = ({
const [isWarningDeleteOpen, setIsWarningDeleteOpen] = useState(false);
const [shouldDeleteFile, setShouldDeleteFile] = useState(false);
const [isFormDisabled, setIsFormDisabled] = useState(false);
const [formErrors, setFormErrors] = useState(null);
const [displayNextButton, setDisplayNextButton] = useState(false);
const [reducerState, dispatch] = useReducer(reducer, initialState, init);
const { currentStep, fileToEdit, filesToDownload, filesToUpload } = reducerState.toJS();
@ -150,6 +151,8 @@ const ModalStepper = ({
let type = 'ON_CHANGE';
if (name === 'url') {
setFormErrors(null);
val = value.split('\n');
type = 'ON_CHANGE_URLS_TO_DOWNLOAD';
}
@ -166,12 +169,24 @@ const ModalStepper = ({
toggleModalWarning();
};
const handleClickNextButton = () => {
// Navigate to next step
dispatch({
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
nextStep: next,
});
const handleClickNextButton = async () => {
try {
await urlSchema.validate(
{ filesToDownload: filesToDownload.filter(url => !isEmpty(url)) },
{ abortEarly: false }
);
setFormErrors(null);
// Navigate to next step
dispatch({
type: 'ADD_URLS_TO_FILES_TO_UPLOAD',
nextStep: next,
});
} catch (err) {
const formattedErrors = getYupError(err);
setFormErrors(formattedErrors.filesToDownload);
}
};
const handleClickDeleteFile = async () => {
@ -197,6 +212,7 @@ const ModalStepper = ({
onClosed();
setIsFormDisabled(false);
setDisplayNextButton(false);
setFormErrors(null);
dispatch({
type: 'RESET_PROPS',
@ -416,6 +432,7 @@ const ModalStepper = ({
fileToEdit={fileToEdit}
filesToDownload={filesToDownload}
filesToUpload={filesToUpload}
formErrors={formErrors}
components={components}
isEditingUploadedFile={currentStep === 'edit'}
isFormDisabled={isFormDisabled}

View File

@ -14,6 +14,8 @@
"form.input.decription.file-alt": "This text will be displayed if the asset cant be shown.",
"form.input.label.file-caption": "Caption",
"form.input.label.file-name": "File name",
"form.upload-url.error.url.invalid": "One URL is invalid",
"form.upload-url.error.url.invalids": "{number} URLs are invalids",
"header.actions.upload-assets": "Upload assets",
"header.content.assets-empty": "No asset",
"header.content.assets-multiple": "{number} assets",

View File

@ -0,0 +1,17 @@
import { get } from 'lodash';
const getYupError = error => {
return get(error, 'inner', []).reduce((acc, curr) => {
acc[
curr.path
.split('[')
.join('.')
.split(']')
.join('')
] = { id: curr.message, number: curr.params.wrongURLsNumber };
return acc;
}, {});
};
export default getYupError;

View File

@ -13,4 +13,6 @@ export { default as getFilesToDownload } from './getFilesToDownload';
export { default as getRequestUrl } from './getRequestUrl';
export { default as getTrad } from './getTrad';
export { default as getType } from './getType';
export { default as getYupError } from './getYupError';
export { default as ItemTypes } from './ItemTypes';
export { default as urlSchema } from './urlYupSchema';

View File

@ -0,0 +1,41 @@
/* eslint-disable no-template-curly-in-string */
import * as yup from 'yup';
import { translatedErrors as errorsTrads } from 'strapi-helper-plugin';
import getTrad from './getTrad';
const urlSchema = yup.object().shape({
filesToDownload: yup
.array()
.of(yup.string())
.test({
name: 'isUrlValid',
message: '${path}',
test(values) {
const filtered = values.filter(val => {
return !val.startsWith('http');
});
const filteredLength = filtered.length;
if (filteredLength === 0) {
return true;
}
const errorMessage =
filteredLength > 1
? 'form.upload-url.error.url.invalids'
: 'form.upload-url.error.url.invalid';
return this.createError({
path: this.path,
message: getTrad(errorMessage),
params: { wrongURLsNumber: filtered.length },
});
},
})
.min(0, errorsTrads.min)
.max(20, errorsTrads.max),
});
export default urlSchema;