mirror of
https://github.com/strapi/strapi.git
synced 2025-08-08 00:37:38 +00:00
Merge branch 'features/media-lib' of github.com:strapi/strapi into media-lib/wysiwyg
This commit is contained in:
commit
3553025d59
@ -15,6 +15,7 @@ import CardControl from '../CardControl';
|
|||||||
|
|
||||||
const BrowseAssets = () => {
|
const BrowseAssets = () => {
|
||||||
const {
|
const {
|
||||||
|
allowedTypes,
|
||||||
count,
|
count,
|
||||||
files,
|
files,
|
||||||
goTo,
|
goTo,
|
||||||
@ -136,6 +137,7 @@ const BrowseAssets = () => {
|
|||||||
onChange={handleFileSelection}
|
onChange={handleFileSelection}
|
||||||
selectedItems={selectedFiles}
|
selectedItems={selectedFiles}
|
||||||
onCardClick={handleListCardClick}
|
onCardClick={handleListCardClick}
|
||||||
|
allowedTypes={allowedTypes}
|
||||||
smallCards
|
smallCards
|
||||||
renderCardControl={renderCardControl}
|
renderCardControl={renderCardControl}
|
||||||
/>
|
/>
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import React, { memo } from 'react';
|
import React, { memo } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { formatBytes, getExtension, getType } from '../../utils';
|
import { useGlobalContext } from 'strapi-helper-plugin';
|
||||||
|
import { formatBytes, getExtension, getType, getTrad } from '../../utils';
|
||||||
|
|
||||||
import Flex from '../Flex';
|
import Flex from '../Flex';
|
||||||
import Text from '../Text';
|
import Text from '../Text';
|
||||||
@ -15,6 +16,7 @@ import Wrapper from '../CardWrapper';
|
|||||||
|
|
||||||
const Card = ({
|
const Card = ({
|
||||||
id,
|
id,
|
||||||
|
isDisabled,
|
||||||
checked,
|
checked,
|
||||||
children,
|
children,
|
||||||
errorMessage,
|
errorMessage,
|
||||||
@ -33,15 +35,21 @@ const Card = ({
|
|||||||
withFileCaching,
|
withFileCaching,
|
||||||
withoutFileInfo,
|
withoutFileInfo,
|
||||||
}) => {
|
}) => {
|
||||||
|
const { formatMessage } = useGlobalContext();
|
||||||
const fileSize = formatBytes(size, 0);
|
const fileSize = formatBytes(size, 0);
|
||||||
const fileType = mime || type;
|
const fileType = mime || type;
|
||||||
|
|
||||||
const handleClick = () => {
|
const handleClick = () => {
|
||||||
onClick(id);
|
if (!isDisabled) {
|
||||||
|
onClick(id);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Wrapper onClick={handleClick}>
|
<Wrapper
|
||||||
|
title={isDisabled ? formatMessage({ id: getTrad('list.assets.type-not-allowed') }) : null}
|
||||||
|
onClick={handleClick}
|
||||||
|
>
|
||||||
<CardImgWrapper checked={checked} small={small}>
|
<CardImgWrapper checked={checked} small={small}>
|
||||||
<CardPreview
|
<CardPreview
|
||||||
hasError={hasError}
|
hasError={hasError}
|
||||||
@ -84,6 +92,7 @@ Card.defaultProps = {
|
|||||||
children: null,
|
children: null,
|
||||||
errorMessage: null,
|
errorMessage: null,
|
||||||
id: null,
|
id: null,
|
||||||
|
isDisabled: false,
|
||||||
hasError: false,
|
hasError: false,
|
||||||
hasIcon: false,
|
hasIcon: false,
|
||||||
height: null,
|
height: null,
|
||||||
@ -102,6 +111,7 @@ Card.defaultProps = {
|
|||||||
|
|
||||||
Card.propTypes = {
|
Card.propTypes = {
|
||||||
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
id: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
|
||||||
|
isDisabled: PropTypes.bool,
|
||||||
checked: PropTypes.bool,
|
checked: PropTypes.bool,
|
||||||
children: PropTypes.node,
|
children: PropTypes.node,
|
||||||
errorMessage: PropTypes.string,
|
errorMessage: PropTypes.string,
|
||||||
|
@ -11,10 +11,12 @@ const Wrapper = styled.div`
|
|||||||
`;
|
`;
|
||||||
|
|
||||||
Wrapper.defaultProps = {
|
Wrapper.defaultProps = {
|
||||||
|
isDisabled: false,
|
||||||
isDraggable: false,
|
isDraggable: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
Wrapper.propTypes = {
|
Wrapper.propTypes = {
|
||||||
|
isDisabled: PropTypes.bool,
|
||||||
isDraggable: PropTypes.bool,
|
isDraggable: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import Padded from '../Padded';
|
|||||||
const Filters = ({ onChange, onClick, filters }) => {
|
const Filters = ({ onChange, onClick, filters }) => {
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<FiltersPicker filters={filters} onChange={onChange} />
|
<FiltersPicker onChange={onChange} />
|
||||||
<Padded left size="sm" />
|
<Padded left size="sm" />
|
||||||
<FiltersList filters={filters} onClick={onClick} />
|
<FiltersList filters={filters} onClick={onClick} />
|
||||||
</>
|
</>
|
||||||
|
@ -12,7 +12,7 @@ import InputWrapper from './InputWrapper';
|
|||||||
import FilterButton from './FilterButton';
|
import FilterButton from './FilterButton';
|
||||||
import FilterInput from './FilterInput';
|
import FilterInput from './FilterInput';
|
||||||
|
|
||||||
const FiltersCard = ({ onChange, filters }) => {
|
const FiltersCard = ({ onChange }) => {
|
||||||
const { plugins } = useGlobalContext();
|
const { plugins } = useGlobalContext();
|
||||||
const timestamps = getFileModelTimestamps(plugins);
|
const timestamps = getFileModelTimestamps(plugins);
|
||||||
const [state, dispatch] = useReducer(reducer, initialState, () => init(initialState, timestamps));
|
const [state, dispatch] = useReducer(reducer, initialState, () => init(initialState, timestamps));
|
||||||
@ -20,9 +20,7 @@ const FiltersCard = ({ onChange, filters }) => {
|
|||||||
|
|
||||||
const type = filtersForm[name].type;
|
const type = filtersForm[name].type;
|
||||||
const filtersOptions = getFilterType(type);
|
const filtersOptions = getFilterType(type);
|
||||||
const options = ['image', 'video', 'file'].filter(
|
const options = ['image', 'video', 'file'];
|
||||||
f => !filters.find(e => e.value === f && e.isDisabled)
|
|
||||||
);
|
|
||||||
|
|
||||||
const handleChange = ({ target: { name, value } }) => {
|
const handleChange = ({ target: { name, value } }) => {
|
||||||
dispatch({
|
dispatch({
|
||||||
@ -89,12 +87,10 @@ const FiltersCard = ({ onChange, filters }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
FiltersCard.defaultProps = {
|
FiltersCard.defaultProps = {
|
||||||
filters: [],
|
|
||||||
onChange: () => {},
|
onChange: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
FiltersCard.propTypes = {
|
FiltersCard.propTypes = {
|
||||||
filters: PropTypes.arrayOf(PropTypes.object),
|
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ import Picker from '../Picker';
|
|||||||
|
|
||||||
import formatFilter from './utils/formatFilter';
|
import formatFilter from './utils/formatFilter';
|
||||||
|
|
||||||
const FiltersPicker = ({ onChange, filters }) => {
|
const FiltersPicker = ({ onChange }) => {
|
||||||
const handleChange = ({ target: { value } }) => {
|
const handleChange = ({ target: { value } }) => {
|
||||||
onChange({ target: { name: 'filters', value: formatFilter(value) } });
|
onChange({ target: { name: 'filters', value: formatFilter(value) } });
|
||||||
};
|
};
|
||||||
@ -25,7 +25,6 @@ const FiltersPicker = ({ onChange, filters }) => {
|
|||||||
)}
|
)}
|
||||||
renderSectionContent={onToggle => (
|
renderSectionContent={onToggle => (
|
||||||
<FiltersCard
|
<FiltersCard
|
||||||
filters={filters}
|
|
||||||
onChange={e => {
|
onChange={e => {
|
||||||
handleChange(e);
|
handleChange(e);
|
||||||
onToggle();
|
onToggle();
|
||||||
@ -38,12 +37,10 @@ const FiltersPicker = ({ onChange, filters }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
FiltersPicker.defaultProps = {
|
FiltersPicker.defaultProps = {
|
||||||
filters: [],
|
|
||||||
onChange: () => {},
|
onChange: () => {},
|
||||||
};
|
};
|
||||||
|
|
||||||
FiltersPicker.propTypes = {
|
FiltersPicker.propTypes = {
|
||||||
filters: PropTypes.arrayOf(PropTypes.object),
|
|
||||||
onChange: PropTypes.func,
|
onChange: PropTypes.func,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@ import PropTypes from 'prop-types';
|
|||||||
import { Checkbox } from '@buffetjs/core';
|
import { Checkbox } from '@buffetjs/core';
|
||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { prefixFileUrlWithBackendUrl } from 'strapi-helper-plugin';
|
import { prefixFileUrlWithBackendUrl } from 'strapi-helper-plugin';
|
||||||
import { getTrad } from '../../utils';
|
import { getTrad, getType } from '../../utils';
|
||||||
import Card from '../Card';
|
import Card from '../Card';
|
||||||
import CardControlsWrapper from '../CardControlsWrapper';
|
import CardControlsWrapper from '../CardControlsWrapper';
|
||||||
import ListWrapper from '../ListWrapper';
|
import ListWrapper from '../ListWrapper';
|
||||||
@ -12,6 +12,7 @@ import ListCell from './ListCell';
|
|||||||
import ListRow from './ListRow';
|
import ListRow from './ListRow';
|
||||||
|
|
||||||
const List = ({
|
const List = ({
|
||||||
|
allowedTypes,
|
||||||
clickable,
|
clickable,
|
||||||
data,
|
data,
|
||||||
onChange,
|
onChange,
|
||||||
@ -23,7 +24,7 @@ const List = ({
|
|||||||
}) => {
|
}) => {
|
||||||
const selectedAssets = selectedItems.length;
|
const selectedAssets = selectedItems.length;
|
||||||
|
|
||||||
const handleClick = e => {
|
const handleCheckboxClick = e => {
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -40,12 +41,15 @@ const List = ({
|
|||||||
{data.map(item => {
|
{data.map(item => {
|
||||||
const { id } = item;
|
const { id } = item;
|
||||||
const url = get(item, ['formats', 'thumbnail', 'url'], item.url);
|
const url = get(item, ['formats', 'thumbnail', 'url'], item.url);
|
||||||
|
const isAllowed =
|
||||||
|
allowedTypes.length > 0 ? allowedTypes.includes(getType(item.mime)) : true;
|
||||||
const checked = selectedItems.findIndex(file => file.id === id) !== -1;
|
const checked = selectedItems.findIndex(file => file.id === id) !== -1;
|
||||||
const fileUrl = prefixFileUrlWithBackendUrl(url);
|
const fileUrl = prefixFileUrlWithBackendUrl(url);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ListCell key={id}>
|
<ListCell key={id}>
|
||||||
<Card
|
<Card
|
||||||
|
isDisabled={!isAllowed}
|
||||||
checked={checked}
|
checked={checked}
|
||||||
{...item}
|
{...item}
|
||||||
hasIcon={clickable}
|
hasIcon={clickable}
|
||||||
@ -55,14 +59,16 @@ const List = ({
|
|||||||
>
|
>
|
||||||
{(checked || canSelect) && (
|
{(checked || canSelect) && (
|
||||||
<>
|
<>
|
||||||
<CardControlsWrapper leftAlign className="card-control-wrapper">
|
{isAllowed && (
|
||||||
<Checkbox
|
<CardControlsWrapper leftAlign className="card-control-wrapper">
|
||||||
name={`${id}`}
|
<Checkbox
|
||||||
onChange={onChange}
|
name={`${id}`}
|
||||||
onClick={handleClick}
|
onChange={onChange}
|
||||||
value={checked}
|
onClick={handleCheckboxClick}
|
||||||
/>
|
value={checked}
|
||||||
</CardControlsWrapper>
|
/>
|
||||||
|
</CardControlsWrapper>
|
||||||
|
)}
|
||||||
{renderCardControl && (
|
{renderCardControl && (
|
||||||
<CardControlsWrapper className="card-control-wrapper">
|
<CardControlsWrapper className="card-control-wrapper">
|
||||||
{renderCardControl(id)}
|
{renderCardControl(id)}
|
||||||
@ -80,6 +86,7 @@ const List = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
List.defaultProps = {
|
List.defaultProps = {
|
||||||
|
allowedTypes: [],
|
||||||
clickable: false,
|
clickable: false,
|
||||||
canSelect: true,
|
canSelect: true,
|
||||||
data: [],
|
data: [],
|
||||||
@ -91,6 +98,7 @@ List.defaultProps = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
List.propTypes = {
|
List.propTypes = {
|
||||||
|
allowedTypes: PropTypes.array,
|
||||||
clickable: PropTypes.bool,
|
clickable: PropTypes.bool,
|
||||||
canSelect: PropTypes.bool,
|
canSelect: PropTypes.bool,
|
||||||
data: PropTypes.array,
|
data: PropTypes.array,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import React, { useReducer, useState, useRef, useEffect } from 'react';
|
import React, { useReducer, useState, useRef, useEffect } from 'react';
|
||||||
import { includes, isEmpty, toString } from 'lodash';
|
import { includes, isEmpty, toString, isEqual, intersectionWith } from 'lodash';
|
||||||
import { useHistory, useLocation } from 'react-router-dom';
|
import { useHistory, useLocation } from 'react-router-dom';
|
||||||
import { Header } from '@buffetjs/custom';
|
import { Header } from '@buffetjs/custom';
|
||||||
import { useDebounce } from '@buffetjs/hooks';
|
import { useDebounce } from '@buffetjs/hooks';
|
||||||
@ -183,9 +183,15 @@ const HomePage = () => {
|
|||||||
let updatedQueryParams = generateNewSearch({ [name]: value });
|
let updatedQueryParams = generateNewSearch({ [name]: value });
|
||||||
|
|
||||||
if (name === 'filters') {
|
if (name === 'filters') {
|
||||||
const filters = [...generateFiltersFromSearch(search), value];
|
const existingFilters = generateFiltersFromSearch(search);
|
||||||
|
const canAddFilter = intersectionWith(existingFilters, [value], isEqual).length === 0;
|
||||||
|
updatedQueryParams = generateNewSearch({ [name]: existingFilters });
|
||||||
|
|
||||||
updatedQueryParams = generateNewSearch({ [name]: filters });
|
if (canAddFilter) {
|
||||||
|
const filters = [...existingFilters, value];
|
||||||
|
|
||||||
|
updatedQueryParams = generateNewSearch({ [name]: filters });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (name === '_limit') {
|
if (name === '_limit') {
|
||||||
|
@ -20,13 +20,6 @@ const InputModal = ({
|
|||||||
step,
|
step,
|
||||||
}) => {
|
}) => {
|
||||||
const singularTypes = allowedTypes.map(type => type.substring(0, type.length - 1));
|
const singularTypes = allowedTypes.map(type => type.substring(0, type.length - 1));
|
||||||
const typesToDisable = ['video', 'image', 'file'].filter(f => !singularTypes.includes(f));
|
|
||||||
const nContainsFilters = typesToDisable.map(type => ({
|
|
||||||
name: 'mime',
|
|
||||||
filter: '_ncontains',
|
|
||||||
value: type,
|
|
||||||
isDisabled: true,
|
|
||||||
}));
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<DndProvider backend={HTML5Backend}>
|
<DndProvider backend={HTML5Backend}>
|
||||||
@ -35,7 +28,6 @@ const InputModal = ({
|
|||||||
onClosed={onClosed}
|
onClosed={onClosed}
|
||||||
initialFilesToUpload={filesToUpload}
|
initialFilesToUpload={filesToUpload}
|
||||||
initialFileToEdit={fileToEdit}
|
initialFileToEdit={fileToEdit}
|
||||||
initialFilters={nContainsFilters}
|
|
||||||
isOpen={isOpen}
|
isOpen={isOpen}
|
||||||
multiple={multiple}
|
multiple={multiple}
|
||||||
noNavigation={noNavigation}
|
noNavigation={noNavigation}
|
||||||
|
@ -12,6 +12,7 @@ import {
|
|||||||
createNewFilesToUploadArray,
|
createNewFilesToUploadArray,
|
||||||
urlSchema,
|
urlSchema,
|
||||||
getFileModelTimestamps,
|
getFileModelTimestamps,
|
||||||
|
formatFilters,
|
||||||
} from '../../utils';
|
} from '../../utils';
|
||||||
import InputModalStepperContext from '../../contexts/InputModal/InputModalDataManager';
|
import InputModalStepperContext from '../../contexts/InputModal/InputModalDataManager';
|
||||||
import init from './init';
|
import init from './init';
|
||||||
@ -24,7 +25,6 @@ const InputModalStepperProvider = ({
|
|||||||
children,
|
children,
|
||||||
initialFilesToUpload,
|
initialFilesToUpload,
|
||||||
initialFileToEdit,
|
initialFileToEdit,
|
||||||
initialFilters,
|
|
||||||
isOpen,
|
isOpen,
|
||||||
multiple,
|
multiple,
|
||||||
noNavigation,
|
noNavigation,
|
||||||
@ -39,6 +39,7 @@ const InputModalStepperProvider = ({
|
|||||||
const [reducerState, dispatch] = useReducer(reducer, initialState, state =>
|
const [reducerState, dispatch] = useReducer(reducer, initialState, state =>
|
||||||
init({
|
init({
|
||||||
...state,
|
...state,
|
||||||
|
allowedTypes,
|
||||||
currentStep: step,
|
currentStep: step,
|
||||||
fileToEdit: initialFileToEdit,
|
fileToEdit: initialFileToEdit,
|
||||||
selectedFiles: Array.isArray(selectedFiles) ? selectedFiles : [selectedFiles],
|
selectedFiles: Array.isArray(selectedFiles) ? selectedFiles : [selectedFiles],
|
||||||
@ -50,7 +51,6 @@ const InputModalStepperProvider = ({
|
|||||||
: [],
|
: [],
|
||||||
params: {
|
params: {
|
||||||
...state.params,
|
...state.params,
|
||||||
filters: initialFilters,
|
|
||||||
_sort: `${updated_at}:DESC`,
|
_sort: `${updated_at}:DESC`,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@ -294,10 +294,16 @@ const InputModalStepperProvider = ({
|
|||||||
handleRemoveFileToUpload(fileIndex);
|
handleRemoveFileToUpload(fileIndex);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const getFilters = () => {
|
||||||
|
const compactedParams = compactParams(params);
|
||||||
|
const searchParams = generateSearchFromFilters(compactedParams, ['_limit', '_sort', '_start']);
|
||||||
|
|
||||||
|
return formatFilters(searchParams);
|
||||||
|
};
|
||||||
|
|
||||||
const fetchMediaLibFilesCount = async () => {
|
const fetchMediaLibFilesCount = async () => {
|
||||||
const requestURL = getRequestUrl('files/count');
|
const requestURL = getRequestUrl('files/count');
|
||||||
const compactedParams = compactParams(params);
|
const paramsToSend = getFilters();
|
||||||
const paramsToSend = generateSearchFromFilters(compactedParams, ['_limit', '_sort', '_start']);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await request(`${requestURL}?${paramsToSend}`, {
|
return await request(`${requestURL}?${paramsToSend}`, {
|
||||||
@ -322,8 +328,7 @@ const InputModalStepperProvider = ({
|
|||||||
|
|
||||||
const fetchMediaLibFiles = async () => {
|
const fetchMediaLibFiles = async () => {
|
||||||
const requestURL = getRequestUrl('files');
|
const requestURL = getRequestUrl('files');
|
||||||
const compactedParams = compactParams(params);
|
const paramsToSend = getFilters();
|
||||||
const paramsToSend = generateSearchFromFilters(compactedParams);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await request(`${requestURL}?${paramsToSend}`, {
|
return await request(`${requestURL}?${paramsToSend}`, {
|
||||||
@ -474,7 +479,6 @@ InputModalStepperProvider.propTypes = {
|
|||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
initialFilesToUpload: PropTypes.object,
|
initialFilesToUpload: PropTypes.object,
|
||||||
initialFileToEdit: PropTypes.object,
|
initialFileToEdit: PropTypes.object,
|
||||||
initialFilters: PropTypes.arrayOf(PropTypes.object),
|
|
||||||
isOpen: PropTypes.bool,
|
isOpen: PropTypes.bool,
|
||||||
multiple: PropTypes.bool.isRequired,
|
multiple: PropTypes.bool.isRequired,
|
||||||
noNavigation: PropTypes.bool,
|
noNavigation: PropTypes.bool,
|
||||||
@ -486,7 +490,6 @@ InputModalStepperProvider.propTypes = {
|
|||||||
|
|
||||||
InputModalStepperProvider.defaultProps = {
|
InputModalStepperProvider.defaultProps = {
|
||||||
initialFileToEdit: null,
|
initialFileToEdit: null,
|
||||||
initialFilters: [],
|
|
||||||
initialFilesToUpload: null,
|
initialFilesToUpload: null,
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
noNavigation: false,
|
noNavigation: false,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import produce from 'immer';
|
import produce from 'immer';
|
||||||
import { intersectionWith, differenceWith, unionWith, set } from 'lodash';
|
import { intersectionWith, differenceWith, unionWith, set, isEqual } from 'lodash';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
createNewFilesToDownloadArray,
|
createNewFilesToDownloadArray,
|
||||||
@ -30,6 +30,17 @@ 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_FILES_TO_UPLOAD': {
|
||||||
|
draftState.filesToUpload = [
|
||||||
|
...draftState.filesToUpload,
|
||||||
|
...createNewFilesToUploadArray(action.filesToUpload),
|
||||||
|
].map((fileToUpload, index) => ({
|
||||||
|
...fileToUpload,
|
||||||
|
originalIndex: index,
|
||||||
|
}));
|
||||||
|
draftState.currentStep = action.nextStep;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'ADD_URLS_TO_FILES_TO_UPLOAD': {
|
case 'ADD_URLS_TO_FILES_TO_UPLOAD': {
|
||||||
draftState.filesToUpload = [
|
draftState.filesToUpload = [
|
||||||
...draftState.filesToUpload,
|
...draftState.filesToUpload,
|
||||||
@ -43,12 +54,32 @@ const reducer = (state, action) =>
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'CLEAN_FILES_ERROR': {
|
||||||
|
draftState.filesToUpload.forEach((fileToUpload, index) => {
|
||||||
|
draftState.filesToUpload[index] = {
|
||||||
|
...fileToUpload,
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'CLEAR_FILES_TO_UPLOAD_AND_DOWNLOAD': {
|
case 'CLEAR_FILES_TO_UPLOAD_AND_DOWNLOAD': {
|
||||||
draftState.filesToUpload = [];
|
draftState.filesToUpload = [];
|
||||||
draftState.filesToDownload = [];
|
draftState.filesToDownload = [];
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'EDIT_EXISTING_FILE': {
|
||||||
|
const index = draftState.selectedFiles.findIndex(
|
||||||
|
selectedFile => selectedFile.id === action.file.id
|
||||||
|
);
|
||||||
|
|
||||||
|
if (index !== -1) {
|
||||||
|
draftState.selectedFiles[index] = action.file;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'FILE_DOWNLOADED': {
|
case 'FILE_DOWNLOADED': {
|
||||||
const index = state.filesToUpload.findIndex(file => file.tempId === action.fileTempId);
|
const index = state.filesToUpload.findIndex(file => file.tempId === action.fileTempId);
|
||||||
|
|
||||||
@ -60,32 +91,13 @@ const reducer = (state, action) =>
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'ON_CHANGE': {
|
|
||||||
set(draftState.fileToEdit, action.keys.split('.'), action.value);
|
|
||||||
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;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'SET_PARAM': {
|
case 'GO_TO': {
|
||||||
const { name, value } = action.param;
|
draftState.currentStep = action.to;
|
||||||
|
|
||||||
if (name === 'filters') {
|
|
||||||
draftState.params.filters.push(value);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (name === '_limit') {
|
|
||||||
draftState.params._start = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
draftState.params[name] = value;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'MOVE_ASSET': {
|
case 'MOVE_ASSET': {
|
||||||
@ -97,6 +109,18 @@ const reducer = (state, action) =>
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'ON_ABORT_UPLOAD': {
|
||||||
|
draftState.fileToEdit.isUploading = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'ON_CHANGE': {
|
||||||
|
set(draftState.fileToEdit, action.keys.split('.'), action.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'ON_CHANGE_URLS_TO_DOWNLOAD': {
|
||||||
|
set(draftState, ['filesToDownload'], action.value);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'ON_FILE_SELECTION': {
|
case 'ON_FILE_SELECTION': {
|
||||||
const { id } = action;
|
const { id } = action;
|
||||||
const stringId = id.toString();
|
const stringId = id.toString();
|
||||||
@ -111,71 +135,8 @@ const reducer = (state, action) =>
|
|||||||
draftState.selectedFiles.push(fileToStore);
|
draftState.selectedFiles.push(fileToStore);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'TOGGLE_SELECT_ALL': {
|
case 'ON_SUBMIT_EDIT_EXISTING_FILE': {
|
||||||
const comparator = (first, second) => first.id === second.id;
|
draftState.fileToEdit.isUploading = true;
|
||||||
const isSelected =
|
|
||||||
intersectionWith(state.selectedFiles, state.files, comparator).length ===
|
|
||||||
state.files.length;
|
|
||||||
|
|
||||||
if (isSelected) {
|
|
||||||
draftState.selectedFiles = differenceWith(state.selectedFiles, state.files, comparator);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
draftState.selectedFiles = unionWith(state.selectedFiles, state.files, comparator);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SET_FILE_ERROR': {
|
|
||||||
draftState.filesToUpload.forEach((fileToUpload, index) => {
|
|
||||||
if (fileToUpload.originalIndex === action.fileIndex) {
|
|
||||||
draftState.filesToUpload[index] = {
|
|
||||||
...draftState.filesToUpload[index],
|
|
||||||
isUploading: false,
|
|
||||||
hasError: true,
|
|
||||||
errorMessage: action.errorMessage,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'REMOVE_FILTER': {
|
|
||||||
const { filterToRemove } = action;
|
|
||||||
|
|
||||||
draftState.params.filters.splice(filterToRemove, 1);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'GO_TO': {
|
|
||||||
draftState.currentStep = action.to;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'RESET_PROPS': {
|
|
||||||
if (action.defaultSort) {
|
|
||||||
draftState.params._sort = action.defaultSort;
|
|
||||||
} else {
|
|
||||||
return initialState;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SET_FILES_UPLOADING_STATE': {
|
|
||||||
draftState.filesToUpload.forEach((fileToUpload, index) => {
|
|
||||||
draftState.filesToUpload[index] = {
|
|
||||||
...fileToUpload,
|
|
||||||
isUploading: true,
|
|
||||||
hasError: false,
|
|
||||||
errorMessage: null,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ADD_FILES_TO_UPLOAD': {
|
|
||||||
draftState.filesToUpload = [
|
|
||||||
...draftState.filesToUpload,
|
|
||||||
...createNewFilesToUploadArray(action.filesToUpload),
|
|
||||||
].map((fileToUpload, index) => ({
|
|
||||||
...fileToUpload,
|
|
||||||
originalIndex: index,
|
|
||||||
}));
|
|
||||||
draftState.currentStep = action.nextStep;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'REMOVE_FILE_TO_UPLOAD': {
|
case 'REMOVE_FILE_TO_UPLOAD': {
|
||||||
@ -195,30 +156,37 @@ const reducer = (state, action) =>
|
|||||||
draftState.filesToUpload.splice(index, 1);
|
draftState.filesToUpload.splice(index, 1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'REMOVE_FILTER': {
|
||||||
|
const { filterToRemove } = action;
|
||||||
|
|
||||||
|
draftState.params.filters.splice(filterToRemove, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'RESET_PROPS': {
|
||||||
|
if (action.defaultSort) {
|
||||||
|
draftState.params._sort = action.defaultSort;
|
||||||
|
} else {
|
||||||
|
return initialState;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
case 'SET_CROP_RESULT': {
|
case 'SET_CROP_RESULT': {
|
||||||
draftState.fileToEdit.file = action.blob;
|
draftState.fileToEdit.file = action.blob;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'CLEAN_FILES_ERROR': {
|
case 'SET_FILE_ERROR': {
|
||||||
draftState.filesToUpload.forEach((fileToUpload, index) => {
|
draftState.filesToUpload.forEach((fileToUpload, index) => {
|
||||||
draftState.filesToUpload[index] = {
|
if (fileToUpload.originalIndex === action.fileIndex) {
|
||||||
...fileToUpload,
|
draftState.filesToUpload[index] = {
|
||||||
hasError: false,
|
...draftState.filesToUpload[index],
|
||||||
errorMessage: null,
|
isUploading: false,
|
||||||
};
|
hasError: true,
|
||||||
|
errorMessage: action.errorMessage,
|
||||||
|
};
|
||||||
|
}
|
||||||
});
|
});
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'SET_NEW_FILE_TO_EDIT': {
|
|
||||||
draftState.fileToEdit = draftState.filesToUpload[action.fileIndex];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SET_FILE_TO_EDIT': {
|
|
||||||
draftState.fileToEdit = formatFileForEditing(
|
|
||||||
state.files.find(file => file.id.toString() === action.fileId.toString())
|
|
||||||
);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'SET_FILE_TO_DOWNLOAD_ERROR': {
|
case 'SET_FILE_TO_DOWNLOAD_ERROR': {
|
||||||
const index = state.filesToUpload.findIndex(file => file.tempId === action.fileTempId);
|
const index = state.filesToUpload.findIndex(file => file.tempId === action.fileTempId);
|
||||||
|
|
||||||
@ -231,20 +199,10 @@ const reducer = (state, action) =>
|
|||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'SET_FORM_DISABLED': {
|
case 'SET_FILE_TO_EDIT': {
|
||||||
draftState.isFormDisabled = action.isFormDisabled;
|
draftState.fileToEdit = formatFileForEditing(
|
||||||
break;
|
state.files.find(file => file.id.toString() === action.fileId.toString())
|
||||||
}
|
);
|
||||||
case 'ON_ABORT_UPLOAD': {
|
|
||||||
draftState.fileToEdit.isUploading = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'TOGGLE_MODAL_WARNING': {
|
|
||||||
draftState.isWarningDeleteOpen = !state.isWarningDeleteOpen;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case 'ON_SUBMIT_EDIT_EXISTING_FILE': {
|
|
||||||
draftState.fileToEdit.isUploading = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'SET_FILE_TO_EDIT_ERROR': {
|
case 'SET_FILE_TO_EDIT_ERROR': {
|
||||||
@ -253,14 +211,61 @@ const reducer = (state, action) =>
|
|||||||
draftState.fileToEdit.errorMessage = action.errorMessage;
|
draftState.fileToEdit.errorMessage = action.errorMessage;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'EDIT_EXISTING_FILE': {
|
case 'SET_FILES_UPLOADING_STATE': {
|
||||||
const index = draftState.selectedFiles.findIndex(
|
draftState.filesToUpload.forEach((fileToUpload, index) => {
|
||||||
selectedFile => selectedFile.id === action.file.id
|
draftState.filesToUpload[index] = {
|
||||||
);
|
...fileToUpload,
|
||||||
|
isUploading: true,
|
||||||
|
hasError: false,
|
||||||
|
errorMessage: null,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'SET_FORM_DISABLED': {
|
||||||
|
draftState.isFormDisabled = action.isFormDisabled;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'SET_NEW_FILE_TO_EDIT': {
|
||||||
|
draftState.fileToEdit = draftState.filesToUpload[action.fileIndex];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'SET_PARAM': {
|
||||||
|
const { name, value } = action.param;
|
||||||
|
|
||||||
if (index !== -1) {
|
if (name === 'filters') {
|
||||||
draftState.selectedFiles[index] = action.file;
|
const canAddFilter =
|
||||||
|
intersectionWith(state.params.filters, [value], isEqual).length === 0;
|
||||||
|
|
||||||
|
if (canAddFilter) {
|
||||||
|
draftState.params.filters.push(value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (name === '_limit') {
|
||||||
|
draftState.params._start = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
draftState.params[name] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'TOGGLE_MODAL_WARNING': {
|
||||||
|
draftState.isWarningDeleteOpen = !state.isWarningDeleteOpen;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 'TOGGLE_SELECT_ALL': {
|
||||||
|
const comparator = (first, second) => first.id === second.id;
|
||||||
|
const isSelected =
|
||||||
|
intersectionWith(state.selectedFiles, state.files, comparator).length ===
|
||||||
|
state.files.length;
|
||||||
|
|
||||||
|
if (isSelected) {
|
||||||
|
draftState.selectedFiles = differenceWith(state.selectedFiles, state.files, comparator);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
draftState.selectedFiles = unionWith(state.selectedFiles, state.files, comparator);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1933,4 +1933,105 @@ describe('UPLOAD | containers | ModalStepper | reducer', () => {
|
|||||||
expect(reducer(state, action)).toEqual(expected);
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('SET_PARAM', () => {
|
||||||
|
it('should set the _start param to 0 if the pagination limit changed', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'SET_PARAM',
|
||||||
|
param: {
|
||||||
|
name: '_limit',
|
||||||
|
value: 50,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
params: {
|
||||||
|
_start: 10,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
params: {
|
||||||
|
_start: 0,
|
||||||
|
_limit: 50,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add filter to params', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'SET_PARAM',
|
||||||
|
param: {
|
||||||
|
name: 'filters',
|
||||||
|
value: {
|
||||||
|
name: 'mime',
|
||||||
|
filter: '_contains',
|
||||||
|
value: 'image',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
params: {
|
||||||
|
_start: 0,
|
||||||
|
filters: [],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
params: {
|
||||||
|
_start: 0,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: 'mime',
|
||||||
|
filter: '_contains',
|
||||||
|
value: 'image',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not add filter to params if it is already exist', () => {
|
||||||
|
const action = {
|
||||||
|
type: 'SET_PARAM',
|
||||||
|
param: {
|
||||||
|
name: 'filters',
|
||||||
|
value: {
|
||||||
|
name: 'mime',
|
||||||
|
filter: '_contains',
|
||||||
|
value: 'image',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const state = {
|
||||||
|
params: {
|
||||||
|
_start: 0,
|
||||||
|
_limit: 50,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: 'mime',
|
||||||
|
filter: '_contains',
|
||||||
|
value: 'image',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const expected = {
|
||||||
|
params: {
|
||||||
|
_start: 0,
|
||||||
|
_limit: 50,
|
||||||
|
filters: [
|
||||||
|
{
|
||||||
|
name: 'mime',
|
||||||
|
filter: '_contains',
|
||||||
|
value: 'image',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
expect(reducer(state, action)).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
"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.",
|
||||||
|
"list.assets.type-not-allowed": "This type of file is not allowed.",
|
||||||
"list.assets.selected.plural": "{number} assets selected",
|
"list.assets.selected.plural": "{number} assets selected",
|
||||||
"list.assets.selected.singular": "{number} asset selected",
|
"list.assets.selected.singular": "{number} asset selected",
|
||||||
"modal.header.browse": "Upload assets",
|
"modal.header.browse": "Upload assets",
|
||||||
|
@ -0,0 +1,23 @@
|
|||||||
|
const formatFilters = params => {
|
||||||
|
const indexOfFileFilterContains = params.indexOf('mime_contains=file');
|
||||||
|
const indexOfFileFilterNContains = params.indexOf('mime_ncontains=file');
|
||||||
|
let paramsToReturn = params;
|
||||||
|
|
||||||
|
if (indexOfFileFilterContains !== -1) {
|
||||||
|
paramsToReturn = paramsToReturn.replace(
|
||||||
|
'mime_contains=file',
|
||||||
|
'mime_ncontains=image&mime_ncontains=video'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (indexOfFileFilterNContains !== -1) {
|
||||||
|
paramsToReturn = paramsToReturn.replace(
|
||||||
|
'mime_ncontains=file',
|
||||||
|
'mime_contains=image&mime_contains=video'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return paramsToReturn;
|
||||||
|
};
|
||||||
|
|
||||||
|
export default formatFilters;
|
@ -6,6 +6,7 @@ export { default as createNewFilesToDownloadArray } from './createNewFilesToDown
|
|||||||
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 formatFilters } from './formatFilters';
|
||||||
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';
|
||||||
|
@ -0,0 +1,21 @@
|
|||||||
|
import formatFilters from '../formatFilters';
|
||||||
|
|
||||||
|
describe('UPLOAD | utils | formatFilters', () => {
|
||||||
|
it('should remove the file filter and add image and video filters', () => {
|
||||||
|
const stringParams = '&mime_ncontains=file&mime_contains=file';
|
||||||
|
|
||||||
|
const actual = formatFilters(stringParams);
|
||||||
|
const expected =
|
||||||
|
'&mime_contains=image&mime_contains=video&mime_ncontains=image&mime_ncontains=video';
|
||||||
|
|
||||||
|
expect(actual).toEqual(expected);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return the string params if there is no file filter', () => {
|
||||||
|
const stringParams = '&mime_contains=image&mime_contains=video';
|
||||||
|
|
||||||
|
const actual = formatFilters(stringParams);
|
||||||
|
const expected = '&mime_contains=image&mime_contains=video';
|
||||||
|
expect(actual).toEqual(expected);
|
||||||
|
});
|
||||||
|
});
|
Loading…
x
Reference in New Issue
Block a user