mirror of
https://github.com/strapi/strapi.git
synced 2025-10-13 17:15:33 +00:00
Merge pull request #5676 from strapi/fix/upload-url-error
Add url validation
This commit is contained in:
commit
01a5bd4fb4
@ -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),
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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}
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
|
@ -14,6 +14,8 @@
|
||||
"form.input.decription.file-alt": "This text will be displayed if the asset can’t 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",
|
||||
|
17
packages/strapi-plugin-upload/admin/src/utils/getYupError.js
Normal file
17
packages/strapi-plugin-upload/admin/src/utils/getYupError.js
Normal 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;
|
@ -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';
|
||||
|
@ -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;
|
Loading…
x
Reference in New Issue
Block a user