[Manager] Improve node pack card design (#3089)

This commit is contained in:
Christian Byrne
2025-03-17 07:36:35 -07:00
committed by GitHub
parent d23aec4ceb
commit a7a8cc633b
5 changed files with 101 additions and 21 deletions

View File

@@ -41,26 +41,51 @@
</template>
<template #content>
<ContentDivider />
<div class="flex flex-1 p-5 mt-3 cursor-pointer">
<div class="flex-shrink-0 mr-4">
<PackIcon :node-pack="nodePack" />
</div>
<div class="flex flex-col flex-1 min-w-0">
<div
class="self-stretch px-4 py-3 inline-flex justify-start items-start cursor-pointer"
>
<PackIcon :node-pack="nodePack" />
<div
class="px-4 inline-flex flex-col justify-start items-start overflow-hidden"
>
<span
class="text-lg font-bold pb-4 truncate overflow-hidden text-ellipsis"
class="text-sm font-bold truncate overflow-hidden text-ellipsis"
:title="nodePack.name"
>
{{ nodePack.name }}
</span>
<div class="flex-1">
<div
class="self-stretch inline-flex justify-center items-center gap-2.5"
>
<p
v-if="nodePack.description"
class="text-sm text-color-secondary m-0 line-clamp-3 overflow-hidden"
class="flex-1 justify-start text-muted text-sm font-medium leading-3 break-words overflow-hidden min-h-12 line-clamp-3"
:title="nodePack.description"
>
{{ nodePack.description }}
</p>
</div>
<div
class="self-stretch inline-flex justify-start items-center gap-2"
>
<div
v-if="nodesCount"
class="px-2 py-1 flex justify-center text-sm items-center gap-1"
>
<div class="text-center justify-center font-medium leading-3">
{{ nodesCount }} {{ $t('g.nodes') }}
</div>
</div>
<div class="px-2 py-1 flex justify-center items-center gap-1">
<div
v-if="isUpdateAvailable"
class="w-4 h-4 relative overflow-hidden"
>
<i class="pi pi-arrow-circle-up text-blue-600" />
</div>
<PackVersionBadge :node-pack="nodePack" />
</div>
</div>
</div>
</div>
</template>
@@ -76,21 +101,37 @@ import Card from 'primevue/card'
import { computed } from 'vue'
import ContentDivider from '@/components/common/ContentDivider.vue'
import PackVersionBadge from '@/components/dialog/content/manager/PackVersionBadge.vue'
import PackEnableToggle from '@/components/dialog/content/manager/button/PackEnableToggle.vue'
import PackInstallButton from '@/components/dialog/content/manager/button/PackInstallButton.vue'
import PackCardFooter from '@/components/dialog/content/manager/packCard/PackCardFooter.vue'
import PackIcon from '@/components/dialog/content/manager/packIcon/PackIcon.vue'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import type { components } from '@/types/comfyRegistryTypes'
import { compareVersions, isSemVer } from '@/utils/formatUtil'
const { nodePack, isSelected = false } = defineProps<{
nodePack: components['schemas']['Node']
isSelected?: boolean
}>()
const managerStore = useComfyManagerStore()
const { isPackInstalled, getInstalledPackVersion } = useComfyManagerStore()
const isPackInstalled = computed(() =>
managerStore.isPackInstalled(nodePack?.id)
)
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
const isUpdateAvailable = computed(() => {
if (!isInstalled.value) return false
const latestVersion = nodePack.latest_version?.version
if (!latestVersion) return false
const installedVersion = getInstalledPackVersion(nodePack.id)
// Don't attempt to show update available for nightly GitHub packs
if (installedVersion && !isSemVer(installedVersion)) return false
return compareVersions(latestVersion, installedVersion) > 0
})
// TODO: remove type assertion once comfy_nodes is added to node (pack) info type in backend
const nodesCount = computed(() => (nodePack as any).comfy_nodes?.length)
</script>

View File

@@ -1,10 +1,11 @@
<template>
<div class="flex justify-between p-5 text-xs text-muted">
<div
class="flex justify-between p-5 text-xs text-muted font-medium leading-3"
>
<div class="flex items-center gap-2 cursor-pointer">
<span v-if="nodePack.publisher?.name">
{{ nodePack.publisher.name }}
<span v-if="publisherName" class="max-w-40 truncate">
{{ publisherName }}
</span>
<PackVersionBadge v-if="isInstalled" :node-pack="nodePack" />
<span v-else-if="nodePack.latest_version">
{{ nodePack.latest_version.version }}
</span>
@@ -26,14 +27,16 @@
<script setup lang="ts">
import { computed } from 'vue'
import PackVersionBadge from '@/components/dialog/content/manager/PackVersionBadge.vue'
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
import type { components } from '@/types/comfyRegistryTypes'
const { nodePack } = defineProps<{
nodePack: components['schemas']['Node']
}>()
const { isPackInstalled } = useComfyManagerStore()
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
const publisherName = computed(() => {
if (!nodePack) return null
const { publisher, author } = nodePack
return publisher?.name ?? publisher?.id ?? author
})
</script>

View File

@@ -131,7 +131,9 @@ export const useAlgoliaSearchService = () => {
status: algoliaNode.status,
icon: algoliaNode.icon_url,
latest_version: toRegistryLatestVersion(algoliaNode),
publisher: toRegistryPublisher(algoliaNode)
publisher: toRegistryPublisher(algoliaNode),
// @ts-expect-error remove when comfy_nodes is added to node (pack) info
comfy_nodes: algoliaNode.comfy_nodes
}
}

View File

@@ -178,6 +178,11 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
enqueueTask(withLogs(task, `Disabling ${params.id}`))
}
const getInstalledPackVersion = (packId: string) => {
const pack = installedPacks.value[packId]
return pack?.ver
}
const clearLogs = () => {
taskLogs.value = []
}
@@ -197,6 +202,7 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
installedPacksIds,
isPackInstalled: isInstalledPackId,
isPackEnabled: isEnabledPackId,
getInstalledPackVersion,
// Pack actions
installPack,

View File

@@ -384,3 +384,31 @@ export const downloadUrlToHfRepoUrl = (url: string): string => {
return url
}
}
export const isSemVer = (version: string) => {
const regex = /^(\d+)\.(\d+)\.(\d+)$/
return regex.test(version)
}
const normalizeVersion = (version: string) =>
version
.split(/[+.-]/)
.map(Number)
.filter((part) => !Number.isNaN(part))
export function compareVersions(versionA: string, versionB: string): number {
versionA ??= '0.0.0'
versionB ??= '0.0.0'
const aParts = normalizeVersion(versionA)
const bParts = normalizeVersion(versionB)
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
const aPart = aParts[i] ?? 0
const bPart = bParts[i] ?? 0
if (aPart < bPart) return -1
if (aPart > bPart) return 1
}
return 0
}