Rearrange workflow tabs (#2026)

This commit is contained in:
Fahd Arafat
2024-12-23 16:51:17 +02:00
committed by GitHub
parent 1af0b4f992
commit cfb884b118
3 changed files with 123 additions and 42 deletions

View File

@@ -0,0 +1,108 @@
<template>
<div class="flex p-2 gap-2 workflow-tab" ref="workflowTabRef" v-bind="$attrs">
<span
class="workflow-label text-sm max-w-[150px] truncate inline-block"
v-tooltip.bottom="workflowOption.workflow.key"
>
{{ workflowOption.workflow.filename }}
</span>
<div class="relative">
<span
class="status-indicator"
v-if="
!workspaceStore.shiftDown &&
(workflowOption.workflow.isModified ||
!workflowOption.workflow.isPersisted)
"
>•</span
>
<Button
class="close-button p-0 w-auto"
icon="pi pi-times"
text
severity="secondary"
size="small"
@click.stop="onCloseWorkflow(workflowOption)"
/>
</div>
</div>
</template>
<script setup lang="ts">
import { ComfyWorkflow } from '@/stores/workflowStore'
import { useWorkflowStore } from '@/stores/workflowStore'
import Button from 'primevue/button'
import { ref } from 'vue'
import { workflowService } from '@/services/workflowService'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import { usePragmaticDraggable, usePragmaticDroppable } from '@/hooks/dndHooks'
interface WorkflowOption {
value: string
workflow: ComfyWorkflow
}
const props = defineProps<{
class?: string
workflowOption: WorkflowOption
}>()
const workspaceStore = useWorkspaceStore()
const workflowStore = useWorkflowStore()
const workflowTabRef = ref<HTMLElement | null>(null)
const closeWorkflows = async (options: WorkflowOption[]) => {
for (const opt of options) {
if (
!(await workflowService.closeWorkflow(opt.workflow, {
warnIfUnsaved: !workspaceStore.shiftDown
}))
) {
// User clicked cancel
break
}
}
}
const onCloseWorkflow = (option: WorkflowOption) => {
closeWorkflows([option])
}
const tabGetter = () => workflowTabRef.value as HTMLElement
usePragmaticDraggable(tabGetter, {
getInitialData: () => {
return {
workflowKey: props.workflowOption.workflow.key
}
}
})
usePragmaticDroppable(tabGetter, {
getData: () => {
return {
workflowKey: props.workflowOption.workflow.key
}
},
onDrop: (e) => {
const fromIndex = workflowStore.openWorkflows.findIndex(
(wf) => wf.key === e.source.data.workflowKey
)
const toIndex = workflowStore.openWorkflows.findIndex(
(wf) => wf.key === e.location.current.dropTargets[0]?.data.workflowKey
)
if (fromIndex !== toIndex) {
workflowStore.reorderWorkflows(fromIndex, toIndex)
}
}
})
</script>
<style scoped>
.status-indicator {
@apply absolute font-bold;
font-size: 1.5rem;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
</style>

View File

@@ -9,36 +9,11 @@
dataKey="value"
>
<template #option="{ option }">
<div
class="flex p-2 gap-2"
<WorkflowTab
@contextmenu="showContextMenu($event, option)"
@click.middle="onCloseWorkflow(option)"
>
<span
class="workflow-label text-sm max-w-[150px] truncate inline-block"
v-tooltip.bottom="option.workflow.key"
>
{{ option.workflow.filename }}
</span>
<div class="relative">
<span
class="status-indicator"
v-if="
!workspaceStore.shiftDown &&
(option.workflow.isModified || !option.workflow.isPersisted)
"
>•</span
>
<Button
class="close-button p-0 w-auto"
icon="pi pi-times"
text
severity="secondary"
size="small"
@click.stop="onCloseWorkflow(option)"
/>
</div>
</div>
:workflow-option="option"
/>
</template>
</SelectButton>
<Button
@@ -52,6 +27,7 @@
</template>
<script setup lang="ts">
import WorkflowTab from '@/components/topbar/WorkflowTab.vue'
import { ComfyWorkflow } from '@/stores/workflowStore'
import { useWorkflowStore } from '@/stores/workflowStore'
import { useCommandStore } from '@/stores/commandStore'
@@ -78,11 +54,6 @@ const workflowStore = useWorkflowStore()
const rightClickedTab = ref<WorkflowOption>(null)
const menu = ref()
const showContextMenu = (event, option) => {
rightClickedTab.value = option
menu.value.show(event)
}
const workflowToOption = (workflow: ComfyWorkflow): WorkflowOption => ({
value: workflow.path,
workflow
@@ -126,6 +97,10 @@ const onCloseWorkflow = (option: WorkflowOption) => {
closeWorkflows([option])
}
const showContextMenu = (event, option) => {
rightClickedTab.value = option
menu.value.show(event)
}
const contextMenuItems = computed(() => {
const tab = rightClickedTab.value as WorkflowOption
if (!tab) return []
@@ -166,7 +141,6 @@ const contextMenuItems = computed(() => {
}
]
})
const commandStore = useCommandStore()
</script>
@@ -189,14 +163,6 @@ const commandStore = useCommandStore()
@apply visible;
}
.status-indicator {
@apply absolute font-bold;
font-size: 1.5rem;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
:deep(.p-togglebutton:hover) .status-indicator {
@apply hidden;
}

View File

@@ -145,6 +145,7 @@ export interface WorkflowStore {
modifiedWorkflows: ComfyWorkflow[]
getWorkflowByPath: (path: string) => ComfyWorkflow | null
syncWorkflows: (dir?: string) => Promise<void>
reorderWorkflows: (from: number, to: number) => void
}
export const useWorkflowStore = defineStore('workflow', () => {
@@ -202,6 +203,11 @@ export const useWorkflowStore = defineStore('workflow', () => {
const openWorkflows = computed(() =>
openWorkflowPaths.value.map((path) => workflowLookup.value[path])
)
const reorderWorkflows = (from: number, to: number) => {
const movedTab = openWorkflowPaths.value[from]
openWorkflowPaths.value.splice(from, 1)
openWorkflowPaths.value.splice(to, 0, movedTab)
}
const isOpen = (workflow: ComfyWorkflow) =>
openWorkflowPathSet.value.has(workflow.path)
@@ -388,6 +394,7 @@ export const useWorkflowStore = defineStore('workflow', () => {
renameWorkflow,
deleteWorkflow,
saveWorkflow,
reorderWorkflows,
workflows,
bookmarkedWorkflows,