diff --git a/frontend/src/lib/components/flows/map/FlowModuleSchemaItem.svelte b/frontend/src/lib/components/flows/map/FlowModuleSchemaItem.svelte
index 0bd3c10066..cf454c0da7 100644
--- a/frontend/src/lib/components/flows/map/FlowModuleSchemaItem.svelte
+++ b/frontend/src/lib/components/flows/map/FlowModuleSchemaItem.svelte
@@ -143,7 +143,6 @@
let flowStateStore = $derived(flowEditorContext?.flowStateStore)
let assets = $derived(id ? $flowStateStore?.[id]?.assetsCache : undefined)
- let containsSelectedAsset = $derived(assets?.some((a) => assetEq(a, selectedAssetStore?.val)))
let stepHistoryLoader = getStepHistoryLoaderContext()
@@ -276,8 +275,7 @@
class={classNames(
'w-full module flex rounded-sm cursor-pointer max-w-full ',
'flex relative',
- deletable ? aiModuleActionToBgColor(action) : '',
- containsSelectedAsset ? '!bg-surface-hover' : ''
+ deletable ? aiModuleActionToBgColor(action) : ''
)}
style="width: 275px; height: 34px; background-color: {hover && bgHoverColor
? bgHoverColor
@@ -292,8 +290,7 @@
diff --git a/frontend/src/lib/components/graph/FlowGraphV2.svelte b/frontend/src/lib/components/graph/FlowGraphV2.svelte
index b1e090cfb8..3b437644ed 100644
--- a/frontend/src/lib/components/graph/FlowGraphV2.svelte
+++ b/frontend/src/lib/components/graph/FlowGraphV2.svelte
@@ -17,6 +17,7 @@
import {
graphBuilder,
isTriggerStep,
+ type AssetN,
type InlineScript,
type InsertKind,
type NodeLayout,
@@ -50,11 +51,18 @@
import SubflowBound from './renderers/nodes/SubflowBound.svelte'
import { deepEqual } from 'fast-equals'
import ViewportResizer from './ViewportResizer.svelte'
+ import type { FlowEditorContext } from '../flows/types'
+ import AssetNode from './renderers/nodes/AssetNode.svelte'
+ import { formatAsset } from '../assets/lib'
let useDataflow: Writable = writable(false)
const triggerContext = getContext('TriggerContext')
+ const flowEditorContextOpt: FlowEditorContext | undefined =
+ getContext('FlowEditorContext')
+ const flowStateStoreOpt = flowEditorContextOpt.flowStateStore
+
let fullWidth = 0
let width = $state(0)
@@ -220,9 +228,11 @@
.decross(nodes.length > 20 ? decrossTwoLayer() : decrossOpt())
.coord(coordCenter())
.nodeSize((d) => {
+ const id: string | undefined = d?.data?.['id'] ?? ''
+ const assetOffset = $flowStateStoreOpt?.[id]?.assetsCache?.length ? 100 : 0
return [
- (nodeWidths[d?.data?.['id'] ?? ''] ?? 1) * (NODE.width + NODE.gap.horizontal * 1),
- NODE.height + NODE.gap.vertical
+ (nodeWidths[id] ?? 1) * (NODE.width + NODE.gap.horizontal * 1),
+ NODE.height + NODE.gap.vertical + assetOffset
] as readonly [number, number]
})
boxSize = layout(dag as any)
@@ -256,6 +266,55 @@
return newNodes
}
+ function computeAssetNodes(nodes: Node[]) {
+ const ASSET_X_GAP = 20
+ const ASSET_WIDTH = 180
+ const ASSET_Y_OFFSET = 55
+ return nodes.flatMap((node) => {
+ const assets = $flowStateStoreOpt?.[node.id]?.assetsCache
+ const assetNodes = assets?.map(
+ (asset, assetIdx) =>
+ ({
+ id: `${node.id}-asset-${formatAsset(asset)}`,
+ type: 'asset',
+ data: { asset },
+ position: {
+ x:
+ (ASSET_WIDTH + ASSET_X_GAP) * (assetIdx - assets.length / 2) +
+ (NODE.width + ASSET_X_GAP) / 2,
+ y: ASSET_Y_OFFSET
+ },
+ parentId: node.id,
+ width: ASSET_WIDTH
+ }) satisfies Node & AssetN
+ )
+ return assetNodes ?? []
+ })
+ }
+
+ function computeAssetEdges(edges: Edge[], assetNodes: (Node & AssetN)[]): Edge[] {
+ return assetNodes.map(
+ (n) =>
+ ({
+ id: `${n.id}-edge`,
+ source: n.parentId ?? '',
+ target: n.id,
+ type: 'empty',
+ data: {
+ insertable: false,
+ sourceId: n.id,
+ targetId: n.parentId,
+ moving: moving,
+ eventHandlers: eventHandler,
+ index: 0,
+ enableTrigger: false,
+ disableAi: disableAi,
+ disableMoveIds: []
+ }
+ }) satisfies Edge
+ )
+ }
+
let eventHandler = {
deleteBranch: (detail, label) => {
$selectedId = label
@@ -344,7 +403,9 @@
let newGraph = graph
nodes = layoutNodes(newGraph.nodes)
- edges = newGraph.edges
+ const assetNodes = computeAssetNodes(nodes)
+ nodes = [...nodes, ...assetNodes]
+ edges = [...newGraph.edges, ...computeAssetEdges(newGraph.edges, assetNodes)]
await tick()
height = Math.max(...nodes.map((n) => n.position.y + NODE.height + 100), minHeight)
}
@@ -363,7 +424,8 @@
branchOneEnd: BranchOneEndNode,
subflowBound: SubflowBound,
noBranch: NoBranchNode,
- trigger: TriggersNode
+ trigger: TriggersNode,
+ asset: AssetNode
} as any
const edgeTypes = {
diff --git a/frontend/src/lib/components/graph/graphBuilder.svelte.ts b/frontend/src/lib/components/graph/graphBuilder.svelte.ts
index 4a1032ff01..5145537361 100644
--- a/frontend/src/lib/components/graph/graphBuilder.svelte.ts
+++ b/frontend/src/lib/components/graph/graphBuilder.svelte.ts
@@ -4,6 +4,7 @@ import { getDependeeAndDependentComponents } from '../flows/flowExplorer'
import { dfsByModule } from '../flows/previousResults'
import { defaultIfEmptyString } from '$lib/utils'
import type { GraphModuleState } from './model'
+import type { Asset } from '../assets/lib'
export type InsertKind =
| 'script'
@@ -90,6 +91,7 @@ export type FlowNode =
| SubflowBoundN
| NoBranchN
| TriggerN
+ | AssetN
export type InputN = {
type: 'input2'
@@ -256,6 +258,13 @@ export type TriggerN = {
}
}
+export type AssetN = {
+ type: 'asset'
+ data: {
+ asset: Asset
+ }
+}
+
// input2: InputNode,
// module: ModuleNode,
// branchAllStart: BranchAllStart,
diff --git a/frontend/src/lib/components/graph/renderers/nodes/AssetNode.svelte b/frontend/src/lib/components/graph/renderers/nodes/AssetNode.svelte
new file mode 100644
index 0000000000..bea1ca4289
--- /dev/null
+++ b/frontend/src/lib/components/graph/renderers/nodes/AssetNode.svelte
@@ -0,0 +1,36 @@
+
+
+
+ {#snippet children({ darkMode })}
+
+ (selectedAssetStore.val = data.asset)}
+ onmouseleave={() => (selectedAssetStore.val = undefined)}
+ >
+
+
+ {formatAsset(data.asset)}
+
+
+ {/snippet}
+