From 4a9abe0d008cd79232289b03f00ebb3af4b86933 Mon Sep 17 00:00:00 2001 From: bymyself Date: Fri, 13 Jun 2025 13:57:35 -0700 Subject: [PATCH] [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. --- .../content/ManagerProgressDialogContent.vue | 30 +++++---- .../content/manager/PackVersionBadge.test.ts | 14 ++--- .../content/manager/PackVersionBadge.vue | 7 +-- .../PackVersionSelectorPopover.test.ts | 11 ++-- .../manager/PackVersionSelectorPopover.vue | 31 +++++----- .../manager/button/PackEnableToggle.vue | 61 +++++++++++-------- .../manager/button/PackInstallButton.vue | 31 +++++----- .../manager/button/PackUninstallButton.vue | 15 +++-- .../content/manager/packCard/PackCard.vue | 18 ++++-- .../dialog/footer/ManagerProgressFooter.vue | 2 +- .../dialog/header/ManagerProgressHeader.vue | 6 +- 11 files changed, 126 insertions(+), 100 deletions(-) diff --git a/src/components/dialog/content/ManagerProgressDialogContent.vue b/src/components/dialog/content/ManagerProgressDialogContent.vue index b5256025d..b1b4272d8 100644 --- a/src/components/dialog/content/ManagerProgressDialogContent.vue +++ b/src/components/dialog/content/ManagerProgressDialogContent.vue @@ -18,7 +18,7 @@ 'max-h-0': !isExpanded }" > -
+
- {{ panel.taskName }} + {{ log.taskName }} {{ isInProgress(index) @@ -52,24 +52,24 @@
-
{{ log }}
+
{{ logLine }}
@@ -90,17 +90,23 @@ import { useManagerProgressDialogStore } from '@/stores/comfyManagerStore' -const { taskLogs } = useComfyManagerStore() +const comfyManagerStore = useComfyManagerStore() const progressDialogContent = useManagerProgressDialogStore() -const managerStore = useComfyManagerStore() 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 isCollapsed = computed(() => !isExpanded.value) +const focusedLogs = computed(() => { + if (progressDialogContent.getActiveTabIndex() === 0) { + return comfyManagerStore.succeededTasksLogs + } + return comfyManagerStore.failedTasksLogs +}) + const collapsedPanels = ref>({}) const togglePanel = (index: number) => { collapsedPanels.value[index] = !collapsedPanels.value[index] @@ -115,7 +121,7 @@ const { y: scrollY } = useScroll(sectionsContainerRef, { const lastPanelRef = ref(null) 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) => { if (!el) return false diff --git a/src/components/dialog/content/manager/PackVersionBadge.test.ts b/src/components/dialog/content/manager/PackVersionBadge.test.ts index 9bd897986..05f3efcfb 100644 --- a/src/components/dialog/content/manager/PackVersionBadge.test.ts +++ b/src/components/dialog/content/manager/PackVersionBadge.test.ts @@ -1,12 +1,12 @@ import { VueWrapper, mount } from '@vue/test-utils' import { createPinia } from 'pinia' +import Button from 'primevue/button' import PrimeVue from 'primevue/config' import { beforeEach, describe, expect, it, vi } from 'vitest' import { nextTick } from 'vue' import { createI18n } from 'vue-i18n' import enMessages from '@/locales/en/main.json' -import { SelectedVersion } from '@/types/comfyManagerTypes' import PackVersionBadge from './PackVersionBadge.vue' import PackVersionSelectorPopover from './PackVersionSelectorPopover.vue' @@ -118,9 +118,9 @@ describe('PackVersionBadge', () => { props: { nodePack: noVersionPack } }) - const badge = wrapper.find('[role="button"]') - expect(badge.exists()).toBe(true) - expect(badge.find('span').text()).toBe(SelectedVersion.NIGHTLY) + const button = wrapper.findComponent(Button) + expect(button.exists()).toBe(true) + expect(button.props('label')).toBe('nightly') }) it('falls back to NIGHTLY when nodePack.id is missing', () => { @@ -132,9 +132,9 @@ describe('PackVersionBadge', () => { props: { nodePack: invalidPack } }) - const badge = wrapper.find('[role="button"]') - expect(badge.exists()).toBe(true) - expect(badge.find('span').text()).toBe(SelectedVersion.NIGHTLY) + const button = wrapper.findComponent(Button) + expect(button.exists()).toBe(true) + expect(button.props('label')).toBe('nightly') }) it('toggles the popover when button is clicked', async () => { diff --git a/src/components/dialog/content/manager/PackVersionBadge.vue b/src/components/dialog/content/manager/PackVersionBadge.vue index 5a6ee32e2..fd05240c8 100644 --- a/src/components/dialog/content/manager/PackVersionBadge.vue +++ b/src/components/dialog/content/manager/PackVersionBadge.vue @@ -42,8 +42,7 @@ import { computed, ref, watch } from 'vue' import PackVersionSelectorPopover from '@/components/dialog/content/manager/PackVersionSelectorPopover.vue' import { usePackUpdateStatus } from '@/composables/nodePack/usePackUpdateStatus' import { useComfyManagerStore } from '@/stores/comfyManagerStore' -import { SelectedVersion } from '@/types/comfyManagerTypes' -import { components } from '@/types/comfyRegistryTypes' +import type { components } from '@/types/comfyRegistryTypes' import { isSemVer } from '@/utils/formatUtil' const TRUNCATED_HASH_LENGTH = 7 @@ -64,11 +63,11 @@ const popoverRef = ref() const managerStore = useComfyManagerStore() const installedVersion = computed(() => { - if (!nodePack.id) return SelectedVersion.NIGHTLY + if (!nodePack.id) return 'nightly' const version = managerStore.installedPacks[nodePack.id]?.ver ?? nodePack.latest_version?.version ?? - SelectedVersion.NIGHTLY + 'nightly' // If Git hash, truncate to 7 characters return isSemVer(version) ? version : version.slice(0, TRUNCATED_HASH_LENGTH) diff --git a/src/components/dialog/content/manager/PackVersionSelectorPopover.test.ts b/src/components/dialog/content/manager/PackVersionSelectorPopover.test.ts index 6a1d9dc56..51fa89ae0 100644 --- a/src/components/dialog/content/manager/PackVersionSelectorPopover.test.ts +++ b/src/components/dialog/content/manager/PackVersionSelectorPopover.test.ts @@ -8,7 +8,8 @@ import { nextTick } from 'vue' import { createI18n } from 'vue-i18n' 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' @@ -123,8 +124,8 @@ describe('PackVersionSelectorPopover', () => { expect(options.length).toBe(defaultMockVersions.length + 2) // 2 special options + version options // Check that special options exist - expect(options.some((o) => o.value === SelectedVersion.NIGHTLY)).toBe(true) - expect(options.some((o) => o.value === SelectedVersion.LATEST)).toBe(true) + expect(options.some((o) => o.value === 'nightly')).toBe(true) + expect(options.some((o) => o.value === 'latest')).toBe(true) // Check that version options exist expect(options.some((o) => o.value === '1.0.0')).toBe(true) @@ -304,7 +305,7 @@ describe('PackVersionSelectorPopover', () => { await waitForPromises() const listbox = wrapper.findComponent(Listbox) 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 () => { @@ -325,7 +326,7 @@ describe('PackVersionSelectorPopover', () => { await waitForPromises() const listbox = wrapper.findComponent(Listbox) expect(listbox.exists()).toBe(true) - expect(listbox.props('modelValue')).toBe(SelectedVersion.NIGHTLY) + expect(listbox.props('modelValue')).toBe('nightly') }) }) }) diff --git a/src/components/dialog/content/manager/PackVersionSelectorPopover.vue b/src/components/dialog/content/manager/PackVersionSelectorPopover.vue index 020b3e352..45c1bc5b1 100644 --- a/src/components/dialog/content/manager/PackVersionSelectorPopover.vue +++ b/src/components/dialog/content/manager/PackVersionSelectorPopover.vue @@ -69,12 +69,8 @@ import ContentDivider from '@/components/common/ContentDivider.vue' import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue' import { useComfyRegistryService } from '@/services/comfyRegistryService' import { useComfyManagerStore } from '@/stores/comfyManagerStore' -import { - ManagerChannel, - ManagerDatabaseSource, - SelectedVersion -} from '@/types/comfyManagerTypes' -import { components } from '@/types/comfyRegistryTypes' +import type { components } from '@/types/comfyRegistryTypes' +import { components as ManagerComponents } from '@/types/generatedManagerTypes' import { isSemVer } from '@/utils/formatUtil' const { nodePack } = defineProps<{ @@ -92,19 +88,20 @@ const managerStore = useComfyManagerStore() const isQueueing = ref(false) -const selectedVersion = ref(SelectedVersion.LATEST) +const selectedVersion = ref('latest') onMounted(() => { - const initialVersion = getInitialSelectedVersion() ?? SelectedVersion.LATEST + const initialVersion = getInitialSelectedVersion() ?? 'latest' selectedVersion.value = // Use NIGHTLY when version is a Git hash - isSemVer(initialVersion) ? initialVersion : SelectedVersion.NIGHTLY + isSemVer(initialVersion) ? initialVersion : 'nightly' }) const getInitialSelectedVersion = () => { if (!nodePack.id) return // 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 (managerStore.isPackInstalled(nodePack.id)) @@ -143,7 +140,7 @@ const onNodePackChange = async () => { // Add Latest option const defaultVersions = [ { - value: SelectedVersion.LATEST, + value: 'latest' as ManagerComponents['schemas']['SelectedVersion'], label: t('manager.latestVersion') } ] @@ -151,7 +148,7 @@ const onNodePackChange = async () => { // Add Nightly option if there is a non-empty `repository` field if (nodePack.repository?.length) { defaultVersions.push({ - value: SelectedVersion.NIGHTLY, + value: 'nightly' as ManagerComponents['schemas']['SelectedVersion'], label: t('manager.nightlyVersion') }) } @@ -172,12 +169,16 @@ whenever( const handleSubmit = async () => { isQueueing.value = true + if (!nodePack.id) { + throw new Error('Node ID is required for installation') + } + await managerStore.installPack.call({ id: nodePack.id, - repository: nodePack.repository ?? '', - channel: ManagerChannel.DEFAULT, - mode: ManagerDatabaseSource.CACHE, version: selectedVersion.value, + repository: nodePack.repository ?? '', + channel: 'default' as ManagerComponents['schemas']['ManagerChannel'], + mode: 'cache' as ManagerComponents['schemas']['ManagerDatabaseSource'], selected_version: selectedVersion.value }) diff --git a/src/components/dialog/content/manager/button/PackEnableToggle.vue b/src/components/dialog/content/manager/button/PackEnableToggle.vue index 8f994aeb6..f8b241ba9 100644 --- a/src/components/dialog/content/manager/button/PackEnableToggle.vue +++ b/src/components/dialog/content/manager/button/PackEnableToggle.vue @@ -15,12 +15,8 @@ import ToggleSwitch from 'primevue/toggleswitch' import { computed, ref } from 'vue' import { useComfyManagerStore } from '@/stores/comfyManagerStore' -import { - InstallPackParams, - ManagerChannel, - SelectedVersion -} from '@/types/comfyManagerTypes' import type { components } from '@/types/comfyRegistryTypes' +import { components as ManagerComponents } from '@/types/generatedManagerTypes' const TOGGLE_DEBOUNCE_MS = 256 @@ -28,37 +24,42 @@ const { nodePack } = defineProps<{ nodePack: components['schemas']['Node'] }>() -const { isPackEnabled, enablePack, disablePack, installedPacks } = - useComfyManagerStore() +const { isPackEnabled, enablePack, disablePack } = useComfyManagerStore() const isLoading = ref(false) 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 = () => - enablePack.call({ +const handleEnable = () => { + if (!nodePack.id) { + throw new Error('Node ID is required for enabling') + } + return enablePack.call({ id: nodePack.id, - version: version.value, - selected_version: version.value, + version: + nodePack.latest_version?.version ?? + ('latest' as ManagerComponents['schemas']['SelectedVersion']), + selected_version: + nodePack.latest_version?.version ?? + ('latest' as ManagerComponents['schemas']['SelectedVersion']), repository: nodePack.repository ?? '', - channel: ManagerChannel.DEFAULT, - mode: 'default' as InstallPackParams['mode'] + channel: 'default' as ManagerComponents['schemas']['ManagerChannel'], + mode: 'cache' as ManagerComponents['schemas']['ManagerDatabaseSource'], + skip_post_install: false }) +} -const handleDisable = () => - disablePack({ +const handleDisable = () => { + if (!nodePack.id) { + throw new Error('Node ID is required for disabling') + } + return disablePack({ id: nodePack.id, - version: version.value + version: + nodePack.latest_version?.version ?? + ('latest' as ManagerComponents['schemas']['SelectedVersion']) }) +} const handleToggle = async (enable: boolean) => { if (isLoading.value) return @@ -67,10 +68,16 @@ const handleToggle = async (enable: boolean) => { if (enable) { await handleEnable() } else { - handleDisable() + await handleDisable() } 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 } +) diff --git a/src/components/dialog/content/manager/button/PackInstallButton.vue b/src/components/dialog/content/manager/button/PackInstallButton.vue index 7bba01ef0..62b140083 100644 --- a/src/components/dialog/content/manager/button/PackInstallButton.vue +++ b/src/components/dialog/content/manager/button/PackInstallButton.vue @@ -19,13 +19,9 @@ import { inject, ref } from 'vue' import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue' import { useComfyManagerStore } from '@/stores/comfyManagerStore' -import { - IsInstallingKey, - ManagerChannel, - ManagerDatabaseSource, - SelectedVersion -} from '@/types/comfyManagerTypes' +import { IsInstallingKey } from '@/types/comfyManagerTypes' import type { components } from '@/types/comfyRegistryTypes' +import { components as ManagerComponents } from '@/types/generatedManagerTypes' type NodePack = components['schemas']['Node'] @@ -43,19 +39,26 @@ const onClick = (): void => { 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 versionToInstall = isUnclaimedPack - ? SelectedVersion.NIGHTLY - : installItem.latest_version?.version ?? SelectedVersion.LATEST + ? ('nightly' as ManagerComponents['schemas']['SelectedVersion']) + : installItem.latest_version?.version ?? + ('latest' as ManagerComponents['schemas']['SelectedVersion']) return { id: installItem.id, + version: versionToInstall, repository: installItem.repository ?? '', - channel: ManagerChannel.DEV, - mode: ManagerDatabaseSource.CACHE, - selected_version: versionToInstall, - version: versionToInstall + channel: 'dev' as ManagerComponents['schemas']['ManagerChannel'], + mode: 'cache' as ManagerComponents['schemas']['ManagerDatabaseSource'], + selected_version: versionToInstall } } @@ -65,7 +68,7 @@ const installPack = (item: NodePack) => const installAllPacks = async () => { if (!nodePacks?.length) return - isInstalling.value = true + // isInstalling.value = true const uninstalledPacks = nodePacks.filter( (pack) => !managerStore.isPackInstalled(pack.id) diff --git a/src/components/dialog/content/manager/button/PackUninstallButton.vue b/src/components/dialog/content/manager/button/PackUninstallButton.vue index 5a740f65f..91cba83d2 100644 --- a/src/components/dialog/content/manager/button/PackUninstallButton.vue +++ b/src/components/dialog/content/manager/button/PackUninstallButton.vue @@ -15,7 +15,6 @@