mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2025-07-01 11:13:50 +02:00
Migrate select components and adapt parents
This commit is contained in:
parent
6a6dca3fce
commit
1e039cb1bf
@ -196,7 +196,12 @@
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Sorting bind:sorting bind:isOpen={isSortingOpen}/>
|
<Sorting
|
||||||
|
bind:isOpen={isSortingOpen}
|
||||||
|
presetSorting={sorting}
|
||||||
|
applySorting={(newSort) =>
|
||||||
|
sorting = {...newSort}
|
||||||
|
}/>
|
||||||
|
|
||||||
<MetricSelection
|
<MetricSelection
|
||||||
bind:isOpen={isMetricsSelectionOpen}
|
bind:isOpen={isMetricsSelectionOpen}
|
||||||
|
@ -146,7 +146,14 @@
|
|||||||
</Col>
|
</Col>
|
||||||
<!-- Time Col -->
|
<!-- Time Col -->
|
||||||
<Col>
|
<Col>
|
||||||
<TimeSelection bind:from bind:to />
|
<TimeSelection
|
||||||
|
presetFrom={from}
|
||||||
|
presetTo={to}
|
||||||
|
applyTime={(newFrom, newTo) => {
|
||||||
|
from = newFrom;
|
||||||
|
to = newTo;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<!-- Concurrent Col -->
|
<!-- Concurrent Col -->
|
||||||
<Col class="mt-2 mt-lg-0">
|
<Col class="mt-2 mt-lg-0">
|
||||||
|
@ -697,7 +697,10 @@
|
|||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
<HistogramSelection
|
<HistogramSelection
|
||||||
bind:cluster
|
{cluster}
|
||||||
bind:selectedHistograms
|
|
||||||
bind:isOpen={isHistogramSelectionOpen}
|
bind:isOpen={isHistogramSelectionOpen}
|
||||||
|
presetSelectedHistograms={selectedHistograms}
|
||||||
|
applyChange={(newSelection) => {
|
||||||
|
selectedHistograms = [...newSelection];
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -56,7 +56,7 @@
|
|||||||
|
|
||||||
/* State Init */
|
/* State Init */
|
||||||
let to = $state(toPreset || new Date(Date.now()));
|
let to = $state(toPreset || new Date(Date.now()));
|
||||||
let from = $state(fromPreset || new Date(nowDate.setHours(nowDate.getHours() - 12)));
|
let from = $state(fromPreset || new Date(nowDate.setHours(nowDate.getHours() - 4)));
|
||||||
let selectedResolution = $state(resampleConfig ? resampleDefault : 0);
|
let selectedResolution = $state(resampleConfig ? resampleDefault : 0);
|
||||||
let hostnameFilter = $state("");
|
let hostnameFilter = $state("");
|
||||||
let pendingHostnameFilter = $state("");
|
let pendingHostnameFilter = $state("");
|
||||||
@ -147,7 +147,14 @@
|
|||||||
</Col>
|
</Col>
|
||||||
<!-- Range Col-->
|
<!-- Range Col-->
|
||||||
<Col>
|
<Col>
|
||||||
<TimeSelection bind:from bind:to />
|
<TimeSelection
|
||||||
|
presetFrom={from}
|
||||||
|
presetTo={to}
|
||||||
|
applyTime={(newFrom, newTo) => {
|
||||||
|
from = newFrom;
|
||||||
|
to = newTo;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
</Col>
|
</Col>
|
||||||
<!-- Overview Metric Col-->
|
<!-- Overview Metric Col-->
|
||||||
{#if displayNodeOverview}
|
{#if displayNodeOverview}
|
||||||
|
@ -62,6 +62,7 @@
|
|||||||
let isMetricsSelectionOpen = $state(false);
|
let isMetricsSelectionOpen = $state(false);
|
||||||
let sorting = $state({ field: "startTime", type: "col", order: "DESC" });
|
let sorting = $state({ field: "startTime", type: "col", order: "DESC" });
|
||||||
let selectedCluster = $state(filterPresets?.cluster ? filterPresets.cluster : null);
|
let selectedCluster = $state(filterPresets?.cluster ? filterPresets.cluster : null);
|
||||||
|
let selectedHistogramsBuffer = $state({ all: (ccconfig['user_view_histogramMetrics'] || []) })
|
||||||
let metrics = $state(filterPresets.cluster
|
let metrics = $state(filterPresets.cluster
|
||||||
? ccconfig[`plot_list_selectedMetrics:${filterPresets.cluster}`] ||
|
? ccconfig[`plot_list_selectedMetrics:${filterPresets.cluster}`] ||
|
||||||
ccconfig.plot_list_selectedMetrics
|
ccconfig.plot_list_selectedMetrics
|
||||||
@ -85,10 +86,7 @@
|
|||||||
// let matchedCompareJobs = $state(0);
|
// let matchedCompareJobs = $state(0);
|
||||||
|
|
||||||
/* Derived Vars */
|
/* Derived Vars */
|
||||||
let selectedHistograms = $derived(selectedCluster
|
let selectedHistograms = $derived(selectedCluster ? selectedHistogramsBuffer[selectedCluster] : selectedHistogramsBuffer['all']);
|
||||||
? ccconfig[`user_view_histogramMetrics:${selectedCluster}`] || ( ccconfig['user_view_histogramMetrics'] || [] )
|
|
||||||
: ccconfig['user_view_histogramMetrics'] || []);
|
|
||||||
|
|
||||||
let stats = $derived(
|
let stats = $derived(
|
||||||
queryStore({
|
queryStore({
|
||||||
client: client,
|
client: client,
|
||||||
@ -125,8 +123,21 @@
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/* Effect */
|
||||||
|
$effect(() => {
|
||||||
|
if (!selectedHistogramsBuffer[selectedCluster]) {
|
||||||
|
selectedHistogramsBuffer[selectedCluster] = ccconfig[`user_view_histogramMetrics:${selectedCluster}`];
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
/* On Mount */
|
/* On Mount */
|
||||||
onMount(() => filterComponent.updateFilters());
|
onMount(() => {
|
||||||
|
filterComponent.updateFilters();
|
||||||
|
// Why? -> `$derived(ccconfig[$cluster])` only loads array from last Backend-Query if $cluster changed reactively (without reload)
|
||||||
|
if (filterPresets?.cluster) {
|
||||||
|
selectedHistogramsBuffer[filterPresets.cluster] = ccconfig[`user_view_histogramMetrics:${filterPresets.cluster}`];
|
||||||
|
};
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- ROW1: Status-->
|
<!-- ROW1: Status-->
|
||||||
@ -363,7 +374,13 @@
|
|||||||
</Col>
|
</Col>
|
||||||
</Row>
|
</Row>
|
||||||
|
|
||||||
<Sorting bind:sorting bind:isOpen={isSortingOpen} />
|
<Sorting
|
||||||
|
bind:isOpen={isSortingOpen}
|
||||||
|
presetSorting={sorting}
|
||||||
|
applySorting={(newSort) =>
|
||||||
|
sorting = {...newSort}
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
|
||||||
<MetricSelection
|
<MetricSelection
|
||||||
bind:isOpen={isMetricsSelectionOpen}
|
bind:isOpen={isMetricsSelectionOpen}
|
||||||
@ -378,7 +395,10 @@
|
|||||||
/>
|
/>
|
||||||
|
|
||||||
<HistogramSelection
|
<HistogramSelection
|
||||||
bind:cluster={selectedCluster}
|
cluster={selectedCluster}
|
||||||
bind:selectedHistograms
|
|
||||||
bind:isOpen={isHistogramSelectionOpen}
|
bind:isOpen={isHistogramSelectionOpen}
|
||||||
|
presetSelectedHistograms={selectedHistograms}
|
||||||
|
applyChange={(newSelection) => {
|
||||||
|
selectedHistogramsBuffer[selectedCluster || 'all'] = [...newSelection];
|
||||||
|
}}
|
||||||
/>
|
/>
|
||||||
|
@ -20,16 +20,24 @@
|
|||||||
} from "@sveltestrap/sveltestrap";
|
} from "@sveltestrap/sveltestrap";
|
||||||
import { gql, getContextClient, mutationStore } from "@urql/svelte";
|
import { gql, getContextClient, mutationStore } from "@urql/svelte";
|
||||||
|
|
||||||
export let cluster;
|
/* Svelte 5 Props */
|
||||||
export let selectedHistograms;
|
let {
|
||||||
export let isOpen;
|
cluster,
|
||||||
|
isOpen = $bindable(),
|
||||||
|
presetSelectedHistograms,
|
||||||
|
applyChange
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
/* Const Init */
|
||||||
const client = getContextClient();
|
const client = getContextClient();
|
||||||
const initialized = getContext("initialized");
|
|
||||||
|
|
||||||
function loadHistoMetrics(isInitialized, thisCluster) {
|
/* Derived */
|
||||||
if (!isInitialized) return [];
|
let selectedHistograms = $derived(presetSelectedHistograms); // Non-Const Derived: Is settable
|
||||||
|
const availableMetrics = $derived(loadHistoMetrics(cluster));
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
function loadHistoMetrics(thisCluster) {
|
||||||
|
// isInit Check Removed: Parent Component has finished Init-Query: Globalmetrics available here.
|
||||||
if (!thisCluster) {
|
if (!thisCluster) {
|
||||||
return getContext("globalMetrics")
|
return getContext("globalMetrics")
|
||||||
.filter((gm) => gm?.footprint)
|
.filter((gm) => gm?.footprint)
|
||||||
@ -42,18 +50,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateConfigurationMutation = ({ name, value }) => {
|
|
||||||
return mutationStore({
|
|
||||||
client: client,
|
|
||||||
query: gql`
|
|
||||||
mutation ($name: String!, $value: String!) {
|
|
||||||
updateConfiguration(name: $name, value: $value)
|
|
||||||
}
|
|
||||||
`,
|
|
||||||
variables: { name, value },
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
function updateConfiguration(data) {
|
function updateConfiguration(data) {
|
||||||
updateConfigurationMutation({
|
updateConfigurationMutation({
|
||||||
name: data.name,
|
name: data.name,
|
||||||
@ -67,6 +63,7 @@
|
|||||||
|
|
||||||
function closeAndApply() {
|
function closeAndApply() {
|
||||||
isOpen = !isOpen;
|
isOpen = !isOpen;
|
||||||
|
applyChange(selectedHistograms)
|
||||||
updateConfiguration({
|
updateConfiguration({
|
||||||
name: cluster
|
name: cluster
|
||||||
? `user_view_histogramMetrics:${cluster}`
|
? `user_view_histogramMetrics:${cluster}`
|
||||||
@ -75,8 +72,18 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$: availableMetrics = loadHistoMetrics($initialized, cluster);
|
/* Mutation */
|
||||||
|
const updateConfigurationMutation = ({ name, value }) => {
|
||||||
|
return mutationStore({
|
||||||
|
client: client,
|
||||||
|
query: gql`
|
||||||
|
mutation ($name: String!, $value: String!) {
|
||||||
|
updateConfiguration(name: $name, value: $value)
|
||||||
|
}
|
||||||
|
`,
|
||||||
|
variables: { name, value },
|
||||||
|
});
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal {isOpen} toggle={() => (isOpen = !isOpen)}>
|
<Modal {isOpen} toggle={() => (isOpen = !isOpen)}>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getContext } from "svelte";
|
import { getContext, onMount } from "svelte";
|
||||||
import {
|
import {
|
||||||
Icon,
|
Icon,
|
||||||
Button,
|
Button,
|
||||||
@ -18,44 +18,73 @@
|
|||||||
ModalHeader,
|
ModalHeader,
|
||||||
ModalFooter,
|
ModalFooter,
|
||||||
} from "@sveltestrap/sveltestrap";
|
} from "@sveltestrap/sveltestrap";
|
||||||
import { getSortItems } from "../utils.js";
|
|
||||||
|
|
||||||
export let isOpen = false;
|
/* Svelte 5 Props */
|
||||||
export let sorting = { field: "startTime", type: "col", order: "DESC" };
|
let {
|
||||||
|
isOpen = $bindable(false),
|
||||||
let sortableColumns = [];
|
presetSorting = { field: "startTime", type: "col", order: "DESC" },
|
||||||
let activeColumnIdx;
|
applySorting
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
/* Const Init */
|
||||||
const initialized = getContext("initialized");
|
const initialized = getContext("initialized");
|
||||||
|
const globalMetrics = getContext("globalMetrics");
|
||||||
|
const fixedSortables = $state([
|
||||||
|
{ field: "startTime", type: "col", text: "Start Time (Default)", order: "DESC" },
|
||||||
|
{ field: "duration", type: "col", text: "Duration", order: "DESC" },
|
||||||
|
{ field: "numNodes", type: "col", text: "Number of Nodes", order: "DESC" },
|
||||||
|
{ field: "numHwthreads", type: "col", text: "Number of HWThreads", order: "DESC" },
|
||||||
|
{ field: "numAcc", type: "col", text: "Number of Accelerators", order: "DESC" },
|
||||||
|
{ field: "energy", type: "col", text: "Total Energy", order: "DESC" },
|
||||||
|
]);
|
||||||
|
|
||||||
function loadSortables(isInitialized) {
|
/* State Init */
|
||||||
if (!isInitialized) return;
|
let sorting = $state({...presetSorting})
|
||||||
sortableColumns = [
|
let activeColumnIdx = $state(0);
|
||||||
{ field: "startTime", type: "col", text: "Start Time", order: "DESC" },
|
let metricSortables = $state([]);
|
||||||
{ field: "duration", type: "col", text: "Duration", order: "DESC" },
|
|
||||||
{ field: "numNodes", type: "col", text: "Number of Nodes", order: "DESC" },
|
|
||||||
{ field: "numHwthreads", type: "col", text: "Number of HWThreads", order: "DESC" },
|
|
||||||
{ field: "numAcc", type: "col", text: "Number of Accelerators", order: "DESC" },
|
|
||||||
{ field: "energy", type: "col", text: "Total Energy", order: "DESC" },
|
|
||||||
...getSortItems()
|
|
||||||
]
|
|
||||||
}
|
|
||||||
|
|
||||||
function loadActiveIndex(isInitialized) {
|
/* Derived */
|
||||||
if (!isInitialized) return;
|
let sortableColumns = $derived([...fixedSortables, ...metricSortables]);
|
||||||
|
|
||||||
|
/* Effect */
|
||||||
|
$effect(() => {
|
||||||
|
if ($initialized) {
|
||||||
|
loadMetricSortables();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
function loadMetricSortables() {
|
||||||
|
metricSortables = globalMetrics.map((gm) => {
|
||||||
|
if (gm?.footprint) {
|
||||||
|
return {
|
||||||
|
field: gm.name + '_' + gm.footprint,
|
||||||
|
type: 'foot',
|
||||||
|
text: gm.name + ' (' + gm.footprint + ')',
|
||||||
|
order: 'DESC'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}).filter((r) => r != null)
|
||||||
|
};
|
||||||
|
|
||||||
|
function loadActiveIndex() {
|
||||||
activeColumnIdx = sortableColumns.findIndex(
|
activeColumnIdx = sortableColumns.findIndex(
|
||||||
(col) => col.field == sorting.field,
|
(col) => col.field == sorting.field,
|
||||||
);
|
);
|
||||||
sortableColumns[activeColumnIdx].order = sorting.order;
|
sortableColumns[activeColumnIdx].order = sorting.order;
|
||||||
}
|
}
|
||||||
|
|
||||||
$: loadSortables($initialized);
|
function resetSorting(sort) {
|
||||||
$: loadActiveIndex($initialized)
|
sorting = {...sort};
|
||||||
|
loadActiveIndex();
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Modal
|
<Modal
|
||||||
{isOpen}
|
{isOpen}
|
||||||
toggle={() => {
|
toggle={() => {
|
||||||
|
resetSorting(presetSorting);
|
||||||
isOpen = !isOpen;
|
isOpen = !isOpen;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
@ -66,7 +95,7 @@
|
|||||||
<ListGroupItem>
|
<ListGroupItem>
|
||||||
<button
|
<button
|
||||||
class="sort"
|
class="sort"
|
||||||
on:click={() => {
|
onclick={() => {
|
||||||
if (activeColumnIdx == i) {
|
if (activeColumnIdx == i) {
|
||||||
col.order = col.order == "DESC" ? "ASC" : "DESC";
|
col.order = col.order == "DESC" ? "ASC" : "DESC";
|
||||||
} else {
|
} else {
|
||||||
@ -96,11 +125,27 @@
|
|||||||
</ModalBody>
|
</ModalBody>
|
||||||
<ModalFooter>
|
<ModalFooter>
|
||||||
<Button
|
<Button
|
||||||
color="primary"
|
color="warning"
|
||||||
on:click={() => {
|
onclick={() => {
|
||||||
isOpen = false;
|
isOpen = false;
|
||||||
}}>Close</Button
|
resetSorting({ field: "startTime", type: "col", order: "DESC" });
|
||||||
|
applySorting(sorting);
|
||||||
|
}}>Reset</Button
|
||||||
>
|
>
|
||||||
|
<Button
|
||||||
|
color="primary"
|
||||||
|
onclick={() => {
|
||||||
|
applySorting(sorting);
|
||||||
|
isOpen = false;
|
||||||
|
}}>Close & Apply</Button
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
color="secondary"
|
||||||
|
onclick={() => {
|
||||||
|
resetSorting(presetSorting);
|
||||||
|
isOpen = false
|
||||||
|
}}>Cancel
|
||||||
|
</Button>
|
||||||
</ModalFooter>
|
</ModalFooter>
|
||||||
</Modal>
|
</Modal>
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
import {
|
import {
|
||||||
Icon,
|
Icon,
|
||||||
Input,
|
Input,
|
||||||
@ -20,78 +19,96 @@
|
|||||||
InputGroupText,
|
InputGroupText,
|
||||||
} from "@sveltestrap/sveltestrap";
|
} from "@sveltestrap/sveltestrap";
|
||||||
|
|
||||||
export let from;
|
/* Svelte 5 Props */
|
||||||
export let to;
|
let {
|
||||||
export let customEnabled = true;
|
presetFrom,
|
||||||
export let options = {
|
presetTo,
|
||||||
"Last quarter hour": 15 * 60,
|
customEnabled = true,
|
||||||
"Last half hour": 30 * 60,
|
options = {
|
||||||
"Last hour": 60 * 60,
|
"Last quarter hour": 15 * 60,
|
||||||
"Last 2hrs": 2 * 60 * 60,
|
"Last half hour": 30 * 60,
|
||||||
"Last 4hrs": 4 * 60 * 60,
|
"Last hour": 60 * 60,
|
||||||
"Last 12hrs": 12 * 60 * 60,
|
"Last 2hrs": 2 * 60 * 60,
|
||||||
"Last 24hrs": 24 * 60 * 60,
|
"Last 4hrs": 4 * 60 * 60,
|
||||||
|
"Last 12hrs": 12 * 60 * 60,
|
||||||
|
"Last 24hrs": 24 * 60 * 60,
|
||||||
|
},
|
||||||
|
applyTime
|
||||||
|
} = $props();
|
||||||
|
|
||||||
|
/* Const Init */
|
||||||
|
const defaultTo = new Date(Date.now());
|
||||||
|
const defaultFrom = new Date(defaultTo.setHours(defaultTo.getHours() - 4));
|
||||||
|
|
||||||
|
/* State Init */
|
||||||
|
let timeType = $state("range");
|
||||||
|
let pendingCustomFrom = $state(null);
|
||||||
|
let pendingCustomTo = $state(null);
|
||||||
|
|
||||||
|
/* Derived */
|
||||||
|
let timeRange = $derived.by(() => {
|
||||||
|
if (presetTo && presetFrom) {
|
||||||
|
return ((presetTo.getTime() - presetFrom.getTime()) / 1000)
|
||||||
|
} else {
|
||||||
|
return ((defaultTo.getTime() - defaultFrom.getTime()) / 1000)
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let unknownRange = $derived(!Object.values(options).includes(timeRange));
|
||||||
|
|
||||||
|
/* Functions */
|
||||||
|
function updateTimeRange() {
|
||||||
|
let now = Date.now();
|
||||||
|
let t = timeRange * 1000;
|
||||||
|
applyTime(new Date(now - t), new Date(now));
|
||||||
};
|
};
|
||||||
|
|
||||||
$: pendingFrom = from;
|
function updateTimeCustom() {
|
||||||
$: pendingTo = to;
|
if (pendingCustomFrom && pendingCustomTo) {
|
||||||
|
applyTime(new Date(pendingCustomFrom), new Date(pendingCustomTo));
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
let timeRange = // If both times set, return diff, else: display custom select
|
|
||||||
(to && from) ? ((to.getTime() - from.getTime()) / 1000) : -1;
|
|
||||||
|
|
||||||
function updateTimeRange() {
|
|
||||||
if (timeRange == -1) {
|
|
||||||
pendingFrom = null;
|
|
||||||
pendingTo = null;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
let now = Date.now(),
|
|
||||||
t = timeRange * 1000;
|
|
||||||
from = pendingFrom = new Date(now - t);
|
|
||||||
to = pendingTo = new Date(now);
|
|
||||||
dispatch("change", { from, to });
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateExplicitTimeRange(type, event) {
|
|
||||||
let d = new Date(Date.parse(event.target.value));
|
|
||||||
if (type == "from") pendingFrom = d;
|
|
||||||
else pendingTo = d;
|
|
||||||
|
|
||||||
if (pendingFrom != null && pendingTo != null) {
|
|
||||||
from = pendingFrom;
|
|
||||||
to = pendingTo;
|
|
||||||
dispatch("change", { from, to });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<InputGroup class="inline-from">
|
<InputGroup class="inline-from">
|
||||||
<InputGroupText><Icon name="clock-history" /></InputGroupText>
|
<InputGroupText><Icon name="clock-history" /></InputGroupText>
|
||||||
<InputGroupText>Range</InputGroupText>
|
{#if customEnabled}
|
||||||
<select
|
<Input
|
||||||
class="form-select"
|
type="select"
|
||||||
bind:value={timeRange}
|
style="max-width:fit-content;background-color:#f8f9fa;"
|
||||||
on:change={updateTimeRange}
|
bind:value={timeType}
|
||||||
>
|
>
|
||||||
{#if customEnabled}
|
<option value="range">Range</option>
|
||||||
<option value={-1}>Custom</option>
|
<option value="custom">Custom</option>
|
||||||
{/if}
|
</Input>
|
||||||
{#each Object.entries(options) as [name, seconds]}
|
{:else}
|
||||||
<option value={seconds}>{name}</option>
|
<InputGroupText>Range</InputGroupText>
|
||||||
{/each}
|
{/if}
|
||||||
</select>
|
|
||||||
{#if timeRange == -1}
|
{#if timeType === "range"}
|
||||||
|
<Input
|
||||||
|
type="select"
|
||||||
|
bind:value={timeRange}
|
||||||
|
onchange={updateTimeRange}
|
||||||
|
>
|
||||||
|
{#if unknownRange}
|
||||||
|
<option value={timeRange} disabled>Select new range...</option>
|
||||||
|
{/if}
|
||||||
|
{#each Object.entries(options) as [name, seconds]}
|
||||||
|
<option value={seconds}>{name}</option>
|
||||||
|
{/each}
|
||||||
|
</Input>
|
||||||
|
{:else}
|
||||||
<InputGroupText>from</InputGroupText>
|
<InputGroupText>from</InputGroupText>
|
||||||
<Input
|
<Input
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
on:change={(event) => updateExplicitTimeRange("from", event)}
|
bind:value={pendingCustomFrom}
|
||||||
|
onchange={updateTimeCustom}
|
||||||
></Input>
|
></Input>
|
||||||
<InputGroupText>to</InputGroupText>
|
<InputGroupText>to</InputGroupText>
|
||||||
<Input
|
<Input
|
||||||
type="datetime-local"
|
type="datetime-local"
|
||||||
on:change={(event) => updateExplicitTimeRange("to", event)}
|
bind:value={pendingCustomTo}
|
||||||
|
onchange={updateTimeCustom}
|
||||||
></Input>
|
></Input>
|
||||||
{/if}
|
{/if}
|
||||||
</InputGroup>
|
</InputGroup>
|
||||||
|
@ -388,24 +388,6 @@ export function findJobFootprintThresholds(job, stat, metricConfig) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getSortItems() {
|
|
||||||
//console.time('sort')
|
|
||||||
const globalMetrics = getContext("globalMetrics")
|
|
||||||
const result = globalMetrics.map((gm) => {
|
|
||||||
if (gm?.footprint) {
|
|
||||||
return {
|
|
||||||
field: gm.name + '_' + gm.footprint,
|
|
||||||
type: 'foot',
|
|
||||||
text: gm.name + ' (' + gm.footprint + ')',
|
|
||||||
order: 'DESC'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}).filter((r) => r != null)
|
|
||||||
//console.timeEnd('sort')
|
|
||||||
return [...result];
|
|
||||||
};
|
|
||||||
|
|
||||||
function getMetricConfigDeep(metric, cluster, subCluster) {
|
function getMetricConfigDeep(metric, cluster, subCluster) {
|
||||||
const clusters = getContext("clusters");
|
const clusters = getContext("clusters");
|
||||||
if (cluster != null) {
|
if (cluster != null) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user