mirror of
https://github.com/strapi/strapi.git
synced 2025-11-01 18:33:55 +00:00
Merge branch 'master' into features/api-token-v2
This commit is contained in:
commit
52c0a74418
@ -108,10 +108,21 @@ export const UploadingAssetCard = ({
|
||||
</Card>
|
||||
{error ? (
|
||||
<Typography variant="pi" fontWeight="bold" textColor="danger600">
|
||||
{formatMessage({
|
||||
id: getTrad(`apiError.${error.response.data.error.message}`),
|
||||
defaultMessage: error.response.data.error.message,
|
||||
})}
|
||||
{formatMessage(
|
||||
error?.response?.data?.error?.message
|
||||
? {
|
||||
id: getTrad(`apiError.${error.response.data.error.message}`),
|
||||
defaultMessage: error.response.data.error.message,
|
||||
/* See issue: https://github.com/strapi/strapi/issues/13867
|
||||
A proxy might return an error, before the request reaches Strapi
|
||||
and therefore we need to handle errors gracefully.
|
||||
*/
|
||||
}
|
||||
: {
|
||||
id: getTrad('upload.generic-error'),
|
||||
defaultMessage: 'An error occured while uploading the file.',
|
||||
}
|
||||
)}
|
||||
</Typography>
|
||||
) : (
|
||||
undefined
|
||||
|
||||
@ -6,7 +6,6 @@ import { stringify } from 'qs';
|
||||
import {
|
||||
LoadingIndicatorPage,
|
||||
useFocusWhenNavigate,
|
||||
NoPermissions,
|
||||
AnErrorOccurred,
|
||||
SearchURLQuery,
|
||||
useSelectionState,
|
||||
@ -15,8 +14,6 @@ import {
|
||||
} from '@strapi/helper-plugin';
|
||||
import { Layout, ContentLayout, ActionLayout } from '@strapi/design-system/Layout';
|
||||
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 { Divider } from '@strapi/design-system/Divider';
|
||||
import { BaseCheckbox } from '@strapi/design-system/BaseCheckbox';
|
||||
@ -38,7 +35,6 @@ import { getTrad, containsAssetFilter } from '../../utils';
|
||||
import { PaginationFooter } from '../../components/PaginationFooter';
|
||||
import { useMediaLibraryPermissions } from '../../hooks/useMediaLibraryPermissions';
|
||||
import { useFolder } from '../../hooks/useFolder';
|
||||
import { EmptyAssets } from '../../components/EmptyAssets';
|
||||
import { BulkActions } from './components/BulkActions';
|
||||
import {
|
||||
FolderCard,
|
||||
@ -48,6 +44,7 @@ import {
|
||||
} from '../../components/FolderCard';
|
||||
import { Filters } from './components/Filters';
|
||||
import { Header } from './components/Header';
|
||||
import { EmptyOrNoPermissions } from './components/EmptyOrNoPermissions';
|
||||
|
||||
const BoxWithHeight = styled(Box)`
|
||||
height: ${32 / 16}rem;
|
||||
@ -227,43 +224,15 @@ export const MediaLibrary = () => {
|
||||
{(assetsError || foldersError) && <AnErrorOccurred />}
|
||||
|
||||
{folderCount === 0 && assetCount === 0 && (
|
||||
<EmptyAssets
|
||||
action={
|
||||
canCreate &&
|
||||
!isFiltering && (
|
||||
<Button
|
||||
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',
|
||||
})
|
||||
}
|
||||
<EmptyOrNoPermissions
|
||||
canCreate={canCreate}
|
||||
canRead={canRead}
|
||||
isFiltering={isFiltering}
|
||||
onActionClick={toggleUploadAssetDialog}
|
||||
/>
|
||||
)}
|
||||
|
||||
{canRead ? (
|
||||
{canRead && (
|
||||
<>
|
||||
{folderCount > 0 && (
|
||||
<FolderList
|
||||
@ -387,8 +356,6 @@ export const MediaLibrary = () => {
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<NoPermissions />
|
||||
)}
|
||||
</ContentLayout>
|
||||
</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();
|
||||
});
|
||||
|
||||
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', () => {
|
||||
useQueryParams.mockReturnValueOnce([{ rawQuery: '', query: { filters: 'true' } }, jest.fn()]);
|
||||
useAssets.mockReturnValueOnce({
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
{
|
||||
"apiError.FileTooBig": "The uploaded file exceeds the maximum allowed asset size.",
|
||||
"upload.generic-error": "An error occurred while uploading the file.",
|
||||
"bulk.select.label": "Select all assets",
|
||||
"button.next": "Next",
|
||||
"checkControl.crop-duplicate": "Duplicate & crop the asset",
|
||||
@ -43,8 +44,9 @@
|
||||
"list.assets-empty.subtitle": "Add one to the list.",
|
||||
"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": "Upload your first assets...",
|
||||
"list.assets.empty.no-permissions": "The asset list is empty.",
|
||||
"list.assets.empty": "Media Library 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.not-supported-content": "No preview available",
|
||||
"list.assets.preview-asset": "Preview for the video at path {path}",
|
||||
|
||||
@ -27,7 +27,6 @@
|
||||
"test:front:watch:ce": "cross-env IS_EE=false jest --config ./jest.config.front.js --watchAll"
|
||||
},
|
||||
"dependencies": {
|
||||
"@apollo/federation": "^0.28.0",
|
||||
"@graphql-tools/schema": "8.1.2",
|
||||
"@graphql-tools/utils": "^8.9.0",
|
||||
"@strapi/utils": "4.3.2",
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
"test": "echo \"no tests yet\""
|
||||
},
|
||||
"dependencies": {
|
||||
"aws-sdk": "2.1186.0",
|
||||
"aws-sdk": "2.1188.0",
|
||||
"lodash": "4.17.21"
|
||||
},
|
||||
"engines": {
|
||||
|
||||
28
yarn.lock
28
yarn.lock
@ -40,15 +40,6 @@
|
||||
dependencies:
|
||||
"@jridgewell/trace-mapping" "^0.3.0"
|
||||
|
||||
"@apollo/federation@^0.28.0":
|
||||
version "0.28.0"
|
||||
resolved "https://registry.yarnpkg.com/@apollo/federation/-/federation-0.28.0.tgz#bbfcde3f327b3ec65dcfd98c6f52d6623a38b251"
|
||||
integrity sha512-M5Dp0XJhuxEOzYjPWWK5VtIqEI1IFRioh1+XHrls90UC8R+b6VXa0UxMO/zfKv00APr4gBODMcfRe5w97NSruw==
|
||||
dependencies:
|
||||
apollo-graphql "^0.9.3"
|
||||
apollo-server-types "^3.0.2"
|
||||
lodash.xorby "^4.7.0"
|
||||
|
||||
"@apollo/protobufjs@1.2.2":
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/@apollo/protobufjs/-/protobufjs-1.2.2.tgz#4bd92cd7701ccaef6d517cdb75af2755f049f87c"
|
||||
@ -8632,7 +8623,7 @@ apollo-datasource@^3.3.2:
|
||||
"@apollo/utils.keyvaluecache" "^1.0.1"
|
||||
apollo-server-env "^4.2.1"
|
||||
|
||||
apollo-graphql@^0.9.0, apollo-graphql@^0.9.3:
|
||||
apollo-graphql@^0.9.0:
|
||||
version "0.9.6"
|
||||
resolved "https://registry.yarnpkg.com/apollo-graphql/-/apollo-graphql-0.9.6.tgz#756312a92685b0547f82cceb04f5b2d6e9f0df5c"
|
||||
integrity sha512-CrqJxZwfu/U5x0bYYPPluwu1G+oC3jjKFK/EVn9CDcpi4+yD9rAYko/h1iUB5A6VRQhA4Boluc7QexMYQ2tCng==
|
||||
@ -8760,7 +8751,7 @@ apollo-server-plugin-base@^3.6.2:
|
||||
dependencies:
|
||||
apollo-server-types "^3.6.2"
|
||||
|
||||
apollo-server-types@^3.0.2, apollo-server-types@^3.1.1, apollo-server-types@^3.5.2, apollo-server-types@^3.6.2:
|
||||
apollo-server-types@^3.1.1, apollo-server-types@^3.5.2, apollo-server-types@^3.6.2:
|
||||
version "3.6.2"
|
||||
resolved "https://registry.yarnpkg.com/apollo-server-types/-/apollo-server-types-3.6.2.tgz#34bb0c335fcce3057cbdf72b3b63da182de6fc84"
|
||||
integrity sha512-9Z54S7NB+qW1VV+kmiqwU2Q6jxWfX89HlSGCGOo3zrkrperh85LrzABgN9S92+qyeHYd72noMDg2aI039sF3dg==
|
||||
@ -9114,10 +9105,10 @@ available-typed-arrays@^1.0.5:
|
||||
resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7"
|
||||
integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==
|
||||
|
||||
aws-sdk@2.1186.0, aws-sdk@^2.382.0:
|
||||
version "2.1186.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1186.0.tgz#f08fc5f1f53defa1fff83177621947dc0ca8d29b"
|
||||
integrity sha512-3yDWwNWgbSH9tRVyan0PlRU938Po9QH+06XHwRNwAa/6bixYl4L48c6YgpfxBpwl0IvcCCTivD7ZqshndwishQ==
|
||||
aws-sdk@2.1188.0, aws-sdk@^2.382.0:
|
||||
version "2.1188.0"
|
||||
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.1188.0.tgz#94b710948ef2924093a8d6fe42443a792385afa2"
|
||||
integrity sha512-4KXwjRjbCzU1luTOeH+ded92H51I4UuHaZzx2EI+JA0II1+q48heTxFlFd7yp7jGz9UwjPb6k12Jv1W3r0JWxA==
|
||||
dependencies:
|
||||
buffer "4.9.2"
|
||||
events "1.1.1"
|
||||
@ -18137,11 +18128,6 @@ lodash.uniq@4.5.0:
|
||||
resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773"
|
||||
integrity sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==
|
||||
|
||||
lodash.xorby@^4.7.0:
|
||||
version "4.7.0"
|
||||
resolved "https://registry.yarnpkg.com/lodash.xorby/-/lodash.xorby-4.7.0.tgz#9c19a6f9f063a6eb53dd03c1b6871799801463d7"
|
||||
integrity sha1-nBmm+fBjputT3QPBtocXmYAUY9c=
|
||||
|
||||
lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7.0:
|
||||
version "4.17.21"
|
||||
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
|
||||
@ -20837,8 +20823,6 @@ path-case@^2.1.0:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/path-case/-/path-case-2.1.1.tgz#94b8037c372d3fe2906e465bb45e25d226e8eea5"
|
||||
integrity sha1-lLgDfDctP+KQbkZbtF4l0ibo7qU=
|
||||
dependencies:
|
||||
no-case "^2.2.0"
|
||||
|
||||
path-dirname@^1.0.0:
|
||||
version "1.0.2"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user