Skip to content

Commit a7a8cc6

Browse files
[Manager] Improve node pack card design (#3089)
1 parent d23aec4 commit a7a8cc6

File tree

5 files changed

+101
-21
lines changed

5 files changed

+101
-21
lines changed

src/components/dialog/content/manager/packCard/PackCard.vue

+53-12
Original file line numberDiff line numberDiff line change
@@ -41,26 +41,51 @@
4141
</template>
4242
<template #content>
4343
<ContentDivider />
44-
<div class="flex flex-1 p-5 mt-3 cursor-pointer">
45-
<div class="flex-shrink-0 mr-4">
46-
<PackIcon :node-pack="nodePack" />
47-
</div>
48-
<div class="flex flex-col flex-1 min-w-0">
44+
<div
45+
class="self-stretch px-4 py-3 inline-flex justify-start items-start cursor-pointer"
46+
>
47+
<PackIcon :node-pack="nodePack" />
48+
<div
49+
class="px-4 inline-flex flex-col justify-start items-start overflow-hidden"
50+
>
4951
<span
50-
class="text-lg font-bold pb-4 truncate overflow-hidden text-ellipsis"
52+
class="text-sm font-bold truncate overflow-hidden text-ellipsis"
5153
:title="nodePack.name"
5254
>
5355
{{ nodePack.name }}
5456
</span>
55-
<div class="flex-1">
57+
<div
58+
class="self-stretch inline-flex justify-center items-center gap-2.5"
59+
>
5660
<p
5761
v-if="nodePack.description"
58-
class="text-sm text-color-secondary m-0 line-clamp-3 overflow-hidden"
62+
class="flex-1 justify-start text-muted text-sm font-medium leading-3 break-words overflow-hidden min-h-12 line-clamp-3"
5963
:title="nodePack.description"
6064
>
6165
{{ nodePack.description }}
6266
</p>
6367
</div>
68+
<div
69+
class="self-stretch inline-flex justify-start items-center gap-2"
70+
>
71+
<div
72+
v-if="nodesCount"
73+
class="px-2 py-1 flex justify-center text-sm items-center gap-1"
74+
>
75+
<div class="text-center justify-center font-medium leading-3">
76+
{{ nodesCount }} {{ $t('g.nodes') }}
77+
</div>
78+
</div>
79+
<div class="px-2 py-1 flex justify-center items-center gap-1">
80+
<div
81+
v-if="isUpdateAvailable"
82+
class="w-4 h-4 relative overflow-hidden"
83+
>
84+
<i class="pi pi-arrow-circle-up text-blue-600" />
85+
</div>
86+
<PackVersionBadge :node-pack="nodePack" />
87+
</div>
88+
</div>
6489
</div>
6590
</div>
6691
</template>
@@ -76,21 +101,37 @@ import Card from 'primevue/card'
76101
import { computed } from 'vue'
77102
78103
import ContentDivider from '@/components/common/ContentDivider.vue'
104+
import PackVersionBadge from '@/components/dialog/content/manager/PackVersionBadge.vue'
79105
import PackEnableToggle from '@/components/dialog/content/manager/button/PackEnableToggle.vue'
80106
import PackInstallButton from '@/components/dialog/content/manager/button/PackInstallButton.vue'
81107
import PackCardFooter from '@/components/dialog/content/manager/packCard/PackCardFooter.vue'
82108
import PackIcon from '@/components/dialog/content/manager/packIcon/PackIcon.vue'
83109
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
84110
import type { components } from '@/types/comfyRegistryTypes'
111+
import { compareVersions, isSemVer } from '@/utils/formatUtil'
85112
86113
const { nodePack, isSelected = false } = defineProps<{
87114
nodePack: components['schemas']['Node']
88115
isSelected?: boolean
89116
}>()
90117
91-
const managerStore = useComfyManagerStore()
118+
const { isPackInstalled, getInstalledPackVersion } = useComfyManagerStore()
119+
120+
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
121+
const isUpdateAvailable = computed(() => {
122+
if (!isInstalled.value) return false
123+
124+
const latestVersion = nodePack.latest_version?.version
125+
if (!latestVersion) return false
126+
127+
const installedVersion = getInstalledPackVersion(nodePack.id)
128+
129+
// Don't attempt to show update available for nightly GitHub packs
130+
if (installedVersion && !isSemVer(installedVersion)) return false
131+
132+
return compareVersions(latestVersion, installedVersion) > 0
133+
})
92134
93-
const isPackInstalled = computed(() =>
94-
managerStore.isPackInstalled(nodePack?.id)
95-
)
135+
// TODO: remove type assertion once comfy_nodes is added to node (pack) info type in backend
136+
const nodesCount = computed(() => (nodePack as any).comfy_nodes?.length)
96137
</script>

src/components/dialog/content/manager/packCard/PackCardFooter.vue

+11-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<template>
2-
<div class="flex justify-between p-5 text-xs text-muted">
2+
<div
3+
class="flex justify-between p-5 text-xs text-muted font-medium leading-3"
4+
>
35
<div class="flex items-center gap-2 cursor-pointer">
4-
<span v-if="nodePack.publisher?.name">
5-
{{ nodePack.publisher.name }}
6+
<span v-if="publisherName" class="max-w-40 truncate">
7+
{{ publisherName }}
68
</span>
7-
<PackVersionBadge v-if="isInstalled" :node-pack="nodePack" />
89
<span v-else-if="nodePack.latest_version">
910
{{ nodePack.latest_version.version }}
1011
</span>
@@ -26,14 +27,16 @@
2627
<script setup lang="ts">
2728
import { computed } from 'vue'
2829
29-
import PackVersionBadge from '@/components/dialog/content/manager/PackVersionBadge.vue'
30-
import { useComfyManagerStore } from '@/stores/comfyManagerStore'
3130
import type { components } from '@/types/comfyRegistryTypes'
3231
3332
const { nodePack } = defineProps<{
3433
nodePack: components['schemas']['Node']
3534
}>()
3635
37-
const { isPackInstalled } = useComfyManagerStore()
38-
const isInstalled = computed(() => isPackInstalled(nodePack?.id))
36+
const publisherName = computed(() => {
37+
if (!nodePack) return null
38+
39+
const { publisher, author } = nodePack
40+
return publisher?.name ?? publisher?.id ?? author
41+
})
3942
</script>

src/services/algoliaSearchService.ts

+3-1
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,9 @@ export const useAlgoliaSearchService = () => {
131131
status: algoliaNode.status,
132132
icon: algoliaNode.icon_url,
133133
latest_version: toRegistryLatestVersion(algoliaNode),
134-
publisher: toRegistryPublisher(algoliaNode)
134+
publisher: toRegistryPublisher(algoliaNode),
135+
// @ts-expect-error remove when comfy_nodes is added to node (pack) info
136+
comfy_nodes: algoliaNode.comfy_nodes
135137
}
136138
}
137139

src/stores/comfyManagerStore.ts

+6
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,11 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
178178
enqueueTask(withLogs(task, `Disabling ${params.id}`))
179179
}
180180

181+
const getInstalledPackVersion = (packId: string) => {
182+
const pack = installedPacks.value[packId]
183+
return pack?.ver
184+
}
185+
181186
const clearLogs = () => {
182187
taskLogs.value = []
183188
}
@@ -197,6 +202,7 @@ export const useComfyManagerStore = defineStore('comfyManager', () => {
197202
installedPacksIds,
198203
isPackInstalled: isInstalledPackId,
199204
isPackEnabled: isEnabledPackId,
205+
getInstalledPackVersion,
200206

201207
// Pack actions
202208
installPack,

src/utils/formatUtil.ts

+28
Original file line numberDiff line numberDiff line change
@@ -384,3 +384,31 @@ export const downloadUrlToHfRepoUrl = (url: string): string => {
384384
return url
385385
}
386386
}
387+
388+
export const isSemVer = (version: string) => {
389+
const regex = /^(\d+)\.(\d+)\.(\d+)$/
390+
return regex.test(version)
391+
}
392+
393+
const normalizeVersion = (version: string) =>
394+
version
395+
.split(/[+.-]/)
396+
.map(Number)
397+
.filter((part) => !Number.isNaN(part))
398+
399+
export function compareVersions(versionA: string, versionB: string): number {
400+
versionA ??= '0.0.0'
401+
versionB ??= '0.0.0'
402+
403+
const aParts = normalizeVersion(versionA)
404+
const bParts = normalizeVersion(versionB)
405+
406+
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
407+
const aPart = aParts[i] ?? 0
408+
const bPart = bParts[i] ?? 0
409+
if (aPart < bPart) return -1
410+
if (aPart > bPart) return 1
411+
}
412+
413+
return 0
414+
}

0 commit comments

Comments
 (0)