diff --git a/frontend/src/lib/components/DropdownV2.svelte b/frontend/src/lib/components/DropdownV2.svelte index ceeeb64a03..5b4f2beec6 100644 --- a/frontend/src/lib/components/DropdownV2.svelte +++ b/frontend/src/lib/components/DropdownV2.svelte @@ -1,8 +1,8 @@ + +{#if computedItems} +
+ {#each computedItems ?? [] as item} + item?.action?.(e)} + href={item?.href} + disabled={item?.disabled} + class={twMerge( + 'px-4 py-2 text-primary hover:bg-surface-hover hover:text-primary cursor-pointer text-xs transition-all', + 'flex flex-row gap-2 items-center', + item?.disabled && 'text-gray-400 cursor-not-allowed', + item?.type === 'delete' && + !item?.disabled && + 'text-red-500 hover:bg-red-100 hover:text-red-500' + )} + > + {#if item.icon} + + {/if} + {item.displayName} + + {/each} +
+{:else} + +{/if} diff --git a/frontend/src/lib/components/common/table/AppRow.svelte b/frontend/src/lib/components/common/table/AppRow.svelte index 1ec6540b85..b2a8cd5a10 100644 --- a/frontend/src/lib/components/common/table/AppRow.svelte +++ b/frontend/src/lib/components/common/table/AppRow.svelte @@ -4,12 +4,7 @@ import type MoveDrawer from '$lib/components/MoveDrawer.svelte' import SharedBadge from '$lib/components/SharedBadge.svelte' import type ShareModal from '$lib/components/ShareModal.svelte' - import { - AppService, - DraftService, - type ListableApp, - type WorkspaceDeployUISettings - } from '$lib/gen' + import { AppService, DraftService, type ListableApp } from '$lib/gen' import { userStore, workspaceStore } from '$lib/stores' import { createEventDispatcher } from 'svelte' import Button from '../button/Button.svelte' @@ -37,6 +32,7 @@ import AppDeploymentHistory from '$lib/components/apps/editor/AppDeploymentHistory.svelte' import AppJsonEditor from '$lib/components/apps/editor/AppJsonEditor.svelte' import { isDeployable } from '$lib/utils_deployable' + import { getDeployUiSettings } from '$lib/components/home/deploy_ui' export let app: ListableApp & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean } export let marked: string | undefined @@ -47,7 +43,6 @@ export let deleteConfirmedCallback: (() => void) | undefined export let depth: number = 0 export let menuOpen: boolean = false - export let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined const dispatch = createEventDispatcher() @@ -120,7 +115,7 @@ {/if} { + items={async () => { let { draft_only, canWrite, summary, execution_mode, path, has_draft } = app if (draft_only) { @@ -170,7 +165,7 @@ disabled: !canWrite, hide: $userStore?.operator }, - ...(isDeployable('app', path, deployUiSettings) + ...(isDeployable('app', path, await getDeployUiSettings()) ? [ { displayName: 'Deploy to staging/prod', diff --git a/frontend/src/lib/components/common/table/FlowRow.svelte b/frontend/src/lib/components/common/table/FlowRow.svelte index 6e96465f02..bb66037e25 100644 --- a/frontend/src/lib/components/common/table/FlowRow.svelte +++ b/frontend/src/lib/components/common/table/FlowRow.svelte @@ -6,7 +6,7 @@ import ScheduleEditor from '$lib/components/ScheduleEditor.svelte' import SharedBadge from '$lib/components/SharedBadge.svelte' import type ShareModal from '$lib/components/ShareModal.svelte' - import { FlowService, type Flow, DraftService, type WorkspaceDeployUISettings } from '$lib/gen' + import { FlowService, type Flow, DraftService } from '$lib/gen' import { userStore, workspaceStore } from '$lib/stores' import { createEventDispatcher } from 'svelte' import Badge from '../badge/Badge.svelte' @@ -33,6 +33,7 @@ HistoryIcon } from 'lucide-svelte' import FlowHistory from '$lib/components/flows/FlowHistory.svelte' + import { getDeployUiSettings } from '$lib/components/home/deploy_ui' export let flow: Flow & { has_draft?: boolean; draft_only?: boolean; canWrite: boolean } export let marked: string | undefined @@ -44,7 +45,6 @@ export let errorHandlerMuted: boolean export let depth: number = 0 export let menuOpen: boolean = false - export let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined const dispatch = createEventDispatcher() @@ -135,7 +135,7 @@ { + items={async () => { let { draft_only, path, archived, has_draft } = flow let owner = isOwner(path, $userStore, $workspaceStore) if (draft_only) { @@ -193,7 +193,7 @@ copyToClipboard(path) } }, - ...(isDeployable('flow', path, deployUiSettings) + ...(isDeployable('flow', path, await getDeployUiSettings()) ? [ { displayName: 'Deploy to staging/prod', diff --git a/frontend/src/lib/components/common/table/RawAppRow.svelte b/frontend/src/lib/components/common/table/RawAppRow.svelte index e40f59a76f..087c29f9bf 100644 --- a/frontend/src/lib/components/common/table/RawAppRow.svelte +++ b/frontend/src/lib/components/common/table/RawAppRow.svelte @@ -4,7 +4,7 @@ import type MoveDrawer from '$lib/components/MoveDrawer.svelte' import SharedBadge from '$lib/components/SharedBadge.svelte' import type ShareModal from '$lib/components/ShareModal.svelte' - import { RawAppService, type ListableRawApp, type WorkspaceDeployUISettings } from '$lib/gen' + import { RawAppService, type ListableRawApp } from '$lib/gen' import { userStore, workspaceStore } from '$lib/stores' import { createEventDispatcher } from 'svelte' import Button from '../button/Button.svelte' @@ -16,6 +16,7 @@ import type DeployWorkspaceDrawer from '$lib/components/DeployWorkspaceDrawer.svelte' import { FileUp, Globe, Pen, Share, Trash } from 'lucide-svelte' import { isDeployable } from '$lib/utils_deployable' + import { getDeployUiSettings } from '$lib/components/home/deploy_ui' export let app: ListableRawApp & { canWrite: boolean } export let marked: string | undefined @@ -26,7 +27,6 @@ export let deploymentDrawer: DeployWorkspaceDrawer export let depth: number = 0 export let menuOpen: boolean = false - export let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined let updateAppDrawer: Drawer @@ -88,7 +88,7 @@ {/if} { + items={async () => { let { summary, path, canWrite } = app return [ @@ -100,7 +100,7 @@ }, disabled: !canWrite }, - ...(isDeployable('app', path, deployUiSettings) + ...(isDeployable('app', path, await getDeployUiSettings()) ? [ { displayName: 'Deploy to prod/staging', diff --git a/frontend/src/lib/components/common/table/ScriptRow.svelte b/frontend/src/lib/components/common/table/ScriptRow.svelte index a962e17c32..af53bc4387 100644 --- a/frontend/src/lib/components/common/table/ScriptRow.svelte +++ b/frontend/src/lib/components/common/table/ScriptRow.svelte @@ -7,12 +7,7 @@ import SharedBadge from '$lib/components/SharedBadge.svelte' import type ShareModal from '$lib/components/ShareModal.svelte' - import { - ScriptService, - type Script, - DraftService, - type WorkspaceDeployUISettings - } from '$lib/gen' + import { ScriptService, type Script, DraftService } from '$lib/gen' import { userStore, workspaceStore } from '$lib/stores' import { createEventDispatcher } from 'svelte' @@ -44,6 +39,7 @@ import { Drawer, DrawerContent } from '..' import NoMainFuncBadge from '$lib/components/NoMainFuncBadge.svelte' import Tooltip from '$lib/components/Tooltip.svelte' + import { getDeployUiSettings } from '$lib/components/home/deploy_ui' export let script: Script & { canWrite: boolean; use_codebase: boolean } export let marked: string | undefined @@ -56,7 +52,6 @@ export let showCode: (path: string, summary: string) => void export let depth: number = 0 export let menuOpen: boolean = false - export let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined const dispatch = createEventDispatcher() @@ -166,7 +161,7 @@ {/if} { + items={async () => { let owner = isOwner(script.path, $userStore, $workspaceStore) if (script.draft_only) { return [ @@ -219,7 +214,7 @@ disabled: !owner || script.archived, hide: $userStore?.operator }, - ...(isDeployable('script', script.path, deployUiSettings) + ...(isDeployable('script', script.path, await getDeployUiSettings()) ? [ { displayName: 'Deploy to staging/prod', diff --git a/frontend/src/lib/components/home/Item.svelte b/frontend/src/lib/components/home/Item.svelte index ccaabb68b0..91ef63179d 100644 --- a/frontend/src/lib/components/home/Item.svelte +++ b/frontend/src/lib/components/home/Item.svelte @@ -10,9 +10,6 @@ import ShareModal from '../ShareModal.svelte' import { createEventDispatcher } from 'svelte' import { ArrowBigUp } from 'lucide-svelte' - import { enterpriseLicense, workspaceStore } from '$lib/stores' - import { WorkspaceService, type WorkspaceDeployUISettings } from '$lib/gen' - import { ALL_DEPLOYABLE } from '$lib/utils_deployable' export let item export let depth: number = 0 @@ -26,19 +23,6 @@ let menuOpen: boolean = false export let showCode: (path: string, summary: string) => void - - let deployUiSettings: WorkspaceDeployUISettings | undefined = undefined - - async function getDeployUiSettings() { - if (!$enterpriseLicense) { - deployUiSettings = ALL_DEPLOYABLE - return - } - let settings = await WorkspaceService.getSettings({ workspace: $workspaceStore! }) - deployUiSettings = settings.deploy_ui ?? ALL_DEPLOYABLE - } - getDeployUiSettings() - {#if item.type == 'script'} @@ -58,7 +42,6 @@ {depth} bind:menuOpen {showCode} - {deployUiSettings} /> {:else if item.type == 'flow'} {:else if item.type == 'app'} {:else if item.type == 'raw_app'} {/if} diff --git a/frontend/src/lib/components/home/deploy_ui.ts b/frontend/src/lib/components/home/deploy_ui.ts new file mode 100644 index 0000000000..662d9d25bd --- /dev/null +++ b/frontend/src/lib/components/home/deploy_ui.ts @@ -0,0 +1,23 @@ +import { enterpriseLicense, workspaceStore } from '$lib/stores' +import { WorkspaceService, type WorkspaceDeployUISettings } from '$lib/gen' +import { ALL_DEPLOYABLE } from '$lib/utils_deployable' +import { get, writable } from 'svelte/store' + +const deployUiStore = writable>({}) +export async function getDeployUiSettings(): Promise { + let deployUiSettings = get(deployUiStore) + let workspace = get(workspaceStore) + if (!deployUiSettings[workspace!]) { + deployUiSettings[workspace!] = await getDeployUiSettingsInner() + deployUiStore.set(deployUiSettings) + } + return deployUiSettings[workspace!] +} + +async function getDeployUiSettingsInner(): Promise { + if (!get(enterpriseLicense)) { + return ALL_DEPLOYABLE + } + let settings = await WorkspaceService.getSettings({ workspace: get(workspaceStore)! }) + return settings.deploy_ui ?? ALL_DEPLOYABLE +}