mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-02-11 21:41:46 +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.
|
// AddJobCountGrouped augments existing statistics with additional job counts by category.
|
||||||
//
|
//
|
||||||
// This method enriches JobsStatistics returned by JobsStatsGrouped or JobCountGrouped
|
// 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:
|
// Parameters:
|
||||||
// - ctx: Context for security checks
|
// - ctx: Context for security checks
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { onMount } from "svelte";
|
import { getContext, onMount } from "svelte";
|
||||||
import {
|
import {
|
||||||
Row,
|
Row,
|
||||||
Col,
|
Col,
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
Spinner,
|
Spinner,
|
||||||
InputGroup,
|
InputGroup,
|
||||||
Input,
|
Input,
|
||||||
|
Tooltip
|
||||||
} from "@sveltestrap/sveltestrap";
|
} from "@sveltestrap/sveltestrap";
|
||||||
import {
|
import {
|
||||||
queryStore,
|
queryStore,
|
||||||
@@ -29,6 +30,9 @@
|
|||||||
scramble,
|
scramble,
|
||||||
scrambleNames,
|
scrambleNames,
|
||||||
} from "./generic/utils.js";
|
} from "./generic/utils.js";
|
||||||
|
import {
|
||||||
|
formatDurationTime
|
||||||
|
} from "./generic/units.js";
|
||||||
import Filters from "./generic/Filters.svelte";
|
import Filters from "./generic/Filters.svelte";
|
||||||
|
|
||||||
/* Svelte 5 Props */
|
/* Svelte 5 Props */
|
||||||
@@ -40,6 +44,7 @@
|
|||||||
/* Const Init */
|
/* Const Init */
|
||||||
const {} = init();
|
const {} = init();
|
||||||
const client = getContextClient();
|
const client = getContextClient();
|
||||||
|
const shortDuration = getContext("cc-config").jobList_hideShortRunningJobs; // Always configured
|
||||||
|
|
||||||
/* State Init*/
|
/* 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
|
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" });
|
let sorting = $state({ field: "totalJobs", direction: "desc" });
|
||||||
|
|
||||||
/* Derived Vars */
|
/* 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(
|
let stats = $derived(
|
||||||
queryStore({
|
queryStore({
|
||||||
client: client,
|
client: client,
|
||||||
query: gql`
|
query: gql`
|
||||||
query($jobFilters: [JobFilter!]!) {
|
query($jobFilters: [JobFilter!]!, $fetchRunning: Boolean!) {
|
||||||
rows: jobsStatistics(filter: $jobFilters, groupBy: ${type}) {
|
rows: jobsStatistics(filter: $jobFilters, groupBy: ${type}) {
|
||||||
id
|
id
|
||||||
name
|
name
|
||||||
totalJobs
|
totalJobs
|
||||||
|
shortJobs
|
||||||
|
totalCores @include(if: $fetchRunning)
|
||||||
|
totalAccs @include(if: $fetchRunning)
|
||||||
totalWalltime
|
totalWalltime
|
||||||
totalCoreHours
|
totalCoreHours
|
||||||
totalAccHours
|
totalAccHours
|
||||||
}
|
}
|
||||||
}`,
|
}`,
|
||||||
variables: { jobFilters },
|
variables: {
|
||||||
|
jobFilters,
|
||||||
|
fetchRunning
|
||||||
|
},
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -184,6 +204,60 @@
|
|||||||
{/if}
|
{/if}
|
||||||
</Button>
|
</Button>
|
||||||
</th>
|
</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">
|
<th scope="col">
|
||||||
Total Walltime
|
Total Walltime
|
||||||
<Button
|
<Button
|
||||||
@@ -231,11 +305,11 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
{#if $stats.fetching}
|
{#if $stats.fetching}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4" style="text-align: center;"><Spinner secondary /></td>
|
<td colspan={numCols} style="text-align: center;"><Spinner secondary /></td>
|
||||||
</tr>
|
</tr>
|
||||||
{:else if $stats.error}
|
{:else if $stats.error}
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="4"
|
<td colspan={numCols}
|
||||||
><Card body color="danger" class="mb-3">{$stats.error.message}</Card
|
><Card body color="danger" class="mb-3">{$stats.error.message}</Card
|
||||||
></td
|
></td
|
||||||
>
|
>
|
||||||
@@ -266,13 +340,18 @@
|
|||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<td>{row.totalJobs}</td>
|
<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.totalWalltime}</td>
|
||||||
<td>{row.totalCoreHours}</td>
|
<td>{row.totalCoreHours}</td>
|
||||||
<td>{row.totalAccHours}</td>
|
<td>{row.totalAccHours}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{:else}
|
{:else}
|
||||||
<tr>
|
<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>
|
</tr>
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
Reference in New Issue
Block a user