mirror of
https://github.com/strapi/strapi.git
synced 2025-09-22 14:59:07 +00:00
Merge pull request #13978 from strapi/fix/ml-permissions-view
ML: Improve canRead and canCreate permission messages
This commit is contained in:
commit
d73b847c5c
@ -6,7 +6,6 @@ import { stringify } from 'qs';
|
|||||||
import {
|
import {
|
||||||
LoadingIndicatorPage,
|
LoadingIndicatorPage,
|
||||||
useFocusWhenNavigate,
|
useFocusWhenNavigate,
|
||||||
NoPermissions,
|
|
||||||
AnErrorOccurred,
|
AnErrorOccurred,
|
||||||
SearchURLQuery,
|
SearchURLQuery,
|
||||||
useSelectionState,
|
useSelectionState,
|
||||||
@ -15,8 +14,6 @@ import {
|
|||||||
} from '@strapi/helper-plugin';
|
} from '@strapi/helper-plugin';
|
||||||
import { Layout, ContentLayout, ActionLayout } from '@strapi/design-system/Layout';
|
import { Layout, ContentLayout, ActionLayout } from '@strapi/design-system/Layout';
|
||||||
import { Main } from '@strapi/design-system/Main';
|
import { Main } from '@strapi/design-system/Main';
|
||||||
import { Button } from '@strapi/design-system/Button';
|
|
||||||
import Plus from '@strapi/icons/Plus';
|
|
||||||
import { Box } from '@strapi/design-system/Box';
|
import { Box } from '@strapi/design-system/Box';
|
||||||
import { Divider } from '@strapi/design-system/Divider';
|
import { Divider } from '@strapi/design-system/Divider';
|
||||||
import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
|
import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
|
||||||
@ -38,7 +35,6 @@ import { getTrad, containsAssetFilter } from '../../utils';
|
|||||||
import { PaginationFooter } from '../../components/PaginationFooter';
|
import { PaginationFooter } from '../../components/PaginationFooter';
|
||||||
import { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';
|
import { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';
|
||||||
import { useFolder } from '../../hooks/useFolder';
|
import { useFolder } from '../../hooks/useFolder';
|
||||||
import { EmptyAssets } from '../../components/EmptyAssets';
|
|
||||||
import { BulkActions } from './components/BulkActions';
|
import { BulkActions } from './components/BulkActions';
|
||||||
import {
|
import {
|
||||||
FolderCard,
|
FolderCard,
|
||||||
@ -48,6 +44,7 @@ import {
|
|||||||
} from '../../components/FolderCard';
|
} from '../../components/FolderCard';
|
||||||
import { Filters } from './components/Filters';
|
import { Filters } from './components/Filters';
|
||||||
import { Header } from './components/Header';
|
import { Header } from './components/Header';
|
||||||
|
import { EmptyOrNoPermissions } from './components/EmptyOrNoPermissions';
|
||||||
|
|
||||||
const BoxWithHeight = styled(Box)`
|
const BoxWithHeight = styled(Box)`
|
||||||
height: ${32 / 16}rem;
|
height: ${32 / 16}rem;
|
||||||
@ -219,43 +216,15 @@ export const MediaLibrary = () => {
|
|||||||
{(assetsError || foldersError) && <AnErrorOccurred />}
|
{(assetsError || foldersError) && <AnErrorOccurred />}
|
||||||
|
|
||||||
{folderCount === 0 && assetCount === 0 && (
|
{folderCount === 0 && assetCount === 0 && (
|
||||||
<EmptyAssets
|
<EmptyOrNoPermissions
|
||||||
action={
|
canCreate={canCreate}
|
||||||
canCreate &&
|
canRead={canRead}
|
||||||
!isFiltering && (
|
isFiltering={isFiltering}
|
||||||
<Button
|
onActionClick={toggleUploadAssetDialog}
|
||||||
variant="secondary"
|
|
||||||
startIcon={<Plus />}
|
|
||||||
onClick={toggleUploadAssetDialog}
|
|
||||||
>
|
|
||||||
{formatMessage({
|
|
||||||
id: getTrad('header.actions.add-assets'),
|
|
||||||
defaultMessage: 'Add new assets',
|
|
||||||
})}
|
|
||||||
</Button>
|
|
||||||
)
|
|
||||||
}
|
|
||||||
content={
|
|
||||||
// eslint-disable-next-line no-nested-ternary
|
|
||||||
isFiltering
|
|
||||||
? formatMessage({
|
|
||||||
id: getTrad('list.assets-empty.title-withSearch'),
|
|
||||||
defaultMessage: 'There are no elements with the applied filters',
|
|
||||||
})
|
|
||||||
: canCreate
|
|
||||||
? formatMessage({
|
|
||||||
id: getTrad('list.assets.empty'),
|
|
||||||
defaultMessage: 'Upload your first assets...',
|
|
||||||
})
|
|
||||||
: formatMessage({
|
|
||||||
id: getTrad('list.assets.empty.no-permissions'),
|
|
||||||
defaultMessage: 'The asset list is empty',
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{canRead ? (
|
{canRead && (
|
||||||
<>
|
<>
|
||||||
{folderCount > 0 && (
|
{folderCount > 0 && (
|
||||||
<FolderList
|
<FolderList
|
||||||
@ -379,8 +348,6 @@ export const MediaLibrary = () => {
|
|||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</>
|
</>
|
||||||
) : (
|
|
||||||
<NoPermissions />
|
|
||||||
)}
|
)}
|
||||||
</ContentLayout>
|
</ContentLayout>
|
||||||
</Main>
|
</Main>
|
||||||
|
@ -0,0 +1,71 @@
|
|||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { useIntl } from 'react-intl';
|
||||||
|
|
||||||
|
import { Button } from '@strapi/design-system/Button';
|
||||||
|
import EmptyPermissions from '@strapi/icons/EmptyPermissions';
|
||||||
|
import Plus from '@strapi/icons/Plus';
|
||||||
|
|
||||||
|
import { EmptyAssets } from '../../../components/EmptyAssets';
|
||||||
|
import { getTrad } from '../../../utils';
|
||||||
|
|
||||||
|
const getContentIntlMessage = ({ isFiltering, canCreate, canRead }) => {
|
||||||
|
if (isFiltering) {
|
||||||
|
return {
|
||||||
|
id: 'list.assets-empty.title-withSearch',
|
||||||
|
defaultMessage: 'There are no elements with the applied filters',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (canRead) {
|
||||||
|
if (canCreate) {
|
||||||
|
return {
|
||||||
|
id: 'list.assets.empty-upload',
|
||||||
|
defaultMessage: 'Upload your first assets...',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: 'list.assets.empty',
|
||||||
|
defaultMessage: 'Media Library is empty',
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: 'header.actions.no-permissions',
|
||||||
|
defaultMessage: 'No permissions to view',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const EmptyOrNoPermissions = ({ canCreate, isFiltering, canRead, onActionClick }) => {
|
||||||
|
const { formatMessage } = useIntl();
|
||||||
|
const content = getContentIntlMessage({ isFiltering, canCreate, canRead });
|
||||||
|
|
||||||
|
return (
|
||||||
|
<EmptyAssets
|
||||||
|
icon={!canRead ? EmptyPermissions : null}
|
||||||
|
action={
|
||||||
|
canCreate &&
|
||||||
|
!isFiltering && (
|
||||||
|
<Button variant="secondary" startIcon={<Plus />} onClick={onActionClick}>
|
||||||
|
{formatMessage({
|
||||||
|
id: getTrad('header.actions.add-assets'),
|
||||||
|
defaultMessage: 'Add new assets',
|
||||||
|
})}
|
||||||
|
</Button>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
content={formatMessage({
|
||||||
|
...content,
|
||||||
|
id: getTrad(content.id),
|
||||||
|
})}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
EmptyOrNoPermissions.propTypes = {
|
||||||
|
canCreate: PropTypes.bool.isRequired,
|
||||||
|
canRead: PropTypes.bool.isRequired,
|
||||||
|
isFiltering: PropTypes.bool.isRequired,
|
||||||
|
onActionClick: PropTypes.func.isRequired,
|
||||||
|
};
|
@ -0,0 +1,53 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { ThemeProvider, lightTheme } from '@strapi/design-system';
|
||||||
|
import { render } from '@testing-library/react';
|
||||||
|
import { IntlProvider } from 'react-intl';
|
||||||
|
|
||||||
|
import { EmptyOrNoPermissions } from '../EmptyOrNoPermissions';
|
||||||
|
|
||||||
|
const setup = props =>
|
||||||
|
render(
|
||||||
|
<ThemeProvider theme={lightTheme}>
|
||||||
|
<IntlProvider locale="en" messages={{}}>
|
||||||
|
<EmptyOrNoPermissions
|
||||||
|
onActionClick={() => {}}
|
||||||
|
isFiltering={false}
|
||||||
|
canCreate
|
||||||
|
canRead
|
||||||
|
{...props}
|
||||||
|
/>
|
||||||
|
</IntlProvider>
|
||||||
|
</ThemeProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
describe('EmptyOrNoPermissions', () => {
|
||||||
|
test('isFiltering', () => {
|
||||||
|
const { queryByText } = setup({ isFiltering: true });
|
||||||
|
|
||||||
|
expect(queryByText('There are no elements with the applied filters')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('canCreate', () => {
|
||||||
|
const { queryByText } = setup({});
|
||||||
|
|
||||||
|
expect(queryByText('Add new assets')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('isFiltering and canCreate', () => {
|
||||||
|
const { queryByText } = setup({ isFiltering: true });
|
||||||
|
|
||||||
|
expect(queryByText('Add new assets')).not.toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('canRead and not canCreate', () => {
|
||||||
|
const { queryByText } = setup({ canCreate: false });
|
||||||
|
|
||||||
|
expect(queryByText('Media Library is empty')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
|
||||||
|
test('not canRead', () => {
|
||||||
|
const { queryByText } = setup({ canRead: false });
|
||||||
|
|
||||||
|
expect(queryByText('No permissions to view')).toBeInTheDocument();
|
||||||
|
});
|
||||||
|
});
|
@ -500,26 +500,6 @@ describe('Media library homepage', () => {
|
|||||||
expect(screen.queryByText('Upload your first assets...')).toBeInTheDocument();
|
expect(screen.queryByText('Upload your first assets...')).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('does not display empty assets action, if there are no assets and the user does not have create permissions', () => {
|
|
||||||
useMediaLibraryPermissions.mockReturnValueOnce({
|
|
||||||
isLoading: false,
|
|
||||||
canCreate: false,
|
|
||||||
canRead: false,
|
|
||||||
});
|
|
||||||
useAssets.mockReturnValueOnce({
|
|
||||||
isLoading: false,
|
|
||||||
error: null,
|
|
||||||
data: {
|
|
||||||
pagination: FIXTURE_ASSET_PAGINATION,
|
|
||||||
results: FIXTURE_ASSETS,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
renderML();
|
|
||||||
|
|
||||||
expect(screen.queryByText('header.actions.add-assets')).not.toBeInTheDocument();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('does not display empty assets action, if there are no assets, no folders and the user is currently filtering', () => {
|
it('does not display empty assets action, if there are no assets, no folders and the user is currently filtering', () => {
|
||||||
useQueryParams.mockReturnValueOnce([{ rawQuery: '', query: { filters: 'true' } }, jest.fn()]);
|
useQueryParams.mockReturnValueOnce([{ rawQuery: '', query: { filters: 'true' } }, jest.fn()]);
|
||||||
useAssets.mockReturnValueOnce({
|
useAssets.mockReturnValueOnce({
|
||||||
|
@ -44,8 +44,9 @@
|
|||||||
"list.assets-empty.subtitle": "Add one to the list.",
|
"list.assets-empty.subtitle": "Add one to the list.",
|
||||||
"list.assets-empty.title": "There are no assets yet",
|
"list.assets-empty.title": "There are no assets yet",
|
||||||
"list.assets-empty.title-withSearch": "There are no elements with the applied filters",
|
"list.assets-empty.title-withSearch": "There are no elements with the applied filters",
|
||||||
"list.assets.empty": "Upload your first assets...",
|
"list.assets.empty": "Media Library is empty",
|
||||||
"list.assets.empty.no-permissions": "The asset list is empty.",
|
"list.assets.empty-upload": "Upload your first assets...",
|
||||||
|
"list.assets.empty.no-permissions": "No permissions to view",
|
||||||
"list.assets.loading-asset": "Loading the preview for the media: {path}",
|
"list.assets.loading-asset": "Loading the preview for the media: {path}",
|
||||||
"list.assets.not-supported-content": "No preview available",
|
"list.assets.not-supported-content": "No preview available",
|
||||||
"list.assets.preview-asset": "Preview for the video at path {path}",
|
"list.assets.preview-asset": "Preview for the video at path {path}",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user