mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-30 11:11:53 +00:00
[TS] Fix ts-strict errors in Vue components (Part 4) (#3134)
This commit is contained in:
@@ -131,7 +131,7 @@ const onNodeContentClick = async (
|
|||||||
}
|
}
|
||||||
emit('nodeClick', node, e)
|
emit('nodeClick', node, e)
|
||||||
}
|
}
|
||||||
const menu = ref(null)
|
const menu = ref<InstanceType<typeof ContextMenu> | null>(null)
|
||||||
const menuTargetNode = ref<RenderedTreeExplorerNode | null>(null)
|
const menuTargetNode = ref<RenderedTreeExplorerNode | null>(null)
|
||||||
const extraMenuItems = computed(() => {
|
const extraMenuItems = computed(() => {
|
||||||
return menuTargetNode.value?.contextMenuItems
|
return menuTargetNode.value?.contextMenuItems
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ onMounted(async () => {
|
|||||||
await validateUrl(props.modelValue)
|
await validateUrl(props.modelValue)
|
||||||
})
|
})
|
||||||
|
|
||||||
const handleInput = (value: string) => {
|
const handleInput = (value: string | undefined) => {
|
||||||
// Update internal value without emitting
|
// Update internal value without emitting
|
||||||
internalValue.value = cleanInput(value)
|
internalValue.value = cleanInput(value ?? '')
|
||||||
// Reset validation state when user types
|
// Reset validation state when user types
|
||||||
validationState.value = ValidationState.IDLE
|
validationState.value = ValidationState.IDLE
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
<PanelTemplate
|
<PanelTemplate
|
||||||
v-for="category in settingCategories"
|
v-for="category in settingCategories"
|
||||||
:key="category.key"
|
:key="category.key"
|
||||||
:value="category.label"
|
:value="category.label ?? ''"
|
||||||
>
|
>
|
||||||
<template #header>
|
<template #header>
|
||||||
<CurrentUserMessage v-if="tabValue === 'Comfy'" />
|
<CurrentUserMessage v-if="tabValue === 'Comfy'" />
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
v-for="widget in widgets"
|
v-for="widget in widgets"
|
||||||
:key="widget.id"
|
:key="widget.id"
|
||||||
:widget="widget"
|
:widget="widget"
|
||||||
:widget-state="domWidgetStore.widgetStates.get(widget.id)"
|
:widget-state="domWidgetStore.widgetStates.get(widget.id)!"
|
||||||
@update:widget-value="widget.value = $event"
|
@update:widget-value="widget.value = $event"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
@@ -56,7 +56,7 @@ const updateWidgets = () => {
|
|||||||
(widget.computedHeight ?? 50) - margin * 2
|
(widget.computedHeight ?? 50) - margin * 2
|
||||||
]
|
]
|
||||||
// TODO: optimize this logic as it's O(n), where n is the number of nodes
|
// TODO: optimize this logic as it's O(n), where n is the number of nodes
|
||||||
widgetState.zIndex = lgCanvas.graph.nodes.indexOf(node)
|
widgetState.zIndex = lgCanvas.graph?.nodes.indexOf(node) ?? -1
|
||||||
widgetState.readonly = lgCanvas.read_only
|
widgetState.readonly = lgCanvas.read_only
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ const positionSelectionOverlay = (canvas: LGraphCanvas) => {
|
|||||||
|
|
||||||
// Register listener on canvas creation.
|
// Register listener on canvas creation.
|
||||||
watch(
|
watch(
|
||||||
() => canvasStore.canvas,
|
() => canvasStore.canvas as LGraphCanvas | null,
|
||||||
(canvas: LGraphCanvas | null) => {
|
(canvas: LGraphCanvas | null) => {
|
||||||
if (!canvas) return
|
if (!canvas) return
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
>
|
>
|
||||||
<template #icon>
|
<template #icon>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<i class="pi pi-circle-fill" :style="{ color: currentColor }" />
|
<i class="pi pi-circle-fill" :style="{ color: currentColor ?? '' }" />
|
||||||
<i class="pi pi-chevron-down" :style="{ fontSize: '0.5rem' }" />
|
<i class="pi pi-chevron-down" :style="{ fontSize: '0.5rem' }" />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ const cpuMode = computed({
|
|||||||
selected.value = value ? 'cpu' : null
|
selected.value = value ? 'cpu' : null
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const selected = defineModel<TorchDeviceType>('device', {
|
const selected = defineModel<TorchDeviceType | null>('device', {
|
||||||
required: true
|
required: true
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -100,12 +100,12 @@ onMounted(async () => {
|
|||||||
await validatePath(paths.defaultInstallPath)
|
await validatePath(paths.defaultInstallPath)
|
||||||
})
|
})
|
||||||
|
|
||||||
const validatePath = async (path: string) => {
|
const validatePath = async (path: string | undefined) => {
|
||||||
try {
|
try {
|
||||||
pathError.value = ''
|
pathError.value = ''
|
||||||
pathExists.value = false
|
pathExists.value = false
|
||||||
nonDefaultDrive.value = false
|
nonDefaultDrive.value = false
|
||||||
const validation = await electron.validateInstallPath(path)
|
const validation = await electron.validateInstallPath(path ?? '')
|
||||||
|
|
||||||
// Create a pre-formatted list of errors
|
// Create a pre-formatted list of errors
|
||||||
if (!validation.isValid) {
|
if (!validation.isValid) {
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ import { isInChina } from '@/utils/networkUtil'
|
|||||||
import { ValidationState, mergeValidationStates } from '@/utils/validationUtil'
|
import { ValidationState, mergeValidationStates } from '@/utils/validationUtil'
|
||||||
|
|
||||||
const showMirrorInputs = ref(false)
|
const showMirrorInputs = ref(false)
|
||||||
const { device } = defineProps<{ device: TorchDeviceType }>()
|
const { device } = defineProps<{ device: TorchDeviceType | null }>()
|
||||||
const pythonMirror = defineModel<string>('pythonMirror', { required: true })
|
const pythonMirror = defineModel<string>('pythonMirror', { required: true })
|
||||||
const pypiMirror = defineModel<string>('pypiMirror', { required: true })
|
const pypiMirror = defineModel<string>('pypiMirror', { required: true })
|
||||||
const torchMirror = defineModel<string>('torchMirror', { required: true })
|
const torchMirror = defineModel<string>('torchMirror', { required: true })
|
||||||
@@ -95,7 +95,7 @@ const mirrors = computed<[UVMirror, ModelRef<string>][]>(() =>
|
|||||||
[
|
[
|
||||||
[PYTHON_MIRROR, pythonMirror],
|
[PYTHON_MIRROR, pythonMirror],
|
||||||
[PYPI_MIRROR, pypiMirror],
|
[PYPI_MIRROR, pypiMirror],
|
||||||
[getTorchMirrorItem(device), torchMirror]
|
[getTorchMirrorItem(device ?? 'cpu'), torchMirror]
|
||||||
] as [UVMirror, ModelRef<string>][]
|
] as [UVMirror, ModelRef<string>][]
|
||||||
).map(([item, modelValue]) => [
|
).map(([item, modelValue]) => [
|
||||||
userIsInChina.value ? useFallbackMirror(item) : item,
|
userIsInChina.value ? useFallbackMirror(item) : item,
|
||||||
|
|||||||
@@ -56,7 +56,8 @@ const props = defineProps<{
|
|||||||
node: RenderedTreeExplorerNode<ComfyNodeDefImpl>
|
node: RenderedTreeExplorerNode<ComfyNodeDefImpl>
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const nodeDef = computed(() => props.node.data)
|
// Note: node.data should be present for leaf nodes.
|
||||||
|
const nodeDef = computed(() => props.node.data!)
|
||||||
const nodeBookmarkStore = useNodeBookmarkStore()
|
const nodeBookmarkStore = useNodeBookmarkStore()
|
||||||
const isBookmarked = computed(() =>
|
const isBookmarked = computed(() =>
|
||||||
nodeBookmarkStore.isBookmarked(nodeDef.value)
|
nodeBookmarkStore.isBookmarked(nodeDef.value)
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
// @ts-strict-ignore
|
|
||||||
// Disabled because of https://github.com/Comfy-Org/ComfyUI_frontend/issues/1184
|
|
||||||
import { mount } from '@vue/test-utils'
|
|
||||||
import PrimeVue from 'primevue/config'
|
|
||||||
import Galleria from 'primevue/galleria'
|
|
||||||
import { beforeEach, describe, expect, it } from 'vitest'
|
|
||||||
|
|
||||||
import ComfyImage from '@/components/common/ComfyImage.vue'
|
|
||||||
import { ResultItemImpl } from '@/stores/queueStore'
|
|
||||||
|
|
||||||
import ResultGallery from '../ResultGallery.vue'
|
|
||||||
|
|
||||||
type ResultGalleryProps = typeof ResultGallery.__props
|
|
||||||
|
|
||||||
describe('ResultGallery', () => {
|
|
||||||
let mockResultItem: ResultItemImpl
|
|
||||||
|
|
||||||
beforeEach(() => {
|
|
||||||
mockResultItem = new ResultItemImpl({
|
|
||||||
filename: 'test.jpg',
|
|
||||||
type: 'images',
|
|
||||||
nodeId: 1,
|
|
||||||
mediaType: 'images'
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
const mountResultGallery = (props: ResultGalleryProps, options = {}) => {
|
|
||||||
return mount(ResultGallery, {
|
|
||||||
global: {
|
|
||||||
plugins: [PrimeVue],
|
|
||||||
components: { Galleria, ComfyImage }
|
|
||||||
},
|
|
||||||
props,
|
|
||||||
...options
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const clickElement = async (element: Element) => {
|
|
||||||
element.dispatchEvent(new MouseEvent('mousedown'))
|
|
||||||
element.dispatchEvent(new MouseEvent('mouseup'))
|
|
||||||
}
|
|
||||||
|
|
||||||
it('is dismissed when overlay mask is clicked', async () => {
|
|
||||||
const wrapper = mountResultGallery({
|
|
||||||
activeIndex: 0,
|
|
||||||
allGalleryItems: [mockResultItem]
|
|
||||||
})
|
|
||||||
wrapper.vm.galleryVisible = true
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.findComponent(Galleria).exists()).toBe(true)
|
|
||||||
expect(wrapper.vm.galleryVisible).toBe(true)
|
|
||||||
|
|
||||||
// Since Galleria uses teleport, we need to query the mask in the global document
|
|
||||||
const mask = document.querySelector('[data-mask]')
|
|
||||||
expect(mask).not.toBeNull()
|
|
||||||
|
|
||||||
// Click the overlay mask to dismiss the gallery
|
|
||||||
await clickElement(mask)
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.galleryVisible).toBe(false)
|
|
||||||
})
|
|
||||||
|
|
||||||
it('is not dismissed when gallery is clicked', async () => {
|
|
||||||
const wrapper = mountResultGallery({
|
|
||||||
activeIndex: 0,
|
|
||||||
allGalleryItems: [mockResultItem]
|
|
||||||
})
|
|
||||||
wrapper.vm.galleryVisible = true
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.findComponent(Galleria).exists()).toBe(true)
|
|
||||||
expect(wrapper.vm.galleryVisible).toBe(true)
|
|
||||||
|
|
||||||
// Since Galleria uses teleport, we need to query the mask in the global document
|
|
||||||
const gallery = document.querySelector('.p-galleria-content')
|
|
||||||
expect(gallery).not.toBeNull()
|
|
||||||
|
|
||||||
// The gallery should not be dismissed when the gallery itself is clicked
|
|
||||||
await clickElement(gallery)
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.galleryVisible).toBe(true)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
Reference in New Issue
Block a user