diff --git a/packages/frontend/src/filters/kmg.ts b/packages/frontend/src/filters/kmg.ts
new file mode 100644
index 000000000000..6cabacff869a
--- /dev/null
+++ b/packages/frontend/src/filters/kmg.ts
@@ -0,0 +1,9 @@
+export default (v, fractionDigits = 0) => {
+ if (v == null) return 'N/A';
+ if (v == 0) return '0';
+ const sizes = ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y', 'R', 'Q'];
+ const isMinus = v < 0;
+ if (isMinus) v = -v;
+ const i = Math.floor(Math.log(v) / Math.log(1000));
+ return (isMinus ? '-' : '') + (v / Math.pow(1000, i)).toFixed(fractionDigits).replace(/(\.[1-9]*)0+$/, '$1').replace(/\.$/, '') + (sizes[i] ?? `e+${ i * 3 }`);
+};
diff --git a/packages/frontend/src/widgets/WidgetJobQueue.vue b/packages/frontend/src/widgets/WidgetJobQueue.vue
index 10bc257e12d3..966885beb7d6 100644
--- a/packages/frontend/src/widgets/WidgetJobQueue.vue
+++ b/packages/frontend/src/widgets/WidgetJobQueue.vue
@@ -10,19 +10,19 @@ SPDX-License-Identifier: AGPL-3.0-only
Process
-
{{ number(current.inbox.activeSincePrevTick) }}
+
{{ kmg(current.inbox.activeSincePrevTick, 2) }}
Active
-
{{ number(current.inbox.active) }}
+
{{ kmg(current.inbox.active, 2) }}
Delayed
-
{{ number(current.inbox.delayed) }}
+
{{ kmg(current.inbox.delayed, 2) }}
Waiting
-
{{ number(current.inbox.waiting) }}
+
{{ kmg(current.inbox.waiting, 2) }}
@@ -31,19 +31,19 @@ SPDX-License-Identifier: AGPL-3.0-only
Process
-
{{ number(current.deliver.activeSincePrevTick) }}
+
{{ kmg(current.deliver.activeSincePrevTick, 2) }}
Active
-
{{ number(current.deliver.active) }}
+
{{ kmg(current.deliver.active, 2) }}
Delayed
-
{{ number(current.deliver.delayed) }}
+
{{ kmg(current.deliver.delayed, 2) }}
Waiting
-
{{ number(current.deliver.waiting) }}
+
{{ kmg(current.deliver.waiting, 2) }}
@@ -55,7 +55,7 @@ import { onUnmounted, reactive, ref } from 'vue';
import { useWidgetPropsManager, WidgetComponentEmits, WidgetComponentExpose, WidgetComponentProps } from './widget.js';
import { GetFormResultType } from '@/scripts/form.js';
import { useStream } from '@/stream.js';
-import number from '@/filters/number.js';
+import kmg from '@/filters/kmg.js';
import * as sound from '@/scripts/sound.js';
import { deepClone } from '@/scripts/clone.js';
import { defaultStore } from '@/store.js';
@@ -120,10 +120,10 @@ for (const domain of ['inbox', 'deliver']) {
const onStats = (stats) => {
for (const domain of ['inbox', 'deliver']) {
prev[domain] = deepClone(current[domain]);
- current[domain].activeSincePrevTick = stats[domain].activeSincePrevTick;
- current[domain].active = stats[domain].active;
- current[domain].waiting = stats[domain].waiting;
- current[domain].delayed = stats[domain].delayed;
+ current[domain].activeSincePrevTick = 123;
+ current[domain].active = 1234;
+ current[domain].waiting = 123456789123456789123456789123456789123456789123456789123456789123456789123456789123456789;
+ current[domain].delayed = 123456789;
if (current[domain].waiting > 0 && widgetProps.sound && jammedAudioBuffer.value && !jammedSoundNodePlaying.value) {
const soundNode = sound.createSourceNode(jammedAudioBuffer.value, 1);