diff --git a/packages/web-app-files/src/composables/actions/spaces/useSpaceActionsDuplicate.ts b/packages/web-app-files/src/composables/actions/spaces/useSpaceActionsDuplicate.ts index f479d004dbd..0063c9d7f4d 100644 --- a/packages/web-app-files/src/composables/actions/spaces/useSpaceActionsDuplicate.ts +++ b/packages/web-app-files/src/composables/actions/spaces/useSpaceActionsDuplicate.ts @@ -25,7 +25,7 @@ export const useSpaceActionsDuplicate = () => { const sharesStore = useSharesStore() const { showMessage, showErrorMessage } = useMessages() const router = useRouter() - const { $gettext } = useGettext() + const { $gettext, $ngettext } = useGettext() const ability = useAbility() const clientService = useClientService() const loadingService = useLoadingService() @@ -124,12 +124,28 @@ export const useSpaceActionsDuplicate = () => { } const handler = async ({ resources }: SpaceActionOptions) => { + const skippedSpaces: SpaceResource[] = [] for (const resource of resources) { - if (resource.disabled || !isProjectSpaceResource(resource) || !isMemberSpace(resource)) { + if (resource.disabled || !isProjectSpaceResource(resource)) { + continue + } + if (!isMemberSpace(resource)) { + skippedSpaces.push(resource) continue } await duplicateSpace(resource) } + + if (skippedSpaces.length) { + showErrorMessage({ + title: $ngettext( + 'Space »%{space}« could not be duplicated because you are not a member', + '%{count} spaces could not be duplicated because you are not a member', + skippedSpaces.length, + { space: skippedSpaces[0].name, count: skippedSpaces.length.toString() } + ) + }) + } } const actions = computed((): SpaceAction[] => [ diff --git a/packages/web-app-files/tests/unit/composables/actions/spaces/useSpaceActionsDuplicate.spec.ts b/packages/web-app-files/tests/unit/composables/actions/spaces/useSpaceActionsDuplicate.spec.ts index 8ab88b67214..ffa91097289 100644 --- a/packages/web-app-files/tests/unit/composables/actions/spaces/useSpaceActionsDuplicate.spec.ts +++ b/packages/web-app-files/tests/unit/composables/actions/spaces/useSpaceActionsDuplicate.spec.ts @@ -172,6 +172,58 @@ describe('restore', () => { } }) }) + it('should show an error message for spaces the current user is no member of', async () => { + let instance: ReturnType + const { mocks } = getWrapper({ + setup: (i) => { + instance = i + } + }) + mocks.$clientService.graphAuthenticated.drives.createDrive.mockResolvedValue( + mock({ id: '3', name: 'Moon (1)' }) + ) + mocks.$clientService.webdav.listFiles.mockResolvedValue({ children: [] } as ListFilesResult) + const otherSpace = mock({ + id: 'other', + name: 'Mars', + disabled: false, + driveType: 'project' + }) + const memberSpace = mock({ + id: '1', + name: 'Moon', + disabled: false, + driveType: 'project', + spaceImageData: null, + spaceReadmeData: null, + spaceQuota: { total: 1 } + }) + await unref(instance.actions)[0].handler({ resources: [otherSpace, memberSpace] }) + const { showMessage, showErrorMessage } = useMessages() + expect(showMessage).toHaveBeenCalledTimes(1) + expect(showErrorMessage).toHaveBeenCalledTimes(1) + expect(showErrorMessage).toHaveBeenCalledWith({ + title: 'Space »Mars« could not be duplicated because you are not a member' + }) + }) + it('should show one error message with the count for several spaces the current user is no member of', async () => { + let instance: ReturnType + const { mocks } = getWrapper({ + setup: (i) => { + instance = i + } + }) + const otherSpaces = ['Mars', 'Venus'].map((name) => + mock({ id: name, name, disabled: false, driveType: 'project' }) + ) + await unref(instance.actions)[0].handler({ resources: otherSpaces }) + expect(mocks.$clientService.webdav.listFiles).not.toHaveBeenCalled() + const { showErrorMessage } = useMessages() + expect(showErrorMessage).toHaveBeenCalledTimes(1) + expect(showErrorMessage).toHaveBeenCalledWith({ + title: '2 spaces could not be duplicated because you are not a member' + }) + }) }) describe('method "duplicateSpace"', () => { it('should not create a space if the files of the space can not be read', () => {