mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-04-29 18:52:19 +00:00
[manager] Update UI components for new manager interface
Updated manager dialog components, pack cards, version selectors, and action buttons to work with the new manager API and state management structure.
This commit is contained in:
@@ -18,7 +18,7 @@
|
|||||||
'max-h-0': !isExpanded
|
'max-h-0': !isExpanded
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<div v-for="(panel, index) in taskPanels" :key="index">
|
<div v-for="(log, index) in focusedLogs" :key="index">
|
||||||
<Panel
|
<Panel
|
||||||
:expanded="collapsedPanels[index] || false"
|
:expanded="collapsedPanels[index] || false"
|
||||||
toggleable
|
toggleable
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
<template #header>
|
<template #header>
|
||||||
<div class="flex items-center justify-between w-full py-2">
|
<div class="flex items-center justify-between w-full py-2">
|
||||||
<div class="flex flex-col text-sm font-medium leading-normal">
|
<div class="flex flex-col text-sm font-medium leading-normal">
|
||||||
<span>{{ panel.taskName }}</span>
|
<span>{{ log.taskName }}</span>
|
||||||
<span class="text-muted">
|
<span class="text-muted">
|
||||||
{{
|
{{
|
||||||
isInProgress(index)
|
isInProgress(index)
|
||||||
@@ -52,24 +52,24 @@
|
|||||||
</template>
|
</template>
|
||||||
<div
|
<div
|
||||||
:ref="
|
:ref="
|
||||||
index === taskPanels.length - 1
|
index === focusedLogs.length - 1
|
||||||
? (el) => (lastPanelRef = el as HTMLElement)
|
? (el) => (lastPanelRef = el as HTMLElement)
|
||||||
: undefined
|
: undefined
|
||||||
"
|
"
|
||||||
class="overflow-y-auto h-64 rounded-lg bg-black"
|
class="overflow-y-auto h-64 rounded-lg bg-black"
|
||||||
:class="{
|
:class="{
|
||||||
'h-64': index !== taskPanels.length - 1,
|
'h-64': index !== focusedLogs.length - 1,
|
||||||
'flex-grow': index === taskPanels.length - 1
|
'flex-grow': index === focusedLogs.length - 1
|
||||||
}"
|
}"
|
||||||
@scroll="handleScroll"
|
@scroll="handleScroll"
|
||||||
>
|
>
|
||||||
<div class="h-full">
|
<div class="h-full">
|
||||||
<div
|
<div
|
||||||
v-for="(log, logIndex) in panel.logs"
|
v-for="(logLine, logIndex) in log.logs"
|
||||||
:key="logIndex"
|
:key="logIndex"
|
||||||
class="text-neutral-400 dark-theme:text-muted"
|
class="text-neutral-400 dark-theme:text-muted"
|
||||||
>
|
>
|
||||||
<pre class="whitespace-pre-wrap break-words">{{ log }}</pre>
|
<pre class="whitespace-pre-wrap break-words">{{ logLine }}</pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -90,17 +90,23 @@ import {
|
|||||||
useManagerProgressDialogStore
|
useManagerProgressDialogStore
|
||||||
} from '@/stores/comfyManagerStore'
|
} from '@/stores/comfyManagerStore'
|
||||||
|
|
||||||
const { taskLogs } = useComfyManagerStore()
|
const comfyManagerStore = useComfyManagerStore()
|
||||||
const progressDialogContent = useManagerProgressDialogStore()
|
const progressDialogContent = useManagerProgressDialogStore()
|
||||||
const managerStore = useComfyManagerStore()
|
|
||||||
|
|
||||||
const isInProgress = (index: number) =>
|
const isInProgress = (index: number) =>
|
||||||
index === taskPanels.value.length - 1 && managerStore.uncompletedCount > 0
|
index === comfyManagerStore.managerQueue.historyCount - 1 &&
|
||||||
|
comfyManagerStore.isLoading
|
||||||
|
|
||||||
const taskPanels = computed(() => taskLogs)
|
|
||||||
const isExpanded = computed(() => progressDialogContent.isExpanded)
|
const isExpanded = computed(() => progressDialogContent.isExpanded)
|
||||||
const isCollapsed = computed(() => !isExpanded.value)
|
const isCollapsed = computed(() => !isExpanded.value)
|
||||||
|
|
||||||
|
const focusedLogs = computed(() => {
|
||||||
|
if (progressDialogContent.getActiveTabIndex() === 0) {
|
||||||
|
return comfyManagerStore.succeededTasksLogs
|
||||||
|
}
|
||||||
|
return comfyManagerStore.failedTasksLogs
|
||||||
|
})
|
||||||
|
|
||||||
const collapsedPanels = ref<Record<number, boolean>>({})
|
const collapsedPanels = ref<Record<number, boolean>>({})
|
||||||
const togglePanel = (index: number) => {
|
const togglePanel = (index: number) => {
|
||||||
collapsedPanels.value[index] = !collapsedPanels.value[index]
|
collapsedPanels.value[index] = !collapsedPanels.value[index]
|
||||||
@@ -115,7 +121,7 @@ const { y: scrollY } = useScroll(sectionsContainerRef, {
|
|||||||
|
|
||||||
const lastPanelRef = ref<HTMLElement | null>(null)
|
const lastPanelRef = ref<HTMLElement | null>(null)
|
||||||
const isUserScrolling = ref(false)
|
const isUserScrolling = ref(false)
|
||||||
const lastPanelLogs = computed(() => taskPanels.value?.at(-1)?.logs)
|
const lastPanelLogs = computed(() => focusedLogs.value?.at(-1)?.logs)
|
||||||
|
|
||||||
const isAtBottom = (el: HTMLElement | null) => {
|
const isAtBottom = (el: HTMLElement | null) => {
|
||||||
if (!el) return false
|
if (!el) return false
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
import { VueWrapper, mount } from '@vue/test-utils'
|
import { VueWrapper, mount } from '@vue/test-utils'
|
||||||
import { createPinia } from 'pinia'
|
import { createPinia } from 'pinia'
|
||||||
|
import Button from 'primevue/button'
|
||||||
import PrimeVue from 'primevue/config'
|
import PrimeVue from 'primevue/config'
|
||||||
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
||||||
import { nextTick } from 'vue'
|
import { nextTick } from 'vue'
|
||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import enMessages from '@/locales/en/main.json'
|
import enMessages from '@/locales/en/main.json'
|
||||||
import { SelectedVersion } from '@/types/comfyManagerTypes'
|
|
||||||
|
|
||||||
import PackVersionBadge from './PackVersionBadge.vue'
|
import PackVersionBadge from './PackVersionBadge.vue'
|
||||||
import PackVersionSelectorPopover from './PackVersionSelectorPopover.vue'
|
import PackVersionSelectorPopover from './PackVersionSelectorPopover.vue'
|
||||||
@@ -118,9 +118,9 @@ describe('PackVersionBadge', () => {
|
|||||||
props: { nodePack: noVersionPack }
|
props: { nodePack: noVersionPack }
|
||||||
})
|
})
|
||||||
|
|
||||||
const badge = wrapper.find('[role="button"]')
|
const button = wrapper.findComponent(Button)
|
||||||
expect(badge.exists()).toBe(true)
|
expect(button.exists()).toBe(true)
|
||||||
expect(badge.find('span').text()).toBe(SelectedVersion.NIGHTLY)
|
expect(button.props('label')).toBe('nightly')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('falls back to NIGHTLY when nodePack.id is missing', () => {
|
it('falls back to NIGHTLY when nodePack.id is missing', () => {
|
||||||
@@ -132,9 +132,9 @@ describe('PackVersionBadge', () => {
|
|||||||
props: { nodePack: invalidPack }
|
props: { nodePack: invalidPack }
|
||||||
})
|
})
|
||||||
|
|
||||||
const badge = wrapper.find('[role="button"]')
|
const button = wrapper.findComponent(Button)
|
||||||
expect(badge.exists()).toBe(true)
|
expect(button.exists()).toBe(true)
|
||||||
expect(badge.find('span').text()).toBe(SelectedVersion.NIGHTLY)
|
expect(button.props('label')).toBe('nightly')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('toggles the popover when button is clicked', async () => {
|
it('toggles the popover when button is clicked', async () => {
|
||||||
|
|||||||
@@ -42,8 +42,7 @@ import { computed, ref, watch } from 'vue'
|
|||||||
import PackVersionSelectorPopover from '@/components/dialog/content/manager/PackVersionSelectorPopover.vue'
|
import PackVersionSelectorPopover from '@/components/dialog/content/manager/PackVersionSelectorPopover.vue'
|
||||||
import { usePackUpdateStatus } from '@/composables/nodePack/usePackUpdateStatus'
|
import { usePackUpdateStatus } from '@/composables/nodePack/usePackUpdateStatus'
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||||
import { SelectedVersion } from '@/types/comfyManagerTypes'
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
import { components } from '@/types/comfyRegistryTypes'
|
|
||||||
import { isSemVer } from '@/utils/formatUtil'
|
import { isSemVer } from '@/utils/formatUtil'
|
||||||
|
|
||||||
const TRUNCATED_HASH_LENGTH = 7
|
const TRUNCATED_HASH_LENGTH = 7
|
||||||
@@ -64,11 +63,11 @@ const popoverRef = ref()
|
|||||||
const managerStore = useComfyManagerStore()
|
const managerStore = useComfyManagerStore()
|
||||||
|
|
||||||
const installedVersion = computed(() => {
|
const installedVersion = computed(() => {
|
||||||
if (!nodePack.id) return SelectedVersion.NIGHTLY
|
if (!nodePack.id) return 'nightly'
|
||||||
const version =
|
const version =
|
||||||
managerStore.installedPacks[nodePack.id]?.ver ??
|
managerStore.installedPacks[nodePack.id]?.ver ??
|
||||||
nodePack.latest_version?.version ??
|
nodePack.latest_version?.version ??
|
||||||
SelectedVersion.NIGHTLY
|
'nightly'
|
||||||
|
|
||||||
// If Git hash, truncate to 7 characters
|
// If Git hash, truncate to 7 characters
|
||||||
return isSemVer(version) ? version : version.slice(0, TRUNCATED_HASH_LENGTH)
|
return isSemVer(version) ? version : version.slice(0, TRUNCATED_HASH_LENGTH)
|
||||||
|
|||||||
@@ -8,7 +8,8 @@ import { nextTick } from 'vue'
|
|||||||
import { createI18n } from 'vue-i18n'
|
import { createI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import enMessages from '@/locales/en/main.json'
|
import enMessages from '@/locales/en/main.json'
|
||||||
import { SelectedVersion } from '@/types/comfyManagerTypes'
|
|
||||||
|
// SelectedVersion is now using direct strings instead of enum
|
||||||
|
|
||||||
import PackVersionSelectorPopover from './PackVersionSelectorPopover.vue'
|
import PackVersionSelectorPopover from './PackVersionSelectorPopover.vue'
|
||||||
|
|
||||||
@@ -123,8 +124,8 @@ describe('PackVersionSelectorPopover', () => {
|
|||||||
expect(options.length).toBe(defaultMockVersions.length + 2) // 2 special options + version options
|
expect(options.length).toBe(defaultMockVersions.length + 2) // 2 special options + version options
|
||||||
|
|
||||||
// Check that special options exist
|
// Check that special options exist
|
||||||
expect(options.some((o) => o.value === SelectedVersion.NIGHTLY)).toBe(true)
|
expect(options.some((o) => o.value === 'nightly')).toBe(true)
|
||||||
expect(options.some((o) => o.value === SelectedVersion.LATEST)).toBe(true)
|
expect(options.some((o) => o.value === 'latest')).toBe(true)
|
||||||
|
|
||||||
// Check that version options exist
|
// Check that version options exist
|
||||||
expect(options.some((o) => o.value === '1.0.0')).toBe(true)
|
expect(options.some((o) => o.value === '1.0.0')).toBe(true)
|
||||||
@@ -304,7 +305,7 @@ describe('PackVersionSelectorPopover', () => {
|
|||||||
await waitForPromises()
|
await waitForPromises()
|
||||||
const listbox = wrapper.findComponent(Listbox)
|
const listbox = wrapper.findComponent(Listbox)
|
||||||
expect(listbox.exists()).toBe(true)
|
expect(listbox.exists()).toBe(true)
|
||||||
expect(listbox.props('modelValue')).toBe(SelectedVersion.NIGHTLY)
|
expect(listbox.props('modelValue')).toBe('nightly')
|
||||||
})
|
})
|
||||||
|
|
||||||
it('defaults to nightly when publisher name is "Unclaimed"', async () => {
|
it('defaults to nightly when publisher name is "Unclaimed"', async () => {
|
||||||
@@ -325,7 +326,7 @@ describe('PackVersionSelectorPopover', () => {
|
|||||||
await waitForPromises()
|
await waitForPromises()
|
||||||
const listbox = wrapper.findComponent(Listbox)
|
const listbox = wrapper.findComponent(Listbox)
|
||||||
expect(listbox.exists()).toBe(true)
|
expect(listbox.exists()).toBe(true)
|
||||||
expect(listbox.props('modelValue')).toBe(SelectedVersion.NIGHTLY)
|
expect(listbox.props('modelValue')).toBe('nightly')
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -69,12 +69,8 @@ import ContentDivider from '@/components/common/ContentDivider.vue'
|
|||||||
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
|
||||||
import { useComfyRegistryService } from '@/services/comfyRegistryService'
|
import { useComfyRegistryService } from '@/services/comfyRegistryService'
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||||
import {
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
ManagerChannel,
|
import { components as ManagerComponents } from '@/types/generatedManagerTypes'
|
||||||
ManagerDatabaseSource,
|
|
||||||
SelectedVersion
|
|
||||||
} from '@/types/comfyManagerTypes'
|
|
||||||
import { components } from '@/types/comfyRegistryTypes'
|
|
||||||
import { isSemVer } from '@/utils/formatUtil'
|
import { isSemVer } from '@/utils/formatUtil'
|
||||||
|
|
||||||
const { nodePack } = defineProps<{
|
const { nodePack } = defineProps<{
|
||||||
@@ -92,19 +88,20 @@ const managerStore = useComfyManagerStore()
|
|||||||
|
|
||||||
const isQueueing = ref(false)
|
const isQueueing = ref(false)
|
||||||
|
|
||||||
const selectedVersion = ref<string>(SelectedVersion.LATEST)
|
const selectedVersion = ref<string>('latest')
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
const initialVersion = getInitialSelectedVersion() ?? SelectedVersion.LATEST
|
const initialVersion = getInitialSelectedVersion() ?? 'latest'
|
||||||
selectedVersion.value =
|
selectedVersion.value =
|
||||||
// Use NIGHTLY when version is a Git hash
|
// Use NIGHTLY when version is a Git hash
|
||||||
isSemVer(initialVersion) ? initialVersion : SelectedVersion.NIGHTLY
|
isSemVer(initialVersion) ? initialVersion : 'nightly'
|
||||||
})
|
})
|
||||||
|
|
||||||
const getInitialSelectedVersion = () => {
|
const getInitialSelectedVersion = () => {
|
||||||
if (!nodePack.id) return
|
if (!nodePack.id) return
|
||||||
|
|
||||||
// If unclaimed, set selected version to nightly
|
// If unclaimed, set selected version to nightly
|
||||||
if (nodePack.publisher?.name === 'Unclaimed') return SelectedVersion.NIGHTLY
|
if (nodePack.publisher?.name === 'Unclaimed')
|
||||||
|
return 'nightly' as ManagerComponents['schemas']['SelectedVersion']
|
||||||
|
|
||||||
// If node pack is installed, set selected version to the installed version
|
// If node pack is installed, set selected version to the installed version
|
||||||
if (managerStore.isPackInstalled(nodePack.id))
|
if (managerStore.isPackInstalled(nodePack.id))
|
||||||
@@ -143,7 +140,7 @@ const onNodePackChange = async () => {
|
|||||||
// Add Latest option
|
// Add Latest option
|
||||||
const defaultVersions = [
|
const defaultVersions = [
|
||||||
{
|
{
|
||||||
value: SelectedVersion.LATEST,
|
value: 'latest' as ManagerComponents['schemas']['SelectedVersion'],
|
||||||
label: t('manager.latestVersion')
|
label: t('manager.latestVersion')
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -151,7 +148,7 @@ const onNodePackChange = async () => {
|
|||||||
// Add Nightly option if there is a non-empty `repository` field
|
// Add Nightly option if there is a non-empty `repository` field
|
||||||
if (nodePack.repository?.length) {
|
if (nodePack.repository?.length) {
|
||||||
defaultVersions.push({
|
defaultVersions.push({
|
||||||
value: SelectedVersion.NIGHTLY,
|
value: 'nightly' as ManagerComponents['schemas']['SelectedVersion'],
|
||||||
label: t('manager.nightlyVersion')
|
label: t('manager.nightlyVersion')
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -172,12 +169,16 @@ whenever(
|
|||||||
|
|
||||||
const handleSubmit = async () => {
|
const handleSubmit = async () => {
|
||||||
isQueueing.value = true
|
isQueueing.value = true
|
||||||
|
if (!nodePack.id) {
|
||||||
|
throw new Error('Node ID is required for installation')
|
||||||
|
}
|
||||||
|
|
||||||
await managerStore.installPack.call({
|
await managerStore.installPack.call({
|
||||||
id: nodePack.id,
|
id: nodePack.id,
|
||||||
repository: nodePack.repository ?? '',
|
|
||||||
channel: ManagerChannel.DEFAULT,
|
|
||||||
mode: ManagerDatabaseSource.CACHE,
|
|
||||||
version: selectedVersion.value,
|
version: selectedVersion.value,
|
||||||
|
repository: nodePack.repository ?? '',
|
||||||
|
channel: 'default' as ManagerComponents['schemas']['ManagerChannel'],
|
||||||
|
mode: 'cache' as ManagerComponents['schemas']['ManagerDatabaseSource'],
|
||||||
selected_version: selectedVersion.value
|
selected_version: selectedVersion.value
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -15,12 +15,8 @@ import ToggleSwitch from 'primevue/toggleswitch'
|
|||||||
import { computed, ref } from 'vue'
|
import { computed, ref } from 'vue'
|
||||||
|
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||||
import {
|
|
||||||
InstallPackParams,
|
|
||||||
ManagerChannel,
|
|
||||||
SelectedVersion
|
|
||||||
} from '@/types/comfyManagerTypes'
|
|
||||||
import type { components } from '@/types/comfyRegistryTypes'
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
|
import { components as ManagerComponents } from '@/types/generatedManagerTypes'
|
||||||
|
|
||||||
const TOGGLE_DEBOUNCE_MS = 256
|
const TOGGLE_DEBOUNCE_MS = 256
|
||||||
|
|
||||||
@@ -28,37 +24,42 @@ const { nodePack } = defineProps<{
|
|||||||
nodePack: components['schemas']['Node']
|
nodePack: components['schemas']['Node']
|
||||||
}>()
|
}>()
|
||||||
|
|
||||||
const { isPackEnabled, enablePack, disablePack, installedPacks } =
|
const { isPackEnabled, enablePack, disablePack } = useComfyManagerStore()
|
||||||
useComfyManagerStore()
|
|
||||||
|
|
||||||
const isLoading = ref(false)
|
const isLoading = ref(false)
|
||||||
|
|
||||||
const isEnabled = computed(() => isPackEnabled(nodePack.id))
|
const isEnabled = computed(() => isPackEnabled(nodePack.id))
|
||||||
const version = computed(() => {
|
|
||||||
const id = nodePack.id
|
|
||||||
if (!id) return SelectedVersion.NIGHTLY
|
|
||||||
return (
|
|
||||||
installedPacks[id]?.ver ??
|
|
||||||
nodePack.latest_version?.version ??
|
|
||||||
SelectedVersion.NIGHTLY
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
const handleEnable = () =>
|
const handleEnable = () => {
|
||||||
enablePack.call({
|
if (!nodePack.id) {
|
||||||
|
throw new Error('Node ID is required for enabling')
|
||||||
|
}
|
||||||
|
return enablePack.call({
|
||||||
id: nodePack.id,
|
id: nodePack.id,
|
||||||
version: version.value,
|
version:
|
||||||
selected_version: version.value,
|
nodePack.latest_version?.version ??
|
||||||
|
('latest' as ManagerComponents['schemas']['SelectedVersion']),
|
||||||
|
selected_version:
|
||||||
|
nodePack.latest_version?.version ??
|
||||||
|
('latest' as ManagerComponents['schemas']['SelectedVersion']),
|
||||||
repository: nodePack.repository ?? '',
|
repository: nodePack.repository ?? '',
|
||||||
channel: ManagerChannel.DEFAULT,
|
channel: 'default' as ManagerComponents['schemas']['ManagerChannel'],
|
||||||
mode: 'default' as InstallPackParams['mode']
|
mode: 'cache' as ManagerComponents['schemas']['ManagerDatabaseSource'],
|
||||||
|
skip_post_install: false
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const handleDisable = () =>
|
const handleDisable = () => {
|
||||||
disablePack({
|
if (!nodePack.id) {
|
||||||
|
throw new Error('Node ID is required for disabling')
|
||||||
|
}
|
||||||
|
return disablePack({
|
||||||
id: nodePack.id,
|
id: nodePack.id,
|
||||||
version: version.value
|
version:
|
||||||
|
nodePack.latest_version?.version ??
|
||||||
|
('latest' as ManagerComponents['schemas']['SelectedVersion'])
|
||||||
})
|
})
|
||||||
|
}
|
||||||
|
|
||||||
const handleToggle = async (enable: boolean) => {
|
const handleToggle = async (enable: boolean) => {
|
||||||
if (isLoading.value) return
|
if (isLoading.value) return
|
||||||
@@ -67,10 +68,16 @@ const handleToggle = async (enable: boolean) => {
|
|||||||
if (enable) {
|
if (enable) {
|
||||||
await handleEnable()
|
await handleEnable()
|
||||||
} else {
|
} else {
|
||||||
handleDisable()
|
await handleDisable()
|
||||||
}
|
}
|
||||||
isLoading.value = false
|
isLoading.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
const onToggle = debounce(handleToggle, TOGGLE_DEBOUNCE_MS, { trailing: true })
|
const onToggle = debounce(
|
||||||
|
(enable: boolean) => {
|
||||||
|
void handleToggle(enable)
|
||||||
|
},
|
||||||
|
TOGGLE_DEBOUNCE_MS,
|
||||||
|
{ trailing: true }
|
||||||
|
)
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
@@ -19,13 +19,9 @@ import { inject, ref } from 'vue'
|
|||||||
|
|
||||||
import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue'
|
import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue'
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||||
import {
|
import { IsInstallingKey } from '@/types/comfyManagerTypes'
|
||||||
IsInstallingKey,
|
|
||||||
ManagerChannel,
|
|
||||||
ManagerDatabaseSource,
|
|
||||||
SelectedVersion
|
|
||||||
} from '@/types/comfyManagerTypes'
|
|
||||||
import type { components } from '@/types/comfyRegistryTypes'
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
|
import { components as ManagerComponents } from '@/types/generatedManagerTypes'
|
||||||
|
|
||||||
type NodePack = components['schemas']['Node']
|
type NodePack = components['schemas']['Node']
|
||||||
|
|
||||||
@@ -43,19 +39,26 @@ const onClick = (): void => {
|
|||||||
|
|
||||||
const managerStore = useComfyManagerStore()
|
const managerStore = useComfyManagerStore()
|
||||||
|
|
||||||
const createPayload = (installItem: NodePack) => {
|
const createPayload = (
|
||||||
|
installItem: NodePack
|
||||||
|
): ManagerComponents['schemas']['InstallPackParams'] => {
|
||||||
|
if (!installItem.id) {
|
||||||
|
throw new Error('Node ID is required for installation')
|
||||||
|
}
|
||||||
|
|
||||||
const isUnclaimedPack = installItem.publisher?.name === 'Unclaimed'
|
const isUnclaimedPack = installItem.publisher?.name === 'Unclaimed'
|
||||||
const versionToInstall = isUnclaimedPack
|
const versionToInstall = isUnclaimedPack
|
||||||
? SelectedVersion.NIGHTLY
|
? ('nightly' as ManagerComponents['schemas']['SelectedVersion'])
|
||||||
: installItem.latest_version?.version ?? SelectedVersion.LATEST
|
: installItem.latest_version?.version ??
|
||||||
|
('latest' as ManagerComponents['schemas']['SelectedVersion'])
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: installItem.id,
|
id: installItem.id,
|
||||||
|
version: versionToInstall,
|
||||||
repository: installItem.repository ?? '',
|
repository: installItem.repository ?? '',
|
||||||
channel: ManagerChannel.DEV,
|
channel: 'dev' as ManagerComponents['schemas']['ManagerChannel'],
|
||||||
mode: ManagerDatabaseSource.CACHE,
|
mode: 'cache' as ManagerComponents['schemas']['ManagerDatabaseSource'],
|
||||||
selected_version: versionToInstall,
|
selected_version: versionToInstall
|
||||||
version: versionToInstall
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -65,7 +68,7 @@ const installPack = (item: NodePack) =>
|
|||||||
const installAllPacks = async () => {
|
const installAllPacks = async () => {
|
||||||
if (!nodePacks?.length) return
|
if (!nodePacks?.length) return
|
||||||
|
|
||||||
isInstalling.value = true
|
// isInstalling.value = true
|
||||||
|
|
||||||
const uninstalledPacks = nodePacks.filter(
|
const uninstalledPacks = nodePacks.filter(
|
||||||
(pack) => !managerStore.isPackInstalled(pack.id)
|
(pack) => !managerStore.isPackInstalled(pack.id)
|
||||||
|
|||||||
@@ -15,7 +15,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue'
|
import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue'
|
||||||
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
|
||||||
import type { ManagerPackInfo } from '@/types/comfyManagerTypes'
|
|
||||||
import type { components } from '@/types/comfyRegistryTypes'
|
import type { components } from '@/types/comfyRegistryTypes'
|
||||||
|
|
||||||
type NodePack = components['schemas']['Node']
|
type NodePack = components['schemas']['Node']
|
||||||
@@ -26,16 +25,16 @@ const { nodePacks } = defineProps<{
|
|||||||
|
|
||||||
const managerStore = useComfyManagerStore()
|
const managerStore = useComfyManagerStore()
|
||||||
|
|
||||||
const createPayload = (uninstallItem: NodePack): ManagerPackInfo => {
|
const uninstallPack = (item: NodePack) => {
|
||||||
return {
|
if (!item.id) {
|
||||||
id: uninstallItem.id,
|
throw new Error('Node ID is required for uninstallation')
|
||||||
version: uninstallItem.latest_version?.version
|
|
||||||
}
|
}
|
||||||
|
return managerStore.uninstallPack({
|
||||||
|
id: item.id,
|
||||||
|
version: item.latest_version?.version ?? ''
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const uninstallPack = (item: NodePack) =>
|
|
||||||
managerStore.uninstallPack(createPayload(item))
|
|
||||||
|
|
||||||
const uninstallItems = async () => {
|
const uninstallItems = async () => {
|
||||||
if (!nodePacks?.length) return
|
if (!nodePacks?.length) return
|
||||||
await Promise.all(nodePacks.map(uninstallPack))
|
await Promise.all(nodePacks.map(uninstallPack))
|
||||||
|
|||||||
@@ -119,12 +119,20 @@ provide(IsInstallingKey, isInstalling)
|
|||||||
|
|
||||||
const { isPackInstalled, isPackEnabled } = useComfyManagerStore()
|
const { isPackInstalled, isPackEnabled } = useComfyManagerStore()
|
||||||
|
|
||||||
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
|
const isDisabled = ref(false)
|
||||||
const isDisabled = computed(
|
const managerStore = useComfyManagerStore()
|
||||||
() => isInstalled.value && !isPackEnabled(nodePack?.id)
|
|
||||||
)
|
|
||||||
|
|
||||||
whenever(isInstalled, () => (isInstalling.value = false))
|
// Watch the installedPacks object directly (which gets updated from WebSocket)
|
||||||
|
whenever(
|
||||||
|
() => managerStore.installedPacksIds,
|
||||||
|
() => {
|
||||||
|
const isInstalled = isPackInstalled(nodePack?.id)
|
||||||
|
isDisabled.value = isInstalled && !isPackEnabled(nodePack?.id)
|
||||||
|
|
||||||
|
// Update isInstalling state after installation is complete
|
||||||
|
if (isInstalling.value && isInstalled) isInstalling.value = false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
const nodesCount = computed(() =>
|
const nodesCount = computed(() =>
|
||||||
isMergedNodePack(nodePack) ? nodePack.comfy_nodes?.length : undefined
|
isMergedNodePack(nodePack) ? nodePack.comfy_nodes?.length : undefined
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ const dialogStore = useDialogStore()
|
|||||||
const progressDialogContent = useManagerProgressDialogStore()
|
const progressDialogContent = useManagerProgressDialogStore()
|
||||||
const comfyManagerStore = useComfyManagerStore()
|
const comfyManagerStore = useComfyManagerStore()
|
||||||
|
|
||||||
const isInProgress = computed(() => comfyManagerStore.uncompletedCount > 0)
|
const isInProgress = computed(() => comfyManagerStore.isProcessingTasks)
|
||||||
|
|
||||||
const closeDialog = () => {
|
const closeDialog = () => {
|
||||||
dialogStore.closeDialog({ key: 'global-manager-progress-dialog' })
|
dialogStore.closeDialog({ key: 'global-manager-progress-dialog' })
|
||||||
|
|||||||
@@ -18,13 +18,15 @@
|
|||||||
|
|
||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import TabMenu from 'primevue/tabmenu'
|
import TabMenu from 'primevue/tabmenu'
|
||||||
import { ref } from 'vue'
|
import { computed } from 'vue'
|
||||||
import { useI18n } from 'vue-i18n'
|
import { useI18n } from 'vue-i18n'
|
||||||
|
|
||||||
import { useManagerProgressDialogStore } from '@/stores/comfyManagerStore'
|
import { useManagerProgressDialogStore } from '@/stores/comfyManagerStore'
|
||||||
|
|
||||||
const progressDialogContent = useManagerProgressDialogStore()
|
const progressDialogContent = useManagerProgressDialogStore()
|
||||||
const activeTabIndex = ref(0)
|
const activeTabIndex = computed(() => {
|
||||||
|
return progressDialogContent.getActiveTabIndex()
|
||||||
|
})
|
||||||
const { t } = useI18n()
|
const { t } = useI18n()
|
||||||
const tabs = [
|
const tabs = [
|
||||||
{ label: t('manager.installationQueue') },
|
{ label: t('manager.installationQueue') },
|
||||||
|
|||||||
Reference in New Issue
Block a user