Migrate job view stats table

This commit is contained in:
Christoph Kluge
2025-06-04 11:28:45 +02:00
parent 927e25c72c
commit 5e696c10d5
3 changed files with 126 additions and 94 deletions

View File

@@ -2,73 +2,56 @@
@component Job-View subcomponent; Single Statistics entry component for statstable
Properties:
- `host String`: The hostname (== node)
- `metric String`: The metric name
- `data [Object]`: The jobs statsdata for host-metric-scope
- `scope String`: The selected scope
- `data [Object]`: The jobs statsdata
-->
<script>
import { Icon } from "@sveltestrap/sveltestrap";
export let host;
export let metric;
export let scope;
export let data;
/* Svelte 5 Props */
let {
data,
scope,
} = $props();
let entrySorting = {
id: { dir: "down", active: true },
min: { dir: "up", active: false },
avg: { dir: "up", active: false },
max: { dir: "up", active: false },
};
/* State Init */
let sortBy = $state("id");
let sortDir = $state("down");
function compareNumbers(a, b) {
return a.id - b.id;
}
/* Derived */
const sortedData = $derived(updateData(data, sortBy, sortDir));
function sortByField(field) {
let s = entrySorting[field];
if (s.active) {
s.dir = s.dir == "up" ? "down" : "up";
} else {
for (let field in entrySorting) entrySorting[field].active = false;
s.active = true;
}
entrySorting = { ...entrySorting };
stats = stats.sort((a, b) => {
if (a == null || b == null) return -1;
if (field === "id") {
return s.dir != "up" ?
a[field].localeCompare(b[field], undefined, {numeric: true, sensitivity: 'base'}) :
b[field].localeCompare(a[field], undefined, {numeric: true, sensitivity: 'base'})
/* Functions */
function updateData(data, sortBy, sortDir) {
data.sort((a, b) => {
if (a == null || b == null) {
return -1;
} else if (sortBy === "id") {
return sortDir != "up"
? a[sortBy].localeCompare(b[sortBy], undefined, {numeric: true, sensitivity: 'base'})
: b[sortBy].localeCompare(a[sortBy], undefined, {numeric: true, sensitivity: 'base'});
} else {
return s.dir != "up"
? a.data[field] - b.data[field]
: b.data[field] - a.data[field];
}
return sortDir != "up"
? a.data[sortBy] - b.data[sortBy]
: b.data[sortBy] - a.data[sortBy];
};
});
}
$: stats = data
?.find((d) => d.name == metric && d.scope == scope)
?.stats.filter((s) => s.hostname == host && s.data != null)
?.sort(compareNumbers) || [];
return [...data];
};
</script>
{#if stats == null || stats.length == 0}
{#if data == null || data.length == 0}
<td colspan={scope == "node" ? 3 : 4}><i>No data</i></td>
{:else if stats.length == 1 && scope == "node"}
{:else if data.length == 1 && scope == "node"}
<td>
{stats[0].data.min}
{data[0].data.min}
</td>
<td>
{stats[0].data.avg}
{data[0].data.avg}
</td>
<td>
{stats[0].data.max}
{data[0].data.max}
</td>
{:else}
<td colspan="4">
@@ -76,17 +59,18 @@
<tbody>
<tr>
{#each ["id", "min", "avg", "max"] as field}
<th on:click={() => sortByField(field)}>
<th onclick={() => {
sortBy = field;
sortDir = (sortDir == "up" ? "down" : "up");
}}>
Sort
<Icon
name="caret-{entrySorting[field].dir}{entrySorting[field].active
? '-fill'
: ''}"
name="caret-{sortBy == field? sortDir: 'down'}{sortBy == field? '-fill': ''}"
/>
</th>
{/each}
</tr>
{#each stats as s, i}
{#each sortedData as s, i}
<tr>
<th>{s.id ?? i}</th>
<td>{s.data.min}</td>