mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-03-15 04:17:30 +01:00
add nullsafes to frontend
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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)) {
|
||||||
|
|||||||
@@ -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"
|
||||||
|
|||||||
@@ -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
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Reference in New Issue
Block a user