mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-02-10 10:00:08 +00:00
Co-authored-by: Terry Jia <terryjia88@gmail.com> Co-authored-by: Chenlei Hu <hcl@comfy.org> Co-authored-by: github-actions <github-actions@github.com> Co-authored-by: Chenlei Hu <huchenlei@proton.me> Co-authored-by: Comfy Org PR Bot <snomiao+comfy-pr@gmail.com>
135 lines
4.2 KiB
Vue
135 lines
4.2 KiB
Vue
<template>
|
|
<div
|
|
class="flex flex-col h-[83vh] w-[90vw] relative pb-6"
|
|
data-testid="template-workflows-content"
|
|
>
|
|
<Button
|
|
v-if="isSmallScreen"
|
|
:icon="isSideNavOpen ? 'pi pi-chevron-left' : 'pi pi-chevron-right'"
|
|
text
|
|
class="absolute top-1/2 -translate-y-1/2 z-10"
|
|
:class="isSideNavOpen ? 'left-[19rem]' : 'left-2'"
|
|
@click="toggleSideNav"
|
|
/>
|
|
<Divider
|
|
class="m-0 [&::before]:border-surface-border/70 [&::before]:border-t-2"
|
|
/>
|
|
<div class="flex flex-1 relative overflow-hidden">
|
|
<aside
|
|
v-if="isSideNavOpen"
|
|
class="absolute translate-x-0 top-0 left-0 h-full w-80 shadow-md z-5 transition-transform duration-300 ease-in-out"
|
|
>
|
|
<ProgressSpinner
|
|
v-if="!workflowTemplatesStore.isLoaded || !isReady"
|
|
class="absolute w-8 h-full inset-0"
|
|
/>
|
|
<TemplateWorkflowsSideNav
|
|
:tabs="tabs"
|
|
:selected-tab="selectedTab"
|
|
@update:selected-tab="handleTabSelection"
|
|
/>
|
|
</aside>
|
|
<div
|
|
class="flex-1 transition-all duration-300"
|
|
:class="{
|
|
'pl-80': isSideNavOpen || !isSmallScreen,
|
|
'pl-8': !isSideNavOpen && isSmallScreen
|
|
}"
|
|
>
|
|
<TemplateWorkflowView
|
|
v-if="isReady && selectedTab"
|
|
class="px-12 py-4"
|
|
:title="selectedTab.title"
|
|
:source-module="selectedTab.moduleName"
|
|
:templates="selectedTab.templates"
|
|
:loading="workflowLoading"
|
|
:category-title="selectedTab.title"
|
|
@load-workflow="loadWorkflow"
|
|
/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { useAsyncState } from '@vueuse/core'
|
|
import Button from 'primevue/button'
|
|
import Divider from 'primevue/divider'
|
|
import ProgressSpinner from 'primevue/progressspinner'
|
|
import { computed, ref, watch } from 'vue'
|
|
import { useI18n } from 'vue-i18n'
|
|
|
|
import TemplateWorkflowView from '@/components/templates/TemplateWorkflowView.vue'
|
|
import TemplateWorkflowsSideNav from '@/components/templates/TemplateWorkflowsSideNav.vue'
|
|
import { useResponsiveCollapse } from '@/composables/element/useResponsiveCollapse'
|
|
import { api } from '@/scripts/api'
|
|
import { app } from '@/scripts/app'
|
|
import { useDialogStore } from '@/stores/dialogStore'
|
|
import { useWorkflowTemplatesStore } from '@/stores/workflowTemplatesStore'
|
|
import type { WorkflowTemplates } from '@/types/workflowTemplateTypes'
|
|
|
|
const { t } = useI18n()
|
|
|
|
const {
|
|
isSmallScreen,
|
|
isOpen: isSideNavOpen,
|
|
toggle: toggleSideNav
|
|
} = useResponsiveCollapse()
|
|
|
|
const workflowTemplatesStore = useWorkflowTemplatesStore()
|
|
const { isReady } = useAsyncState(
|
|
workflowTemplatesStore.loadWorkflowTemplates,
|
|
null
|
|
)
|
|
|
|
const selectedTab = ref<WorkflowTemplates | null>(null)
|
|
const selectFirstTab = () => {
|
|
const firstTab = workflowTemplatesStore.groupedTemplates[0].modules[0]
|
|
handleTabSelection(firstTab)
|
|
}
|
|
watch(isReady, selectFirstTab, { once: true })
|
|
|
|
const workflowLoading = ref<string | null>(null)
|
|
|
|
const tabs = computed(() => workflowTemplatesStore.groupedTemplates)
|
|
|
|
const handleTabSelection = (selection: WorkflowTemplates | null) => {
|
|
//Listbox allows deselecting so this special case is ignored here
|
|
if (selection !== selectedTab.value && selection !== null) {
|
|
selectedTab.value = selection
|
|
|
|
// On small screens, close the sidebar when a category is selected
|
|
if (isSmallScreen.value) {
|
|
isSideNavOpen.value = false
|
|
}
|
|
}
|
|
}
|
|
|
|
const loadWorkflow = async (id: string) => {
|
|
if (!isReady.value) return
|
|
|
|
workflowLoading.value = id
|
|
let json
|
|
if (selectedTab.value?.moduleName === 'default') {
|
|
// Default templates provided by frontend are served on this separate endpoint
|
|
json = await fetch(api.fileURL(`/templates/${id}.json`)).then((r) =>
|
|
r.json()
|
|
)
|
|
} else {
|
|
json = await fetch(
|
|
api.apiURL(
|
|
`/workflow_templates/${selectedTab.value?.moduleName}/${id}.json`
|
|
)
|
|
).then((r) => r.json())
|
|
}
|
|
useDialogStore().closeDialog()
|
|
const workflowName =
|
|
selectedTab.value?.moduleName === 'default'
|
|
? t(`templateWorkflows.template.${id}`, id)
|
|
: id
|
|
await app.loadGraphData(json, true, true, workflowName)
|
|
|
|
return false
|
|
}
|
|
</script>
|