[Manager] Button to open manager from Missing Nodes dialog (#3395)

This commit is contained in:
Christian Byrne
2025-04-11 09:28:42 +08:00
committed by GitHub
parent 9e7690405a
commit 05e0036898
4 changed files with 102 additions and 58 deletions

View File

@@ -30,6 +30,9 @@
</div> </div>
</template> </template>
</ListBox> </ListBox>
<div class="flex justify-end py-3">
<Button label="Open Manager" @click="openManager" size="small" outlined />
</div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -38,7 +41,9 @@ import ListBox from 'primevue/listbox'
import { computed } from 'vue' import { computed } from 'vue'
import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue' import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
import { useDialogService } from '@/services/dialogService'
import type { MissingNodeType } from '@/types/comfy' import type { MissingNodeType } from '@/types/comfy'
import { ManagerTab } from '@/types/comfyManagerTypes'
const props = defineProps<{ const props = defineProps<{
missingNodeTypes: MissingNodeType[] missingNodeTypes: MissingNodeType[]
@@ -64,6 +69,12 @@ const uniqueNodes = computed(() => {
return { label: node } return { label: node }
}) })
}) })
const openManager = () => {
useDialogService().showManagerDialog({
initialTab: ManagerTab.Missing
})
}
</script> </script>
<style scoped> <style scoped>

View File

@@ -113,15 +113,12 @@ import { useRegistrySearch } from '@/composables/useRegistrySearch'
import { useComfyManagerStore } from '@/stores/comfyManagerStore' import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import { useComfyRegistryStore } from '@/stores/comfyRegistryStore' import { useComfyRegistryStore } from '@/stores/comfyRegistryStore'
import type { TabItem } from '@/types/comfyManagerTypes' import type { TabItem } from '@/types/comfyManagerTypes'
import { ManagerTab } from '@/types/comfyManagerTypes'
import { components } from '@/types/comfyRegistryTypes' import { components } from '@/types/comfyRegistryTypes'
enum ManagerTab { const { initialTab = ManagerTab.All } = defineProps<{
All = 'all', initialTab: ManagerTab
Installed = 'installed', }>()
Workflow = 'workflow',
Missing = 'missing',
UpdateAvailable = 'updateAvailable'
}
const { t } = useI18n() const { t } = useI18n()
const comfyManagerStore = useComfyManagerStore() const comfyManagerStore = useComfyManagerStore()
@@ -159,7 +156,9 @@ const tabs = ref<TabItem[]>([
icon: 'pi-sync' icon: 'pi-sync'
} }
]) ])
const selectedTab = ref<TabItem>(tabs.value[0]) const selectedTab = ref<TabItem>(
tabs.value.find((tab) => tab.id === initialTab) || tabs.value[0]
)
const { const {
searchQuery, searchQuery,
@@ -221,53 +220,68 @@ const isOutdatedPack = (pack: components['schemas']['Node']) => {
const filterOutdatedPacks = (packs: components['schemas']['Node'][]) => const filterOutdatedPacks = (packs: components['schemas']['Node'][]) =>
packs.filter(isOutdatedPack) packs.filter(isOutdatedPack)
watch([isUpdateAvailableTab, installedPacks], () => { watch(
if (!isUpdateAvailableTab.value) return [isUpdateAvailableTab, installedPacks],
() => {
if (!isUpdateAvailableTab.value) return
if (!isEmptySearch.value) { if (!isEmptySearch.value) {
displayPacks.value = filterOutdatedPacks(installedPacks.value) displayPacks.value = filterOutdatedPacks(installedPacks.value)
} else if (!installedPacks.value.length) { } else if (!installedPacks.value.length) {
startFetchInstalled() startFetchInstalled()
} else { } else {
displayPacks.value = filterOutdatedPacks(installedPacks.value) displayPacks.value = filterOutdatedPacks(installedPacks.value)
} }
}) },
{ immediate: true }
)
watch([isInstalledTab, installedPacks], () => { watch(
if (!isInstalledTab.value) return [isInstalledTab, installedPacks],
() => {
if (!isInstalledTab.value) return
if (!isEmptySearch.value) { if (!isEmptySearch.value) {
displayPacks.value = filterInstalledPack(searchResults.value) displayPacks.value = filterInstalledPack(searchResults.value)
} else if ( } else if (
!installedPacks.value.length && !installedPacks.value.length &&
!installedPacksReady.value && !installedPacksReady.value &&
!isLoadingInstalled.value !isLoadingInstalled.value
) { ) {
startFetchInstalled() startFetchInstalled()
} else { } else {
displayPacks.value = installedPacks.value displayPacks.value = installedPacks.value
} }
}) },
{ immediate: true }
)
watch([isMissingTab, isWorkflowTab, workflowPacks], () => { watch(
if (!isWorkflowTab.value && !isMissingTab.value) return [isMissingTab, isWorkflowTab, workflowPacks, installedPacks],
() => {
if (!isWorkflowTab.value && !isMissingTab.value) return
if (!isEmptySearch.value) { if (!isEmptySearch.value) {
displayPacks.value = isMissingTab.value displayPacks.value = isMissingTab.value
? filterMissingPacks(filterWorkflowPack(searchResults.value)) ? filterMissingPacks(filterWorkflowPack(searchResults.value))
: filterWorkflowPack(searchResults.value) : filterWorkflowPack(searchResults.value)
} else if ( } else if (
!workflowPacks.value.length && !workflowPacks.value.length &&
!isLoadingWorkflow.value && !isLoadingWorkflow.value &&
!workflowPacksReady.value !workflowPacksReady.value
) { ) {
startFetchWorkflowPacks() startFetchWorkflowPacks()
} else { if (isMissingTab.value) {
displayPacks.value = isMissingTab.value startFetchInstalled()
? filterMissingPacks(workflowPacks.value) }
: workflowPacks.value } else {
} displayPacks.value = isMissingTab.value
}) ? filterMissingPacks(workflowPacks.value)
: workflowPacks.value
}
},
{ immediate: true }
)
watch([isAllTab, searchResults], () => { watch([isAllTab, searchResults], () => {
if (!isAllTab.value) return if (!isAllTab.value) return
@@ -277,25 +291,33 @@ watch([isAllTab, searchResults], () => {
const onResultsChange = () => { const onResultsChange = () => {
switch (selectedTab.value?.id) { switch (selectedTab.value?.id) {
case ManagerTab.Installed: case ManagerTab.Installed:
displayPacks.value = filterInstalledPack(searchResults.value) displayPacks.value = isEmptySearch.value
? installedPacks.value
: filterInstalledPack(searchResults.value)
break break
case ManagerTab.Workflow: case ManagerTab.Workflow:
displayPacks.value = filterWorkflowPack(searchResults.value) displayPacks.value = isEmptySearch.value
? workflowPacks.value
: filterWorkflowPack(searchResults.value)
break break
case ManagerTab.Missing: case ManagerTab.Missing:
displayPacks.value = filterMissingPacks( if (!isEmptySearch.value) {
filterWorkflowPack(searchResults.value) displayPacks.value = filterMissingPacks(
) filterWorkflowPack(searchResults.value)
)
}
break break
case ManagerTab.UpdateAvailable: case ManagerTab.UpdateAvailable:
displayPacks.value = filterOutdatedPacks(searchResults.value) displayPacks.value = isEmptySearch.value
? filterOutdatedPacks(installedPacks.value)
: filterOutdatedPacks(searchResults.value)
break break
default: default:
displayPacks.value = searchResults.value displayPacks.value = searchResults.value
} }
} }
watch(searchResults, onResultsChange, { flush: 'pre' }) watch(searchResults, onResultsChange, { flush: 'post' })
watch(() => comfyManagerStore.installedPacksIds, onResultsChange) watch(() => comfyManagerStore.installedPacksIds, onResultsChange)
const isLoading = computed(() => { const isLoading = computed(() => {

View File

@@ -16,6 +16,7 @@ import TemplateWorkflowsDialogHeader from '@/components/templates/TemplateWorkfl
import { t } from '@/i18n' import { t } from '@/i18n'
import type { ExecutionErrorWsMessage } from '@/schemas/apiSchema' import type { ExecutionErrorWsMessage } from '@/schemas/apiSchema'
import { type ShowDialogOptions, useDialogStore } from '@/stores/dialogStore' import { type ShowDialogOptions, useDialogStore } from '@/stores/dialogStore'
import { ManagerTab } from '@/types/comfyManagerTypes'
export type ConfirmationDialogType = export type ConfirmationDialogType =
| 'default' | 'default'
@@ -117,7 +118,9 @@ export const useDialogService = () => {
} }
function showManagerDialog( function showManagerDialog(
props: InstanceType<typeof ManagerDialogContent>['$props'] = {} props: InstanceType<typeof ManagerDialogContent>['$props'] = {
initialTab: ManagerTab.All
}
) { ) {
dialogStore.showDialog({ dialogStore.showDialog({
key: 'global-manager', key: 'global-manager',

View File

@@ -10,6 +10,14 @@ export type PackField = keyof RegistryPack | null
export const IsInstallingKey: InjectionKey<Ref<boolean>> = export const IsInstallingKey: InjectionKey<Ref<boolean>> =
Symbol('isInstalling') Symbol('isInstalling')
export enum ManagerTab {
All = 'all',
Installed = 'installed',
Workflow = 'workflow',
Missing = 'missing',
UpdateAvailable = 'updateAvailable'
}
export interface TabItem { export interface TabItem {
id: string id: string
label: string label: string