Highlight assets used in modules

This commit is contained in:
Diego Imbert
2025-07-01 11:03:34 +02:00
parent a05b8bc56c
commit c6c908c3c8
8 changed files with 57 additions and 15 deletions
+3 -1
View File
@@ -431,6 +431,7 @@
}
const flowStateStore = writable({} as FlowState)
const selectedAssetStore = $state({ val: undefined })
const previewArgsStore = $state({ val: {} })
const scriptEditorDrawer = writable(undefined)
@@ -469,7 +470,8 @@
editPanelSize: undefined,
payloadData: undefined
}),
currentEditor: writable(undefined)
currentEditor: writable(undefined),
selectedAssetStore
})
setContext<PropPickerContext>('PropPickerContext', {
flowPropPickerConfig: writable<FlowPropPickerConfig | undefined>(undefined),
@@ -565,6 +565,7 @@
}
const previewArgsStore = $state({ val: initialArgs })
const selectedAssetStore = $state({ val: undefined })
const scriptEditorDrawer = writable<ScriptEditorDrawer | undefined>(undefined)
const moving = writable<{ id: string } | undefined>(undefined)
const history = initHistory(flowStore.val)
@@ -603,7 +604,8 @@
customUi,
insertButtonOpen,
executionCount: writable(0),
flowInputEditorState: flowInputEditorStateStore
flowInputEditorState: flowInputEditorStateStore,
selectedAssetStore
})
// Add triggers context store
@@ -8,7 +8,7 @@
import ExploreAssetButton, {
assetCanBeExplored
} from '../../../routes/(root)/(logged)/assets/ExploreAssetButton.svelte'
import { formatAsset, parseAsset } from './lib'
import { formatAsset, parseAsset, type Asset } from './lib'
import DbManagerDrawer from '../DBManagerDrawer.svelte'
import { untrack } from 'svelte'
import { ResourceService } from '$lib/gen'
@@ -16,17 +16,26 @@
import Button from '../common/button/Button.svelte'
import Tooltip from '../meltComponents/Tooltip.svelte'
import ResourceEditorDrawer from '../ResourceEditorDrawer.svelte'
import type { Placement } from '@floating-ui/core'
let {
assets: assetsUris,
enableChangeAnimation = true,
size = 'xs',
noBtnText = false
noBtnText = false,
outline = false,
popoverPlacement = 'bottom-end',
onHoverLi,
disableLiTooltip = false
}: {
assets: string[]
enableChangeAnimation?: boolean
size?: 'xs' | '3xs'
noBtnText?: boolean
outline?: boolean
popoverPlacement?: Placement
disableLiTooltip?: boolean
onHoverLi?: (asset: Asset, eventType: 'enter' | 'leave') => void
} = $props()
const assets = $derived(assetsUris.map(parseAsset).filter((x) => !!x) ?? [])
@@ -37,7 +46,6 @@
let dbManagerDrawer: DbManagerDrawer | undefined = $state()
let resourceEditorDrawer: ResourceEditorDrawer | undefined = $state()
let isOpen = $state(false)
let resourceDataCache: Record<string, string | undefined> = $state({})
$effect(() => {
@@ -73,18 +81,21 @@
</script>
<Popover
floatingConfig={{ strategy: 'absolute', placement: 'bottom-end' }}
floatingConfig={{ strategy: 'absolute', placement: popoverPlacement }}
usePointerDownOutside
closeOnOtherPopoverOpen
bind:isOpen
escapeBehavior="ignore"
>
<svelte:fragment slot="trigger">
<div
class={twMerge(
size === '3xs' ? 'h-[1.6rem]' : 'py-1.5',
'text-xs flex items-center gap-1.5 px-2 rounded-md border border-tertiary/30 relative',
'text-xs flex items-center gap-1.5 px-2 rounded-md relative',
'border border-tertiary/30 outline outline-2',
'bg-surface hover:bg-surface-hover active:bg-surface',
'transition-colors hover:text-primary cursor-pointer'
outline ? 'outline-tertiary' : 'outline-transparent',
'transition-all hover:text-primary cursor-pointer'
)}
>
<div
@@ -103,8 +114,12 @@
<ul class="divide-y rounded-md">
{#each assets as asset}
{#if asset}
<li class="text-sm px-4 h-12 flex gap-4 items-center justify-between">
<Tooltip class="select-none max-w-48 truncate">
<li
class="text-sm px-4 h-12 flex gap-4 items-center justify-between hover:bg-surface-hover"
onmouseenter={() => onHoverLi?.(asset, 'enter')}
onmouseleave={() => onHoverLi?.(asset, 'leave')}
>
<Tooltip class="select-none max-w-48 truncate" disablePopup={disableLiTooltip}>
{formatAsset(asset)}
<svelte:fragment slot="text">
{formatAsset(asset)}
@@ -24,3 +24,8 @@ export function getAssetUsagePageUri(usage: ListAssetsResponse[number]['usages']
return `/flows/get/${usage.usage_path}`
}
}
export function assetEquals(a: Asset | undefined, b: Asset | undefined): boolean {
if (!a || !b) return a === b
return a.kind === b.kind && a.path === b.path
}
@@ -42,7 +42,7 @@
import ModuleTest from '$lib/components/ModuleTest.svelte'
import { getStepHistoryLoaderContext } from '$lib/components/stepHistoryLoader.svelte'
import AssetsDropdownButton from '$lib/components/assets/AssetsDropdownButton.svelte'
import { formatAsset } from '$lib/components/assets/lib'
import { assetEquals, formatAsset } from '$lib/components/assets/lib'
interface Props {
selected?: boolean
@@ -115,7 +115,7 @@
const flowEditorContext = getContext<FlowEditorContext | undefined>('FlowEditorContext')
const flowInputsStore = flowEditorContext?.flowInputsStore
const selectedAssetStore = flowEditorContext?.selectedAssetStore
const dispatch = createEventDispatcher()
const propPickerContext = getContext<PropPickerContext>('PropPickerContext')
@@ -143,6 +143,7 @@
let flowStateStore = $derived(flowEditorContext?.flowStateStore)
let assets = $derived(id ? $flowStateStore?.[id]?.assetsCache : undefined)
let containsSelectedAsset = $derived(assets?.some((a) => assetEquals(a, selectedAssetStore?.val)))
let stepHistoryLoader = getStepHistoryLoaderContext()
@@ -467,7 +468,10 @@
{#if !action}
<div
class="absolute top-1/2 -translate-y-1/2 -translate-x-[100%] -left-[0] flex flex-col gap-1 justify-center mt-[0.55rem] w-fit px-2 h-9 min-w-14"
class={twMerge(
'absolute top-1/2 -translate-y-1/2 -translate-x-[100%] -left-[0] flex flex-col gap-1 justify-center w-fit px-2 h-9 min-w-14 transition-all',
(hover || selected) && outputPickerVisible ? 'mt-[0.6rem]' : ''
)}
>
{#if deletable && (hover || selected) && outputPickerVisible}
<div transition:fade={{ duration: 100 }}>
@@ -515,13 +519,20 @@
{/if}
</div>
{/if}
{#if assets?.length && (hover || selected)}
{#if assets?.length && (hover || selected || containsSelectedAsset)}
<div transition:fade={{ duration: 100 }}>
<AssetsDropdownButton
popoverPlacement="left"
size="3xs"
assets={assets.map(formatAsset)}
enableChangeAnimation={selected}
noBtnText
outline={containsSelectedAsset}
disableLiTooltip
onHoverLi={(asset, eventType) => {
if (selectedAssetStore)
selectedAssetStore.val = eventType === 'enter' ? asset : undefined
}}
/>
</div>
{/if}
@@ -8,6 +8,7 @@ import type Editor from '../Editor.svelte'
import type SimpleEditor from '../SimpleEditor.svelte'
import type { StateStore } from '$lib/utils'
import type { TestSteps } from './testSteps.svelte'
import type { Asset } from '../assets/lib'
export type FlowInput = Record<
string,
@@ -78,4 +79,5 @@ export type FlowEditorContext = {
customUi: FlowBuilderWhitelabelCustomUi
insertButtonOpen: Writable<boolean>
executionCount: Writable<number>
selectedAssetStore: StateStore<Asset | undefined>
}
@@ -17,6 +17,7 @@
import { Button } from '$lib/components/common'
import DocLink from '$lib/components/apps/editor/settingsPanel/DocLink.svelte'
import type { FloatingConfig } from '@melt-ui/svelte/internal/actions/floating'
import type { EscapeBehaviorType } from '@melt-ui/svelte/internal/actions'
export let closeButton: boolean = false
export let displayArrow: boolean = false
@@ -35,6 +36,7 @@
export let disabled: boolean = false
export let documentationLink: string | undefined = undefined
export let disableFocusTrap: boolean = false
export let escapeBehavior: EscapeBehaviorType = 'close'
let fullScreen = false
const dispatch = createEventDispatcher()
@@ -48,6 +50,7 @@
forceVisible: true,
portal,
disableFocusTrap,
escapeBehavior,
onOpenChange: ({ curr, next }) => {
if (curr != next) {
dispatch('openChange', next)
+3 -1
View File
@@ -68,6 +68,7 @@
let initialCode = JSON.stringify(flowStore, null, 4)
const flowStateStore = writable({} as FlowState)
const selectedAssetStore = $state({ val: undefined })
const previewArgsStore = $state({ val: {} })
const scriptEditorDrawer = writable(undefined)
@@ -106,7 +107,8 @@
editPanelSize: undefined,
payloadData: undefined
}),
currentEditor: writable(undefined)
currentEditor: writable(undefined),
selectedAssetStore
})
setContext<PropPickerContext>('PropPickerContext', {
flowPropPickerConfig: writable<FlowPropPickerConfig | undefined>(undefined),