Compare commits

...

2 Commits

Author SHA1 Message Date
Austin
223831c514 Add test 2026-04-29 15:40:25 -07:00
Austin
bbbb55c410 Allow uploading workflows to library by dnd 2026-04-29 15:40:25 -07:00
3 changed files with 82 additions and 14 deletions

View File

@@ -7,17 +7,19 @@ import { getMimeType } from '@e2e/fixtures/utils/mimeTypeUtil'
import { assetPath } from '@e2e/fixtures/utils/paths'
import { nextFrame } from '@e2e/fixtures/utils/timing'
type DragAndDropOptions = {
fileName?: string
url?: string
dropPosition?: Position
waitForUpload?: boolean
preserveNativePropagation?: boolean
}
export class DragDropHelper {
constructor(private readonly page: Page) {}
async dragAndDropExternalResource(
options: {
fileName?: string
url?: string
dropPosition?: Position
waitForUpload?: boolean
preserveNativePropagation?: boolean
} = {}
options: DragAndDropOptions = {}
): Promise<void> {
const {
dropPosition = { x: 100, y: 100 },
@@ -143,17 +145,14 @@ export class DragDropHelper {
async dragAndDropFile(
fileName: string,
options: { dropPosition?: Position; waitForUpload?: boolean } = {}
options: DragAndDropOptions = {}
): Promise<void> {
return this.dragAndDropExternalResource({ fileName, ...options })
}
async dragAndDropURL(
url: string,
options: {
dropPosition?: Position
preserveNativePropagation?: boolean
} = {}
options: DragAndDropOptions = {}
): Promise<void> {
return this.dragAndDropExternalResource({ url, ...options })
}

View File

@@ -364,6 +364,34 @@ test.describe('Workflows sidebar', () => {
.toEqual(['*Unsaved Workflow', '*workflow1 (Copy)'])
})
test('Can upload workflow to library by drag and drop', async ({
comfyPage
}) => {
await comfyPage.workflow.setupWorkflowsDirectory({})
const { workflowsTab } = comfyPage.menu
expect(await workflowsTab.getTopLevelSavedWorkflowNames()).not.toContain(
'default'
)
const sidebarBox = (await comfyPage.page
.locator('.workflows-sidebar-tab')
.boundingBox())!
const dropPosition = {
x: sidebarBox.x + sidebarBox.width / 2,
y: sidebarBox.y + sidebarBox.height / 2
}
await comfyPage.dragDrop.dragAndDropFile('default.json', {
dropPosition,
preserveNativePropagation: true
})
await expect
.poll(() => workflowsTab.getTopLevelSavedWorkflowNames())
.toContain('default')
})
test('Can drop workflow from workflows sidebar', async ({ comfyPage }) => {
await comfyPage.workflow.setupWorkflowsDirectory({
'workflow1.json': 'default.json'

View File

@@ -1,9 +1,15 @@
<template>
<SidebarTabTemplate
ref="sidebarTabRef"
:title="title"
v-bind="$attrs"
:data-testid="dataTestid"
class="workflows-sidebar-tab"
:class="
cn(
'workflows-sidebar-tab',
isOverDropZone && 'bg-primary-500/10 ring-4 ring-primary-500 ring-inset'
)
"
>
<template #alt-title>
<slot name="alt-title" />
@@ -140,8 +146,10 @@
</template>
<script setup lang="ts">
import { cn } from '@comfyorg/tailwind-utils'
import { unrefElement, useDropZone } from '@vueuse/core'
import ConfirmDialog from 'primevue/confirmdialog'
import { computed, nextTick, onMounted, ref } from 'vue'
import { computed, nextTick, onMounted, ref, useTemplateRef } from 'vue'
import { useI18n } from 'vue-i18n'
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
@@ -162,6 +170,8 @@ import {
useWorkflowBookmarkStore,
useWorkflowStore
} from '@/platform/workflow/management/stores/workflowStore'
import { validateComfyWorkflow } from '@/platform/workflow/validation/schemas/workflowSchema'
import { getDataFromJSON } from '@/scripts/metadata/json'
import { useWorkspaceStore } from '@/stores/workspaceStore'
import type { TreeExplorerNode, TreeNode } from '@/types/treeExplorerTypes'
import {
@@ -189,6 +199,7 @@ const settingStore = useSettingStore()
const workflowTabsPosition = computed(() =>
settingStore.get('Comfy.Workflow.WorkflowTabsPosition')
)
const sidebarTabRef = useTemplateRef('sidebarTabRef')
const searchBoxRef = ref()
@@ -349,4 +360,34 @@ onMounted(async () => {
searchBoxRef.value?.focus()
await workflowBookmarkStore.loadBookmarks()
})
const sidebarTabGetter = () => {
const el = unrefElement(sidebarTabRef)
return el instanceof HTMLElement ? el : undefined
}
const { isOverDropZone } = useDropZone(sidebarTabGetter, {
onDrop: async (files) => {
if (!files?.length) return
await Promise.allSettled(
files.map(async (file) => {
const { workflow } = (await getDataFromJSON(file)) ?? {}
if (!workflow) return
const workflowJSON = await validateComfyWorkflow(workflow)
if (!workflowJSON) return
const comfyWorkflow = workflowStore.createNewTemporary(
file.name,
workflowJSON
)
await workflowStore.closeWorkflow(comfyWorkflow)
await comfyWorkflow.save()
})
)
await workflowStore.syncWorkflows()
},
dataTypes: ['application/json'],
multiple: true,
preventDefaultForUnhandled: false
})
</script>