Workflows/Templates fixes

Match styles

Make workflows button functional

When opening a workflow or template from linear mode that does not
explicitly have a value set for linear mode, open the workflow or
template in linear mode

Known issue: workflows sidebar pane has a higher min-width than the
outputs panel. This is not an easy fix and I may have to re-implement
our own splitter component to smooth over the annoyances I've faced
This commit is contained in:
Austin Mroz
2026-01-06 11:45:05 -08:00
parent 664150b6a3
commit 2845320ddf
3 changed files with 25 additions and 27 deletions

View File

@@ -151,6 +151,7 @@ import {
useWorkflowBookmarkStore, useWorkflowBookmarkStore,
useWorkflowStore useWorkflowStore
} from '@/platform/workflow/management/stores/workflowStore' } from '@/platform/workflow/management/stores/workflowStore'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { useWorkspaceStore } from '@/stores/workspaceStore' import { useWorkspaceStore } from '@/stores/workspaceStore'
import type { TreeExplorerNode, TreeNode } from '@/types/treeExplorerTypes' import type { TreeExplorerNode, TreeNode } from '@/types/treeExplorerTypes'
import { appendJsonExt } from '@/utils/formatUtil' import { appendJsonExt } from '@/utils/formatUtil'
@@ -238,7 +239,12 @@ const renderTreeNode = (
e: MouseEvent e: MouseEvent
) { ) {
if (this.leaf) { if (this.leaf) {
const canvasStore = useCanvasStore()
const fromLinearMode = canvasStore.linearMode
await workflowService.openWorkflow(workflow) await workflowService.openWorkflow(workflow)
const extra = workflow.activeState?.extra
if (extra && extra.linearMode === undefined && fromLinearMode)
canvasStore.linearMode = extra.linearMode = true
} else { } else {
toggleNodeOnEvent(e, this) toggleNodeOnEvent(e, this)
} }

View File

@@ -9,6 +9,7 @@ import type {
TemplateInfo, TemplateInfo,
WorkflowTemplates WorkflowTemplates
} from '@/platform/workflow/templates/types/template' } from '@/platform/workflow/templates/types/template'
import { useCanvasStore } from '@/renderer/core/canvas/canvasStore'
import { api } from '@/scripts/api' import { api } from '@/scripts/api'
import { app } from '@/scripts/app' import { app } from '@/scripts/app'
import { useDialogStore } from '@/stores/dialogStore' import { useDialogStore } from '@/stores/dialogStore'
@@ -121,28 +122,7 @@ export function useTemplateWorkflows() {
if (!template || !template.sourceModule) return false if (!template || !template.sourceModule) return false
// Use the stored source module for loading // Use the stored source module for loading
const actualSourceModule = template.sourceModule sourceModule = template.sourceModule
json = await fetchTemplateJson(id, actualSourceModule)
// Use source module for name
const workflowName =
actualSourceModule === 'default'
? t(`templateWorkflows.template.${id}`, id)
: id
if (isCloud) {
useTelemetry()?.trackTemplate({
workflow_name: id,
template_source: actualSourceModule
})
}
dialogStore.closeDialog()
await app.loadGraphData(json, true, true, workflowName, {
openSource: 'template'
})
return true
} }
// Regular case for normal categories // Regular case for normal categories
@@ -159,12 +139,18 @@ export function useTemplateWorkflows() {
template_source: sourceModule template_source: sourceModule
}) })
} }
dialogStore.closeDialog() dialogStore.closeDialog()
const canvasStore = useCanvasStore()
const fromLinearMode = canvasStore.linearMode
await app.loadGraphData(json, true, true, workflowName, { await app.loadGraphData(json, true, true, workflowName, {
openSource: 'template' openSource: 'template'
}) })
const extra = app.rootGraph.extra
if (extra && extra.linearMode === undefined && fromLinearMode)
canvasStore.linearMode = extra.linearMode = true
return true return true
} catch (error) { } catch (error) {
console.error('Error loading workflow template:', error) console.error('Error loading workflow template:', error)

View File

@@ -14,7 +14,9 @@ import { computed, ref, shallowRef, useTemplateRef, watch } from 'vue'
import { downloadFile } from '@/base/common/downloadUtil' import { downloadFile } from '@/base/common/downloadUtil'
import Load3dViewerContent from '@/components/load3d/Load3dViewerContent.vue' import Load3dViewerContent from '@/components/load3d/Load3dViewerContent.vue'
import SidebarIcon from '@/components/sidebar/SidebarIcon.vue'
import SidebarTemplatesButton from '@/components/sidebar/SidebarTemplatesButton.vue' import SidebarTemplatesButton from '@/components/sidebar/SidebarTemplatesButton.vue'
import WorkflowsSidebarTab from '@/components/sidebar/tabs/WorkflowsSidebarTab.vue'
import TopbarBadges from '@/components/topbar/TopbarBadges.vue' import TopbarBadges from '@/components/topbar/TopbarBadges.vue'
import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue' import WorkflowTabs from '@/components/topbar/WorkflowTabs.vue'
import Popover from '@/components/ui/Popover.vue' import Popover from '@/components/ui/Popover.vue'
@@ -60,6 +62,7 @@ const workflowStore = useWorkflowStore()
void outputs.fetchMediaList() void outputs.fetchMediaList()
const displayWorkflows = ref(false)
const hasPreview = ref(false) const hasPreview = ref(false)
whenever( whenever(
() => nodeOutputStore.latestPreview[0], () => nodeOutputStore.latestPreview[0],
@@ -307,7 +310,6 @@ const itemStats = computed<StatItem[]>(() => {
{ content: formatTime(activeItem.value.created_at) }, { content: formatTime(activeItem.value.created_at) },
{ content: formatDuration(user_metadata.executionTimeInSeconds) }, { content: formatDuration(user_metadata.executionTimeInSeconds) },
allOutputs && { content: `${allOutputs.length} asset` }, allOutputs && { content: `${allOutputs.length} asset` },
//TODO asset icon
(activeOutput && mediaTypes[getMediaType(activeOutput)]) ?? {} (activeOutput && mediaTypes[getMediaType(activeOutput)]) ?? {}
].filter((i) => !!i) ].filter((i) => !!i)
}) })
@@ -421,9 +423,11 @@ function downloadAsset(item: AssetItem) {
<div <div
class="h-full flex flex-col w-14 shrink-0 overflow-hidden items-center p-2 border-r border-node-component-border" class="h-full flex flex-col w-14 shrink-0 overflow-hidden items-center p-2 border-r border-node-component-border"
> >
<Button class="bg-transparent"> <SidebarIcon
<i class="size-4 icon-[comfy--workflow] bg-muted-foreground" /> icon="icon-[comfy--workflow]"
</Button> :selected="displayWorkflows"
@click="displayWorkflows = !displayWorkflows"
/>
<SidebarTemplatesButton /> <SidebarTemplatesButton />
<div class="flex-1" /> <div class="flex-1" />
<div class="p-1 bg-secondary-background rounded-lg w-10"> <div class="p-1 bg-secondary-background rounded-lg w-10">
@@ -445,7 +449,9 @@ function downloadAsset(item: AssetItem) {
</Button> </Button>
</div> </div>
</div> </div>
<WorkflowsSidebarTab v-if="displayWorkflows" class="min-w-0" />
<linear-outputs <linear-outputs
v-else
ref="outputsRef" ref="outputsRef"
class="h-full min-w-24 grow-1 p-3 overflow-y-auto border-r-1 border-node-component-border flex flex-col items-center" class="h-full min-w-24 grow-1 p-3 overflow-y-auto border-r-1 border-node-component-border flex flex-col items-center"
> >