mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-02-11 13:31:45 +01:00
add shortjobs and resource sums to project and user lists
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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>
|
||||
  <!-- 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}
|
||||
|
||||
Reference in New Issue
Block a user