Merge pull request #13497 from strapi/features/ML-folder-mime-filter

ML: Skip loading folders, if an asset-only filter is applied
This commit is contained in:
Gustav Hansen 2022-06-08 10:34:39 +01:00 committed by GitHub
commit 049661fe98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 164 additions and 14 deletions

View File

@ -253,6 +253,7 @@ export const BrowseStep = ({
BrowseStep.defaultProps = {
allowedTypes: [],
folders: [],
multiple: false,
onSelectAllAsset: undefined,
onEditAsset: undefined,
@ -262,7 +263,7 @@ BrowseStep.propTypes = {
allowedTypes: PropTypes.arrayOf(PropTypes.string),
assets: PropTypes.arrayOf(AssetDefinition).isRequired,
canCreate: PropTypes.bool.isRequired,
folders: PropTypes.arrayOf(FolderDefinition).isRequired,
folders: PropTypes.arrayOf(FolderDefinition),
multiple: PropTypes.bool,
onAddAsset: PropTypes.func.isRequired,
onChangeFilters: PropTypes.func.isRequired,

View File

@ -131,7 +131,7 @@ describe('BrowseStep', () => {
setup({
folders: [],
assets: [],
queryObject: { page: 1, pageSize: 10, filters: {}, _q: 'true' },
queryObject: { page: 1, pageSize: 10, filters: { $and: [] }, _q: 'true' },
});
expect(screen.getByText('There are no assets with the applied filters')).toBeInTheDocument();
@ -141,7 +141,7 @@ describe('BrowseStep', () => {
setup({
folders: [],
assets: FIXTURE_ASSETS,
queryObject: { page: 1, pageSize: 10, filters: {}, _q: 'true' },
queryObject: { page: 1, pageSize: 10, filters: { $and: [] }, _q: 'true' },
});
expect(screen.queryByText('Assets')).not.toBeInTheDocument();
@ -149,7 +149,7 @@ describe('BrowseStep', () => {
it('does not display folders title if searching and no assets', () => {
setup({
queryObject: { page: 1, pageSize: 10, filters: {}, _q: 'true' },
queryObject: { page: 1, pageSize: 10, filters: { $and: [] }, _q: 'true' },
});
expect(screen.queryByText('Folders')).not.toBeInTheDocument();

View File

@ -12,7 +12,7 @@ import { Loader } from '@strapi/design-system/Loader';
import { Stack } from '@strapi/design-system/Stack';
import { NoPermissions, AnErrorOccurred, useSelectionState, pxToRem } from '@strapi/helper-plugin';
import getTrad from '../../utils/getTrad';
import { getTrad, containsAssetFilter } from '../../utils';
import { SelectedStep } from './SelectedStep';
import { BrowseStep } from './BrowseStep';
import { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';
@ -70,6 +70,7 @@ export const AssetDialog = ({
error: errorAssets,
} = useAssets({ skipWhen: !canRead, query: queryObject });
const { data: folders, isLoading: isLoadingFolders, error: errorFolders } = useFolders({
enabled: canRead && !containsAssetFilter(queryObject) && pagination?.page === 1,
query: queryObject,
});

View File

@ -2,13 +2,14 @@ import React from 'react';
import { IntlProvider } from 'react-intl';
import { ThemeProvider, lightTheme } from '@strapi/design-system';
import { QueryClientProvider, QueryClient } from 'react-query';
import { render as renderTL, screen, waitFor } from '@testing-library/react';
import { render as renderTL, screen } from '@testing-library/react';
import { MemoryRouter } from 'react-router-dom';
import { AssetDialog } from '..';
import { useFolders } from '../../../hooks/useFolders';
import { useAssets } from '../../../hooks/useAssets';
import { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';
import useModalQueryParams from '../../../hooks/useModalQueryParams';
jest.mock('@strapi/helper-plugin', () => ({
...jest.requireActual('@strapi/helper-plugin'),
@ -19,6 +20,9 @@ jest.mock('@strapi/helper-plugin', () => ({
jest.mock('../../../hooks/useMediaLibraryPermissions');
jest.mock('../../../hooks/useFolders');
jest.mock('../../../hooks/useAssets');
jest.mock('../../../hooks/useModalQueryParams');
console.error = jest.fn();
const queryClient = new QueryClient({
defaultOptions: {
@ -91,7 +95,7 @@ describe('AssetDialog', () => {
describe('content', () => {
describe('empty state', () => {
it('shows a specific empty state when the user is not allowed to see the content', async () => {
it('shows a specific empty state when the user is not allowed to see the content', () => {
useMediaLibraryPermissions.mockReturnValueOnce({
isLoading: false,
canRead: false,
@ -99,11 +103,12 @@ describe('AssetDialog', () => {
renderML();
await waitFor(() =>
expect(
screen.getByText("You don't have the permissions to access that content")
).toBeInTheDocument()
);
expect(
screen.getByText("You don't have the permissions to access that content")
).toBeInTheDocument();
expect(screen.queryByText('Folders')).not.toBeInTheDocument();
expect(screen.queryByText('Assets')).not.toBeInTheDocument();
expect(screen.getByRole('dialog').getAttribute('aria-busy')).toBe(null);
});
@ -143,6 +148,45 @@ describe('AssetDialog', () => {
expect(screen.getByText('Folder 1')).toBeInTheDocument();
});
it('does not display folders, if the current page !== 1', () => {
useAssets.mockReturnValueOnce({
isLoading: false,
error: null,
data: { pagination: { page: 2 } },
});
expect(screen.queryByText('Folder 1')).not.toBeInTheDocument();
});
it('does not display folders, if the mime-type filter was applied', () => {
useModalQueryParams.mockReturnValueOnce([
{
queryObject: {
page: 1,
sort: 'updatedAt:DESC',
pageSize: 10,
filters: {
$and: [
{
mime: true,
},
],
},
},
},
{
onChangeFilters: jest.fn(),
onChangePage: jest.fn(),
onChangePageSize: jest.fn(),
onChangeSort: jest.fn(),
onChangeSearch: jest.fn(),
onChangeFolder: jest.fn(),
},
]);
expect(screen.queryByText('Folder 1')).not.toBeInTheDocument();
});
});
});
});

View File

@ -0,0 +1,22 @@
const useModalQueryParams = jest.fn().mockReturnValue([
{
queryObject: {
page: 1,
sort: 'updatedAt:DESC',
pageSize: 10,
filters: {
$and: [],
},
},
},
{
onChangeFilters: jest.fn(),
onChangePage: jest.fn(),
onChangePageSize: jest.fn(),
onChangeSort: jest.fn(),
onChangeSearch: jest.fn(),
onChangeFolder: jest.fn(),
},
]);
export default useModalQueryParams;

View File

@ -33,7 +33,7 @@ import { FolderList } from '../../components/FolderList';
import SortPicker from '../../components/SortPicker';
import { useAssets } from '../../hooks/useAssets';
import { useFolders } from '../../hooks/useFolders';
import { getTrad } from '../../utils';
import { getTrad, containsAssetFilter } from '../../utils';
import { PaginationFooter } from '../../components/PaginationFooter';
import { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';
import { EmptyAssets } from '../../components/EmptyAssets';
@ -78,7 +78,7 @@ export const MediaLibrary = () => {
});
const { data: folders, isLoading: foldersLoading, errors: foldersError } = useFolders({
enabled: assetsData?.pagination?.page === 1,
enabled: canRead && assetsData?.pagination?.page === 1 && !containsAssetFilter(query),
query,
});

View File

@ -412,6 +412,29 @@ describe('Media library homepage', () => {
expect(useFolders).toHaveBeenCalledWith(expect.objectContaining({ enabled: false }));
});
it('does not fetch folders if the mime-type was applied', () => {
useAssets.mockReturnValueOnce({
isLoading: false,
data: {
pagination: {
...FIXTURE_ASSET_PAGINATION,
pageCount: 2,
page: 2,
total: 2,
},
results: FIXTURE_ASSETS,
},
});
useQueryParams.mockReturnValueOnce([
{ rawQuery: '', query: { _q: '', filters: { $and: { mime: 'audio' } } } },
jest.fn(),
]);
renderML();
expect(useFolders).toHaveBeenCalledWith(expect.objectContaining({ enabled: false }));
});
it('displays assets', () => {
renderML();

View File

@ -0,0 +1,19 @@
const containsMimeTypeFilter = query => {
const filters = query?.filters?.$and;
if (!filters) {
return false;
}
const result = filters.find(filter => {
return Object.keys(filter).includes('mime');
});
return !!result;
};
const containsAssetFilter = query => {
return containsMimeTypeFilter(query);
};
export default containsAssetFilter;

View File

@ -4,4 +4,5 @@ export { default as getRequestUrl } from './getRequestUrl';
export { default as getTrad } from './getTrad';
export { default as findRecursiveFolderByValue } from './findRecursiveFolderByValue';
export { default as findRecursiveFolderMetadatas } from './findRecursiveFolderMetadatas';
export { default as containsAssetFilter } from './containsAssetFilter';
export * from './formatDuration';

View File

@ -0,0 +1,39 @@
import { containsAssetFilter } from '..';
describe('containsAssetFilter', () => {
test('does not fail on empty query objects', () => {
expect(containsAssetFilter(null)).toBeFalsy();
expect(containsAssetFilter({})).toBeFalsy();
expect(containsAssetFilter({ filters: {} })).toBeFalsy();
expect(containsAssetFilter({ filters: { $and: [] } })).toBeFalsy();
});
test('recognizes the mime-type filter', () => {
expect(
containsAssetFilter({
filters: {
$and: [
{
mime: 'image',
},
],
},
})
).toBeTruthy();
expect(
containsAssetFilter({
filters: {
$and: [
{
some: 'filter',
},
{
mime: 'image',
},
],
},
})
).toBeTruthy();
});
});