Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions packages/core/upload/admin/src/ai/components/AIAssetCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const AssetCardActions = ({ asset }: { asset: File }) => {
const dispatch = useAIUploadModalContext('AssetCardActions', (s) => s.dispatch);
const state = useAIUploadModalContext('AssetCardActions', (s) => s.state);
const onClose = useAIUploadModalContext('AssetCardActions', (s) => s.onClose);
const { canUpdate, canCopyLink, canDownload } = useMediaLibraryPermissions();
const { canUpdate, canDelete, canCopyLink, canDownload } = useMediaLibraryPermissions();

const [isEditModalOpen, setIsEditModalOpen] = React.useState(false);

Expand Down Expand Up @@ -112,19 +112,21 @@ const AssetCardActions = ({ asset }: { asset: File }) => {

return (
<CardActionsContainer onClick={handlePropagationClick} position="end">
<Dialog.Root>
<Dialog.Trigger>
<IconButton
label={formatMessage({
id: getTrad('control-card.remove-selection'),
defaultMessage: 'Remove from selection',
})}
>
<Trash />
</IconButton>
</Dialog.Trigger>
<ConfirmDialog onConfirm={handleConfirmRemove} />
</Dialog.Root>
{canDelete && (
<Dialog.Root>
<Dialog.Trigger>
<IconButton
label={formatMessage({
id: getTrad('control-card.remove-selection'),
defaultMessage: 'Remove from selection',
})}
>
<Trash />
</IconButton>
</Dialog.Trigger>
<ConfirmDialog onConfirm={handleConfirmRemove} />
</Dialog.Root>
)}

<Modal.Root open={isEditModalOpen} onOpenChange={setIsEditModalOpen}>
<Modal.Trigger>
Expand All @@ -146,6 +148,7 @@ const AssetCardActions = ({ asset }: { asset: File }) => {
}
onClose={(arg) => handleEditAsset(arg as File)}
canUpdate={canUpdate}
canDelete={canDelete}
canCopyLink={canCopyLink}
canDownload={canDownload}
omitFields={['caption', 'alternativeText']}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export const AssetContent = ({
canCreate,
isLoading: isLoadingPermissions,
canUpdate,
canDelete,
canCopyLink,
canDownload,
} = useMediaLibraryPermissions();
Expand Down Expand Up @@ -223,6 +224,7 @@ export const AssetContent = ({
onClose={() => setAssetToEdit(undefined)}
asset={assetToEdit as EditAsset}
canUpdate={canUpdate}
canDelete={canDelete}
canCopyLink={canCopyLink}
canDownload={canDownload}
trackedLocation={trackedLocation}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ export interface Asset extends Omit<FileDefinition, 'folder'> {
interface EditAssetContentProps {
asset?: Asset;
canUpdate?: boolean;
canDelete?: boolean;
canCopyLink?: boolean;
canDownload?: boolean;
trackedLocation?: string;
Expand All @@ -91,6 +92,7 @@ export const EditAssetContent = ({
onClose,
asset,
canUpdate = false,
canDelete = false,
canCopyLink = false,
canDownload = false,
trackedLocation,
Expand Down Expand Up @@ -230,6 +232,7 @@ export const EditAssetContent = ({
<PreviewBox
asset={asset!}
canUpdate={canUpdate}
canDelete={canDelete}
canCopyLink={canCopyLink}
canDownload={canDownload}
onDelete={onClose}
Expand Down Expand Up @@ -438,6 +441,7 @@ export const EditAssetContent = ({
interface EditAssetDialogProps {
asset: Asset;
canUpdate?: boolean;
canDelete?: boolean;
canCopyLink?: boolean;
canDownload?: boolean;
trackedLocation?: string;
Expand All @@ -449,6 +453,7 @@ export const EditAssetDialog = ({
open,
onClose,
canUpdate = false,
canDelete = false,
canCopyLink = false,
canDownload = false,
...restProps
Expand All @@ -459,6 +464,7 @@ export const EditAssetDialog = ({
<EditAssetContent
onClose={onClose}
canUpdate={canUpdate}
canDelete={canDelete}
canCopyLink={canCopyLink}
canDownload={canDownload}
{...restProps}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ interface Asset extends Omit<FileDefinition, 'folder'> {
interface PreviewBoxProps {
asset: Asset;
canUpdate: boolean;
canDelete: boolean;
canCopyLink: boolean;
canDownload: boolean;
replacementFile?: File;
Expand All @@ -63,6 +64,7 @@ interface PreviewBoxProps {
export const PreviewBox = ({
asset,
canUpdate,
canDelete,
canCopyLink,
canDownload,
onDelete,
Expand Down Expand Up @@ -244,7 +246,7 @@ export const PreviewBox = ({

<ActionRow paddingLeft={3} paddingRight={3} justifyContent="flex-end">
<Flex gap={1}>
{canUpdate && !asset.isLocal && (
{canDelete && !asset.isLocal && (
<IconButton
label={formatMessage({
id: 'global.delete',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ const renderCompo = () =>
asset={asset}
onClose={jest.fn()}
canUpdate
canDelete
canCopyLink
canDownload
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,30 @@ const store = configureStore({
middleware: (getDefaultMiddleware) => getDefaultMiddleware().concat(adminApi.middleware),
});

const renderCompo = (props = { canUpdate: true, canCopyLink: true, canDownload: true }) =>
const renderCompo = (
props: Partial<{
canUpdate: boolean;
canDelete: boolean;
canCopyLink: boolean;
canDownload: boolean;
}> = {}
) =>
render(
<Provider store={store}>
<QueryClientProvider client={queryClient}>
<DesignSystemProvider>
<IntlProvider locale="en" messages={messageForPlugin} defaultLocale="en">
<NotificationsProvider>
<EditAssetDialog open asset={asset} onClose={jest.fn()} {...props} />
<EditAssetDialog
open
asset={asset}
onClose={jest.fn()}
canUpdate
canDelete
canCopyLink
canDownload
{...props}
/>
</NotificationsProvider>
</IntlProvider>
</DesignSystemProvider>
Expand Down Expand Up @@ -188,17 +204,17 @@ describe('<EditAssetDialog />', () => {
});

describe('PreviewBox', () => {
it('opens the delete dialog when pressing the delete button when the user is allowed to update', () => {
renderCompo({ canUpdate: true, canCopyLink: false, canDownload: false });
it('opens the delete dialog when pressing the delete button when the user is allowed to delete', () => {
renderCompo({ canUpdate: true, canDelete: true, canCopyLink: false, canDownload: false });

fireEvent.click(screen.getByRole('button', { name: 'Delete' }));

expect(screen.getByText('Confirmation')).toBeVisible();
expect(screen.getByText('Are you sure?')).toBeVisible();
});

it('does not open the delete dialog when the user is not allowed to update', () => {
renderCompo({ canUpdate: false, canCopyLink: false, canDownload: false });
it('does not open the delete dialog when the user is not allowed to delete', () => {
renderCompo({ canUpdate: true, canDelete: false, canCopyLink: false, canDownload: false });

expect(screen.queryByRole('button', { name: 'Delete' })).not.toBeInTheDocument();
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,12 @@ export const EditFolderContent = ({
const { data: folderStructure, isLoading: folderStructureIsLoading } = useFolderStructure({
enabled: true,
});
const { canCreate, isLoading: isLoadingPermissions, canUpdate } = useMediaLibraryPermissions();
const {
canCreate,
canDelete,
isLoading: isLoadingPermissions,
canUpdate,
} = useMediaLibraryPermissions();
const [showConfirmDialog, setShowConfirmDialog] = React.useState(false);
const { formatMessage, formatDate } = useIntl();
const { trackUsage } = useTracking();
Expand Down Expand Up @@ -289,13 +294,13 @@ export const EditFolderContent = ({
{formatMessage({ id: 'cancel', defaultMessage: 'Cancel' })}
</Button>
<Flex gap={2}>
{isEditing && canUpdate && (
{isEditing && canDelete && (
<Button
type="button"
variant="danger-light"
onClick={() => setShowConfirmDialog(true)}
name="delete"
disabled={!canUpdate || isEditFolderLoading}
disabled={!canDelete || isEditFolderLoading}
>
{formatMessage({
id: getTrad('modal.folder.create.delete'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ const ComponentFixture = (
) => {
const nextProps = {
canUpdate: true,
canDelete: true,
...props,
};

Expand Down Expand Up @@ -238,12 +239,41 @@ describe('EditFolderDialog', () => {
});

test('disables inputs and submit action if users do not have permissions to update', () => {
(useMediaLibraryPermissions as jest.Mock).mockReturnValueOnce({ canUpdate: false });
(useMediaLibraryPermissions as jest.Mock).mockReturnValueOnce({
canUpdate: false,
canDelete: false,
});
const { getByRole } = setup();

expect(getByRole('textbox', { name: 'Name' })).toHaveAttribute('aria-disabled', 'true');
expect(getByRole('combobox', { name: 'Location' })).toBeDisabled();

expect(getByRole('button', { name: 'Create' })).toBeDisabled();
});

test('does not show the delete action if users do not have permissions to delete', () => {
(useMediaLibraryPermissions as jest.Mock).mockReturnValueOnce({
canCreate: true,
canUpdate: true,
canDelete: false,
isLoading: false,
});

setup({
folder: {
id: 1,
name: 'default folder name',
createdAt: 'Mon Oct 24 2022 16:02:14 GMT+0200',
updatedAt: 'Mon Oct 24 2022 16:02:14 GMT+0200',
children: { count: 0 },
files: { count: 0 },
parent: null,
pathId: 1,
path: '1',
type: 'folder',
},
});

expect(screen.queryByRole('button', { name: 'Delete folder' })).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as React from 'react';
import { CarouselInput, CarouselSlide } from '@strapi/design-system';
import { useIntl } from 'react-intl';

import { useMediaLibraryPermissions } from '../../../hooks/useMediaLibraryPermissions';
import { getTrad } from '../../../utils/getTrad';
import { EditAssetDialog } from '../../EditAssetDialog/EditAssetContent';

Expand Down Expand Up @@ -64,6 +65,7 @@ export const CarouselAssets = React.forwardRef(
forwardedRef
) => {
const { formatMessage } = useIntl();
const { canDelete, canUpdate, canCopyLink, canDownload } = useMediaLibraryPermissions();
const [isEditingAsset, setIsEditingAsset] = React.useState(false);

const currentAsset = assets[selectedAssetIndex];
Expand Down Expand Up @@ -153,9 +155,10 @@ export const CarouselAssets = React.forwardRef(
}
}}
asset={currentAsset as Asset}
canUpdate
canCopyLink
canDownload
canUpdate={canUpdate}
canDelete={canDelete}
canCopyLink={canCopyLink}
canDownload={canDownload}
trackedLocation={trackedLocation}
/>
</>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import { CarouselAssets } from '../CarouselAssets';

import type { CarouselAssetsProps } from '../CarouselAssets';

jest.mock('../../../../hooks/useMediaLibraryPermissions');

const ASSET_FIXTURES = [
{
alternativeText: 'alternative text',
Expand Down
1 change: 1 addition & 0 deletions packages/core/upload/admin/src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export const PERMISSIONS = {
configureView: [{ action: 'plugin::upload.configure-view', subject: null }],
settings: [{ action: 'plugin::upload.settings.read', subject: null }],
update: [{ action: 'plugin::upload.assets.update', subject: null, fields: null }],
delete: [{ action: 'plugin::upload.assets.delete', subject: null, fields: null }],
};

export const tableHeaders = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ export const useMediaLibraryPermissions = jest.fn().mockReturnValue({
canRead: true,
canCreate: true,
canUpdate: true,
canDelete: true,
canCopyLink: true,
canDownload: true,
});
Loading