Remove refresh and textfilter from compareView, force id filters only on compare

This commit is contained in:
Christoph Kluge 2025-05-09 14:36:54 +02:00
parent 9ebc49dd1c
commit f210a5f508
3 changed files with 88 additions and 71 deletions

View File

@ -117,28 +117,27 @@
/> />
</Col> </Col>
<Col lg="2" class="mb-2 mb-lg-0"> <Col lg="2" class="mb-2 mb-lg-0">
<TextFilter {#if !showCompare}
{presetProject} <TextFilter
bind:authlevel {presetProject}
bind:roles bind:authlevel
on:set-filter={({ detail }) => filterComponent.updateFilters(detail)} bind:roles
/> on:set-filter={({ detail }) => filterComponent.updateFilters(detail)}
/>
{/if}
</Col> </Col>
<Col lg="2" class="mb-1 mb-lg-0"> <Col lg="2" class="mb-1 mb-lg-0">
<Refresher on:refresh={() => { {#if !showCompare}
if (showCompare) { <Refresher on:refresh={() => {
jobCompare.refreshJobs() jobList.refreshJobs()
jobCompare.refreshAllMetrics() jobList.refreshAllMetrics()
} else { }} />
jobList.refreshJobs() {/if}
jobList.refreshAllMetrics()
}
}} />
</Col> </Col>
<Col lg="2" class="mb-2 mb-lg-0"> <Col lg="2" class="mb-2 mb-lg-0">
<ButtonGroup class="w-100"> <ButtonGroup class="w-100">
<Button color="primary" disabled={matchedListJobs >= 500 && !(selectedJobs.length != 0)} on:click={() => { <Button color="primary" disabled={matchedListJobs >= 500 && !(selectedJobs.length != 0)} on:click={() => {
if (selectedJobs.length != 0) filterComponent.updateFilters({dbId: selectedJobs}) if (selectedJobs.length != 0) filterComponent.updateFilters({dbId: selectedJobs}, true)
showCompare = !showCompare showCompare = !showCompare
}} > }} >
{showCompare ? 'Return to List' : {showCompare ? 'Return to List' :

View File

@ -59,6 +59,39 @@
contains: " Contains", contains: " Contains",
} }
const filterReset = {
projectMatch: "contains",
userMatch: "contains",
jobIdMatch: "eq",
nodeMatch: "eq",
cluster: null,
partition: null,
states: allJobStates,
startTime: { from: null, to: null, range: ""},
tags: [],
duration: {
lessThan: null,
moreThan: null,
from: null,
to: null,
},
dbId: [],
jobId: "",
arrayJobId: null,
user: "",
project: "",
jobName: "",
node: null,
energy: { from: null, to: null },
numNodes: { from: null, to: null },
numHWThreads: { from: null, to: null },
numAccelerators: { from: null, to: null },
stats: [],
};
let filters = { let filters = {
projectMatch: filterPresets.projectMatch || "contains", projectMatch: filterPresets.projectMatch || "contains",
userMatch: filterPresets.userMatch || "contains", userMatch: filterPresets.userMatch || "contains",
@ -108,10 +141,17 @@
isAccsModified = false; isAccsModified = false;
// Can be called from the outside to trigger a 'update' event from this component. // Can be called from the outside to trigger a 'update' event from this component.
export function updateFilters(additionalFilters = null) { // 'force' option empties existing filters and then applies only 'additionalFilters'
if (additionalFilters != null) export function updateFilters(additionalFilters = null, force = false) {
// Empty Current Filter For Force
if (additionalFilters != null && force) {
filters = {...filterReset}
}
// Add Additional Filters
if (additionalFilters != null) {
for (let key in additionalFilters) filters[key] = additionalFilters[key]; for (let key in additionalFilters) filters[key] = additionalFilters[key];
}
// Construct New Filter
let items = []; let items = [];
if (filters.cluster) items.push({ cluster: { eq: filters.cluster } }); if (filters.cluster) items.push({ cluster: { eq: filters.cluster } });
if (filters.node) items.push({ node: { [filters.nodeMatch]: filters.node } }); if (filters.node) items.push({ node: { [filters.nodeMatch]: filters.node } });
@ -185,6 +225,7 @@
function changeURL() { function changeURL() {
const dateToUnixEpoch = (rfc3339) => Math.floor(Date.parse(rfc3339) / 1000); const dateToUnixEpoch = (rfc3339) => Math.floor(Date.parse(rfc3339) / 1000);
let opts = []; let opts = [];
if (filters.cluster) opts.push(`cluster=${filters.cluster}`); if (filters.cluster) opts.push(`cluster=${filters.cluster}`);
if (filters.node) opts.push(`node=${filters.node}`); if (filters.node) opts.push(`node=${filters.node}`);
if (filters.node && filters.nodeMatch != "eq") // "eq" is default-case if (filters.node && filters.nodeMatch != "eq") // "eq" is default-case
@ -245,8 +286,8 @@
for (let stat of filters.stats) { for (let stat of filters.stats) {
opts.push(`stat=${stat.field}-${stat.from}-${stat.to}`); opts.push(`stat=${stat.field}-${stat.from}-${stat.to}`);
} }
if (opts.length == 0 && window.location.search.length <= 1) return; if (opts.length == 0 && window.location.search.length <= 1) return;
let newurl = `${window.location.pathname}?${opts.join("&")}`; let newurl = `${window.location.pathname}?${opts.join("&")}`;
window.history.replaceState(null, "", newurl); window.history.replaceState(null, "", newurl);
} }

View File

@ -1,5 +1,5 @@
<!-- <!--
@component jobCompare component; compares jobs according to set filters @component jobCompare component; compares jobs according to set filters or job selection
Properties: Properties:
- `sorting Object?`: Currently active sorting [Default: {field: "startTime", type: "col", order: "DESC"}] - `sorting Object?`: Currently active sorting [Default: {field: "startTime", type: "col", order: "DESC"}]
@ -8,8 +8,6 @@
- `showFootprint Bool`: If to display the jobFootprint component - `showFootprint Bool`: If to display the jobFootprint component
Functions: Functions:
- `refreshJobs()`: Load jobs data with unchanged parameters and 'network-only' keyword
- `refreshAllMetrics()`: Trigger downstream refresh of all running jobs' metric data
- `queryJobs(filters?: [JobFilter])`: Load jobs data with new filters, starts from page 1 - `queryJobs(filters?: [JobFilter])`: Load jobs data with new filters, starts from page 1
--> -->
@ -30,15 +28,11 @@
// initialized = getContext("initialized"), // initialized = getContext("initialized"),
globalMetrics = getContext("globalMetrics"); globalMetrics = getContext("globalMetrics");
const equalsCheck = (a, b) => {
return JSON.stringify(a) === JSON.stringify(b);
}
export let matchedCompareJobs = 0; export let matchedCompareJobs = 0;
export let filterBuffer = [];
export let metrics = ccconfig.plot_list_selectedMetrics; export let metrics = ccconfig.plot_list_selectedMetrics;
export let filterBuffer = [];
let filter = [...filterBuffer]; let filter = [...filterBuffer] || [];
let comparePlotData = {}; let comparePlotData = {};
let jobIds = []; let jobIds = [];
let jobClusters = []; let jobClusters = [];
@ -83,6 +77,7 @@
}); });
$: matchedCompareJobs = $compareData.data != null ? $compareData.data.jobsMetricStats.length : -1; $: matchedCompareJobs = $compareData.data != null ? $compareData.data.jobsMetricStats.length : -1;
$: if ($compareData.data != null) { $: if ($compareData.data != null) {
jobIds = []; jobIds = [];
jobClusters = []; jobClusters = [];
@ -91,24 +86,6 @@
} }
/* FUNCTIONS */ /* FUNCTIONS */
// Force refresh list with existing unchanged variables (== usually would not trigger reactivity)
export function refreshJobs() {
compareData = queryStore({
client: client,
query: compareQuery,
variables: { filter, metrics },
requestPolicy: "network-only",
});
}
export function refreshAllMetrics() {
// Refresh Job Metrics (Downstream will only query for running jobs)
triggerMetricRefresh = true
setTimeout(function () {
triggerMetricRefresh = false;
}, 100);
}
// (Re-)query and optionally set new filters; Query will be started reactively. // (Re-)query and optionally set new filters; Query will be started reactively.
export function queryJobs(filters) { export function queryJobs(filters) {
if (filters != null) { if (filters != null) {
@ -133,31 +110,31 @@
// Iterate jobs if exists // Iterate jobs if exists
if (jobs) { if (jobs) {
let plotIndex = 0 let plotIndex = 0
jobs.forEach((j) => { jobs.forEach((j) => {
// Collect JobIDs & Clusters for X-Ticks and Legend // Collect JobIDs & Clusters for X-Ticks and Legend
jobIds.push(j.jobId) jobIds.push(j.jobId)
jobClusters.push(`${j.cluster} ${j.subCluster}`) jobClusters.push(`${j.cluster} ${j.subCluster}`)
// Resources // Resources
comparePlotData['resources'].data[0].push(plotIndex) comparePlotData['resources'].data[0].push(plotIndex)
comparePlotData['resources'].data[1].push(j.startTime) comparePlotData['resources'].data[1].push(j.startTime)
comparePlotData['resources'].data[2].push(j.duration) comparePlotData['resources'].data[2].push(j.duration)
comparePlotData['resources'].data[3].push(j.numNodes) comparePlotData['resources'].data[3].push(j.numNodes)
comparePlotData['resources'].data[4].push(j?.numHWThreads?j.numHWThreads:0) comparePlotData['resources'].data[4].push(j?.numHWThreads?j.numHWThreads:0)
comparePlotData['resources'].data[5].push(j?.numAccelerators?j.numAccelerators:0) comparePlotData['resources'].data[5].push(j?.numAccelerators?j.numAccelerators:0)
// Metrics // Metrics
for (let s of j.stats) { for (let s of j.stats) {
comparePlotData[s.name].data[0].push(plotIndex) comparePlotData[s.name].data[0].push(plotIndex)
comparePlotData[s.name].data[1].push(j.startTime) comparePlotData[s.name].data[1].push(j.startTime)
comparePlotData[s.name].data[2].push(j.duration) comparePlotData[s.name].data[2].push(j.duration)
comparePlotData[s.name].data[3].push(s.data.min) comparePlotData[s.name].data[3].push(s.data.min)
comparePlotData[s.name].data[4].push(s.data.avg) comparePlotData[s.name].data[4].push(s.data.avg)
comparePlotData[s.name].data[5].push(s.data.max) comparePlotData[s.name].data[5].push(s.data.max)
} }
plotIndex++ plotIndex++
}) })
} }
} }
// Adapt for Persisting Job Selections in DB later down the line // Adapt for Persisting Job Selections in DB later down the line
// const updateConfigurationMutation = ({ name, value }) => { // const updateConfigurationMutation = ({ name, value }) => {