mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-10-03 13:04:32 +02:00
Migrate user list and analysis view
This commit is contained in:
@@ -31,10 +31,8 @@
|
||||
} from "./generic/utils.js";
|
||||
import Filters from "./generic/Filters.svelte";
|
||||
|
||||
const {} = init();
|
||||
|
||||
export let type;
|
||||
export let filterPresets;
|
||||
/* Svelte 5 Props */
|
||||
let { type, filterPresets } = $props();
|
||||
|
||||
// By default, look at the jobs of the last 30 days:
|
||||
if (filterPresets?.startTime == null) {
|
||||
@@ -51,35 +49,38 @@
|
||||
"Invalid list type provided!",
|
||||
);
|
||||
|
||||
let filterComponent; // 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 jobFilters = [];
|
||||
let nameFilter = "";
|
||||
let sorting = { field: "totalJobs", direction: "down" };
|
||||
|
||||
/* Const Init */
|
||||
const {} = init();
|
||||
const client = getContextClient();
|
||||
$: stats = queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query($jobFilters: [JobFilter!]!) {
|
||||
rows: jobsStatistics(filter: $jobFilters, groupBy: ${type}) {
|
||||
id
|
||||
name
|
||||
totalJobs
|
||||
totalWalltime
|
||||
totalCoreHours
|
||||
totalAccHours
|
||||
}
|
||||
}`,
|
||||
variables: { jobFilters },
|
||||
});
|
||||
|
||||
function changeSorting(event, field) {
|
||||
let target = event.target;
|
||||
while (target.tagName != "BUTTON") target = target.parentElement;
|
||||
/* 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 jobFilters = $state([]);
|
||||
let nameFilter = $state("");
|
||||
let sorting = $state({ field: "totalJobs", direction: "down" });
|
||||
|
||||
let direction = target.children[0].className.includes("up") ? "down" : "up";
|
||||
target.children[0].className = `bi-sort-numeric-${direction}`;
|
||||
sorting = { field, direction };
|
||||
/* Derived Vars */
|
||||
let stats = $derived(
|
||||
queryStore({
|
||||
client: client,
|
||||
query: gql`
|
||||
query($jobFilters: [JobFilter!]!) {
|
||||
rows: jobsStatistics(filter: $jobFilters, groupBy: ${type}) {
|
||||
id
|
||||
name
|
||||
totalJobs
|
||||
totalWalltime
|
||||
totalCoreHours
|
||||
totalAccHours
|
||||
}
|
||||
}`,
|
||||
variables: { jobFilters },
|
||||
})
|
||||
);
|
||||
|
||||
/* Functions */
|
||||
function changeSorting(field) {
|
||||
sorting = { field, direction: sorting?.direction == "down" ? "up" : "down" };
|
||||
}
|
||||
|
||||
function sort(stats, sorting, nameFilter) {
|
||||
@@ -87,10 +88,10 @@
|
||||
? (a, b) => b.id.localeCompare(a.id)
|
||||
: (a, b) => a.id.localeCompare(b.id)
|
||||
|
||||
// "-50": Forces empty strings to the end of the list
|
||||
// Force empty or undefined strings to the end of the list
|
||||
const nameCmp = sorting.direction == "up"
|
||||
? (a, b) => (a.name == '') ? -50 : b.name.localeCompare(a.name)
|
||||
: (a, b) => (b.name == '') ? -50 : a.name.localeCompare(b.name)
|
||||
? (a, b) => !a?.name ? 1 : (!b?.name ? -1 : (b.name.localeCompare(a.name)))
|
||||
: (a, b) => !a?.name ? 1 : (!b?.name ? -1 : (a.name.localeCompare(b.name)))
|
||||
|
||||
const intCmp = sorting.direction == "up"
|
||||
? (a, b) => a[sorting.field] - b[sorting.field]
|
||||
@@ -105,6 +106,7 @@
|
||||
}
|
||||
}
|
||||
|
||||
/* On Mount */
|
||||
onMount(() => filterComponent.updateFilters());
|
||||
</script>
|
||||
|
||||
@@ -129,7 +131,7 @@
|
||||
{filterPresets}
|
||||
startTimeQuickSelect={true}
|
||||
menuText="Only {type.toLowerCase()}s with jobs that match the filters will show up"
|
||||
on:update-filters={({ detail }) => {
|
||||
applyFilters={(detail) => {
|
||||
jobFilters = detail.filters;
|
||||
}}
|
||||
/>
|
||||
@@ -147,9 +149,14 @@
|
||||
<Button
|
||||
color={sorting.field == "id" ? "primary" : "light"}
|
||||
size="sm"
|
||||
on:click={(e) => changeSorting(e, "id")}
|
||||
onclick={() => changeSorting("id")}
|
||||
>
|
||||
<Icon name="sort-numeric-down" />
|
||||
{#if sorting?.field == "id"}
|
||||
<!-- Note on Icon-Name: Arrow-indicator always down, only alpha-indicator switches -->
|
||||
<Icon name={`sort-alpha-${sorting?.direction == 'down' ? 'down' : 'down-alt'}`} />
|
||||
{:else}
|
||||
<Icon name="three-dots-vertical" />
|
||||
{/if}
|
||||
</Button>
|
||||
</th>
|
||||
{#if type == "USER"}
|
||||
@@ -158,9 +165,13 @@
|
||||
<Button
|
||||
color={sorting.field == "name" ? "primary" : "light"}
|
||||
size="sm"
|
||||
on:click={(e) => changeSorting(e, "name")}
|
||||
onclick={() => changeSorting("name")}
|
||||
>
|
||||
<Icon name="sort-numeric-down" />
|
||||
{#if sorting?.field == "name"}
|
||||
<Icon name={`sort-alpha-${sorting?.direction == 'down' ? 'down' : 'down-alt'}`} />
|
||||
{:else}
|
||||
<Icon name="three-dots-vertical" />
|
||||
{/if}
|
||||
</Button>
|
||||
</th>
|
||||
{/if}
|
||||
@@ -169,9 +180,14 @@
|
||||
<Button
|
||||
color={sorting.field == "totalJobs" ? "primary" : "light"}
|
||||
size="sm"
|
||||
on:click={(e) => changeSorting(e, "totalJobs")}
|
||||
onclick={() => changeSorting("totalJobs")}
|
||||
>
|
||||
<Icon name="sort-numeric-down" />
|
||||
{#if sorting?.field == "totalJobs"}
|
||||
<!-- Note on Icon-Name: Arrow-indicator always down, only numeric-indicator switches -->
|
||||
<Icon name={`sort-numeric-${sorting?.direction == 'down' ? 'down-alt' : 'down'}`} />
|
||||
{:else}
|
||||
<Icon name="three-dots-vertical" />
|
||||
{/if}
|
||||
</Button>
|
||||
</th>
|
||||
<th scope="col">
|
||||
@@ -179,9 +195,13 @@
|
||||
<Button
|
||||
color={sorting.field == "totalWalltime" ? "primary" : "light"}
|
||||
size="sm"
|
||||
on:click={(e) => changeSorting(e, "totalWalltime")}
|
||||
onclick={() => changeSorting("totalWalltime")}
|
||||
>
|
||||
<Icon name="sort-numeric-down" />
|
||||
{#if sorting?.field == "totalWalltime"}
|
||||
<Icon name={`sort-numeric-${sorting?.direction == 'down' ? 'down-alt' : 'down'}`} />
|
||||
{:else}
|
||||
<Icon name="three-dots-vertical" />
|
||||
{/if}
|
||||
</Button>
|
||||
</th>
|
||||
<th scope="col">
|
||||
@@ -189,9 +209,13 @@
|
||||
<Button
|
||||
color={sorting.field == "totalCoreHours" ? "primary" : "light"}
|
||||
size="sm"
|
||||
on:click={(e) => changeSorting(e, "totalCoreHours")}
|
||||
onclick={() => changeSorting("totalCoreHours")}
|
||||
>
|
||||
<Icon name="sort-numeric-down" />
|
||||
{#if sorting?.field == "totalCoreHours"}
|
||||
<Icon name={`sort-numeric-${sorting?.direction == 'down' ? 'down-alt' : 'down'}`} />
|
||||
{:else}
|
||||
<Icon name="three-dots-vertical" />
|
||||
{/if}
|
||||
</Button>
|
||||
</th>
|
||||
<th scope="col">
|
||||
@@ -199,9 +223,13 @@
|
||||
<Button
|
||||
color={sorting.field == "totalAccHours" ? "primary" : "light"}
|
||||
size="sm"
|
||||
on:click={(e) => changeSorting(e, "totalAccHours")}
|
||||
onclick={() => changeSorting("totalAccHours")}
|
||||
>
|
||||
<Icon name="sort-numeric-down" />
|
||||
{#if sorting?.field == "totalAccHours"}
|
||||
<Icon name={`sort-numeric-${sorting?.direction == 'down' ? 'down-alt' : 'down'}`} />
|
||||
{:else}
|
||||
<Icon name="three-dots-vertical" />
|
||||
{/if}
|
||||
</Button>
|
||||
</th>
|
||||
</tr>
|
||||
|
Reference in New Issue
Block a user