add shortjobs and resource sums to project and user lists

This commit is contained in:
Christoph Kluge
2026-02-04 12:57:48 +01:00
parent 5d7dd62b72
commit a7a95bb866
2 changed files with 86 additions and 7 deletions

View File

@@ -466,7 +466,7 @@ func (r *JobRepository) JobCountGrouped(
// AddJobCountGrouped augments existing statistics with additional job counts by category.
//
// This method enriches JobsStatistics returned by JobsStatsGrouped or JobCountGrouped
// with counts of running or short-running jobs, matched by group ID.
// with counts of running or short-running (based on ShortRunningJobsDuration) jobs, matched by group ID.
//
// Parameters:
// - ctx: Context for security checks

View File

@@ -7,7 +7,7 @@
-->
<script>
import { onMount } from "svelte";
import { getContext, onMount } from "svelte";
import {
Row,
Col,
@@ -18,6 +18,7 @@
Spinner,
InputGroup,
Input,
Tooltip
} from "@sveltestrap/sveltestrap";
import {
queryStore,
@@ -29,6 +30,9 @@
scramble,
scrambleNames,
} from "./generic/utils.js";
import {
formatDurationTime
} from "./generic/units.js";
import Filters from "./generic/Filters.svelte";
/* Svelte 5 Props */
@@ -40,6 +44,7 @@
/* Const Init */
const {} = init();
const client = getContextClient();
const shortDuration = getContext("cc-config").jobList_hideShortRunningJobs; // Always configured
/* State Init*/
let filterComponent = $state(); // see why here: https://stackoverflow.com/questions/58287729/how-can-i-export-a-function-from-a-svelte-component-that-changes-a-value-in-the
@@ -48,21 +53,36 @@
let sorting = $state({ field: "totalJobs", direction: "desc" });
/* Derived Vars */
const fetchRunning = $derived(jobFilters.some(jf => jf?.state?.length == 1 && jf?.state?.includes("running")));
const numCols = $derived.by(() => {
let colbase = 6
if (fetchRunning) {
colbase += 2
}
return colbase
})
let stats = $derived(
queryStore({
client: client,
query: gql`
query($jobFilters: [JobFilter!]!) {
query($jobFilters: [JobFilter!]!, $fetchRunning: Boolean!) {
rows: jobsStatistics(filter: $jobFilters, groupBy: ${type}) {
id
name
totalJobs
shortJobs
totalCores @include(if: $fetchRunning)
totalAccs @include(if: $fetchRunning)
totalWalltime
totalCoreHours
totalAccHours
}
}`,
variables: { jobFilters },
variables: {
jobFilters,
fetchRunning
},
})
);
@@ -184,6 +204,60 @@
{/if}
</Button>
</th>
<th scope="col">
<span class="mr-1">
Short Jobs
<Icon id="shortjobs-info" style="cursor:help;" size="sm" name="info-circle"/>
</span>
<Tooltip target={`shortjobs-info`} placement="top">
Job duration less than {formatDurationTime(shortDuration)}
</Tooltip>
&#8239; <!-- Narrow Non-Breaking Space -->
<Button
color={sorting.field == "shortJobs" ? "primary" : "light"}
size="sm"
onclick={() => changeSorting("shortJobs")}
>
{#if sorting?.field == "shortJobs"}
<!-- Note on Icon-Name: Arrow-indicator always down, only numeric-indicator switches -->
<Icon name={`sort-numeric-${sorting?.direction == 'desc' ? 'down-alt' : 'down'}`} />
{:else}
<Icon name="three-dots-vertical" />
{/if}
</Button>
</th>
{#if fetchRunning}
<th scope="col">
Total Cores
<Button
color={sorting.field == "totalCores" ? "primary" : "light"}
size="sm"
onclick={() => changeSorting("totalCores")}
>
{#if sorting?.field == "totalJCores"}
<!-- Note on Icon-Name: Arrow-indicator always down, only numeric-indicator switches -->
<Icon name={`sort-numeric-${sorting?.direction == 'desc' ? 'down-alt' : 'down'}`} />
{:else}
<Icon name="three-dots-vertical" />
{/if}
</Button>
</th>
<th scope="col">
Total Accelerators
<Button
color={sorting.field == "totalAccs" ? "primary" : "light"}
size="sm"
onclick={() => changeSorting("totalAccs")}
>
{#if sorting?.field == "totalAccs"}
<!-- Note on Icon-Name: Arrow-indicator always down, only numeric-indicator switches -->
<Icon name={`sort-numeric-${sorting?.direction == 'desc' ? 'down-alt' : 'down'}`} />
{:else}
<Icon name="three-dots-vertical" />
{/if}
</Button>
</th>
{/if}
<th scope="col">
Total Walltime
<Button
@@ -231,11 +305,11 @@
<tbody>
{#if $stats.fetching}
<tr>
<td colspan="4" style="text-align: center;"><Spinner secondary /></td>
<td colspan={numCols} style="text-align: center;"><Spinner secondary /></td>
</tr>
{:else if $stats.error}
<tr>
<td colspan="4"
<td colspan={numCols}
><Card body color="danger" class="mb-3">{$stats.error.message}</Card
></td
>
@@ -266,13 +340,18 @@
>
{/if}
<td>{row.totalJobs}</td>
<td>{row.shortJobs}</td>
{#if fetchRunning}
<td>{row.totalCores}</td>
<td>{row.totalAccs}</td>
{/if}
<td>{row.totalWalltime}</td>
<td>{row.totalCoreHours}</td>
<td>{row.totalAccHours}</td>
</tr>
{:else}
<tr>
<td colspan="4"><i>No {type.toLowerCase()}s/jobs found</i></td>
<td colspan={numCols}><i>No {type.toLowerCase()}s/jobs found</i></td>
</tr>
{/each}
{/if}