diff --git a/frontend/src/lib/components/EditorBar.svelte b/frontend/src/lib/components/EditorBar.svelte index 1b3d6ee8a1..315bfeba75 100644 --- a/frontend/src/lib/components/EditorBar.svelte +++ b/frontend/src/lib/components/EditorBar.svelte @@ -757,8 +757,8 @@ JsonNode ${windmillPathToCamelCaseName(path)} = JsonNode.Parse(await client.GetS { - let s = `'${formatS3Object(s3obj.detail)}'` + onSelectAndClose={(s3obj) => { + let s = `'${formatS3Object(s3obj)}'` if (lang === 'duckdb') { editor?.insertAtCursor(`SELECT * FROM ${s}`) } else if (lang === 'python3') { diff --git a/frontend/src/lib/components/S3FilePicker.svelte b/frontend/src/lib/components/S3FilePicker.svelte index cc061dc18c..16eddb9f1a 100644 --- a/frontend/src/lib/components/S3FilePicker.svelte +++ b/frontend/src/lib/components/S3FilePicker.svelte @@ -2,7 +2,7 @@ import { emptyString, type S3Object } from '$lib/utils' import { Button, Drawer } from './common' import DrawerContent from './common/drawer/DrawerContent.svelte' - import { createEventDispatcher, tick, untrack } from 'svelte' + import { tick, untrack } from 'svelte' import S3FilePickerInner from './S3FilePickerInner.svelte' import Select from './select/Select.svelte' import { FileUp } from 'lucide-svelte' @@ -10,11 +10,6 @@ import { SettingService } from '$lib/gen' import { workspaceStore } from '$lib/stores' - let dispatch = createEventDispatcher<{ - close: { s3: string; storage: string | undefined } | undefined - selectAndClose: { s3: string; storage: string | undefined } - }>() - interface Props { fromWorkspaceSettings?: boolean readOnlyMode: boolean @@ -22,6 +17,8 @@ selectedFileKey?: { s3: string; storage?: string } | undefined folderOnly?: boolean regexFilter?: RegExp | undefined + onClose?: () => void + onSelectAndClose?: (selected: { s3: string; storage: string | undefined }) => void } let { @@ -30,7 +27,9 @@ initialFileKey = $bindable(undefined), selectedFileKey = $bindable(undefined), folderOnly = false, - regexFilter = undefined + regexFilter = undefined, + onClose, + onSelectAndClose }: Props = $props() let drawer: Drawer | undefined = $state() @@ -76,7 +75,7 @@ { - dispatch('close') + onClose?.() s3FilePickerInner?.close?.() }} size="1200px" @@ -93,7 +92,7 @@ { - dispatch('selectAndClose', e.detail) + onSelectAndClose?.(e.detail) drawer?.closeDrawer?.() }} {fromWorkspaceSettings} diff --git a/frontend/src/lib/components/S3ObjectPicker.svelte b/frontend/src/lib/components/S3ObjectPicker.svelte index 6a9d1c9a86..c70983ee83 100644 --- a/frontend/src/lib/components/S3ObjectPicker.svelte +++ b/frontend/src/lib/components/S3ObjectPicker.svelte @@ -39,7 +39,7 @@ { + onClose={() => { rawValue = JSON.stringify(value, null, 2) editor?.setCode(rawValue) }} diff --git a/frontend/src/lib/components/apps/components/display/AppDownload.svelte b/frontend/src/lib/components/apps/components/display/AppDownload.svelte index dbc732bd06..0f38afe1db 100644 --- a/frontend/src/lib/components/apps/components/display/AppDownload.svelte +++ b/frontend/src/lib/components/apps/components/display/AppDownload.svelte @@ -12,6 +12,8 @@ import ComponentErrorHandler from '../helpers/ComponentErrorHandler.svelte' import ResolveStyle from '../helpers/ResolveStyle.svelte' import AlignWrapper from '../helpers/AlignWrapper.svelte' + import { userStore } from '$lib/stores' + import { isPartialS3Object, getS3File } from '../../editor/appUtilsS3' interface Props { id: string @@ -37,7 +39,8 @@ initConfig(components['downloadcomponent'].initialData.configuration, configuration) ) - const { app, worldStore } = getContext('AppViewerContext') + const { app, worldStore, appPath, workspace, isEditor } = + getContext('AppViewerContext') //used so that we can count number of outputs setup for first refresh initOutput($worldStore, id, {}) @@ -45,6 +48,10 @@ let beforeIconComponent: any = $state() let afterIconComponent: any = $state() + let downloadUrl: string | undefined = $state(undefined) + + let token = getContext<{ token?: string }>('AuthToken') + async function handleBeforeIcon() { if (resolvedConfig.beforeIcon) { beforeIconComponent = await loadIcon( @@ -69,6 +76,36 @@ } } + async function loadSource() { + if (isPartialS3Object(resolvedConfig.source)) { + downloadUrl = await getS3File({ + source: resolvedConfig.source.s3, + storage: resolvedConfig.source.storage, + presigned: resolvedConfig.source.presigned, + appPath: $appPath, + username: $userStore?.username, + workspace, + token: token?.token, + isEditor, + configuration + }) + } else if (resolvedConfig.source && typeof resolvedConfig.source !== 'string') { + throw new Error('Invalid source object' + typeof resolvedConfig.source) + } else if (resolvedConfig.source?.startsWith('s3://')) { + downloadUrl = await getS3File({ + source: resolvedConfig.source?.replace('s3://', ''), + appPath: $appPath, + username: $userStore?.username, + workspace, + token: token?.token, + isEditor, + configuration + }) + } else { + downloadUrl = transformBareBase64IfNecessary(resolvedConfig.source) + } + } + let css = $state(initCss($app.css?.downloadcomponent, customCss)) $effect(() => { resolvedConfig.beforeIcon && beforeIconComponent && untrack(() => handleBeforeIcon()) @@ -76,6 +113,9 @@ $effect(() => { resolvedConfig.afterIcon && afterIconComponent && untrack(() => handleAfterIcon()) }) + $effect(() => { + resolvedConfig && loadSource() + }) @@ -102,7 +142,9 @@ {#if render}