Workflow templates (#938)

* Add template gallery

* Add simple test

* Add examples

* Enable floating menu in test
This commit is contained in:
pythongosssss
2024-09-24 08:59:28 +09:00
committed by Chenlei Hu
parent 2aaee5c331
commit bf7652227a
15 changed files with 2016 additions and 0 deletions

View File

@@ -1,6 +1,13 @@
<template>
<SidebarTabTemplate :title="$t('sideToolbar.workflows')">
<template #tool-buttons>
<Button
class="browse-templates-button"
icon="pi pi-th-large"
v-tooltip="$t('sideToolbar.browseTemplates')"
text
@click="browseTemplates"
/>
<Button
class="browse-workflows-button"
icon="pi pi-folder-open"
@@ -112,6 +119,7 @@ import { TreeExplorerNode } from '@/types/treeExplorerTypes'
import { ComfyWorkflow } from '@/scripts/workflows'
import { useI18n } from 'vue-i18n'
import { useTreeExpansion } from '@/hooks/treeHooks'
import { showTemplateWorkflowsDialog } from '@/services/dialogService'
const searchQuery = ref('')
const isSearching = computed(() => searchQuery.value.length > 0)
@@ -145,6 +153,10 @@ const browse = () => {
app.ui.loadFile()
}
const browseTemplates = () => {
showTemplateWorkflowsDialog()
}
const createBlank = () => {
app.workflowManager.setWorkflow(null)
app.clean()

View File

@@ -0,0 +1,81 @@
<template>
<div
class="flex flex-wrap content-around justify-around gap-4"
data-testid="template-workflows-content"
>
<div
v-for="template in templates"
:key="template"
:data-testid="`template-workflow-${template}`"
>
<Card>
<template #header>
<div
class="relative overflow-hidden rounded-lg cursor-pointer"
@click="loadWorkflow(template)"
>
<img
:src="`/templates/${template}.png`"
class="w-64 h-64 rounded-lg object-cover"
/>
<a>
<div
class="absolute top-0 left-0 w-64 h-64 overflow-hidden opacity-0 transition duration-300 ease-in-out hover:opacity-100 bg-opacity-50 bg-black flex items-center justify-center"
>
<i class="pi pi-play-circle"></i>
</div>
</a>
<ProgressSpinner
v-if="loading === template"
class="absolute inset-0 z-1 w-3/12 h-full"
/>
</div>
</template>
<template #subtitle>{{
$t(`templateWorkflows.template.${template}`)
}}</template>
</Card>
</div>
</div>
</template>
<script setup lang="ts">
import { useDialogStore } from '@/stores/dialogStore'
import Card from 'primevue/card'
import ProgressSpinner from 'primevue/progressspinner'
import { ref } from 'vue'
import { app } from '@/scripts/app'
import { api } from '@/scripts/api'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const templates = ['default', 'image2image', 'upscale', 'flux_schnell']
const loading = ref<string | null>(null)
const loadWorkflow = async (id: string) => {
loading.value = id
const json = await fetch(api.fileURL(`templates/${id}.json`)).then((r) =>
r.json()
)
useDialogStore().closeDialog()
await app.loadGraphData(
json,
true,
true,
t(`templateWorkflows.template.${id}`)
)
return false
}
</script>
<style lang="css" scoped>
.p-card {
--p-card-body-padding: 10px 0 0 0;
overflow: hidden;
}
:deep(.p-card-subtitle) {
text-align: center;
}
</style>

View File

@@ -50,6 +50,7 @@ const messages = {
queue: 'Queue',
nodeLibrary: 'Node Library',
workflows: 'Workflows',
browseTemplates: 'Browse example templates',
nodeLibraryTab: {
sortOrder: 'Sort Order'
},
@@ -80,6 +81,15 @@ const messages = {
clipspace: 'Open Clipspace',
resetView: 'Reset canvas view',
clear: 'Clear workflow'
},
templateWorkflows: {
title: 'Get Started with a Template',
template: {
default: 'Image Generation',
image2image: 'Image to Image',
upscale: '2 Pass Upscale',
flux_schnell: 'Flux Schnell'
}
}
},
zh: {

View File

@@ -8,6 +8,8 @@ import SettingDialogContent from '@/components/dialog/content/SettingDialogConte
import SettingDialogHeader from '@/components/dialog/header/SettingDialogHeader.vue'
import type { ExecutionErrorWsMessage } from '@/types/apiTypes'
import ExecutionErrorDialogContent from '@/components/dialog/content/ExecutionErrorDialogContent.vue'
import TemplateWorkflowsContent from '@/components/templates/TemplateWorkflowsContent.vue'
import { i18n } from '@/i18n'
export function showLoadWorkflowWarning(props: {
missingNodeTypes: any[]
@@ -47,3 +49,10 @@ export function showExecutionErrorDialog(error: ExecutionErrorWsMessage) {
}
})
}
export function showTemplateWorkflowsDialog() {
useDialogStore().showDialog({
title: i18n.global.t('templateWorkflows.title'),
component: TemplateWorkflowsContent
})
}