From ab6193b6b5a86e58dd4892c7dc878b93ec1dc0a0 Mon Sep 17 00:00:00 2001 From: Cheney Wang Date: Tue, 7 Jul 2026 09:36:47 -0400 Subject: [PATCH 1/2] Allow location picker file name suggestions --- .../components/EmbedActions/EmbedActions.vue | 1 + .../EmbedActions/EmbedActions.spec.ts | 1 + .../components/Modals/LocationPickerModal.vue | 33 +++++++++++++--- .../Modals/LocationPickerModal.spec.ts | 39 ++++++++++++++++++- 4 files changed, 68 insertions(+), 6 deletions(-) diff --git a/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue b/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue index 3e86fd459c..b7522309c0 100644 --- a/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue +++ b/packages/web-app-files/src/components/EmbedActions/EmbedActions.vue @@ -142,6 +142,7 @@ const emitSelect = (): void => { fileName: unref(fileName), locationQuery: JSON.parse(JSON.stringify(routeToContextQuery(unref(router.currentRoute)))) }) + return } // TODO: adjust type to embedModeLocationPickMessageData later (breaking) diff --git a/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts b/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts index b4381101fb..26f86ef399 100644 --- a/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts +++ b/packages/web-app-files/tests/unit/components/EmbedActions/EmbedActions.spec.ts @@ -108,6 +108,7 @@ describe('EmbedActions', () => { contextRouteQuery: {} } }) + expect(mocks.postMessageMock).toHaveBeenCalledTimes(1) }) }) diff --git a/packages/web-pkg/src/components/Modals/LocationPickerModal.vue b/packages/web-pkg/src/components/Modals/LocationPickerModal.vue index d404920d16..4e0eaa8e2f 100644 --- a/packages/web-pkg/src/components/Modals/LocationPickerModal.vue +++ b/packages/web-pkg/src/components/Modals/LocationPickerModal.vue @@ -25,11 +25,23 @@ import { import { RouteLocationRaw } from 'vue-router' import AppLoadingSpinner from '../AppLoadingSpinner.vue' -const { modal, parentFolderLink, submitButtonTitle, callbackFn } = defineProps<{ +const { + modal, + parentFolderLink, + submitButtonTitle, + chooseFileName, + chooseFileNameSuggestion, + callbackFn +} = defineProps<{ modal: Modal parentFolderLink: RouteLocationRaw submitButtonTitle?: string - callbackFn: (resources: embedModeLocationPickMessageData['resources']) => void + chooseFileName?: boolean + chooseFileNameSuggestion?: string + callbackFn: ( + resources: embedModeLocationPickMessageData['resources'], + options?: { fileName?: string } + ) => void }>() const iframeRef = ref() @@ -48,6 +60,12 @@ iframeUrl.searchParams.append('embed-delegate-authentication', 'false') if (submitButtonTitle) { iframeUrl.searchParams.append('embed-submit-button-title', submitButtonTitle) } +if (chooseFileName) { + iframeUrl.searchParams.append('embed-choose-file-name', 'true') +} +if (chooseFileNameSuggestion) { + iframeUrl.searchParams.append('embed-choose-file-name-suggestion', chooseFileNameSuggestion) +} const onLoad = () => { isLoading.value = false @@ -59,16 +77,21 @@ const onLocationPick = ({ data }: MessageEvent) => { return } - let resources = (data.data as embedModeLocationPickMessageData)?.resources + const payload = data.data as + | embedModeLocationPickMessageData + | embedModeLocationPickMessageData['resources'] + let resources = (payload as embedModeLocationPickMessageData)?.resources + let fileName = (payload as embedModeLocationPickMessageData)?.fileName if (Array.isArray(data.data)) { - resources = data.data + resources = data.data as embedModeLocationPickMessageData['resources'] + fileName = undefined } if (!resources?.length) { return } - callbackFn(resources) + callbackFn(resources, { fileName }) removeModal(modal.id) } diff --git a/packages/web-pkg/tests/unit/components/Modals/LocationPickerModal.spec.ts b/packages/web-pkg/tests/unit/components/Modals/LocationPickerModal.spec.ts index 4f72721d93..e698384d92 100644 --- a/packages/web-pkg/tests/unit/components/Modals/LocationPickerModal.spec.ts +++ b/packages/web-pkg/tests/unit/components/Modals/LocationPickerModal.spec.ts @@ -22,6 +22,15 @@ describe('LocationPickerModal', () => { 'http://localhost:3000/files-spaces-generic?hide-logo=true&embed=true&embed-target=location&embed-delegate-authentication=false&embed-submit-button-title=Move+here' ) }) + it('sets file name picker parameters in iframe src when provided', () => { + const { wrapper } = getWrapper({ + chooseFileName: true, + chooseFileNameSuggestion: 'archive.zip' + }) + expect((wrapper.vm as any).iframeSrc).toEqual( + 'http://localhost:3000/files-spaces-generic?hide-logo=true&embed=true&embed-target=location&embed-delegate-authentication=false&embed-choose-file-name=true&embed-choose-file-name-suggestion=archive.zip' + ) + }) }) describe('method "onLocationPick"', () => { it('does nothing if the event message does not equal "opencloud-embed:select"', () => { @@ -47,6 +56,24 @@ describe('LocationPickerModal', () => { expect((wrapper.vm as any).callbackFn).toHaveBeenCalled() expect(modalStore.removeModal).toHaveBeenCalled() }) + it('passes file name to the callback', () => { + const { wrapper } = getWrapper() + ;(wrapper.vm as any).onLocationPick({ + data: { + name: 'opencloud-embed:select', + data: { + resources: [mock({ storageId: '1' })], + fileName: 'archive.zip' + } + } + } as MessageEvent) + expect((wrapper.vm as any).callbackFn).toHaveBeenCalledWith( + expect.any(Array), + expect.objectContaining({ + fileName: 'archive.zip' + }) + ) + }) it('calls callback function for legacy array payload when message does equal "opencloud-embed:select"', () => { const { wrapper } = getWrapper() const modalStore = useModals() @@ -64,7 +91,15 @@ describe('LocationPickerModal', () => { }) }) -function getWrapper({ submitButtonTitle }: { submitButtonTitle?: string } = {}) { +function getWrapper({ + submitButtonTitle, + chooseFileName, + chooseFileNameSuggestion +}: { + submitButtonTitle?: string + chooseFileName?: boolean + chooseFileNameSuggestion?: string +} = {}) { const mocks = defaultComponentMocks() return { @@ -74,6 +109,8 @@ function getWrapper({ submitButtonTitle }: { submitButtonTitle?: string } = {}) modal: mock(), callbackFn: vi.fn(), submitButtonTitle, + chooseFileName, + chooseFileNameSuggestion, parentFolderLink: { name: 'files-spaces-generic', params: { From bec278ad7c234f113ce93bf642634cbd2316d7ea Mon Sep 17 00:00:00 2001 From: Cheney Wang Date: Thu, 9 Jul 2026 09:45:12 -0400 Subject: [PATCH 2/2] Address location picker file name review --- .../web-pkg/src/components/Modals/LocationPickerModal.vue | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/web-pkg/src/components/Modals/LocationPickerModal.vue b/packages/web-pkg/src/components/Modals/LocationPickerModal.vue index 4e0eaa8e2f..19e6efddec 100644 --- a/packages/web-pkg/src/components/Modals/LocationPickerModal.vue +++ b/packages/web-pkg/src/components/Modals/LocationPickerModal.vue @@ -77,11 +77,8 @@ const onLocationPick = ({ data }: MessageEvent) => { return } - const payload = data.data as - | embedModeLocationPickMessageData - | embedModeLocationPickMessageData['resources'] - let resources = (payload as embedModeLocationPickMessageData)?.resources - let fileName = (payload as embedModeLocationPickMessageData)?.fileName + let resources = (data.data as embedModeLocationPickMessageData)?.resources + let fileName = (data.data as embedModeLocationPickMessageData)?.fileName if (Array.isArray(data.data)) { resources = data.data as embedModeLocationPickMessageData['resources'] fileName = undefined