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:
Chenlei Hu
2024-08-11 19:15:21 -04:00
committed by GitHub
parent edf0396619
commit 281ed0c5d1
8 changed files with 107 additions and 28 deletions

56
package-lock.json generated
View File

@@ -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"

View File

@@ -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",

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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'"

View File

@@ -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>

View File

@@ -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
}
}
}
)

View File

@@ -4,6 +4,7 @@ export interface BaseSidebarTabExtension {
id: string
title: string
icon?: string
iconBadge?: string | (() => string | null)
order?: number
tooltip?: string
}