mirror of
https://github.com/Comfy-Org/ComfyUI_frontend.git
synced 2026-03-07 14:09:59 +00:00
Show pending task count on side bar queue icon (#376)
* remove listener * Store pending task count * Add iconBadge to queue icon
This commit is contained in:
56
package-lock.json
generated
56
package-lock.json
generated
@@ -18,7 +18,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "^2.1.7",
|
||||
"primeicons": "^7.0.0",
|
||||
"primevue": "^4.0.0-rc.2",
|
||||
"primevue": "^4.0.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"vue": "^3.4.31",
|
||||
"vue-i18n": "^9.13.1",
|
||||
@@ -3318,30 +3318,55 @@
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.0.1.tgz",
|
||||
"integrity": "sha512-0psCSZr3906UwC4mTl2ol4aDoLvdbM0ekJFLKvCvC2oQ9z2YZhmUOVZQNNxBW34mChDzZYcAcRWXADQz3z5lBg==",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@primeuix/utils": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@primeuix/utils/-/utils-0.0.5.tgz",
|
||||
"integrity": "sha512-ntUiUgtRtkF8KuaxHffzhYxQxoXk6LAPHm7CVlFjdqS8Rx8xRkLkZVyo84E+pO2hcNFkOGVP/GxHhQ2s94O8zA==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@primevue/core": {
|
||||
"version": "4.0.0-rc.2",
|
||||
"resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.0.0-rc.2.tgz",
|
||||
"integrity": "sha512-S0RGGdW/M/ogIKeif6JwkJrPLC8pyuBYy2zZlloXXj6Fpvk416sMpO308sx89fqvba2d5poT9a+AbkGob4TDtQ==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@primevue/core/-/core-4.0.0.tgz",
|
||||
"integrity": "sha512-M+GF1HYnl/x5J6uevXh1k42J0XnFhp0XHce+cHddWg7v3bVwgsn7LD3AKKcf0A/iQQPXVKX9nY/4/9eFVct67w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primeuix/styled": "^0.0.1"
|
||||
"@primeuix/styled": "^0.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@primeuix/utils": "^0.0.5",
|
||||
"vue": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@primevue/icons": {
|
||||
"version": "4.0.0-rc.2",
|
||||
"resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.0.0-rc.2.tgz",
|
||||
"integrity": "sha512-VZFETBtmpAduGxXhxcYoqiuGriidyz4XR/4NcrR87CQpUWmT13PXfRoqZ1hLXwNZp1XferT1F5GtY1mHcYxJdw==",
|
||||
"node_modules/@primevue/core/node_modules/@primeuix/styled": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/@primeuix/styled/-/styled-0.0.5.tgz",
|
||||
"integrity": "sha512-pVoGn/uPkVm/DyF3TR3EmH/pL/dP4nR42FcYbVduFq9VfO3KVeOEqvcCULHXos66RZO9MCbCFUoLy6ctf9GUGQ==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primevue/core": "4.0.0-rc.2"
|
||||
"@primeuix/utils": "^0.0.5"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@primevue/icons": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/@primevue/icons/-/icons-4.0.0.tgz",
|
||||
"integrity": "sha512-gv9pbj7JjCuW59tW2csIJgg6btTJpkr/mjlfqscEIrYzDGqzCrbfxLur48gA2dyhYsiQPPTbIHFwL944piFgIg==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primevue/core": "4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
@@ -9909,12 +9934,13 @@
|
||||
"integrity": "sha512-jK3Et9UzwzTsd6tzl2RmwrVY/b8raJ3QZLzoDACj+oTJ0oX7L9Hy+XnVwgo4QVKlKpnP/Ur13SXV/pVh4LzaDw=="
|
||||
},
|
||||
"node_modules/primevue": {
|
||||
"version": "4.0.0-rc.2",
|
||||
"resolved": "https://registry.npmjs.org/primevue/-/primevue-4.0.0-rc.2.tgz",
|
||||
"integrity": "sha512-1SICPga4FA5sx27h5FBnMHWidPJRn58mPZj0LNlJygp+9P5ksrtRRNdfDPzmRB+fWcmhvbIxk46meyHeMw1wTQ==",
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/primevue/-/primevue-4.0.0.tgz",
|
||||
"integrity": "sha512-2PFmmJqyXpOcKOdF+gbps5fpSXfoXZp2LwX+hya/b5SDseMt3UNboyEgVI6B+DNbJRrib35EbDiMw+7RIANQ1w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@primevue/core": "4.0.0-rc.2",
|
||||
"@primevue/icons": "4.0.0-rc.2"
|
||||
"@primevue/core": "4.0.0",
|
||||
"@primevue/icons": "4.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=12.11.0"
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"lodash": "^4.17.21",
|
||||
"pinia": "^2.1.7",
|
||||
"primeicons": "^7.0.0",
|
||||
"primevue": "^4.0.0-rc.2",
|
||||
"primevue": "^4.0.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
"vue": "^3.4.31",
|
||||
"vue-i18n": "^9.13.1",
|
||||
|
||||
18
src/App.vue
18
src/App.vue
@@ -6,7 +6,7 @@
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { computed, markRaw, onMounted, watch } from 'vue'
|
||||
import { computed, markRaw, onMounted, onUnmounted, watch } from 'vue'
|
||||
import BlockUI from 'primevue/blockui'
|
||||
import ProgressSpinner from 'primevue/progressspinner'
|
||||
import GraphCanvas from '@/components/graph/GraphCanvas.vue'
|
||||
@@ -17,6 +17,9 @@ import { useI18n } from 'vue-i18n'
|
||||
import { useWorkspaceStore } from './stores/workspaceStateStore'
|
||||
import NodeLibrarySideBarTab from './components/sidebar/tabs/NodeLibrarySideBarTab.vue'
|
||||
import GlobalDialog from './components/dialog/GlobalDialog.vue'
|
||||
import { api } from './scripts/api'
|
||||
import { StatusWsMessageStatus } from './types/apiTypes'
|
||||
import { useQueuePendingTaskCountStore } from './stores/queueStore'
|
||||
|
||||
const isLoading = computed<boolean>(() => useWorkspaceStore().spinner)
|
||||
const theme = computed<string>(() =>
|
||||
@@ -43,6 +46,10 @@ const init = () => {
|
||||
app.extensionManager.registerSidebarTab({
|
||||
id: 'queue',
|
||||
icon: 'pi pi-history',
|
||||
iconBadge: () => {
|
||||
const value = useQueuePendingTaskCountStore().count.toString()
|
||||
return value === '0' ? null : value
|
||||
},
|
||||
title: t('sideToolBar.queue'),
|
||||
tooltip: t('sideToolBar.queue'),
|
||||
component: markRaw(QueueSideBarTab),
|
||||
@@ -58,13 +65,22 @@ const init = () => {
|
||||
})
|
||||
}
|
||||
|
||||
const queuePendingTaskCountStore = useQueuePendingTaskCountStore()
|
||||
const onStatus = (e: CustomEvent<StatusWsMessageStatus>) =>
|
||||
queuePendingTaskCountStore.update(e)
|
||||
|
||||
onMounted(() => {
|
||||
api.addEventListener('status', onStatus)
|
||||
try {
|
||||
init()
|
||||
} catch (e) {
|
||||
console.error('Failed to init Vue app', e)
|
||||
}
|
||||
})
|
||||
|
||||
onUnmounted(() => {
|
||||
api.removeEventListener('status', onStatus)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<template>
|
||||
<Button
|
||||
:icon="props.icon"
|
||||
:class="props.class"
|
||||
text
|
||||
:pt="{
|
||||
@@ -8,16 +7,24 @@
|
||||
props.selected
|
||||
? 'p-button-primary side-bar-button-selected'
|
||||
: 'p-button-secondary'
|
||||
}`,
|
||||
icon: 'side-bar-button-icon'
|
||||
}`
|
||||
}"
|
||||
@click="emit('click', $event)"
|
||||
v-tooltip="{ value: props.tooltip, showDelay: 300, hideDelay: 300 }"
|
||||
/>
|
||||
>
|
||||
<template #icon>
|
||||
<OverlayBadge v-if="shouldShowBadge" :value="overlayValue">
|
||||
<i :class="props.icon + ' side-bar-button-icon'" />
|
||||
</OverlayBadge>
|
||||
<i v-else :class="props.icon + ' side-bar-button-icon'" />
|
||||
</template>
|
||||
</Button>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import OverlayBadge from 'primevue/overlaybadge'
|
||||
import Button from 'primevue/button'
|
||||
import { computed, PropType } from 'vue' // Add this line to import PropsType
|
||||
|
||||
const props = defineProps({
|
||||
icon: String,
|
||||
@@ -29,18 +36,28 @@ const props = defineProps({
|
||||
class: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
iconBadge: {
|
||||
type: [String, Function] as PropType<string | (() => string | null)>,
|
||||
default: ''
|
||||
}
|
||||
})
|
||||
|
||||
const emit = defineEmits(['click'])
|
||||
const overlayValue = computed(() =>
|
||||
typeof props.iconBadge === 'function'
|
||||
? props.iconBadge() || ''
|
||||
: props.iconBadge
|
||||
)
|
||||
const shouldShowBadge = computed(() => !!overlayValue.value)
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.p-button-icon.side-bar-button-icon {
|
||||
.side-bar-button-icon {
|
||||
font-size: var(--sidebar-icon-size) !important;
|
||||
}
|
||||
|
||||
.side-bar-button-selected .p-button-icon.side-bar-button-icon {
|
||||
.side-bar-button-selected .side-bar-button-icon {
|
||||
font-size: var(--sidebar-icon-size) !important;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
v-for="tab in tabs"
|
||||
:key="tab.id"
|
||||
:icon="tab.icon"
|
||||
:iconBadge="tab.iconBadge"
|
||||
:tooltip="tab.tooltip"
|
||||
:selected="tab === selectedTab"
|
||||
:class="tab.id + '-tab-button'"
|
||||
|
||||
@@ -83,7 +83,7 @@ import {
|
||||
TaskItemImpl,
|
||||
useQueueStore
|
||||
} from '@/stores/queueStore'
|
||||
import { computed, onMounted } from 'vue'
|
||||
import { computed, onMounted, onUnmounted } from 'vue'
|
||||
import { api } from '@/scripts/api'
|
||||
|
||||
const confirm = useConfirm()
|
||||
@@ -145,13 +145,16 @@ const confirmRemoveAll = (event) => {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const onStatus = () => queueStore.update()
|
||||
onMounted(() => {
|
||||
api.addEventListener('status', () => {
|
||||
queueStore.update()
|
||||
})
|
||||
api.addEventListener('status', onStatus)
|
||||
|
||||
queueStore.update()
|
||||
})
|
||||
onUnmounted(() => {
|
||||
api.removeEventListener('status', onStatus)
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
@@ -6,7 +6,8 @@ import {
|
||||
TaskType,
|
||||
TaskPrompt,
|
||||
TaskStatus,
|
||||
TaskOutput
|
||||
TaskOutput,
|
||||
StatusWsMessageStatus
|
||||
} from '@/types/apiTypes'
|
||||
import { plainToClass } from 'class-transformer'
|
||||
import _ from 'lodash'
|
||||
@@ -204,3 +205,17 @@ export const useQueueStore = defineStore('queue', {
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
export const useQueuePendingTaskCountStore = defineStore(
|
||||
'queuePendingTaskCount',
|
||||
{
|
||||
state: () => ({
|
||||
count: 0
|
||||
}),
|
||||
actions: {
|
||||
update(e: CustomEvent<StatusWsMessageStatus>) {
|
||||
this.count = e.detail.exec_info.queue_remaining
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
@@ -4,6 +4,7 @@ export interface BaseSidebarTabExtension {
|
||||
id: string
|
||||
title: string
|
||||
icon?: string
|
||||
iconBadge?: string | (() => string | null)
|
||||
order?: number
|
||||
tooltip?: string
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user