From faacf3f3432f1b10a38a271d91e1c5fc42ba7e50 Mon Sep 17 00:00:00 2001 From: Christoph Kluge Date: Thu, 15 Jan 2026 18:17:45 +0100 Subject: [PATCH] svelte state_referenced_locally warning fixes - change to derived where possible - suppress warning elsewhere - discussion here: sveltejs/svelte/issues/17289 --- web/frontend/src/Analysis.root.svelte | 3 ++ web/frontend/src/Header.svelte | 12 ++++++++ web/frontend/src/Job.root.svelte | 1 + web/frontend/src/Jobs.root.svelte | 10 ++++--- web/frontend/src/List.root.svelte | 6 ---- web/frontend/src/Node.root.svelte | 12 ++++---- web/frontend/src/Systems.root.svelte | 4 ++- web/frontend/src/Tags.root.svelte | 1 + web/frontend/src/User.root.svelte | 22 +++++++-------- .../src/analysis/PlotSelection.svelte | 6 ++-- .../src/config/user/PlotColorScheme.svelte | 4 +-- web/frontend/src/generic/Filters.svelte | 1 + web/frontend/src/generic/JobCompare.svelte | 2 +- web/frontend/src/generic/JobList.svelte | 2 +- .../src/generic/filters/Cluster.svelte | 6 ++-- .../src/generic/filters/Duration.svelte | 13 ++++----- .../src/generic/filters/Energy.svelte | 4 +-- .../src/generic/filters/JobStates.svelte | 8 +++--- .../src/generic/filters/Resources.svelte | 21 +++++++------- .../src/generic/filters/StartTime.svelte | 9 +++--- web/frontend/src/generic/filters/Tags.svelte | 5 +++- .../src/generic/helper/Refresher.svelte | 6 ++-- .../src/generic/helper/TagManagement.svelte | 8 +++--- .../src/generic/helper/TextFilter.svelte | 6 ++-- .../src/generic/joblist/JobListRow.svelte | 15 ++++++---- .../src/generic/plots/Comparogram.svelte | 9 ++++++ .../src/generic/plots/DoubleMetricPlot.svelte | 2 +- .../src/generic/plots/MetricPlot.svelte | 4 +-- web/frontend/src/generic/plots/Pie.svelte | 1 + .../src/generic/plots/RooflineHeatmap.svelte | 7 ++--- web/frontend/src/generic/plots/Stacked.svelte | 28 +++++++++---------- .../generic/select/DoubleRangeSlider.svelte | 12 ++++---- .../src/generic/select/SortSelection.svelte | 2 +- web/frontend/src/job/Metric.svelte | 5 ++-- .../src/job/statstab/StatsTable.svelte | 4 +++ .../status/dashdetails/StatisticsDash.svelte | 2 +- .../src/status/dashdetails/StatusDash.svelte | 2 +- .../src/status/dashdetails/UsageDash.svelte | 2 +- web/frontend/src/systems/NodeList.svelte | 6 ++-- .../src/systems/nodelist/NodeInfo.svelte | 8 +++--- .../src/systems/nodelist/NodeListRow.svelte | 13 +++++---- 41 files changed, 167 insertions(+), 127 deletions(-) diff --git a/web/frontend/src/Analysis.root.svelte b/web/frontend/src/Analysis.root.svelte index 6c5d8507..f8ca1f3b 100644 --- a/web/frontend/src/Analysis.root.svelte +++ b/web/frontend/src/Analysis.root.svelte @@ -43,11 +43,14 @@ } = $props(); // By default, look at the jobs of the last 6 hours: + // svelte-ignore state_referenced_locally if (filterPresets?.startTime == null) { + // svelte-ignore state_referenced_locally if (filterPresets == null) filterPresets = {}; let now = new Date(Date.now()); let hourAgo = new Date(now); hourAgo.setHours(hourAgo.getHours() - 6); + // svelte-ignore state_referenced_locally filterPresets.startTime = { from: hourAgo.toISOString(), to: now.toISOString(), diff --git a/web/frontend/src/Header.svelte b/web/frontend/src/Header.svelte index ea818c62..f582ae7f 100644 --- a/web/frontend/src/Header.svelte +++ b/web/frontend/src/Header.svelte @@ -53,7 +53,9 @@ const views = [ { title: "My Jobs", + // svelte-ignore state_referenced_locally requiredRole: roles.user, + // svelte-ignore state_referenced_locally href: `/monitoring/user/${username}`, icon: "bar-chart-line", perCluster: false, @@ -61,7 +63,9 @@ menu: "none", }, { + // svelte-ignore state_referenced_locally title: jobsTitle.get(authlevel), + // svelte-ignore state_referenced_locally requiredRole: roles.user, href: `/monitoring/jobs/`, icon: "card-list", @@ -71,6 +75,7 @@ }, { title: "Tags", + // svelte-ignore state_referenced_locally requiredRole: roles.user, href: "/monitoring/tags/", icon: "tags", @@ -79,7 +84,9 @@ menu: "Jobs", }, { + // svelte-ignore state_referenced_locally title: usersTitle.get(authlevel), + // svelte-ignore state_referenced_locally requiredRole: roles.manager, href: "/monitoring/users/", icon: "people", @@ -88,7 +95,9 @@ menu: "Groups", }, { + // svelte-ignore state_referenced_locally title: projectsTitle.get(authlevel), + // svelte-ignore state_referenced_locally requiredRole: roles.manager, href: "/monitoring/projects/", icon: "journals", @@ -98,6 +107,7 @@ }, { title: "Nodes", + // svelte-ignore state_referenced_locally requiredRole: roles.support, href: "/monitoring/systems/", icon: "hdd-rack", @@ -107,6 +117,7 @@ }, { title: "Analysis", + // svelte-ignore state_referenced_locally requiredRole: roles.support, href: "/monitoring/analysis/", icon: "graph-up", @@ -116,6 +127,7 @@ }, { title: "Status", + // svelte-ignore state_referenced_locally requiredRole: roles.admin, href: "/monitoring/status/", icon: "clipboard-data", diff --git a/web/frontend/src/Job.root.svelte b/web/frontend/src/Job.root.svelte index 4ee19571..2ff7ab62 100644 --- a/web/frontend/src/Job.root.svelte +++ b/web/frontend/src/Job.root.svelte @@ -52,6 +52,7 @@ /* Const Init */ // Important: init() needs to be first const declaration or contextclient will not be initialized before "const client = ..." + // svelte-ignore state_referenced_locally const { query: initq } = init(` job(id: "${dbid}") { id, jobId, user, project, cluster, startTime, diff --git a/web/frontend/src/Jobs.root.svelte b/web/frontend/src/Jobs.root.svelte index 0198b236..705ce133 100644 --- a/web/frontend/src/Jobs.root.svelte +++ b/web/frontend/src/Jobs.root.svelte @@ -37,7 +37,6 @@ /* Const Init */ const { query: initq } = init(); const ccconfig = getContext("cc-config"); - const presetProject = filterPresets?.project ? filterPresets.project : "" /* 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 @@ -51,13 +50,16 @@ let showCompare = $state(false); let isMetricsSelectionOpen = $state(false); let sorting = $state({ field: "startTime", type: "col", order: "DESC" }); - let selectedCluster = $state(filterPresets?.cluster ? filterPresets.cluster : null); - let metrics = $state(filterPresets.cluster + + /* Derived */ + const presetProject = $derived(filterPresets?.project ? filterPresets.project : ""); + let selectedCluster = $derived(filterPresets?.cluster ? filterPresets.cluster : null); + let metrics = $derived(filterPresets.cluster ? ccconfig[`metricConfig_jobListMetrics:${filterPresets.cluster}`] || ccconfig.metricConfig_jobListMetrics : ccconfig.metricConfig_jobListMetrics ); - let showFootprint = $state(filterPresets.cluster + let showFootprint = $derived(filterPresets.cluster ? !!ccconfig[`jobList_showFootprint:${filterPresets.cluster}`] : !!ccconfig.jobList_showFootprint ); diff --git a/web/frontend/src/List.root.svelte b/web/frontend/src/List.root.svelte index ec8f654d..0163cbce 100644 --- a/web/frontend/src/List.root.svelte +++ b/web/frontend/src/List.root.svelte @@ -37,12 +37,6 @@ filterPresets } = $props(); - /* Validate Type */ - console.assert( - type == "USER" || type == "PROJECT", - "Invalid list type provided!", - ); - /* Const Init */ const {} = init(); const client = getContextClient(); diff --git a/web/frontend/src/Node.root.svelte b/web/frontend/src/Node.root.svelte index cf119026..c875f2b2 100644 --- a/web/frontend/src/Node.root.svelte +++ b/web/frontend/src/Node.root.svelte @@ -54,11 +54,6 @@ const nowEpoch = Date.now(); const paging = { itemsPerPage: 50, page: 1 }; const sorting = { field: "startTime", type: "col", order: "DESC" }; - const filter = [ - { cluster: { eq: cluster } }, - { node: { contains: hostname } }, - { state: ["running"] }, - ]; const client = getContextClient(); const nodeMetricsQuery = gql` query ($cluster: String!, $nodes: [String!], $from: Time!, $to: Time!) { @@ -111,11 +106,18 @@ } /* State Init */ + // svelte-ignore state_referenced_locally let from = $state(presetFrom ? presetFrom : new Date(nowEpoch - (4 * 3600 * 1000))); + // svelte-ignore state_referenced_locally let to = $state(presetTo ? presetTo : new Date(nowEpoch)); let systemUnits = $state({}); /* Derived */ + const filter = $derived([ + { cluster: { eq: cluster } }, + { node: { contains: hostname } }, + { state: ["running"] }, + ]); const nodeMetricsData = $derived(queryStore({ client: client, query: nodeMetricsQuery, diff --git a/web/frontend/src/Systems.root.svelte b/web/frontend/src/Systems.root.svelte index d81a64cd..5c62f390 100644 --- a/web/frontend/src/Systems.root.svelte +++ b/web/frontend/src/Systems.root.svelte @@ -51,7 +51,6 @@ /* Const Init */ const { query: initq } = init(); const client = getContextClient(); - const displayNodeOverview = (displayType === 'OVERVIEW'); const ccconfig = getContext("cc-config"); const initialized = getContext("initialized"); const globalMetrics = getContext("globalMetrics"); @@ -66,7 +65,9 @@ let timeoutId = null; /* State Init */ + // svelte-ignore state_referenced_locally let to = $state(presetTo || new Date(Date.now())); + // svelte-ignore state_referenced_locally let from = $state(presetFrom || new Date(nowDate.setHours(nowDate.getHours() - 4))); let selectedResolution = $state(resampleConfig ? resampleDefault : 0); let hostnameFilter = $state(""); @@ -75,6 +76,7 @@ let isMetricsSelectionOpen = $state(false); /* Derived States */ + const displayNodeOverview = $derived((displayType === 'OVERVIEW')); const systemMetrics = $derived($initialized ? [...globalMetrics.filter((gm) => gm?.availability.find((av) => av.cluster == cluster))] : []); const presetSystemUnits = $derived(loadUnits(systemMetrics)); let selectedMetric = $derived.by(() => { diff --git a/web/frontend/src/Tags.root.svelte b/web/frontend/src/Tags.root.svelte index 21dbcf47..b8a8abf8 100644 --- a/web/frontend/src/Tags.root.svelte +++ b/web/frontend/src/Tags.root.svelte @@ -37,6 +37,7 @@ /* State Init */ let pendingChange = $state("none"); + // svelte-ignore state_referenced_locally let tagmap = $state(presetTagmap); /* Functions */ diff --git a/web/frontend/src/User.root.svelte b/web/frontend/src/User.root.svelte index 3c599272..96ee4704 100644 --- a/web/frontend/src/User.root.svelte +++ b/web/frontend/src/User.root.svelte @@ -64,17 +64,7 @@ let isSortingOpen = $state(false); let isMetricsSelectionOpen = $state(false); let sorting = $state({ field: "startTime", type: "col", order: "DESC" }); - let selectedCluster = $state(filterPresets?.cluster ? filterPresets.cluster : null); let selectedHistogramsBuffer = $state({ all: (ccconfig['userView_histogramMetrics'] || []) }) - let metrics = $state(filterPresets.cluster - ? ccconfig[`metricConfig_jobListMetrics:${filterPresets.cluster}`] || - ccconfig.metricConfig_jobListMetrics - : ccconfig.metricConfig_jobListMetrics - ); - let showFootprint = $state(filterPresets.cluster - ? !!ccconfig[`jobList_showFootprint:${filterPresets.cluster}`] - : !!ccconfig.jobList_showFootprint - ); // Histogram Vars let isHistogramSelectionOpen = $state(false); @@ -88,7 +78,17 @@ // let filterBuffer = $state([]); // let matchedCompareJobs = $state(0); - /* Derived Vars */ + /* Derived */ + let selectedCluster = $derived(filterPresets?.cluster ? filterPresets.cluster : null); + let metrics = $derived(filterPresets.cluster + ? ccconfig[`metricConfig_jobListMetrics:${filterPresets.cluster}`] || + ccconfig.metricConfig_jobListMetrics + : ccconfig.metricConfig_jobListMetrics + ); + let showFootprint = $derived(filterPresets.cluster + ? !!ccconfig[`jobList_showFootprint:${filterPresets.cluster}`] + : !!ccconfig.jobList_showFootprint + ); let selectedHistograms = $derived(selectedCluster ? selectedHistogramsBuffer[selectedCluster] : selectedHistogramsBuffer['all']); let stats = $derived( queryStore({ diff --git a/web/frontend/src/analysis/PlotSelection.svelte b/web/frontend/src/analysis/PlotSelection.svelte index ab4eda85..386d2f97 100644 --- a/web/frontend/src/analysis/PlotSelection.svelte +++ b/web/frontend/src/analysis/PlotSelection.svelte @@ -49,11 +49,13 @@ /* State Init */ let isHistogramConfigOpen = $state(false); let isScatterPlotConfigOpen = $state(false); - let metricsInHistograms = $state(presetMetricsInHistograms); - let metricsInScatterplots = $state(presetMetricsInScatterplots); let selectedMetric1 = $state(null); let selectedMetric2 = $state(null); + /* Derived */ + let metricsInHistograms = $derived(presetMetricsInHistograms); + let metricsInScatterplots = $derived(presetMetricsInScatterplots); + /* Functions */ function updateConfiguration(data) { updateConfigurationMutation({ diff --git a/web/frontend/src/config/user/PlotColorScheme.svelte b/web/frontend/src/config/user/PlotColorScheme.svelte index 6b24fd43..cfb2b5b4 100644 --- a/web/frontend/src/config/user/PlotColorScheme.svelte +++ b/web/frontend/src/config/user/PlotColorScheme.svelte @@ -28,8 +28,8 @@ updateSetting } = $props(); - /* State Init */ - let activeRow = $state(JSON.stringify(config?.plotConfiguration_colorScheme)); + /* Derived */ + let activeRow = $derived(JSON.stringify(config?.plotConfiguration_colorScheme)); /* Const Init */ const colorSchemes = { diff --git a/web/frontend/src/generic/Filters.svelte b/web/frontend/src/generic/Filters.svelte index 74417015..8cb6e88a 100644 --- a/web/frontend/src/generic/Filters.svelte +++ b/web/frontend/src/generic/Filters.svelte @@ -89,6 +89,7 @@ }; /* State Init */ + // svelte-ignore state_referenced_locally let filters = $state({ dbId: filterPresets.dbId || [], jobId: filterPresets.jobId || "", diff --git a/web/frontend/src/generic/JobCompare.svelte b/web/frontend/src/generic/JobCompare.svelte index dea324fc..d5283a9a 100644 --- a/web/frontend/src/generic/JobCompare.svelte +++ b/web/frontend/src/generic/JobCompare.svelte @@ -64,10 +64,10 @@ let plotSync = uPlot.sync("compareJobsView"); /* State Init */ - let filter = $state([...filterBuffer] || []); let tableJobIDFilter = $state(""); /* Derived*/ + let filter = $derived([...filterBuffer] || []); const compareData = $derived(queryStore({ client: client, query: compareQuery, diff --git a/web/frontend/src/generic/JobList.svelte b/web/frontend/src/generic/JobList.svelte index b636e6e2..c08a5400 100644 --- a/web/frontend/src/generic/JobList.svelte +++ b/web/frontend/src/generic/JobList.svelte @@ -99,13 +99,13 @@ /* State Init */ let headerPaddingTop = $state(0); let jobs = $state([]); - let filter = $state([...filterBuffer]); let page = $state(1); let itemsPerPage = $state(usePaging ? (ccconfig?.jobList_jobsPerPage || 10) : 10); let triggerMetricRefresh = $state(false); let tableWidth = $state(0); /* Derived */ + let filter = $derived([...filterBuffer]); let paging = $derived({ itemsPerPage, page }); const plotWidth = $derived.by(() => { return Math.floor( diff --git a/web/frontend/src/generic/filters/Cluster.svelte b/web/frontend/src/generic/filters/Cluster.svelte index 2d35e84d..562ee879 100644 --- a/web/frontend/src/generic/filters/Cluster.svelte +++ b/web/frontend/src/generic/filters/Cluster.svelte @@ -34,9 +34,9 @@ const clusters = getContext("clusters"); const initialized = getContext("initialized"); - /* State Init */ - let pendingCluster = $state(presetCluster); - let pendingPartition = $state(presetPartition); + /* Derived */ + let pendingCluster = $derived(presetCluster); + let pendingPartition = $derived(presetPartition); (isOpen = !isOpen)}> diff --git a/web/frontend/src/generic/filters/Duration.svelte b/web/frontend/src/generic/filters/Duration.svelte index 3056d9f9..34f7afb2 100644 --- a/web/frontend/src/generic/filters/Duration.svelte +++ b/web/frontend/src/generic/filters/Duration.svelte @@ -31,14 +31,13 @@ setFilter } = $props(); - /* State Init */ - let pendingDuration = $state(presetDuration); - let lessState = $state(secsToHoursAndMins(presetDuration?.lessThan)); - let moreState = $state(secsToHoursAndMins(presetDuration?.moreThan)); - let fromState = $state(secsToHoursAndMins(presetDuration?.from)); - let toState = $state(secsToHoursAndMins(presetDuration?.to)); + /* Derived */ + let pendingDuration = $derived(presetDuration); + let lessState = $derived(secsToHoursAndMins(presetDuration?.lessThan)); + let moreState = $derived(secsToHoursAndMins(presetDuration?.moreThan)); + let fromState = $derived(secsToHoursAndMins(presetDuration?.from)); + let toState = $derived(secsToHoursAndMins(presetDuration?.to)); - /* Derived Init */ const lessDisabled = $derived( moreState.hours !== 0 || moreState.mins !== 0 || diff --git a/web/frontend/src/generic/filters/Energy.svelte b/web/frontend/src/generic/filters/Energy.svelte index 0a5a8362..4d542add 100644 --- a/web/frontend/src/generic/filters/Energy.svelte +++ b/web/frontend/src/generic/filters/Energy.svelte @@ -28,8 +28,8 @@ setFilter, } = $props(); - /* State Init */ - let energyState = $state(presetEnergy); + /* Derived */ + let energyState = $derived(presetEnergy); (isOpen = !isOpen)}> diff --git a/web/frontend/src/generic/filters/JobStates.svelte b/web/frontend/src/generic/filters/JobStates.svelte index dc622a20..acddef5c 100644 --- a/web/frontend/src/generic/filters/JobStates.svelte +++ b/web/frontend/src/generic/filters/JobStates.svelte @@ -67,10 +67,10 @@ "single_user", ]; - /* State Init */ - let pendingStates = $state([...presetStates]); - let pendingShared = $state(presetShared); - let pendingSchedule = $state(presetSchedule); + /* Derived */ + let pendingStates = $derived([...presetStates]); + let pendingShared = $derived(presetShared); + let pendingSchedule = $derived(presetSchedule); diff --git a/web/frontend/src/generic/filters/Resources.svelte b/web/frontend/src/generic/filters/Resources.svelte index 49a28f8c..aa215025 100644 --- a/web/frontend/src/generic/filters/Resources.svelte +++ b/web/frontend/src/generic/filters/Resources.svelte @@ -79,18 +79,19 @@ let maxNumNodes = $state(128); let maxNumHWThreads = $state(0); let maxNumAccelerators = $state(0); - // Pending - let pendingNumNodes = $state(presetNumNodes); - let pendingNumHWThreads = $state(presetNumHWThreads); - let pendingNumAccelerators = $state(presetNumAccelerators); - let pendingNamedNode = $state(presetNamedNode); - let pendingNodeMatch = $state(presetNodeMatch); - // Changable States - let nodesState = $state(presetNumNodes); - let threadState = $state(presetNumHWThreads); - let accState = $state(presetNumAccelerators); /* Derived States */ + // Pending + let pendingNumNodes = $derived(presetNumNodes); + let pendingNumHWThreads = $derived(presetNumHWThreads); + let pendingNumAccelerators = $derived(presetNumAccelerators); + let pendingNamedNode = $derived(presetNamedNode); + let pendingNodeMatch = $derived(presetNodeMatch); + // Changable States + let nodesState = $derived(presetNumNodes); + let threadState = $derived(presetNumHWThreads); + let accState = $derived(presetNumAccelerators); + const clusters = $derived(getContext("clusters")); const initialized = $derived(getContext("initialized")); // Is Selection Active diff --git a/web/frontend/src/generic/filters/StartTime.svelte b/web/frontend/src/generic/filters/StartTime.svelte index c35acb2a..5d9340e3 100644 --- a/web/frontend/src/generic/filters/StartTime.svelte +++ b/web/frontend/src/generic/filters/StartTime.svelte @@ -48,12 +48,11 @@ const resetFrom = { date: format(ago, "yyyy-MM-dd"), time: format(ago, "HH:mm")}; const resetTo = { date: format(now, "yyyy-MM-dd"), time: format(now, "HH:mm")}; - /* State Init */ - let pendingStartTime = $state(presetStartTime); - let fromState = $state(fromRFC3339(presetStartTime?.from, resetFrom)); - let toState = $state(fromRFC3339(presetStartTime?.to, resetTo)); + /* Derived */ + let pendingStartTime = $derived(presetStartTime); + let fromState = $derived(fromRFC3339(presetStartTime?.from, resetFrom)); + let toState = $derived(fromRFC3339(presetStartTime?.to, resetTo)); - /* Derived Init*/ const rangeSelect = $derived(pendingStartTime?.range ? pendingStartTime.range : "") /* Functions */ diff --git a/web/frontend/src/generic/filters/Tags.svelte b/web/frontend/src/generic/filters/Tags.svelte index 9d726e51..39c2b036 100644 --- a/web/frontend/src/generic/filters/Tags.svelte +++ b/web/frontend/src/generic/filters/Tags.svelte @@ -35,8 +35,11 @@ const initialized = $derived(getContext("initialized")) /* State Init */ - let pendingTags = $state(presetTags); let searchTerm = $state(""); + + /* Derived */ + let pendingTags = $derived(presetTags); + (isOpen = !isOpen)}> diff --git a/web/frontend/src/generic/helper/Refresher.svelte b/web/frontend/src/generic/helper/Refresher.svelte index ca05bf6d..7c477440 100644 --- a/web/frontend/src/generic/helper/Refresher.svelte +++ b/web/frontend/src/generic/helper/Refresher.svelte @@ -18,12 +18,12 @@ onRefresh } = $props(); - /* State Init */ - let refreshInterval = $state(initially ? initially * 1000 : null); - /* Var Init */ let refreshIntervalId = null; + /* Derived */ + let refreshInterval = $derived(initially ? initially * 1000 : null); + /* Functions */ function refreshIntervalChanged() { if (refreshIntervalId != null) clearInterval(refreshIntervalId); diff --git a/web/frontend/src/generic/helper/TagManagement.svelte b/web/frontend/src/generic/helper/TagManagement.svelte index 8d0d5a82..53e80537 100644 --- a/web/frontend/src/generic/helper/TagManagement.svelte +++ b/web/frontend/src/generic/helper/TagManagement.svelte @@ -45,8 +45,6 @@ } = $props(); /* Const Init */ - const isAdmin = (roles && authlevel == roles.admin); - const isSupport = (roles && authlevel == roles.support); const client = getContextClient(); /* State Init */ @@ -54,12 +52,14 @@ let allTags = getContext("tags") let newTagType = $state(""); let newTagName = $state(""); - let newTagScope = $state(username); let filterTerm = $state(""); let pendingChange = $state(false); let isOpen = $state(false); - /* Derived Init */ + /* Derived */ + let newTagScope = $derived(username); + const isAdmin = $derived((roles && authlevel == roles.admin)); + const isSupport = $derived((roles && authlevel == roles.support)); const allTagsFiltered = $derived(($initialized, jobTags, fuzzySearchTags(filterTerm, allTags))); // $init und JobTags only for triggering react const usedTagsFiltered = $derived(matchJobTags(jobTags, allTagsFiltered, 'used', isAdmin, isSupport)); const unusedTagsFiltered = $derived(matchJobTags(jobTags, allTagsFiltered, 'unused', isAdmin, isSupport)); diff --git a/web/frontend/src/generic/helper/TextFilter.svelte b/web/frontend/src/generic/helper/TextFilter.svelte index 020b7999..c38fe33d 100644 --- a/web/frontend/src/generic/helper/TextFilter.svelte +++ b/web/frontend/src/generic/helper/TextFilter.svelte @@ -26,14 +26,16 @@ /* Var Init */ let user = ""; - let project = presetProject ? presetProject : ""; let jobName = ""; let timeoutId = null; /* State Init */ - let mode = $state(presetProject ? "jobName" : "project"); let term = $state(""); + /* Derived */ + let project = $derived(presetProject ? presetProject : ""); + let mode = $derived(presetProject ? "jobName" : "project"); + /* Functions */ function modeChanged() { if (mode == "user") { diff --git a/web/frontend/src/generic/joblist/JobListRow.svelte b/web/frontend/src/generic/joblist/JobListRow.svelte index 8019b967..4604883a 100644 --- a/web/frontend/src/generic/joblist/JobListRow.svelte +++ b/web/frontend/src/generic/joblist/JobListRow.svelte @@ -37,13 +37,7 @@ /* Const Init */ const client = getContextClient(); - const jobId = job.id; const cluster = getContext("clusters"); - const scopes = (job.numNodes == 1) - ? (job.numAcc >= 1) - ? ["core", "accelerator"] - : ["core"] - : ["node"]; const resampleConfig = getContext("resampling") || null; const resampleDefault = resampleConfig ? Math.max(...resampleConfig.resolutions) : 0; const query = gql` @@ -84,6 +78,15 @@ let thresholdStates = $state({}); /* Derived */ + const jobId = $derived(job?.id); + const scopes = $derived.by(() => { + if (job.numNodes == 1) { + if (job.numAcc >= 1) return ["core", "accelerator"]; + else return ["core"]; + } else { + return ["node"]; + }; + }); let isSelected = $derived(previousSelect); let metricsQuery = $derived(queryStore({ client: client, diff --git a/web/frontend/src/generic/plots/Comparogram.svelte b/web/frontend/src/generic/plots/Comparogram.svelte index b391a1f5..b1835c2c 100644 --- a/web/frontend/src/generic/plots/Comparogram.svelte +++ b/web/frontend/src/generic/plots/Comparogram.svelte @@ -73,6 +73,7 @@ ] // UPLOT SCALES INIT // + // svelte-ignore state_referenced_locally if (forResources) { const resSeries = [ { @@ -136,8 +137,11 @@ // UPLOT OPTIONS // const opts = { + // svelte-ignore state_referenced_locally width, + // svelte-ignore state_referenced_locally height, + // svelte-ignore state_referenced_locally title, plugins: [legendAsTooltipPlugin()], series: plotSeries, @@ -147,6 +151,7 @@ space: 25, // Tick Spacing rotate: 30, show: true, + // svelte-ignore state_referenced_locally label: xlabel, values(self, splits) { return splits.map(s => xticks[s]); @@ -164,16 +169,19 @@ scale: "y", grid: { show: true }, labelFont: "sans-serif", + // svelte-ignore state_referenced_locally label: ylabel + (yunit ? ` (${yunit})` : ''), values: (u, vals) => vals.map((v) => formatNumber(v)), }, ], + // svelte-ignore state_referenced_locally bands: forResources ? [] : plotBands, padding: [5, 10, 0, 0], hooks: { draw: [ (u) => { // Draw plot type label: + // svelte-ignore state_referenced_locally let textl = forResources ? "Job Resources by Type" : "Metric Min/Avg/Max for Job Duration"; let textr = "Earlier <- StartTime -> Later"; u.ctx.save(); @@ -196,6 +204,7 @@ x: { time: false }, xst: { time: false }, xrt: { time: false }, + // svelte-ignore state_referenced_locally y: {auto: true, distr: forResources ? 3 : 1}, }, legend: { diff --git a/web/frontend/src/generic/plots/DoubleMetricPlot.svelte b/web/frontend/src/generic/plots/DoubleMetricPlot.svelte index 9579f36b..4f76fc7a 100644 --- a/web/frontend/src/generic/plots/DoubleMetricPlot.svelte +++ b/web/frontend/src/generic/plots/DoubleMetricPlot.svelte @@ -53,7 +53,6 @@ // const subClusterTopology = getContext("getHardwareTopology")(cluster, subCluster); // const metricConfig = getContext("getMetricConfig")(cluster, subCluster, metric); const lineColors = clusterCockpitConfig.plotConfiguration_colorScheme; - const lineWidth = fixLinewidth ? fixLinewidth : clusterCockpitConfig.plotConfiguration_lineWidth / window.devicePixelRatio; // const cbmode = clusterCockpitConfig?.plotConfiguration_colorblindMode || false; const renderSleepTime = 200; // const normalLineColor = "#000000"; @@ -71,6 +70,7 @@ let uplot = $state(null); /* Derived */ + const lineWidth = $derived(fixLinewidth ? fixLinewidth : clusterCockpitConfig.plotConfiguration_lineWidth / window.devicePixelRatio); // const usesMeanStatsSeries = $derived((statisticsSeries?.mean && statisticsSeries.mean.length != 0)); // const resampleTrigger = $derived(resampleConfig?.trigger ? Number(resampleConfig.trigger) : null); // const resampleResolutions = $derived(resampleConfig?.resolutions ? [...resampleConfig.resolutions] : null); diff --git a/web/frontend/src/generic/plots/MetricPlot.svelte b/web/frontend/src/generic/plots/MetricPlot.svelte index cea97095..81fbd3c0 100644 --- a/web/frontend/src/generic/plots/MetricPlot.svelte +++ b/web/frontend/src/generic/plots/MetricPlot.svelte @@ -56,8 +56,6 @@ /* Const Init */ const clusterCockpitConfig = getContext("cc-config"); const resampleConfig = getContext("resampling"); - const subClusterTopology = getContext("getHardwareTopology")(cluster, subCluster); - const metricConfig = getContext("getMetricConfig")(cluster, subCluster, metric); const lineColors = clusterCockpitConfig.plotConfiguration_colorScheme; const lineWidth = clusterCockpitConfig.plotConfiguration_lineWidth / window.devicePixelRatio; const cbmode = clusterCockpitConfig?.plotConfiguration_colorblindMode || false; @@ -77,6 +75,8 @@ let uplot = $state(null); /* Derived */ + const subClusterTopology = $derived(getContext("getHardwareTopology")(cluster, subCluster)); + const metricConfig = $derived(getContext("getMetricConfig")(cluster, subCluster, metric)); const usesMeanStatsSeries = $derived((statisticsSeries?.mean && statisticsSeries.mean.length != 0)); const resampleTrigger = $derived(resampleConfig?.trigger ? Number(resampleConfig.trigger) : null); const resampleResolutions = $derived(resampleConfig?.resolutions ? [...resampleConfig.resolutions] : null); diff --git a/web/frontend/src/generic/plots/Pie.svelte b/web/frontend/src/generic/plots/Pie.svelte index 5e31b7dd..3cfb1821 100644 --- a/web/frontend/src/generic/plots/Pie.svelte +++ b/web/frontend/src/generic/plots/Pie.svelte @@ -95,6 +95,7 @@ animation: false, plugins: { legend: { + // svelte-ignore state_referenced_locally display: displayLegend } } diff --git a/web/frontend/src/generic/plots/RooflineHeatmap.svelte b/web/frontend/src/generic/plots/RooflineHeatmap.svelte index ff2ba84d..0fd0f8e2 100644 --- a/web/frontend/src/generic/plots/RooflineHeatmap.svelte +++ b/web/frontend/src/generic/plots/RooflineHeatmap.svelte @@ -23,9 +23,6 @@ height = 300, } = $props(); - /* Check Before */ - console.assert(tiles, "you must provide tiles!") - /* Const Init */ const axesColor = '#aaaaaa'; const tickFontSize = 10; @@ -42,10 +39,10 @@ /* State Init */ let ctx = $state(); let canvasElement = $state(); - let prevWidth = $state(width); - let prevHeight = $state(height); /* Derived */ + let prevWidth = $derived(width); + let prevHeight = $derived(height); const data = $derived({ tiles: tiles, xLabel: 'Intensity [FLOPS/byte]', diff --git a/web/frontend/src/generic/plots/Stacked.svelte b/web/frontend/src/generic/plots/Stacked.svelte index 06dd83e4..3ee1ce1c 100644 --- a/web/frontend/src/generic/plots/Stacked.svelte +++ b/web/frontend/src/generic/plots/Stacked.svelte @@ -100,12 +100,6 @@ } }; - // Data Prep For uPlot - const sortedData = data?.sort((a, b) => a.state.localeCompare(b.state)) || []; - const collectLabel = sortedData.map(d => d.state); - // Align Data to Timesteps, Introduces 'undefied' as placeholder, reiterate and set those to 0 - const collectData = (sortedData.length > 0) ? uPlot.join(sortedData.map(d => [d.times, d.counts])).map(d => d.map(i => i ? i : 0)) : []; - // STACKED CHART FUNCTIONS // function stack(data, omit) { let data2 = []; @@ -287,14 +281,20 @@ }; } - // UPLOT SERIES INIT - const plotSeries = [ - { - label: "Time", - scale: "x" - }, - ...collectLabel.map(l => seriesConfig[l]) - ] + // UPLOT SERIES INIT: DERIVED FROM PROPS + // Data Prep For uPlot + const sortedData = $derived(data?.sort((a, b) => a.state.localeCompare(b.state)) || []); + const collectLabel = $derived(sortedData.map(d => d.state)); + // Align Data to Timesteps, Introduces 'undefied' as placeholder, reiterate and set those to 0 + const collectData = $derived.by(() => { + if (sortedData.length > 0) { + return uPlot.join(sortedData.map(d => [d.times, d.counts])).map(d => d.map(i => i ? i : 0)) + } else { + return []; + } + }); + // Build Series + const plotSeries = $derived([{label: "Time", scale: "x"}, ...collectLabel.map(l => seriesConfig[l])]); /* Var Init */ let timeoutId = null; diff --git a/web/frontend/src/generic/select/DoubleRangeSlider.svelte b/web/frontend/src/generic/select/DoubleRangeSlider.svelte index f31971fe..12ca7449 100644 --- a/web/frontend/src/generic/select/DoubleRangeSlider.svelte +++ b/web/frontend/src/generic/select/DoubleRangeSlider.svelte @@ -27,14 +27,16 @@ } = $props(); /* State Init */ - let pendingValues = $state([fromPreset, toPreset]); - let sliderFrom = $state(Math.max(((fromPreset == null ? sliderMin : fromPreset) - sliderMin) / (sliderMax - sliderMin), 0.)); - let sliderTo = $state(Math.min(((toPreset == null ? sliderMin : toPreset) - sliderMin) / (sliderMax - sliderMin), 1.)); - let inputFieldFrom = $state(fromPreset.toString()); - let inputFieldTo = $state(toPreset.toString()); let leftHandle = $state(); let sliderMain = $state(); + /* Derived */ + let pendingValues = $derived([fromPreset, toPreset]); + let sliderFrom = $derived(Math.max(((fromPreset == null ? sliderMin : fromPreset) - sliderMin) / (sliderMax - sliderMin), 0.)); + let sliderTo = $derived(Math.min(((toPreset == null ? sliderMin : toPreset) - sliderMin) / (sliderMax - sliderMin), 1.)); + let inputFieldFrom = $derived(fromPreset.toString()); + let inputFieldTo = $derived(toPreset.toString()); + /* Var Init */ let timeoutId = null; diff --git a/web/frontend/src/generic/select/SortSelection.svelte b/web/frontend/src/generic/select/SortSelection.svelte index f895e563..42bf92e1 100644 --- a/web/frontend/src/generic/select/SortSelection.svelte +++ b/web/frontend/src/generic/select/SortSelection.svelte @@ -41,11 +41,11 @@ ]); /* State Init */ - let sorting = $state({...presetSorting}) let activeColumnIdx = $state(0); let metricSortables = $state([]); /* Derived */ + let sorting = $derived({...presetSorting}) let sortableColumns = $derived([...fixedSortables, ...metricSortables]); /* Effect */ diff --git a/web/frontend/src/job/Metric.svelte b/web/frontend/src/job/Metric.svelte index 886b4839..ca32d9f9 100644 --- a/web/frontend/src/job/Metric.svelte +++ b/web/frontend/src/job/Metric.svelte @@ -45,7 +45,6 @@ const statsPattern = /(.*)-stat$/; const resampleConfig = getContext("resampling") || null; const resampleDefault = resampleConfig ? Math.max(...resampleConfig.resolutions) : 0; - const unit = (metricUnit?.prefix ? metricUnit.prefix : "") + (metricUnit?.base ? metricUnit.base : ""); const subQuery = gql` query ($dbid: ID!, $selectedMetrics: [String!]!, $selectedScopes: [MetricScope!]!, $selectedResolution: Int) { singleUpdate: jobMetrics(id: $dbid, metrics: $selectedMetrics, scopes: $selectedScopes, resolution: $selectedResolution) { @@ -79,14 +78,14 @@ `; /* State Init */ - let requestedScopes = $state(presetScopes); let selectedResolution = $state(resampleDefault); - let selectedHost = $state(null); let zoomState = $state(null); let thresholdState = $state(null); /* Derived */ + let requestedScopes = $derived(presetScopes); + const unit = $derived.by(() => { return (metricUnit?.prefix ? metricUnit.prefix : "") + (metricUnit?.base ? metricUnit.base : "")}); const metricData = $derived(queryStore({ client: client, query: subQuery, diff --git a/web/frontend/src/job/statstab/StatsTable.svelte b/web/frontend/src/job/statstab/StatsTable.svelte index 9430fbd5..06b2d105 100644 --- a/web/frontend/src/job/statstab/StatsTable.svelte +++ b/web/frontend/src/job/statstab/StatsTable.svelte @@ -25,9 +25,13 @@ } = $props(); /* State Init */ + // svelte-ignore state_referenced_locally let sortedHosts = $state(hosts); + // svelte-ignore state_referenced_locally let sorting = $state(setupSorting(selectedMetrics)); + // svelte-ignore state_referenced_locally let availableScopes = $state(setupAvailable(jobStats)); + // svelte-ignore state_referenced_locally let selectedScopes = $state(setupSelected(availableScopes)); /* Derived Init */ diff --git a/web/frontend/src/status/dashdetails/StatisticsDash.svelte b/web/frontend/src/status/dashdetails/StatisticsDash.svelte index 0a1cd46f..42c6823f 100644 --- a/web/frontend/src/status/dashdetails/StatisticsDash.svelte +++ b/web/frontend/src/status/dashdetails/StatisticsDash.svelte @@ -38,11 +38,11 @@ const client = getContextClient(); /* State Init */ - let cluster = $state(presetCluster); // Histogram let isHistogramSelectionOpen = $state(false); /* Derived */ + let cluster = $derived(presetCluster); let selectedHistograms = $derived(cluster ? ccconfig[`statusView_selectedHistograms:${cluster}`] || ( ccconfig['statusView_selectedHistograms'] || [] ) : ccconfig['statusView_selectedHistograms'] || []); diff --git a/web/frontend/src/status/dashdetails/StatusDash.svelte b/web/frontend/src/status/dashdetails/StatusDash.svelte index f858969f..5144529f 100644 --- a/web/frontend/src/status/dashdetails/StatusDash.svelte +++ b/web/frontend/src/status/dashdetails/StatusDash.svelte @@ -41,7 +41,6 @@ const client = getContextClient(); /* State Init */ - let cluster = $state(presetCluster); let pieWidth = $state(0); let stackedWidth1 = $state(0); let stackedWidth2 = $state(0); @@ -65,6 +64,7 @@ let totalAccs = $state({}); /* Derived */ + let cluster = $derived(presetCluster); // States for Stacked charts const statesTimed = $derived(queryStore({ client: client, diff --git a/web/frontend/src/status/dashdetails/UsageDash.svelte b/web/frontend/src/status/dashdetails/UsageDash.svelte index 2071465a..928ef957 100644 --- a/web/frontend/src/status/dashdetails/UsageDash.svelte +++ b/web/frontend/src/status/dashdetails/UsageDash.svelte @@ -44,7 +44,6 @@ const durationBinOptions = ["1m","10m","1h","6h","12h"]; /* State Init */ - let cluster = $state(presetCluster) let pagingState = $state({page: 1, itemsPerPage: 10}) // Top 10 let selectedHistograms = $state([]) // Dummy For Refresh let colWidthJobs = $state(0); @@ -53,6 +52,7 @@ let numDurationBins = $state("1h"); /* Derived */ + let cluster = $derived(presetCluster) const topJobsQuery = $derived(queryStore({ client: client, query: gql` diff --git a/web/frontend/src/systems/NodeList.svelte b/web/frontend/src/systems/NodeList.svelte index fa758c18..f512a6ea 100644 --- a/web/frontend/src/systems/NodeList.svelte +++ b/web/frontend/src/systems/NodeList.svelte @@ -38,7 +38,6 @@ /* Const Init */ const client = getContextClient(); - const usePaging = ccconfig?.nodeList_usePaging || false; const nodeListQuery = gql` query ($cluster: String!, $subCluster: String!, $nodeFilter: String!, $stateFilter: String!, $metrics: [String!], $scopes: [MetricScope!]!, $from: Time!, $to: Time!, $paging: PageRequest!, $selectedResolution: Int @@ -94,13 +93,14 @@ /* State Init */ let nodes = $state([]); - let selectedMetrics = $state(pendingSelectedMetrics); let page = $state(1); - let itemsPerPage = $state(usePaging ? (ccconfig?.nodeList_nodesPerPage || 10) : 10); let headerPaddingTop = $state(0); let matchedNodes = $state(0); /* Derived */ + let selectedMetrics = $derived(pendingSelectedMetrics); + let itemsPerPage = $derived(usePaging ? (ccconfig?.nodeList_nodesPerPage || 10) : 10); + const usePaging = $derived(ccconfig?.nodeList_usePaging || false); const paging = $derived({ itemsPerPage, page }); const nodesQuery = $derived(queryStore({ client: client, diff --git a/web/frontend/src/systems/nodelist/NodeInfo.svelte b/web/frontend/src/systems/nodelist/NodeInfo.svelte index 6d1c5266..de5ca14a 100644 --- a/web/frontend/src/systems/nodelist/NodeInfo.svelte +++ b/web/frontend/src/systems/nodelist/NodeInfo.svelte @@ -38,10 +38,6 @@ } = $props(); /* Const Init */ - // Not at least one returned, selected metric: NodeHealth warning - const healthWarn = !dataHealth.includes(true); - // At least one non-returned selected metric: Metric config error? - const metricWarn = dataHealth.includes(false); // Node State Colors const stateColors = { allocated: 'success', @@ -54,6 +50,10 @@ } /* Derived */ + // Not at least one returned, selected metric: NodeHealth warning + const healthWarn = $derived(!dataHealth.includes(true)); + // At least one non-returned selected metric: Metric config error? + const metricWarn = $derived(dataHealth.includes(false)); const userList = $derived(nodeJobsData ? Array.from(new Set(nodeJobsData.jobs.items.map((j) => scrambleNames ? scramble(j.user) : j.user))).sort((a, b) => a.localeCompare(b)) : [] diff --git a/web/frontend/src/systems/nodelist/NodeListRow.svelte b/web/frontend/src/systems/nodelist/NodeListRow.svelte index e7e095ea..0b34fbad 100644 --- a/web/frontend/src/systems/nodelist/NodeListRow.svelte +++ b/web/frontend/src/systems/nodelist/NodeListRow.svelte @@ -27,17 +27,13 @@ } = $props(); /* Var Init*/ + // svelte-ignore state_referenced_locally let plotSync = uPlot.sync(`nodeMetricStack-${nodeData.host}`); /* Const Init */ const client = getContextClient(); const paging = { itemsPerPage: 50, page: 1 }; const sorting = { field: "startTime", type: "col", order: "DESC" }; - const filter = [ - { cluster: { eq: cluster } }, - { node: { contains: nodeData.host } }, - { state: ["running"] }, - ]; const nodeJobsQuery = gql` query ( $filter: [JobFilter!]! @@ -61,6 +57,11 @@ `; /* Derived */ + const filter = $derived([ + { cluster: { eq: cluster } }, + { node: { contains: nodeData.host } }, + { state: ["running"] }, + ]); const nodeJobsData = $derived(queryStore({ client: client, query: nodeJobsQuery, @@ -70,7 +71,7 @@ let extendedLegendData = $derived($nodeJobsData?.data ? buildExtendedLegend() : null); let refinedData = $derived(nodeData?.metrics ? sortAndSelectScope(nodeData.metrics) : null); - let dataHealth = $derived(refinedData.filter((rd) => rd.disabled === false).map((enabled) => (enabled.data.metric.series.length > 0))); + let dataHealth = $derived(refinedData.filter((rd) => rd.disabled === false).map((enabled) => (enabled?.data?.metric?.series?.length > 0))); /* Functions */ const selectScope = (nodeMetrics) =>