Lauris BH 2023-03-20 19:08:53 +02:00 committed by GitHub
parent 2337f1854a
commit 7870c29f5f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 140 additions and 19 deletions

1
web/components.d.ts vendored
View file

@ -12,6 +12,7 @@ declare module '@vue/runtime-core' {
ActionsTab: typeof import('./src/components/repo/settings/ActionsTab.vue')['default']
ActivePipelines: typeof import('./src/components/layout/header/ActivePipelines.vue')['default']
AdminAgentsTab: typeof import('./src/components/admin/settings/AdminAgentsTab.vue')['default']
AdminQueueStats: typeof import('./src/components/admin/settings/queue/AdminQueueStats.vue')['default']
AdminQueueTab: typeof import('./src/components/admin/settings/AdminQueueTab.vue')['default']
AdminSecretsTab: typeof import('./src/components/admin/settings/AdminSecretsTab.vue')['default']
AdminUsersTab: typeof import('./src/components/admin/settings/AdminUsersTab.vue')['default']

View file

@ -22,7 +22,7 @@
"@vueuse/core": "^9.13.0",
"ansi_up": "^5.1.0",
"dayjs": "^1.11.7",
"floating-vue": "2.0.0-beta.20",
"floating-vue": "^2.0.0-beta.20",
"fuse.js": "^6.6.2",
"humanize-duration": "^3.28.0",
"javascript-time-ago": "^2.5.9",
@ -56,7 +56,7 @@
"eslint-plugin-simple-import-sort": "^10.0.0",
"eslint-plugin-vue": "^9.9.0",
"eslint-plugin-vue-scoped-css": "^2.4.0",
"prettier": "^2.8.4",
"prettier": "^2.8.5",
"typescript": "5.0.2",
"unplugin-icons": "^0.15.3",
"unplugin-vue-components": "^0.24.1",

View file

@ -27,14 +27,14 @@ specifiers:
eslint-plugin-simple-import-sort: ^10.0.0
eslint-plugin-vue: ^9.9.0
eslint-plugin-vue-scoped-css: ^2.4.0
floating-vue: 2.0.0-beta.20
floating-vue: ^2.0.0-beta.20
fuse.js: ^6.6.2
humanize-duration: ^3.28.0
javascript-time-ago: ^2.5.9
lodash: ^4.17.21
node-emoji: ^1.11.0
pinia: ^2.0.33
prettier: ^2.8.4
prettier: ^2.8.5
prismjs: ^1.29.0
typescript: 5.0.2
unplugin-icons: ^0.15.3
@ -85,12 +85,12 @@ devDependencies:
eslint-config-airbnb-typescript: 17.0.0_g4ufqspmwdmninnalnmypeb4gi
eslint-config-prettier: 8.7.0_eslint@8.36.0
eslint-plugin-import: 2.27.5_a7er6olmtneep4uytpot6gt7wu
eslint-plugin-prettier: 4.2.1_eqzx3hpkgx5nnvxls3azrcc7dm
eslint-plugin-prettier: 4.2.1_e4jq4ivnnnwcsomlcyj2qoljy4
eslint-plugin-promise: 6.1.1_eslint@8.36.0
eslint-plugin-simple-import-sort: 10.0.0_eslint@8.36.0
eslint-plugin-vue: 9.9.0_eslint@8.36.0
eslint-plugin-vue-scoped-css: 2.4.0_baumsyql7ym4rscil5ymcumriy
prettier: 2.8.4
prettier: 2.8.5
typescript: 5.0.2
unplugin-icons: 0.15.3_@vue+compiler-sfc@3.2.47
unplugin-vue-components: 0.24.1_vue@3.2.47
@ -1763,7 +1763,7 @@ packages:
- supports-color
dev: true
/eslint-plugin-prettier/4.2.1_eqzx3hpkgx5nnvxls3azrcc7dm:
/eslint-plugin-prettier/4.2.1_e4jq4ivnnnwcsomlcyj2qoljy4:
resolution: {integrity: sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==}
engines: {node: '>=12.0.0'}
peerDependencies:
@ -1776,7 +1776,7 @@ packages:
dependencies:
eslint: 8.36.0
eslint-config-prettier: 8.7.0_eslint@8.36.0
prettier: 2.8.4
prettier: 2.8.5
prettier-linter-helpers: 1.0.0
dev: true
@ -2842,8 +2842,8 @@ packages:
fast-diff: 1.2.0
dev: true
/prettier/2.8.4:
resolution: {integrity: sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw==}
/prettier/2.8.5:
resolution: {integrity: sha512-3gzuxrHbKUePRBB4ZeU08VNkUcqEHaUaouNt0m7LGP4Hti/NuB07C7PPTM/LkWqXoJYJn2McEo5+kxPNrtQkLQ==}
engines: {node: '>=10.13.0'}
hasBin: true
dev: true

View file

@ -376,7 +376,14 @@
"tasks": "Tasks",
"task_running": "Task is running",
"task_pending": "Task is pending",
"task_waiting_on_deps": "Task is waiting on dependencies"
"task_waiting_on_deps": "Task is waiting on dependencies",
"stats": {
"completed_count": "Completed Tasks",
"worker_count": "Free",
"running_count": "Running",
"pending_count": "Pending",
"waiting_on_deps_count": "Waiting on dependencies"
}
},
"users": {
"users": "Users",

View file

@ -32,7 +32,7 @@
</div>
<div class="flex flex-col">
<pre>{{ queueInfo?.stats }}</pre>
<AdminQueueStats :stats="queueInfo?.stats" />
<div v-if="tasks.length > 0" class="flex flex-col">
<p class="mt-6 mb-2 text-xl">{{ $t('admin.settings.queue.tasks') }}</p>
@ -85,6 +85,8 @@ import useApiClient from '~/compositions/useApiClient';
import useNotifications from '~/compositions/useNotifications';
import { QueueInfo } from '~/lib/api/types/queue';
import AdminQueueStats from './queue/AdminQueueStats.vue';
const apiClient = useApiClient();
const notifications = useNotifications();
const { t } = useI18n();

View file

@ -0,0 +1,109 @@
<template>
<div v-if="stats" class="flex justify-center">
<div class="bg-gray-100 dark:bg-dark-gray-600 text-color dark:text-gray-400 rounded-md py-5 px-5 w-full">
<div class="flex w-full">
<h3 class="text-lg font-semibold leading-tight uppercase flex-1">
{{ $t('admin.settings.queue.stats.completed_count') }}
</h3>
</div>
<div class="relative overflow-hidden transition-all duration-500">
<div>
<div class="pb-4 lg:pb-6">
<h4 class="text-2xl lg:text-3xl font-semibold leading-tight inline-block">
{{ stats.completed_count }}
</h4>
</div>
<div class="pb-4 lg:pb-6">
<div class="overflow-hidden rounded-full h-3 flex transition-all duration-500">
<div
v-for="item in data"
:key="item.key"
class="h-full"
:class="`${item.color}`"
:style="{ width: `${item.perc}%` }"
>
&nbsp;
</div>
</div>
</div>
<div class="flex -mx-4 sm:flex-wrap">
<div
v-for="(item, index) in data"
:key="item.key"
class="px-4 md:w-1/4 sm:w-full"
:class="{ 'md:border-l border-gray-300 dark:border-gray-600': index !== 0 }"
>
<div class="text-sm whitespace-nowrap overflow-hidden text-ellipsis">
<span class="inline-block w-2 h-2 rounded-full mr-1 align-middle" :class="`${item.color}`">&nbsp;</span>
<span class="align-middle">{{ item.label }}</span>
</div>
<div class="font-medium text-lg">
{{ item.value }}
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts" setup>
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { QueueStats } from '~/lib/api/types/queue';
const { t } = useI18n();
const props = defineProps<{
stats?: QueueStats;
}>();
const total = computed(() => {
if (!props.stats) {
return 0;
}
return (
props.stats.worker_count + props.stats.running_count + props.stats.pending_count + props.stats.waiting_on_deps_count
);
});
const data = computed(() => {
if (!props.stats) {
return [];
}
return [
{
key: 'worker_count',
label: t('admin.settings.queue.stats.worker_count'),
value: props.stats.worker_count,
perc: total.value > 0 ? (props.stats.worker_count / total.value) * 100 : 0,
color: 'bg-green-500',
},
{
key: 'running_count',
label: t('admin.settings.queue.stats.running_count'),
value: props.stats.running_count,
perc: total.value > 0 ? (props.stats.running_count / total.value) * 100 : 100,
color: 'bg-blue-500',
},
{
key: 'pending_count',
label: t('admin.settings.queue.stats.pending_count'),
value: props.stats.pending_count,
perc: total.value > 0 ? (props.stats.pending_count / total.value) * 100 : 0,
color: 'bg-red-500',
},
{
key: 'waiting_on_deps_count',
label: t('admin.settings.queue.stats.waiting_on_deps_count'),
value: props.stats.waiting_on_deps_count,
perc: total.value > 0 ? (props.stats.waiting_on_deps_count / total.value) * 100 : 0,
color: 'bg-red-800',
},
];
});
</script>

View file

@ -7,16 +7,18 @@ export type Task = {
run_on: string[];
};
export type QueueStats = {
worker_count: number;
pending_count: number;
waiting_on_deps_count: number;
running_count: number;
completed_count: number;
};
export type QueueInfo = {
pending: Task[];
waiting_on_deps: Task[];
running: Task[];
stats: {
worker_count: number;
pending_count: number;
waiting_on_deps_count: number;
running_count: number;
completed_count: number;
};
stats: QueueStats;
paused: boolean;
};