Merge pull request #5975 from strapi/front/media-lib-loader

Media lib listView loadingBar and loadingIndicator
This commit is contained in:
cyril lopez 2020-05-06 17:02:23 +02:00 committed by GitHub
commit 8194a255d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 356 additions and 204 deletions

View File

@ -41,18 +41,13 @@ class Notification extends React.Component {
};
render() {
const options =
this.options[this.props.notification.status] || this.options.info;
const options = this.options[this.props.notification.status] || this.options.info;
const {
notification: { message },
} = this.props;
const content =
isObject(message) && message.id ? (
<FormattedMessage
id={message.id}
defaultMessage={message.id}
values={message.values}
/>
<FormattedMessage id={message.id} defaultMessage={message.id} values={message.values} />
) : (
<FormattedMessage id={message} defaultMessage={message} />
);

View File

@ -31,11 +31,7 @@ function StaticLinks() {
return (
<li key={label}>
<StyledLink
href={destination}
target="_blank"
rel="noopener noreferrer"
>
<StyledLink href={destination} target="_blank" rel="noopener noreferrer">
<FontAwesomeIcon icon={icon} />
<FormattedMessage id={`app.components.LeftMenuFooter.${label}`} />
</StyledLink>

View File

@ -402,7 +402,6 @@ exports[`Admin | containers | EditView should match the snapshot 1`] = `
font-size: 2.4rem;
line-height: normal;
font-weight: 600;
text-transform: capitalize;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

View File

@ -151,7 +151,6 @@ exports[`Admin | containers | ListView should match the snapshot 1`] = `
font-size: 2.4rem;
line-height: normal;
font-weight: 600;
text-transform: capitalize;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

View File

@ -22,12 +22,12 @@
"@babel/preset-env": "^7.9.5",
"@babel/preset-react": "^7.9.4",
"@babel/runtime": "^7.9.2",
"@buffetjs/core": "3.1.0-next.2",
"@buffetjs/custom": "3.1.0-next.2",
"@buffetjs/hooks": "3.0.6",
"@buffetjs/icons": "3.1.0-next.2",
"@buffetjs/styles": "3.1.0-next.2",
"@buffetjs/utils": "3.0.6",
"@buffetjs/core": "3.1.0-next.3",
"@buffetjs/custom": "3.1.0-next.3",
"@buffetjs/hooks": "3.1.0-next.3",
"@buffetjs/icons": "3.1.0-next.3",
"@buffetjs/styles": "3.1.0-next.3",
"@buffetjs/utils": "3.1.0-next.3",
"@fortawesome/fontawesome-free": "^5.11.2",
"@fortawesome/fontawesome-svg-core": "^1.2.25",
"@fortawesome/free-brands-svg-icons": "^5.11.2",

View File

@ -0,0 +1,88 @@
import React from 'react';
import PropTypes from 'prop-types';
import { PageFooter, useQuery } from 'strapi-helper-plugin';
import { generatePageFromStart, generateStartFromPage } from '../../../utils';
import List from '../../../components/List';
import ListEmpty from '../../../components/ListEmpty';
import Padded from '../../../components/Padded';
const HomePageList = ({
areResultsEmptyWithSettings,
data,
dataCount,
dataToDelete,
onCardCheck,
onCardClick,
onChange,
onClick,
}) => {
const query = useQuery();
const limit = parseInt(query.get('_limit'), 10) || 10;
const start = parseInt(query.get('_start'), 10) || 0;
const params = {
_limit: limit,
_page: generatePageFromStart(start, limit),
};
const handleChangeListParams = ({ target: { name, value } }) => {
if (name.includes('_page')) {
onChange({
target: { name: '_start', value: generateStartFromPage(value, limit) },
});
} else {
onChange({ target: { name: '_limit', value } });
}
};
if (dataCount > 0 && !areResultsEmptyWithSettings) {
return (
<>
<List
data={data}
onChange={onCardCheck}
onCardClick={onCardClick}
selectedItems={dataToDelete}
/>
<Padded left right size="sm">
<Padded left right size="xs">
<PageFooter
context={{ emitEvent: () => {} }}
count={dataCount}
onChangeParams={handleChangeListParams}
params={params}
/>
</Padded>
</Padded>
</>
);
}
return <ListEmpty onClick={onClick} hasSearchApplied={areResultsEmptyWithSettings} />;
};
HomePageList.defaultProps = {
areResultsEmptyWithSettings: false,
data: [],
dataCount: 0,
dataToDelete: [],
onCardCheck: () => {},
onCardClick: () => {},
onChange: () => {},
onClick: () => {},
};
HomePageList.propTypes = {
areResultsEmptyWithSettings: PropTypes.bool,
data: PropTypes.array,
dataCount: PropTypes.number,
dataToDelete: PropTypes.array,
onCardCheck: PropTypes.func,
onCardClick: PropTypes.func,
onChange: PropTypes.func,
onClick: PropTypes.func,
};
export default HomePageList;

View File

@ -0,0 +1,85 @@
import React, { useEffect, useState } from 'react';
import PropTypes from 'prop-types';
import { useDebounce } from '@buffetjs/hooks';
import { HeaderSearch, useGlobalContext, useQuery } from 'strapi-helper-plugin';
import { getTrad, getFileModelTimestamps } from '../../../utils';
import ControlsWrapper from '../../../components/ControlsWrapper';
import Filters from '../../../components/Filters';
import Padded from '../../../components/Padded';
import SelectAll from '../../../components/SelectAll';
import SortPicker from '../../../components/SortPicker';
const HomePageSettings = ({
areAllCheckboxesSelected,
filters,
hasSomeCheckboxSelected,
onChange,
onFilterDelete,
onSelectAll,
}) => {
const { formatMessage, plugins } = useGlobalContext();
const [, updated_at] = getFileModelTimestamps(plugins);
const query = useQuery();
const [searchValue, setSearchValue] = useState(query.get('_q') || '');
const debouncedSearch = useDebounce(searchValue, 300);
const pluginName = formatMessage({ id: getTrad('plugin.name') });
useEffect(() => {
onChange({ target: { name: '_q', value: debouncedSearch } });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedSearch]);
const handleChangeSearchValue = ({ target: { value } }) => {
setSearchValue(value);
};
const handleClearSearch = () => {
setSearchValue('');
};
return (
<>
<HeaderSearch
label={pluginName}
onChange={handleChangeSearchValue}
onClear={handleClearSearch}
placeholder={formatMessage({ id: getTrad('search.placeholder') })}
name="_q"
value={searchValue}
/>
<ControlsWrapper>
<SelectAll
onChange={onSelectAll}
checked={areAllCheckboxesSelected}
someChecked={hasSomeCheckboxSelected && !areAllCheckboxesSelected}
/>
<Padded right />
<SortPicker onChange={onChange} value={query.get('_sort') || `${updated_at}:DESC`} />
<Padded right />
<Filters onChange={onChange} filters={filters} onClick={onFilterDelete} />
</ControlsWrapper>
</>
);
};
HomePageSettings.defaultProps = {
areAllCheckboxesSelected: false,
filters: [],
hasSomeCheckboxSelected: false,
onChange: () => {},
onFilterDelete: () => {},
onSelectAll: () => {},
};
HomePageSettings.propTypes = {
areAllCheckboxesSelected: PropTypes.bool,
filters: PropTypes.array,
hasSomeCheckboxSelected: PropTypes.bool,
onChange: PropTypes.func,
onFilterDelete: PropTypes.func,
onSelectAll: PropTypes.func,
};
export default HomePageSettings;

View File

@ -0,0 +1,86 @@
import React from 'react';
import PropTypes from 'prop-types';
import { isEmpty } from 'lodash';
import { useLocation } from 'react-router-dom';
import { generateFiltersFromSearch, useQuery } from 'strapi-helper-plugin';
import HomePageSettings from './HomePageSettings';
import HomePageList from './HomePageList';
const HomePageContent = ({
data,
dataCount,
dataToDelete,
onCardCheck,
onCardClick,
onClick,
onFilterDelete,
onParamsChange,
onSelectAll,
}) => {
const query = useQuery();
const { search } = useLocation();
const filters = generateFiltersFromSearch(search);
const hasSomeCheckboxSelected = data.some(item =>
dataToDelete.find(itemToDelete => item.id.toString() === itemToDelete.id.toString())
);
const areAllCheckboxesSelected =
data.every(item =>
dataToDelete.find(itemToDelete => item.id.toString() === itemToDelete.id.toString())
) && hasSomeCheckboxSelected;
const hasFilters = !isEmpty(filters);
const hasSearch = !isEmpty(query.get('_q'));
const areResultsEmptyWithSearchOrFilters = isEmpty(data) && (hasSearch || hasFilters);
return (
<>
<HomePageSettings
areAllCheckboxesSelected={areAllCheckboxesSelected}
filters={filters}
hasSomeCheckboxSelected={hasSomeCheckboxSelected}
onChange={onParamsChange}
onFilterDelete={onFilterDelete}
onSelectAll={onSelectAll}
/>
<HomePageList
areResultsEmptyWithSettings={areResultsEmptyWithSearchOrFilters}
data={data}
dataCount={dataCount}
dataToDelete={dataToDelete}
onCardCheck={onCardCheck}
onCardClick={onCardClick}
onClick={onClick}
onChange={onParamsChange}
/>
</>
);
};
HomePageContent.defaultProps = {
data: [],
dataCount: 0,
dataToDelete: [],
onCardCheck: () => {},
onCardClick: () => {},
onClick: () => {},
onFilterDelete: () => {},
onParamsChange: () => {},
onSelectAll: () => {},
};
HomePageContent.propTypes = {
data: PropTypes.array,
dataCount: PropTypes.number,
dataToDelete: PropTypes.array,
onCardCheck: PropTypes.func,
onCardClick: PropTypes.func,
onClick: PropTypes.func,
onFilterDelete: PropTypes.func,
onParamsChange: PropTypes.func,
onSelectAll: PropTypes.func,
};
export default HomePageContent;

View File

@ -1,35 +1,20 @@
import React, { useReducer, useState, useRef, useEffect } from 'react';
import { includes, isEmpty, toString, isEqual, intersectionWith } from 'lodash';
import React, { useReducer, useRef, useState, useEffect } from 'react';
import { includes, toString, isEqual, intersectionWith } from 'lodash';
import { useHistory, useLocation } from 'react-router-dom';
import { Header } from '@buffetjs/custom';
import { useDebounce } from '@buffetjs/hooks';
import {
HeaderSearch,
PageFooter,
PopUpWarning,
LoadingIndicatorPage,
LoadingIndicator,
useGlobalContext,
generateFiltersFromSearch,
generateSearchFromFilters,
request,
useQuery,
} from 'strapi-helper-plugin';
import {
formatFileForEditing,
getRequestUrl,
getTrad,
generatePageFromStart,
generateStartFromPage,
getFileModelTimestamps,
} from '../../utils';
import { formatFileForEditing, getRequestUrl, getTrad, getFileModelTimestamps } from '../../utils';
import Container from '../../components/Container';
import ControlsWrapper from '../../components/ControlsWrapper';
import HomePageContent from './HomePageContent';
import Padded from '../../components/Padded';
import SelectAll from '../../components/SelectAll';
import SortPicker from '../../components/SortPicker';
import Filters from '../../components/Filters';
import List from '../../components/List';
import ListEmpty from '../../components/ListEmpty';
import ModalStepper from '../ModalStepper';
import { generateStringFromParams, getHeaderLabel } from './utils';
import init from './init';
@ -45,25 +30,17 @@ const HomePage = () => {
const [fileToEdit, setFileToEdit] = useState(null);
const [shouldRefetch, setShouldRefetch] = useState(false);
const [modalInitialStep, setModalInitialStep] = useState('browse');
const [searchValue, setSearchValue] = useState(query.get('_q') || '');
const { push } = useHistory();
const { search } = useLocation();
const isMounted = useRef(true);
const { data, dataCount, dataToDelete, isLoading } = reducerState.toJS();
const pluginName = formatMessage({ id: getTrad('plugin.name') });
const paramsKeys = ['_limit', '_start', '_q', '_sort'];
const debouncedSearch = useDebounce(searchValue, 300);
useEffect(() => {
return () => (isMounted.current = false);
}, []);
useEffect(() => {
handleChangeParams({ target: { name: '_q', value: debouncedSearch } });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [debouncedSearch]);
useEffect(() => {
fetchListData();
@ -84,20 +61,6 @@ const HomePage = () => {
}
};
const fetchListData = async () => {
dispatch({ type: 'GET_DATA' });
const [data, count] = await Promise.all([fetchData(), fetchDataCount()]);
if (isMounted.current) {
dispatch({
type: 'GET_DATA_SUCCEEDED',
data,
count,
});
}
};
const fetchData = async () => {
const dataRequestURL = getRequestUrl('files');
const params = generateStringFromParams(query);
@ -142,6 +105,28 @@ const HomePage = () => {
return null;
};
const fetchListData = async () => {
dispatch({ type: 'GET_DATA' });
const [data, count] = await Promise.all([fetchData(), fetchDataCount()]);
if (isMounted.current) {
dispatch({
type: 'GET_DATA_SUCCEEDED',
data,
count,
});
}
};
const generateNewSearch = (updatedParams = {}) => {
return {
...getSearchParams(),
filters: generateFiltersFromSearch(search),
...updatedParams,
};
};
const getSearchParams = () => {
const params = {};
@ -154,14 +139,6 @@ const HomePage = () => {
return params;
};
const generateNewSearch = (updatedParams = {}) => {
return {
...getSearchParams(),
filters: generateFiltersFromSearch(search),
...updatedParams,
};
};
const handleChangeCheck = ({ target: { name } }) => {
dispatch({
type: 'ON_CHANGE_DATA_TO_DELETE',
@ -169,16 +146,6 @@ const HomePage = () => {
});
};
const handleChangeListParams = ({ target: { name, value } }) => {
if (name.includes('_page')) {
handleChangeParams({
target: { name: '_start', value: generateStartFromPage(value, limit) },
});
} else {
handleChangeParams({ target: { name: '_limit', value } });
}
};
const handleChangeParams = ({ target: { name, value } }) => {
let updatedQueryParams = generateNewSearch({ [name]: value });
@ -203,10 +170,6 @@ const HomePage = () => {
push({ search: encodeURI(newSearch) });
};
const handleChangeSearchValue = ({ target: { value } }) => {
setSearchValue(value);
};
const handleClickEditFile = id => {
const file = formatFileForEditing(data.find(file => toString(file.id) === toString(id)));
@ -215,10 +178,6 @@ const HomePage = () => {
handleClickToggleModal();
};
const handleClearSearch = () => {
setSearchValue('');
};
const handleClickToggleModal = (refetch = false) => {
setIsModalOpen(prev => !prev);
setShouldRefetch(refetch);
@ -316,7 +275,7 @@ const HomePage = () => {
},
content: formatMessage(
{
id: getTrad(getHeaderLabel(data)),
id: getTrad(getHeaderLabel(dataCount)),
},
{ number: dataCount }
),
@ -339,80 +298,25 @@ const HomePage = () => {
],
};
const limit = parseInt(query.get('_limit'), 10) || 10;
const start = parseInt(query.get('_start'), 10) || 0;
const params = {
_limit: limit,
_page: generatePageFromStart(start, limit),
};
const hasSomeCheckboxSelected = data.some(item =>
dataToDelete.find(itemToDelete => item.id.toString() === itemToDelete.id.toString())
);
const areAllCheckboxesSelected =
data.every(item =>
dataToDelete.find(itemToDelete => item.id.toString() === itemToDelete.id.toString())
) && hasSomeCheckboxSelected;
if (isLoading) {
return <LoadingIndicatorPage />;
}
const filters = generateFiltersFromSearch(search);
const hasFilters = !isEmpty(filters);
const hasSearch = !isEmpty(searchValue);
const areResultsEmptyWithSearchOrFilters = isEmpty(data) && (hasSearch || hasFilters);
return (
<Container>
<Header {...headerProps} />
<HeaderSearch
label={pluginName}
onChange={handleChangeSearchValue}
onClear={handleClearSearch}
placeholder={formatMessage({ id: getTrad('search.placeholder') })}
name="_q"
value={searchValue}
/>
<ControlsWrapper>
<SelectAll
onChange={handleSelectAll}
checked={areAllCheckboxesSelected}
someChecked={hasSomeCheckboxSelected && !areAllCheckboxesSelected}
/>
<Padded right />
<SortPicker
onChange={handleChangeParams}
value={query.get('_sort') || `${updated_at}:DESC`}
/>
<Padded right />
<Filters onChange={handleChangeParams} filters={filters} onClick={handleDeleteFilter} />
</ControlsWrapper>
{dataCount > 0 && !areResultsEmptyWithSearchOrFilters ? (
<Header {...headerProps} isLoading={isLoading} />
{isLoading ? (
<>
<List
data={data}
onChange={handleChangeCheck}
onCardClick={handleClickEditFile}
selectedItems={dataToDelete}
/>
<Padded left right size="sm">
<Padded left right size="xs">
<PageFooter
context={{ emitEvent: () => {} }}
count={dataCount}
onChangeParams={handleChangeListParams}
params={params}
/>
</Padded>
</Padded>
<Padded top bottom size="lg" />
<LoadingIndicator />
</>
) : (
<ListEmpty
<HomePageContent
data={data}
dataCount={dataCount}
dataToDelete={dataToDelete}
onCardCheck={handleChangeCheck}
onCardClick={handleClickEditFile}
onClick={handleClickToggleModal}
hasSearchApplied={areResultsEmptyWithSearchOrFilters}
onFilterDelete={handleDeleteFilter}
onParamsChange={handleChangeParams}
onSelectAll={handleSelectAll}
/>
)}
<ModalStepper

View File

@ -40,6 +40,10 @@ const reducer = (state, action) => {
return state.removeIn(['dataToDelete', index]);
}
case 'ON_DELETE_MEDIA_SUCCEEDED':
return state
.update('data', list => list.filter(item => item.get('id') !== action.mediaId))
.update('dataCount', count => count - 1);
case 'TOGGLE_SELECT_ALL': {
const isSelected = state.get('data').every(item => state.get('dataToDelete').includes(item));
@ -57,10 +61,6 @@ const reducer = (state, action) => {
return dataToDelete.concat(newItems);
});
}
case 'ON_DELETE_MEDIA_SUCCEEDED':
return state
.update('data', list => list.filter(item => item.get('id') !== action.mediaId))
.update('dataCount', count => count - 1);
default:
return state;
}

View File

@ -1,9 +1,9 @@
const getHeaderLabel = array => {
const getHeaderLabel = count => {
let headerLabel = 'header.content.assets-single';
if (array.length === 0) {
if (count === 0) {
headerLabel = 'header.content.assets-empty';
} else if (array.length > 1) {
} else if (count > 1) {
headerLabel = 'header.content.assets-multiple';
}

View File

@ -2,25 +2,25 @@ import getHeaderLabel from '../getHeaderLabel';
describe('MEDIA LIBRARY | containers | HomePage | utils', () => {
describe('getHeaderLabel', () => {
it('should return the header translation with this empty suffix if there is no data', () => {
const data = [];
it('should return the header translation with this empty suffix if count is 0', () => {
const count = 0;
const expected = 'header.content.assets-empty';
expect(getHeaderLabel(data)).toEqual(expected);
expect(getHeaderLabel(count)).toEqual(expected);
});
it('should return the header translation with this single suffix if there is 1 element', () => {
const data = ['test'];
it('should return the header translation with this single suffix if count is 1', () => {
const count = 1;
const expected = 'header.content.assets-single';
expect(getHeaderLabel(data)).toEqual(expected);
expect(getHeaderLabel(count)).toEqual(expected);
});
it('should return the header translation with this multiple suffix if there is more than 1 element', () => {
const data = ['test', 'test2'];
it('should return the header translation with this multiple suffix if count is greater than 1', () => {
const count = 2;
const expected = 'header.content.assets-multiple';
expect(getHeaderLabel(data)).toEqual(expected);
expect(getHeaderLabel(count)).toEqual(expected);
});
});
});

View File

@ -992,15 +992,15 @@
lodash "^4.17.13"
to-fast-properties "^2.0.0"
"@buffetjs/core@3.1.0-next.2":
version "3.1.0-next.2"
resolved "https://registry.yarnpkg.com/@buffetjs/core/-/core-3.1.0-next.2.tgz#4c18ce545badf8803fea47080a274c932bcd0c87"
integrity sha512-TaCat7SN+NZPvTh2ly+mo/7Xbub1Q5ASqgmeFkLzZxWliONwy1YV4zIFELXSXug3Tw7b5VI/a1v1Qrrm7qwzSg==
"@buffetjs/core@3.1.0-next.3":
version "3.1.0-next.3"
resolved "https://registry.yarnpkg.com/@buffetjs/core/-/core-3.1.0-next.3.tgz#307276cae9616be940cc005a9fd4046037e45a15"
integrity sha512-KPIgtqfb4RwYG+VYHgHVgYv/a7IQT0PTNxyvLwlOflEGlsIULE8Bx5VfFamaPDkcpQBlGvfXrPYDIHP1tizZ1g==
dependencies:
"@buffetjs/hooks" "3.0.6"
"@buffetjs/icons" "3.1.0-next.2"
"@buffetjs/styles" "3.1.0-next.2"
"@buffetjs/utils" "3.0.6"
"@buffetjs/hooks" "3.1.0-next.3"
"@buffetjs/icons" "3.1.0-next.3"
"@buffetjs/styles" "3.1.0-next.3"
"@buffetjs/utils" "3.1.0-next.3"
"@fortawesome/fontawesome-svg-core" "^1.2.25"
"@fortawesome/free-regular-svg-icons" "^5.11.2"
"@fortawesome/free-solid-svg-icons" "^5.11.2"
@ -1011,31 +1011,31 @@
react-dates "^21.5.1"
react-moment-proptypes "^1.7.0"
"@buffetjs/custom@3.1.0-next.2":
version "3.1.0-next.2"
resolved "https://registry.yarnpkg.com/@buffetjs/custom/-/custom-3.1.0-next.2.tgz#41d83cdd2fbdb64119062b3250b2d587970d87dd"
integrity sha512-UmY6FN0CrlQw4LaOLVHjfyb6v7Q9keHAcCNePyQtmA1S2rGm0USwG0DDRNFnFbHKcnysnISfSRMoyHW5VS1v5g==
"@buffetjs/custom@3.1.0-next.3":
version "3.1.0-next.3"
resolved "https://registry.yarnpkg.com/@buffetjs/custom/-/custom-3.1.0-next.3.tgz#d3f1a593653812746efe0c3b084b40a08b963fa9"
integrity sha512-Pn8mQPRYFDEKONOpJ1Oai1WnHq8V/O9dtWYZKmNJBCBxUIQPHNO0qJGWMPXY1udJvT2OQFn0XWp/EeuE36pkhg==
dependencies:
"@buffetjs/core" "3.1.0-next.2"
"@buffetjs/styles" "3.1.0-next.2"
"@buffetjs/utils" "3.0.6"
"@buffetjs/core" "3.1.0-next.3"
"@buffetjs/styles" "3.1.0-next.3"
"@buffetjs/utils" "3.1.0-next.3"
moment "^2.24.0"
react-moment-proptypes "^1.7.0"
"@buffetjs/hooks@3.0.6":
version "3.0.6"
resolved "https://registry.yarnpkg.com/@buffetjs/hooks/-/hooks-3.0.6.tgz#98b3780fa005193a06f32af2b23e0782358ce5a6"
integrity sha512-boxLYVT/4RauTQmgLkdZWrwdMPS624/91rk4TqWARRmnXeP4+99MErHwqz5z3Bk8aBa3yNWpayu1p25fdoti6A==
"@buffetjs/hooks@3.1.0-next.3":
version "3.1.0-next.3"
resolved "https://registry.yarnpkg.com/@buffetjs/hooks/-/hooks-3.1.0-next.3.tgz#5550c7416aefb56322c56ca3b627836a5ae86b48"
integrity sha512-VnsapTdY1c5dTgoTrHYfoz+hpqZ4C2Ihx+Gp+CJr+J1in3wnkf9TC+vWSIo+jDr+VloSQSNq+ISEu9cEVdPIIw==
"@buffetjs/icons@3.1.0-next.2":
version "3.1.0-next.2"
resolved "https://registry.yarnpkg.com/@buffetjs/icons/-/icons-3.1.0-next.2.tgz#08134a31aa367f7bef454fda4e5a88a7064319f1"
integrity sha512-C3kHl4dRo5vYjcJZlKxiEMVe/gPRyJJEiGQESqpq6oACaiz1TBz3o0GNAIi17dOJuOEqYadVXCogz2u2Ef64+g==
"@buffetjs/icons@3.1.0-next.3":
version "3.1.0-next.3"
resolved "https://registry.yarnpkg.com/@buffetjs/icons/-/icons-3.1.0-next.3.tgz#b745038be6f3214f9136088776b8da07b61d9f26"
integrity sha512-zEA+9iocFlmP0lEDcv12o7AlXJdhEHheRpDXwZFunIMtl/JvCsY58BVUAwCamiX884oGjjv4XvOc6g4FJQO5ew==
"@buffetjs/styles@3.1.0-next.2":
version "3.1.0-next.2"
resolved "https://registry.yarnpkg.com/@buffetjs/styles/-/styles-3.1.0-next.2.tgz#d1e9f7b1b69b6987f3baa9791b5ef0541e8a5435"
integrity sha512-r4+cLqAmvIlN2rBw2imEcxAlWkO3DNTZ8RWPzmsufBhoImsN1ebuL1zcYVSGAttZnI4G80uyDxNywe9Di9iHcw==
"@buffetjs/styles@3.1.0-next.3":
version "3.1.0-next.3"
resolved "https://registry.yarnpkg.com/@buffetjs/styles/-/styles-3.1.0-next.3.tgz#2646a976c3fb5250ad0e8fe0156a508fa3938c68"
integrity sha512-IDmzrU9YQPi/dK/aocNsVvc9hrMxKdFmDgUbHxq84++2rppOIqOUNkGdOoAzcNq9B6e9f7Alu0JQ1AIFTthUXg==
dependencies:
"@fortawesome/fontawesome-free" "^5.12.0"
"@fortawesome/fontawesome-svg-core" "^1.2.22"
@ -1044,10 +1044,10 @@
"@fortawesome/react-fontawesome" "^0.1.4"
react-dates "^21.1.0"
"@buffetjs/utils@3.0.6":
version "3.0.6"
resolved "https://registry.yarnpkg.com/@buffetjs/utils/-/utils-3.0.6.tgz#87f7e0822d907397ae62b4764edcddc516e3ad27"
integrity sha512-DfYrHtmta2KXTc8iy892uGzbs1ygZ37hiXLAYmSWZfJNNk8pamAqnRLcfjVDA/SgTQIVO8unmaPxi3141xfe/Q==
"@buffetjs/utils@3.1.0-next.3":
version "3.1.0-next.3"
resolved "https://registry.yarnpkg.com/@buffetjs/utils/-/utils-3.1.0-next.3.tgz#968f6fd992d477024de86443c67bd0faa246ab15"
integrity sha512-JCJ2wKsjSP3uhVn/xjq5AYenw3ZtWhNSAc8QDK0cJoblntMjsf0MAJKTfVCc1s7SNbkHvIQnLJXOniywOAWxlA==
dependencies:
yup "^0.27.0"