mirror of
https://github.com/ClusterCockpit/cc-backend
synced 2026-02-17 16:31:45 +01:00
review loading indicators in nodeList
This commit is contained in:
@@ -152,12 +152,21 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
$effect(() => {
|
$effect(() => {
|
||||||
// Triggers (Except Paging)
|
// Update NodeListRows metrics only: Keep ordered nodes on page 1
|
||||||
from, to
|
from, to
|
||||||
pendingSelectedMetrics, selectedResolution
|
pendingSelectedMetrics, selectedResolution
|
||||||
|
// Continous Scroll: Paging if parameters change: Existing entries will not match new selections
|
||||||
|
if (!usePaging) {
|
||||||
|
nodes = [];
|
||||||
|
page = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$effect(() => {
|
||||||
|
// Update NodeListRows metrics only: Keep ordered nodes on page 1
|
||||||
hostnameFilter, hoststateFilter
|
hostnameFilter, hoststateFilter
|
||||||
// Continous Scroll: Paging if parameters change: Existing entries will not match new selections
|
// Continous Scroll: Paging if parameters change: Existing entries will not match new selections
|
||||||
// Nodes Array Reset in HandleNodes func
|
nodes = [];
|
||||||
if (!usePaging) {
|
if (!usePaging) {
|
||||||
page = 1;
|
page = 1;
|
||||||
}
|
}
|
||||||
@@ -255,9 +264,11 @@
|
|||||||
{#each nodes as nodeData (nodeData.host)}
|
{#each nodes as nodeData (nodeData.host)}
|
||||||
<NodeListRow {nodeData} {cluster} {selectedMetrics} {globalMetrics} nodeDataFetching={$nodesStore.fetching}/>
|
<NodeListRow {nodeData} {cluster} {selectedMetrics} {globalMetrics} nodeDataFetching={$nodesStore.fetching}/>
|
||||||
{:else}
|
{:else}
|
||||||
<tr>
|
{#if !$nodesStore.fetching}
|
||||||
<td colspan={selectedMetrics.length + 1}> No nodes found </td>
|
<tr>
|
||||||
</tr>
|
<td colspan={selectedMetrics.length + 1}> No nodes found </td>
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
{/if}
|
{/if}
|
||||||
{#if $nodesStore.fetching || !$nodesStore.data}
|
{#if $nodesStore.fetching || !$nodesStore.data}
|
||||||
|
|||||||
@@ -51,6 +51,8 @@
|
|||||||
|
|
||||||
/* Derived */
|
/* Derived */
|
||||||
// Not at least one returned, selected metric: NodeHealth warning
|
// Not at least one returned, selected metric: NodeHealth warning
|
||||||
|
const fetchInfo = $derived(dataHealth.includes('fetching'));
|
||||||
|
// Not at least one returned, selected metric: NodeHealth warning
|
||||||
const healthWarn = $derived(!dataHealth.includes(true));
|
const healthWarn = $derived(!dataHealth.includes(true));
|
||||||
// At least one non-returned selected metric: Metric config error?
|
// At least one non-returned selected metric: Metric config error?
|
||||||
const metricWarn = $derived(dataHealth.includes(false));
|
const metricWarn = $derived(dataHealth.includes(false));
|
||||||
@@ -84,10 +86,17 @@
|
|||||||
<Row cols={{xs: 1, lg: 2}}>
|
<Row cols={{xs: 1, lg: 2}}>
|
||||||
<Col class="mb-2 mb-lg-0">
|
<Col class="mb-2 mb-lg-0">
|
||||||
<InputGroup size="sm">
|
<InputGroup size="sm">
|
||||||
{#if healthWarn}
|
{#if fetchInfo}
|
||||||
|
<InputGroupText class="flex-grow-1 flex-lg-grow-0">
|
||||||
|
<Icon name="arrow-clockwise" style="padding-right: 0.5rem;"/>
|
||||||
|
</InputGroupText>
|
||||||
|
<Button class="flex-grow-1" color="dark" outline disabled>
|
||||||
|
Fetching
|
||||||
|
</Button>
|
||||||
|
{:else if healthWarn}
|
||||||
<InputGroupText class="flex-grow-1 flex-lg-grow-0">
|
<InputGroupText class="flex-grow-1 flex-lg-grow-0">
|
||||||
<Icon name="exclamation-circle" style="padding-right: 0.5rem;"/>
|
<Icon name="exclamation-circle" style="padding-right: 0.5rem;"/>
|
||||||
<span>Jobs</span>
|
<span>Info</span>
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<Button class="flex-grow-1" color="danger" disabled>
|
<Button class="flex-grow-1" color="danger" disabled>
|
||||||
No Metrics
|
No Metrics
|
||||||
@@ -95,7 +104,7 @@
|
|||||||
{:else if metricWarn}
|
{:else if metricWarn}
|
||||||
<InputGroupText class="flex-grow-1 flex-lg-grow-0">
|
<InputGroupText class="flex-grow-1 flex-lg-grow-0">
|
||||||
<Icon name="info-circle" style="padding-right: 0.5rem;"/>
|
<Icon name="info-circle" style="padding-right: 0.5rem;"/>
|
||||||
<span>Jobs</span>
|
<span>Info</span>
|
||||||
</InputGroupText>
|
</InputGroupText>
|
||||||
<Button class="flex-grow-1" color="warning" disabled>
|
<Button class="flex-grow-1" color="warning" disabled>
|
||||||
Missing Metric
|
Missing Metric
|
||||||
|
|||||||
@@ -74,8 +74,8 @@
|
|||||||
);
|
);
|
||||||
|
|
||||||
const extendedLegendData = $derived($nodeJobsData?.data ? buildExtendedLegend() : null);
|
const extendedLegendData = $derived($nodeJobsData?.data ? buildExtendedLegend() : null);
|
||||||
const refinedData = $derived(!nodeDataFetching ? sortAndSelectScope(selectedMetrics, nodeData.metrics) : []);
|
const refinedData = $derived(nodeData?.metrics ? sortAndSelectScope(selectedMetrics, nodeData.metrics) : []);
|
||||||
const dataHealth = $derived(refinedData.filter((rd) => rd.availability == "configured").map((enabled) => (enabled?.data?.metric?.series?.length > 0)));
|
const dataHealth = $derived(refinedData.filter((rd) => rd.availability == "configured").map((enabled) => (nodeDataFetching ? 'fetching' : enabled?.data?.metric?.series?.length > 0)));
|
||||||
|
|
||||||
/* Functions */
|
/* Functions */
|
||||||
function sortAndSelectScope(metricList = [], nodeMetrics = []) {
|
function sortAndSelectScope(metricList = [], nodeMetrics = []) {
|
||||||
@@ -152,73 +152,69 @@
|
|||||||
hoststate={nodeData?.state? nodeData.state: 'notindb'}/>
|
hoststate={nodeData?.state? nodeData.state: 'notindb'}/>
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
{#if nodeDataFetching}
|
{#each refinedData as metricData, i (metricData?.data?.name || i)}
|
||||||
<td colspan={selectedMetrics.length}>
|
{#key metricData}
|
||||||
<div style="text-align:center; margin-top: 1rem;">
|
<td>
|
||||||
<Spinner secondary />
|
{#if !metricData?.data && nodeDataFetching}
|
||||||
</div>
|
<div style="text-align:center; margin-top: 1rem;">
|
||||||
</td>
|
<Spinner secondary />
|
||||||
{:else}
|
</div>
|
||||||
{#each refinedData as metricData, i (metricData?.data?.name || i)}
|
{:else if metricData?.availability == "none"}
|
||||||
{#key metricData}
|
<Card body class="mx-2" color="light">
|
||||||
<td>
|
<p>No dataset(s) returned for <b>{selectedMetrics[i]}</b></p>
|
||||||
{#if metricData?.availability == "none"}
|
<p class="mb-1">Metric is not configured for cluster <b>{cluster}</b>.</p>
|
||||||
<Card body class="mx-2" color="light">
|
</Card>
|
||||||
<p>No dataset(s) returned for <b>{selectedMetrics[i]}</b></p>
|
{:else if metricData?.availability == "disabled"}
|
||||||
<p class="mb-1">Metric is not configured for cluster <b>{cluster}</b>.</p>
|
<Card body class="mx-2" color="info">
|
||||||
</Card>
|
<p>No dataset(s) returned for <b>{selectedMetrics[i]}</b></p>
|
||||||
{:else if metricData?.availability == "disabled"}
|
<p class="mb-1">Metric has been disabled for subcluster <b>{nodeData.subCluster}</b>.</p>
|
||||||
<Card body class="mx-2" color="info">
|
</Card>
|
||||||
<p>No dataset(s) returned for <b>{selectedMetrics[i]}</b></p>
|
{:else if !metricData?.data}
|
||||||
<p class="mb-1">Metric has been disabled for subcluster <b>{nodeData.subCluster}</b>.</p>
|
<Card body class="mx-2" color="warning">
|
||||||
</Card>
|
<p>No dataset(s) returned for <b>{selectedMetrics[i]}</b></p>
|
||||||
{:else if !metricData?.data}
|
<p class="mb-1">Metric or host was not found in metric store for cluster <b>{cluster}</b>.</p>
|
||||||
<Card body class="mx-2" color="warning">
|
</Card>
|
||||||
<p>No dataset(s) returned for <b>{selectedMetrics[i]}</b></p>
|
{:else if !!metricData.data?.metric.statisticsSeries}
|
||||||
<p class="mb-1">Metric or host was not found in metric store for cluster <b>{cluster}</b>.</p>
|
<!-- "No Data"-Warning included in MetricPlot-Component -->
|
||||||
</Card>
|
<MetricPlot
|
||||||
{:else if !!metricData.data?.metric.statisticsSeries}
|
{cluster}
|
||||||
<!-- "No Data"-Warning included in MetricPlot-Component -->
|
subCluster={nodeData.subCluster}
|
||||||
<MetricPlot
|
metric={metricData.data.name}
|
||||||
{cluster}
|
scope={metricData.data.scope}
|
||||||
subCluster={nodeData.subCluster}
|
timestep={metricData.data.metric.timestep}
|
||||||
metric={metricData.data.name}
|
series={metricData.data.metric.series}
|
||||||
scope={metricData.data.scope}
|
statisticsSeries={metricData.data?.metric.statisticsSeries}
|
||||||
timestep={metricData.data.metric.timestep}
|
useStatsSeries={!!metricData.data?.metric.statisticsSeries}
|
||||||
series={metricData.data.metric.series}
|
height={175}
|
||||||
statisticsSeries={metricData.data?.metric.statisticsSeries}
|
{plotSync}
|
||||||
useStatsSeries={!!metricData.data?.metric.statisticsSeries}
|
forNode
|
||||||
height={175}
|
/>
|
||||||
{plotSync}
|
<div class="my-2"></div>
|
||||||
forNode
|
<MetricPlot
|
||||||
/>
|
{cluster}
|
||||||
<div class="my-2"></div>
|
subCluster={nodeData.subCluster}
|
||||||
<MetricPlot
|
metric={metricData.data.name}
|
||||||
{cluster}
|
scope={metricData.data.scope}
|
||||||
subCluster={nodeData.subCluster}
|
timestep={metricData.data.metric.timestep}
|
||||||
metric={metricData.data.name}
|
series={metricData.data.metric.series}
|
||||||
scope={metricData.data.scope}
|
height={175}
|
||||||
timestep={metricData.data.metric.timestep}
|
{extendedLegendData}
|
||||||
series={metricData.data.metric.series}
|
{plotSync}
|
||||||
height={175}
|
forNode
|
||||||
{extendedLegendData}
|
/>
|
||||||
{plotSync}
|
{:else}
|
||||||
forNode
|
<MetricPlot
|
||||||
/>
|
{cluster}
|
||||||
{:else}
|
subCluster={nodeData.subCluster}
|
||||||
<MetricPlot
|
metric={metricData.data.name}
|
||||||
{cluster}
|
scope={metricData.data.scope}
|
||||||
subCluster={nodeData.subCluster}
|
timestep={metricData.data.metric.timestep}
|
||||||
metric={metricData.data.name}
|
series={metricData.data.metric.series}
|
||||||
scope={metricData.data.scope}
|
height={375}
|
||||||
timestep={metricData.data.metric.timestep}
|
forNode
|
||||||
series={metricData.data.metric.series}
|
/>
|
||||||
height={375}
|
{/if}
|
||||||
forNode
|
</td>
|
||||||
/>
|
{/key}
|
||||||
{/if}
|
{/each}
|
||||||
</td>
|
|
||||||
{/key}
|
|
||||||
{/each}
|
|
||||||
{/if}
|
|
||||||
</tr>
|
</tr>
|
||||||
|
|||||||
Reference in New Issue
Block a user