add nullsafes to frontend

This commit is contained in:
Christoph Kluge
2026-03-13 14:20:45 +01:00
parent cbe46c3524
commit bc214f6cea
10 changed files with 36 additions and 36 deletions

View File

@@ -211,7 +211,7 @@
const orderAndMap = (grouped, inputMetrics) => const orderAndMap = (grouped, inputMetrics) =>
inputMetrics.map((metric) => ({ inputMetrics.map((metric) => ({
metric: metric, metric: metric,
data: grouped.find((group) => group[0].name == metric), data: grouped.find((group) => group[0]?.name == metric),
availability: checkMetricAvailability( availability: checkMetricAvailability(
globalMetrics, globalMetrics,
metric, metric,

View File

@@ -148,7 +148,7 @@
showFilter={!showCompare} showFilter={!showCompare}
matchedJobs={showCompare? matchedCompareJobs: matchedListJobs} matchedJobs={showCompare? matchedCompareJobs: matchedListJobs}
applyFilters={(detail) => { applyFilters={(detail) => {
selectedCluster = detail.filters[0]?.cluster selectedCluster = detail?.filters[0]?.cluster
? detail.filters[0].cluster.eq ? detail.filters[0].cluster.eq
: null; : null;
selectedSubCluster = detail.filters[1]?.partition selectedSubCluster = detail.filters[1]?.partition

View File

@@ -159,7 +159,7 @@
variables: { jobFilters, selectedHistograms, numDurationBins, numMetricBins }, variables: { jobFilters, selectedHistograms, numDurationBins, numMetricBins },
}) })
); );
const hasAccHours = $derived($stats?.data?.jobsStatistics[0]?.totalAccHours != 0); const hasAccHours = $derived(($stats?.data?.jobsStatistics[0]?.totalAccHours || 0) != 0);
/* Functions */ /* Functions */
function resetJobSelection() { function resetJobSelection() {
@@ -310,8 +310,8 @@
<tr> <tr>
<th scope="row">Total Jobs</th> <th scope="row">Total Jobs</th>
<td> <td>
<span style="cursor: help;" title="{$stats.data.jobsStatistics[0].totalJobs} Jobs"> <span style="cursor: help;" title="{$stats?.data?.jobsStatistics[0]?.totalJobs || 0} Jobs">
{formatNumber($stats.data.jobsStatistics[0].totalJobs)} Jobs {formatNumber($stats?.data?.jobsStatistics[0]?.totalJobs || 0)} Jobs
</span> </span>
</td> </td>
</tr> </tr>
@@ -326,24 +326,24 @@
</Tooltip> </Tooltip>
</th> </th>
<td> <td>
<span style="cursor: help;" title="{$stats.data.jobsStatistics[0].shortJobs} Jobs"> <span style="cursor: help;" title="{$stats?.data?.jobsStatistics[0]?.shortJobs || 0} Jobs">
{formatNumber($stats.data.jobsStatistics[0].shortJobs)} Jobs {formatNumber($stats?.data?.jobsStatistics[0]?.shortJobs || 0)} Jobs
</span> </span>
</td> </td>
</tr> </tr>
<tr> <tr>
<th scope="row">Total Walltime</th> <th scope="row">Total Walltime</th>
<td> <td>
<span style="cursor: help;" title="{$stats.data.jobsStatistics[0].totalWalltime} Hours"> <span style="cursor: help;" title="{$stats?.data?.jobsStatistics[0]?.totalWalltime || 0} Hours">
{formatNumber($stats.data.jobsStatistics[0].totalWalltime)} Hours {formatNumber($stats?.data?.jobsStatistics[0]?.totalWalltime || 0)} Hours
</span> </span>
</td> </td>
</tr> </tr>
<tr> <tr>
<th scope="row">Total Core Hours</th> <th scope="row">Total Core Hours</th>
<td> <td>
<span style="cursor: help;" title="{$stats.data.jobsStatistics[0].totalCoreHours} Hours"> <span style="cursor: help;" title="{$stats?.data?.jobsStatistics[0]?.totalCoreHours || 0} Hours">
{formatNumber($stats.data.jobsStatistics[0].totalCoreHours)} Hours {formatNumber($stats?.data?.jobsStatistics[0]?.totalCoreHours || 0)} Hours
</span> </span>
</td> </td>
</tr> </tr>
@@ -351,8 +351,8 @@
<tr> <tr>
<th scope="row">Total Accelerator Hours</th> <th scope="row">Total Accelerator Hours</th>
<td> <td>
<span style="cursor: help;" title="{$stats.data.jobsStatistics[0].totalAccHours} Hours"> <span style="cursor: help;" title="{$stats?.data?.jobsStatistics[0]?.totalAccHours || 0} Hours">
{formatNumber($stats.data.jobsStatistics[0].totalAccHours)} Hours {formatNumber($stats?.data?.jobsStatistics[0]?.totalAccHours || 0)} Hours
</span> </span>
</td> </td>
</tr> </tr>
@@ -361,9 +361,9 @@
</Table> </Table>
</Col> </Col>
<Col class="px-1"> <Col class="px-1">
{#key $stats.data.jobsStatistics[0].histDuration} {#key $stats?.data?.jobsStatistics[0]?.histDuration}
<Histogram <Histogram
data={convert2uplot($stats.data.jobsStatistics[0].histDuration)} data={convert2uplot($stats?.data?.jobsStatistics[0]?.histDuration)}
title="Duration Distribution" title="Duration Distribution"
xlabel="Job Runtimes" xlabel="Job Runtimes"
xunit="Runtime" xunit="Runtime"
@@ -376,9 +376,9 @@
{/key} {/key}
</Col> </Col>
<Col class="px-1"> <Col class="px-1">
{#key $stats.data.jobsStatistics[0].histNumNodes} {#key $stats?.data?.jobsStatistics[0]?.histNumNodes}
<Histogram <Histogram
data={convert2uplot($stats.data.jobsStatistics[0].histNumNodes)} data={convert2uplot($stats?.data?.jobsStatistics[0]?.histNumNodes)}
title="Number of Nodes Distribution" title="Number of Nodes Distribution"
xlabel="Allocated Nodes" xlabel="Allocated Nodes"
xunit="Nodes" xunit="Nodes"
@@ -450,9 +450,9 @@
/> />
{/snippet} {/snippet}
{#key $stats.data.jobsStatistics[0].histMetrics} {#key $stats?.data?.jobsStatistics[0]?.histMetrics}
<PlotGrid <PlotGrid
items={$stats.data.jobsStatistics[0].histMetrics} items={$stats?.data?.jobsStatistics[0]?.histMetrics || []}
itemsPerRow={3} itemsPerRow={3}
{gridContent} {gridContent}
/> />

View File

@@ -167,7 +167,7 @@
<p class="mb-2"> <p class="mb-2">
{#if job.numNodes == 1} {#if job.numNodes == 1}
{job.resources[0].hostname} {job?.resources[0]?.hostname}
{:else} {:else}
{job.numNodes} {job.numNodes}
{/if} {/if}

View File

@@ -340,7 +340,7 @@
</script> </script>
<!-- Define $width Wrapper and NoData Card --> <!-- Define $width Wrapper and NoData Card -->
{#if data && data[0].length > 0} {#if data && data[0]?.length > 0}
<div bind:this={plotWrapper} bind:clientWidth={width} <div bind:this={plotWrapper} bind:clientWidth={width}
style="background-color: rgba(255, 255, 255, 1.0);" class="rounded" style="background-color: rgba(255, 255, 255, 1.0);" class="rounded"
></div> ></div>

View File

@@ -129,9 +129,9 @@
/> />
{/snippet} {/snippet}
{#key $metricStatusQuery.data.jobsStatistics[0].histMetrics} {#key $metricStatusQuery?.data?.jobsStatistics[0]?.histMetrics}
<PlotGrid <PlotGrid
items={$metricStatusQuery.data.jobsStatistics[0].histMetrics} items={$metricStatusQuery?.data?.jobsStatistics[0]?.histMetrics}
itemsPerRow={2} itemsPerRow={2}
{gridContent} {gridContent}
/> />

View File

@@ -294,8 +294,8 @@
const flopsData = subclusterData[i].metrics.find((s) => s.name == "flops_any") const flopsData = subclusterData[i].metrics.find((s) => s.name == "flops_any")
const memBwData = subclusterData[i].metrics.find((s) => s.name == "mem_bw") const memBwData = subclusterData[i].metrics.find((s) => s.name == "mem_bw")
const f = flopsData.metric.series[0].statistics.avg const f = flopsData?.metric?.series[0]?.statistics?.avg || 0
const m = memBwData.metric.series[0].statistics.avg const m = memBwData?.metric?.series[0]?.statistics?.avg || 0
let intensity = f / m let intensity = f / m
if (Number.isNaN(intensity) || !Number.isFinite(intensity)) { if (Number.isNaN(intensity) || !Number.isFinite(intensity)) {

View File

@@ -230,10 +230,10 @@
{:else if $topStatsQuery?.data && $nodeStatusQuery?.data} {:else if $topStatsQuery?.data && $nodeStatusQuery?.data}
<Row> <Row>
<Col xs="12" lg="4" class="p-2"> <Col xs="12" lg="4" class="p-2">
{#key $nodeStatusQuery.data.jobsStatistics[0].histDuration} {#key $nodeStatusQuery?.data?.jobsStatistics[0]?.histDuration}
<Histogram <Histogram
data={convert2uplot( data={convert2uplot(
$nodeStatusQuery.data.jobsStatistics[0].histDuration, $nodeStatusQuery?.data?.jobsStatistics[0]?.histDuration,
)} )}
title="Duration Distribution" title="Duration Distribution"
xlabel="Current Job Runtimes" xlabel="Current Job Runtimes"
@@ -356,7 +356,7 @@
<Col xs="12" lg="4" class="p-2"> <Col xs="12" lg="4" class="p-2">
<Histogram <Histogram
data={convert2uplot( data={convert2uplot(
$nodeStatusQuery.data.jobsStatistics[0].histNumNodes, $nodeStatusQuery?.data?.jobsStatistics[0]?.histNumNodes,
)} )}
title="Number of Nodes Distribution" title="Number of Nodes Distribution"
xlabel="Allocated Nodes" xlabel="Allocated Nodes"
@@ -476,7 +476,7 @@
<Col xs="12" lg="4" class="p-2"> <Col xs="12" lg="4" class="p-2">
<Histogram <Histogram
data={convert2uplot( data={convert2uplot(
$nodeStatusQuery.data.jobsStatistics[0].histNumAccs, $nodeStatusQuery?.data?.jobsStatistics[0]?.histNumAccs,
)} )}
title="Number of Accelerators Distribution" title="Number of Accelerators Distribution"
xlabel="Allocated Accs" xlabel="Allocated Accs"

View File

@@ -175,13 +175,13 @@
{:else if item?.data} {:else if item?.data}
<!-- "Empty Series"-Warning included in MetricPlot-Component --> <!-- "Empty Series"-Warning included in MetricPlot-Component -->
<!-- #key: X-axis keeps last selected timerange otherwise --> <!-- #key: X-axis keeps last selected timerange otherwise -->
{#key item.data[0].metric.series[0].data.length} {#key item?.data[0]?.metric?.series[0]?.data?.length}
<MetricPlot <MetricPlot
timestep={item.data[0].metric.timestep} timestep={item?.data[0]?.metric?.timestep || 60}
series={item.data[0].metric.series} series={item?.data[0]?.metric?.series || []}
metric={item.data[0].name} metric={item?.data[0]?.name || 'unknown'}
{cluster} {cluster}
subCluster={item.subCluster} subCluster={item?.subCluster || 'unknown'}
forNode forNode
enableFlip enableFlip
/> />

View File

@@ -109,7 +109,7 @@
<Button class="flex-grow-1" color="warning" disabled> <Button class="flex-grow-1" color="warning" disabled>
Missing Metric Missing Metric
</Button> </Button>
{:else if nodeJobsData.jobs.count == 1 && nodeJobsData.jobs.items[0].shared == "none"} {:else if nodeJobsData.jobs.count == 1 && nodeJobsData?.jobs?.items[0]?.shared == "none"}
<InputGroupText class="flex-grow-1 flex-lg-grow-0"> <InputGroupText class="flex-grow-1 flex-lg-grow-0">
<Icon name="circle-fill" style="padding-right: 0.5rem;"/> <Icon name="circle-fill" style="padding-right: 0.5rem;"/>
<span>Jobs</span> <span>Jobs</span>
@@ -117,7 +117,7 @@
<Button class="flex-grow-1" color="success" disabled> <Button class="flex-grow-1" color="success" disabled>
Exclusive Exclusive
</Button> </Button>
{:else if nodeJobsData.jobs.count >= 1 && !(nodeJobsData.jobs.items[0].shared == "none")} {:else if nodeJobsData.jobs.count >= 1 && !(nodeJobsData?.jobs?.items[0]?.shared == "none")}
<InputGroupText class="flex-grow-1 flex-lg-grow-0"> <InputGroupText class="flex-grow-1 flex-lg-grow-0">
<Icon name="circle-half" style="padding-right: 0.5rem;"/> <Icon name="circle-half" style="padding-right: 0.5rem;"/>
<span>Jobs</span> <span>Jobs</span>