Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
5846117
migrate manager menu items
christian-byrne Apr 9, 2025
d96265a
Update locales [skip ci]
invalid-email-address Apr 9, 2025
d2d8565
switch to v2 manager API endpoints
christian-byrne Apr 9, 2025
cd7d64a
re-arrange menu items
christian-byrne Apr 11, 2025
fd3362e
await promises. update settings schema
christian-byrne Apr 14, 2025
61fa2fd
move legacy option to startup arg
christian-byrne Apr 14, 2025
be7433b
Add banner indicating how to use legacy manager UI
christian-byrne Apr 14, 2025
29cdd57
Update locales [skip ci]
invalid-email-address Apr 14, 2025
7ec70e5
add "Check for Updates", "Install Missing" menu items
christian-byrne Apr 14, 2025
226f84e
Update locales [skip ci]
invalid-email-address Apr 14, 2025
cf174d3
use correct response shape
christian-byrne Apr 14, 2025
e8e558b
improve command names
christian-byrne Apr 14, 2025
8a2747f
dont show missing nodes button in legacy manager mode
christian-byrne Apr 15, 2025
0f97a6f
[Update to v2 API] update WS done message
christian-byrne Apr 15, 2025
2d117b1
Update locales [skip ci]
invalid-email-address Jul 19, 2025
ec923e2
[fix] Fix json syntax error from rebase (#4607)
christian-byrne Jul 30, 2025
8ceb5e4
Fix errors from rebase (removed `Tag` component import and duplicated…
christian-byrne Jul 30, 2025
a2df972
Update locales [skip ci]
invalid-email-address Jul 30, 2025
808adc0
[Manager] "Restarting" state after clicking restart button (#4637)
viva-jinyi Aug 1, 2025
b7f778b
[feat] Add reactive feature flags foundation (#4817)
christian-byrne Aug 7, 2025
2e4b510
[feat] Add v2/ prefix to manager service base URL (#4872)
christian-byrne Aug 9, 2025
3c3ed2b
[cleanup] Remove unused manager route enums (#4875)
christian-byrne Aug 9, 2025
3352c06
fix: v2 prefix (#5145)
viva-jinyi Aug 21, 2025
7d1659c
Fix: Restore api.ts from main branch after incorrect rebase (#5150)
viva-jinyi Aug 22, 2025
6470869
feat: Add loading state to PackInstallButton and improve UI (#5153)
viva-jinyi Aug 23, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
feat: Add loading state to PackInstallButton and improve UI (#5153)
  • Loading branch information
viva-jinyi authored Aug 23, 2025
commit 6470869eb1cffa80b76b8e4ec15b7d383bb148b6
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 8 additions & 0 deletions src/components/button/IconButton.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ const meta: Meta<typeof IconButton> = {
control: { type: 'select' },
options: ['primary', 'secondary', 'transparent']
},
border: {
control: 'boolean',
description: 'Toggle border attribute'
},
disabled: {
control: 'boolean',
description: 'Toggle disable status'
},
onClick: { action: 'clicked' }
}
}
Expand Down
9 changes: 7 additions & 2 deletions src/components/button/IconButton.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<Button unstyled :class="buttonStyle" @click="onClick">
<Button unstyled :class="buttonStyle" :disabled="disabled" @click="onClick">
<slot></slot>
</Button>
</template>
Expand All @@ -11,6 +11,7 @@ import { computed } from 'vue'
import type { BaseButtonProps } from '@/types/buttonTypes'
import {
getBaseButtonClasses,
getBorderButtonTypeClasses,
getButtonTypeClasses,
getIconButtonSizeClasses
} from '@/types/buttonTypes'
Expand All @@ -22,14 +23,18 @@ interface IconButtonProps extends BaseButtonProps {
const {
size = 'md',
type = 'secondary',
border = false,
disabled = false,
class: className,
onClick
} = defineProps<IconButtonProps>()

const buttonStyle = computed(() => {
const baseClasses = `${getBaseButtonClasses()} p-0`
const sizeClasses = getIconButtonSizeClasses(size)
const typeClasses = getButtonTypeClasses(type)
const typeClasses = border
? getBorderButtonTypeClasses(type)
: getButtonTypeClasses(type)

return [baseClasses, sizeClasses, typeClasses, className]
.filter(Boolean)
Expand Down
8 changes: 8 additions & 0 deletions src/components/button/IconTextButton.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,14 @@ const meta: Meta<typeof IconTextButton> = {
control: { type: 'select' },
options: ['primary', 'secondary', 'transparent']
},
border: {
control: 'boolean',
description: 'Toggle border attribute'
},
disabled: {
control: 'boolean',
description: 'Toggle disable status'
},
iconPosition: {
control: { type: 'select' },
options: ['left', 'right']
Expand Down
9 changes: 7 additions & 2 deletions src/components/button/IconTextButton.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<Button unstyled :class="buttonStyle" @click="onClick">
<Button unstyled :class="buttonStyle" :disabled="disabled" @click="onClick">
<slot v-if="iconPosition !== 'right'" name="icon"></slot>
<span>{{ label }}</span>
<slot v-if="iconPosition === 'right'" name="icon"></slot>
Expand All @@ -13,6 +13,7 @@ import { computed } from 'vue'
import type { BaseButtonProps } from '@/types/buttonTypes'
import {
getBaseButtonClasses,
getBorderButtonTypeClasses,
getButtonSizeClasses,
getButtonTypeClasses
} from '@/types/buttonTypes'
Expand All @@ -26,6 +27,8 @@ interface IconTextButtonProps extends BaseButtonProps {
const {
size = 'md',
type = 'primary',
border = false,
disabled = false,
class: className,
iconPosition = 'left',
label,
Expand All @@ -35,7 +38,9 @@ const {
const buttonStyle = computed(() => {
const baseClasses = `${getBaseButtonClasses()} !justify-start gap-2`
const sizeClasses = getButtonSizeClasses(size)
const typeClasses = getButtonTypeClasses(type)
const typeClasses = border
? getBorderButtonTypeClasses(type)
: getButtonTypeClasses(type)

return [baseClasses, sizeClasses, typeClasses, className]
.filter(Boolean)
Expand Down
8 changes: 8 additions & 0 deletions src/components/button/TextButton.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,14 @@ const meta: Meta<typeof TextButton> = {
options: ['sm', 'md'],
defaultValue: 'md'
},
border: {
control: 'boolean',
description: 'Toggle border attribute'
},
disabled: {
control: 'boolean',
description: 'Toggle disable status'
},
type: {
control: { type: 'select' },
options: ['primary', 'secondary', 'transparent'],
Expand Down
9 changes: 7 additions & 2 deletions src/components/button/TextButton.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<template>
<Button unstyled :class="buttonStyle" role="button" @click="onClick">
<Button unstyled :class="buttonStyle" :disabled="disabled" @click="onClick">
<span>{{ label }}</span>
</Button>
</template>
Expand All @@ -11,6 +11,7 @@ import { computed } from 'vue'
import type { BaseButtonProps } from '@/types/buttonTypes'
import {
getBaseButtonClasses,
getBorderButtonTypeClasses,
getButtonSizeClasses,
getButtonTypeClasses
} from '@/types/buttonTypes'
Expand All @@ -23,6 +24,8 @@ interface TextButtonProps extends BaseButtonProps {
const {
size = 'md',
type = 'primary',
border = false,
disabled = false,
class: className,
label,
onClick
Expand All @@ -31,7 +34,9 @@ const {
const buttonStyle = computed(() => {
const baseClasses = getBaseButtonClasses()
const sizeClasses = getButtonSizeClasses(size)
const typeClasses = getButtonTypeClasses(type)
const typeClasses = border
? getBorderButtonTypeClasses(type)
: getButtonTypeClasses(type)

return [baseClasses, sizeClasses, typeClasses, className]
.filter(Boolean)
Expand Down
25 changes: 22 additions & 3 deletions src/components/dialog/content/LoadWorkflowWarning.vue
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,16 @@
</ListBox>
<div v-if="!isLegacyManager" class="flex justify-end py-3">
<PackInstallButton
:disabled="isLoading || !!error || missingNodePacks.length === 0"
size="md"
:disabled="!!error || missingNodePacks.length === 0"
:is-loading="isLoading"
:is-installing="isInstalling"
:node-packs="missingNodePacks"
variant="black"
:label="$t('manager.installAllMissingNodes')"
:label="
isLoading
? $t('manager.gettingInfo')
: $t('manager.installAllMissingNodes')
"
/>
<Button label="Open Manager" size="small" outlined @click="openManager" />
</div>
Expand All @@ -48,12 +54,16 @@ import ListBox from 'primevue/listbox'
import { computed, onMounted, ref } from 'vue'

import NoResultsPlaceholder from '@/components/common/NoResultsPlaceholder.vue'
import MissingCoreNodesMessage from '@/components/dialog/content/MissingCoreNodesMessage.vue'
import { useMissingNodes } from '@/composables/nodePack/useMissingNodes'
import { useComfyManagerService } from '@/services/comfyManagerService'
import { useDialogService } from '@/services/dialogService'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import type { MissingNodeType } from '@/types/comfy'
import { ManagerTab } from '@/types/comfyManagerTypes'

import PackInstallButton from './manager/button/PackInstallButton.vue'

const props = defineProps<{
missingNodeTypes: MissingNodeType[]
}>()
Expand All @@ -62,8 +72,17 @@ const props = defineProps<{
const { missingNodePacks, isLoading, error, missingCoreNodes } =
useMissingNodes()

const comfyManagerStore = useComfyManagerStore()
const isLegacyManager = ref(false)

// Check if any of the missing packs are currently being installed
const isInstalling = computed(() => {
if (!missingNodePacks.value?.length) return false
return missingNodePacks.value.some((pack) =>
comfyManagerStore.isPackInstalling(pack.id)
)
})

const uniqueNodes = computed(() => {
const seenTypes = new Set()
return props.missingNodeTypes
Expand Down
5 changes: 2 additions & 3 deletions src/components/dialog/content/manager/PackVersionBadge.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@
>
<i
v-if="isUpdateAvailable"
class="pi pi-arrow-circle-up text-blue-600"
style="font-size: 8px"
class="pi pi-arrow-circle-up text-blue-600 text-xs"
/>
<span>{{ installedVersion }}</span>
<i class="pi pi-chevron-right" style="font-size: 8px" />
<i class="pi pi-chevron-right text-xxs" />
</div>

<Popover
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
<template>
<PackActionButton
<IconTextButton
v-bind="$attrs"
:label="
label ??
(nodePacks.length > 1 ? $t('manager.installSelected') : $t('g.install'))
"
:severity="variant === 'black' ? undefined : 'secondary'"
:variant="variant"
:loading="isInstalling"
:loading-message="$t('g.installing')"
@action="installAllPacks"
/>
type="transparent"
:label="computedLabel"
:border="true"
:size="size"
:disabled="isLoading || isInstalling"
@click="installAllPacks"
>
<template v-if="isLoading || isInstalling" #icon>
<DotSpinner duration="1s" :size="size === 'sm' ? 12 : 16" />
</template>
</IconTextButton>
</template>

<script setup lang="ts">
import { inject, ref } from 'vue'
import { computed } from 'vue'

import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue'
import IconTextButton from '@/components/button/IconTextButton.vue'
import DotSpinner from '@/components/common/DotSpinner.vue'
import { t } from '@/i18n'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import { ButtonSize } from '@/types/buttonTypes'
import {
IsInstallingKey,
ManagerChannel,
ManagerDatabaseSource,
SelectedVersion
Expand All @@ -28,14 +31,20 @@ import type { components } from '@/types/comfyRegistryTypes'

type NodePack = components['schemas']['Node']

const { nodePacks, variant, label } = defineProps<{
const {
nodePacks,
isLoading = false,
isInstalling = false,
label = 'Install',
size = 'sm'
} = defineProps<{
nodePacks: NodePack[]
variant?: 'default' | 'black'
isLoading?: boolean
isInstalling?: boolean
label?: string
size?: ButtonSize
}>()

const isInstalling = inject(IsInstallingKey, ref(false))

const managerStore = useComfyManagerStore()

const createPayload = (installItem: NodePack) => {
Expand Down Expand Up @@ -68,4 +77,11 @@ const installAllPacks = async () => {
await Promise.all(uninstalledPacks.map(installPack))
managerStore.installPack.clear()
}

const computedLabel = computed(() =>
isInstalling
? t('g.installing')
: label ??
(nodePacks.length > 1 ? t('manager.installSelected') : t('g.install'))
)
</script>
Original file line number Diff line number Diff line change
@@ -1,27 +1,30 @@
<template>
<PackActionButton
<IconTextButton
v-bind="$attrs"
type="transparent"
:label="
nodePacks.length > 1
? $t('manager.uninstallSelected')
: $t('manager.uninstall')
"
severity="danger"
:loading-message="$t('manager.uninstalling')"
@action="uninstallItems"
:border="true"
:size="size"
class="border-red-500"
@click="uninstallItems"
/>
</template>

<script setup lang="ts">
import PackActionButton from '@/components/dialog/content/manager/button/PackActionButton.vue'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import { ButtonSize } from '@/types/buttonTypes'
import type { ManagerPackInfo } from '@/types/comfyManagerTypes'
import type { components } from '@/types/comfyRegistryTypes'

type NodePack = components['schemas']['Node']

const { nodePacks } = defineProps<{
const { nodePacks, size } = defineProps<{
nodePacks: NodePack[]
size?: ButtonSize
}>()

const managerStore = useComfyManagerStore()
Expand Down
Loading