mirror of
https://github.com/tabler/tabler.git
synced 2026-10-12 05:06:55 +04:00
Rework the uptime page, add gauge cards, fix card with code (#3090)
This commit is contained in:
1 parent
06143bf617
commit
3f767ee709
9 files changed
+331
-85
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tabler/preview": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
Fixed the "Card with code" widget rendering its code as plain text instead of a `pre` block.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tabler/preview": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Added a System status panel with 60-day uptime history bars to the Uptime preview page.
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@tabler/preview": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Added ApexCharts gauge cards to the Widgets preview page.
|
||||||
+89
-73
@@ -1,58 +1,102 @@
|
|||||||
---
|
---
|
||||||
import Subheader from '@ui/Subheader.astro'
|
|
||||||
import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
|
import DefaultLayout from '@shared/layouts/DefaultLayout.astro'
|
||||||
import Chart from '@components/demo/Chart.astro'
|
import Chart from '@components/demo/Chart.astro'
|
||||||
import Card from '@ui/Card.astro'
|
import Card from '@ui/Card.astro'
|
||||||
import CardBody from '@ui/CardBody.astro'
|
import CardBody from '@ui/CardBody.astro'
|
||||||
|
import CardHeader from '@ui/CardHeader.astro'
|
||||||
import CardTitle from '@ui/CardTitle.astro'
|
import CardTitle from '@ui/CardTitle.astro'
|
||||||
|
import StatusDot from '@ui/StatusDot.astro'
|
||||||
|
import StatCard from '@components/cards/StatCard.astro'
|
||||||
|
import SystemStatus from '@components/cards/SystemStatus.astro'
|
||||||
|
|
||||||
|
const incidents = [
|
||||||
|
{ color: 'red', title: 'Email delivery outage', date: 'Aug 24, 2026', duration: '42 minutes', resolved: true },
|
||||||
|
{ color: 'yellow', title: 'Slow webhook deliveries', date: 'Aug 12, 2026', duration: '1 hour 8 minutes', resolved: true },
|
||||||
|
{ color: 'yellow', title: 'Dashboard loading slowly', date: 'Aug 3, 2026', duration: '17 minutes', resolved: true },
|
||||||
|
{ color: 'red', title: 'Email delivery outage', date: 'Jul 21, 2026', duration: '2 hours 5 minutes', resolved: true },
|
||||||
|
]
|
||||||
|
|
||||||
|
const periods = [
|
||||||
|
{ period: 'Today', availability: '100%', downtime: 'none', incidents: 0, longest: '–', average: '–' },
|
||||||
|
{ period: 'Last 7 days', availability: '100%', downtime: 'none', incidents: 0, longest: '–', average: '–' },
|
||||||
|
{ period: 'Last 30 days', availability: '99.9028%', downtime: '42 minutes', incidents: 1, longest: '42 minutes', average: '42 minutes' },
|
||||||
|
{ period: 'Last 365 days', availability: '99.9414%', downtime: '5 hours 8 minutes', incidents: 9, longest: '2 hours 5 minutes', average: '34 minutes' },
|
||||||
|
{ period: 'All time', availability: '99.9533%', downtime: '11 hours 40 minutes', incidents: 23, longest: '2 hours 5 minutes', average: '30 minutes' },
|
||||||
|
]
|
||||||
---
|
---
|
||||||
|
|
||||||
<DefaultLayout title="Uptime" pageHeaderFile="uptime" pageMenu="extra.uptime" pageLibs={['apexcharts']}>
|
<DefaultLayout title="Uptime" pageHeaderFile="uptime" pageMenu="extra.uptime" pageLibs={['apexcharts']}>
|
||||||
<div class="row row-cards">
|
<div class="row row-cards">
|
||||||
<div class="col-md-4">
|
<div class="col-sm-6 col-lg-3">
|
||||||
|
<StatCard title="30-day uptime" value="99.9%" icon="activity" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-3">
|
||||||
|
<StatCard title="Currently up for" value="14d 2h 54m" icon="clock" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-3">
|
||||||
|
<StatCard title="Avg. response time" value="142 ms" icon="bolt" />
|
||||||
|
</div>
|
||||||
|
<div class="col-sm-6 col-lg-3">
|
||||||
|
<StatCard title="30-day incidents" value="1" icon="alert-triangle" />
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<SystemStatus id="services" class="h-100" />
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-4">
|
||||||
|
<Card class="h-100">
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Recent incidents</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
|
<div class="list-group list-group-flush">
|
||||||
|
{
|
||||||
|
incidents.map((incident) => (
|
||||||
|
<div class="list-group-item">
|
||||||
|
<div class="row align-items-center">
|
||||||
|
<div class="col-auto">
|
||||||
|
<StatusDot color={incident.color} />
|
||||||
|
</div>
|
||||||
|
<div class="col text-truncate">
|
||||||
|
<div class="fw-medium text-truncate">{incident.title}</div>
|
||||||
|
<div class="text-secondary text-truncate">
|
||||||
|
{incident.date} · {incident.duration}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-auto">
|
||||||
|
<span class="badge bg-green-lt">Resolved</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer mt-auto">
|
||||||
|
<a href="#">View all incidents</a>
|
||||||
|
</div>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
<div class="col-lg-8">
|
||||||
<Card>
|
<Card>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Subheader>Currently up for</Subheader>
|
<CardTitle>Response time in the last 4 months (ms)</CardTitle>
|
||||||
<div class="h3 m-0">14 days 2 hours 54 mins 34 seconds</div>
|
<Chart chartId="uptime" height={15} label="Response time in the last 4 months" />
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4">
|
<div class="col-lg-4">
|
||||||
<Card>
|
<Card>
|
||||||
<CardBody>
|
<CardBody>
|
||||||
<Subheader>Last checked at</Subheader>
|
<CardTitle>Incidents per day</CardTitle>
|
||||||
<div class="h3 m-0">27 seconds ago</div>
|
<Chart chartId="uptime-incidents" height={15} label="Incidents per day" />
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<Card>
|
|
||||||
<CardBody>
|
|
||||||
<Subheader>Incidents</Subheader>
|
|
||||||
<div class="h3 m-0">3</div>
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-8">
|
|
||||||
<Card>
|
|
||||||
<CardBody>
|
|
||||||
<CardTitle>Response times across regions in the last day</CardTitle>
|
|
||||||
<Chart chartId="uptime" height={15} label="Response times across regions in the last day" />
|
|
||||||
</CardBody>
|
|
||||||
</Card>
|
|
||||||
</div>
|
|
||||||
<div class="col-md-4">
|
|
||||||
<Card>
|
|
||||||
<CardBody>
|
|
||||||
<CardTitle>Uptime incidents per day</CardTitle>
|
|
||||||
<Chart chartId="uptime-incidents" height={15} label="Uptime incidents per day" />
|
|
||||||
</CardBody>
|
</CardBody>
|
||||||
</Card>
|
</Card>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
<Card>
|
<Card>
|
||||||
|
<CardHeader>
|
||||||
|
<CardTitle>Availability</CardTitle>
|
||||||
|
</CardHeader>
|
||||||
<div class="card-table table-responsive">
|
<div class="card-table table-responsive">
|
||||||
<table class="table">
|
<table class="table table-vcenter">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>Time period</th>
|
<th>Time period</th>
|
||||||
@@ -63,47 +107,19 @@ import CardTitle from '@ui/CardTitle.astro'
|
|||||||
<th>Avg. incident</th>
|
<th>Avg. incident</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody
|
<tbody>
|
||||||
><tr>
|
{
|
||||||
<td>Today</td>
|
periods.map((row) => (
|
||||||
<td>98.9533%</td>
|
<tr>
|
||||||
<td>1 minute</td>
|
<td>{row.period}</td>
|
||||||
<td>1</td>
|
<td class="fw-medium">{row.availability}</td>
|
||||||
<td>1 minute</td>
|
<td class="text-secondary">{row.downtime}</td>
|
||||||
<td>1 minute</td>
|
<td class="text-secondary">{row.incidents}</td>
|
||||||
</tr>
|
<td class="text-secondary">{row.longest}</td>
|
||||||
<tr>
|
<td class="text-secondary">{row.average}</td>
|
||||||
<td>Last 7 days</td>
|
</tr>
|
||||||
<td>98.9533%</td>
|
))
|
||||||
<td>1 minute</td>
|
}
|
||||||
<td>1</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Last 30 days</td>
|
|
||||||
<td>98.9533%</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>Last 365 days</td>
|
|
||||||
<td>98.9533%</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td>All time</td>
|
|
||||||
<td>98.9533%</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
<td>1</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
<td>1 minute</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -12,9 +12,10 @@ import ProjectSummary from '@shared/components/cards/ProjectSummary.astro'
|
|||||||
import ProjectKanban from '@shared/components/cards/ProjectKanban.astro'
|
import ProjectKanban from '@shared/components/cards/ProjectKanban.astro'
|
||||||
import UserInfo from '@shared/components/cards/UserInfo.astro'
|
import UserInfo from '@shared/components/cards/UserInfo.astro'
|
||||||
import Configuration from '@shared/components/cards/Configuration.astro'
|
import Configuration from '@shared/components/cards/Configuration.astro'
|
||||||
|
import Gauge from '@shared/components/cards/Gauge.astro'
|
||||||
---
|
---
|
||||||
|
|
||||||
<DefaultLayout title="Widgets" pageMenu="extra.widgets">
|
<DefaultLayout title="Widgets" pageMenu="extra.widgets" pageLibs={['apexcharts']}>
|
||||||
<div class="row row-cards">
|
<div class="row row-cards">
|
||||||
<div class="col-12 col-md-6 col-xxl-3 mb-4 mb-xxl-0">
|
<div class="col-12 col-md-6 col-xxl-3 mb-4 mb-xxl-0">
|
||||||
<StatCard title="Earned" value="$2,847" icon="credit-card" countup />
|
<StatCard title="Earned" value="$2,847" icon="credit-card" countup />
|
||||||
@@ -29,6 +30,15 @@ import Configuration from '@shared/components/cards/Configuration.astro'
|
|||||||
<StatCard title="Weekly growth" value="18.4%" icon="discount" countup />
|
<StatCard title="Weekly growth" value="18.4%" icon="discount" countup />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-4">
|
||||||
|
<Gauge id="deliverability" title="Deliverability" value={96} label="delivered" count={48210} total={50219} color="green" description="Share of sent emails accepted by the receiving server. Anything above 95% is healthy." />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<Gauge id="storage" title="Storage used" value={82} label="used" count={410} total={500} color="yellow" description="Disk space taken by uploads and backups, in GB. Consider an upgrade once it passes 80%." />
|
||||||
|
</div>
|
||||||
|
<div class="col-md-4">
|
||||||
|
<Gauge id="onboarding" title="Onboarding" value={58} label="completed" count={1392} total={2400} description="New accounts that finished every setup step. There is no target for this metric yet." />
|
||||||
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<ProjectProgress />
|
<ProjectProgress />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
---
|
---
|
||||||
// Raw CSS text inside .card-code (no highlight markup).
|
// Plain <pre><code> inside .card-code (no highlight markup).
|
||||||
import CardTitle from '@ui/CardTitle.astro'
|
import CardTitle from '@ui/CardTitle.astro'
|
||||||
|
|
||||||
const code = `
|
const code = `.card-footer {
|
||||||
.card-footer {
|
background: transparent;
|
||||||
background: transparent;
|
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-radius: 0 0 1 2;
|
border-radius: 0 0 4px 4px;
|
||||||
}
|
}
|
||||||
}
|
}`
|
||||||
`
|
|
||||||
---
|
---
|
||||||
|
|
||||||
<div class="card">
|
<div class="card">
|
||||||
<div class="card-header">
|
<div class="card-header">
|
||||||
<CardTitle>Card with code</CardTitle>
|
<CardTitle>Card with code</CardTitle>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-code">{code}</div>
|
<div class="card-code">
|
||||||
|
<pre><code>{code}</code></pre>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,91 @@
|
|||||||
|
---
|
||||||
|
import CaptureScript from '../CaptureScript.astro'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id: string
|
||||||
|
title: string
|
||||||
|
description: string
|
||||||
|
value: number
|
||||||
|
label: string
|
||||||
|
count: number
|
||||||
|
total: number
|
||||||
|
countLabel?: string
|
||||||
|
color?: 'green' | 'yellow' | 'neutral'
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id, title, description, value, label, count, total, countLabel = 'of', color = 'neutral' } = Astro.props
|
||||||
|
|
||||||
|
// Needs the `apexcharts` lib on the page (pageLibs / docs-libs).
|
||||||
|
const chartId = `chart-gauge-${id}`
|
||||||
|
const chartColor = color === 'neutral' ? 'var(--tblr-body-color)' : `var(--tblr-${color})`
|
||||||
|
const format = (n: number) => n.toLocaleString('en-US')
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-body">
|
||||||
|
<h3 class="card-title">{title}</h3>
|
||||||
|
<div id={chartId} class="position-relative mx-auto" style="width: 10rem; max-width: 100%" role="img" aria-label={`${title}: ${value}%`}></div>
|
||||||
|
<p class="text-secondary mt-3 mb-0" style="min-height: 2lh">{description}</p>
|
||||||
|
</div>
|
||||||
|
<div class="card-footer d-flex text-secondary">
|
||||||
|
<div><span class="fw-medium text-body">{format(count)}</span> {countLabel} {format(total)}</div>
|
||||||
|
<div class="ms-auto">{format(total - count)} remaining</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<CaptureScript>
|
||||||
|
<!-- BEGIN GAUGE -->
|
||||||
|
<script is:inline define:vars={{ chartId, value, label, chartColor }}>
|
||||||
|
function initGauge() {
|
||||||
|
window.tabler_chart ??= {}
|
||||||
|
|
||||||
|
window.ApexCharts &&
|
||||||
|
(window.tabler_chart[chartId] = new ApexCharts(document.getElementById(chartId), {
|
||||||
|
series: [value],
|
||||||
|
chart: {
|
||||||
|
type: 'radialBar',
|
||||||
|
height: 160,
|
||||||
|
sparkline: {
|
||||||
|
enabled: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plotOptions: {
|
||||||
|
radialBar: {
|
||||||
|
hollow: {
|
||||||
|
size: '64%',
|
||||||
|
},
|
||||||
|
track: {
|
||||||
|
background: 'var(--tblr-border-color)',
|
||||||
|
},
|
||||||
|
dataLabels: {
|
||||||
|
name: {
|
||||||
|
show: true,
|
||||||
|
offsetY: 18,
|
||||||
|
fontSize: '12px',
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
fontWeight: 400,
|
||||||
|
color: 'var(--tblr-secondary)',
|
||||||
|
},
|
||||||
|
value: {
|
||||||
|
show: true,
|
||||||
|
offsetY: -12,
|
||||||
|
fontSize: '24px',
|
||||||
|
fontFamily: 'inherit',
|
||||||
|
fontWeight: 500,
|
||||||
|
color: 'var(--tblr-body-color)',
|
||||||
|
formatter: (val) => `${val}%`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
colors: [chartColor],
|
||||||
|
stroke: {
|
||||||
|
lineCap: 'round',
|
||||||
|
},
|
||||||
|
labels: [label],
|
||||||
|
})).render()
|
||||||
|
}
|
||||||
|
|
||||||
|
document.readyState !== 'loading' ? initGauge() : document.addEventListener('DOMContentLoaded', initGauge, { once: true })
|
||||||
|
</script>
|
||||||
|
<!-- END GAUGE -->
|
||||||
|
</CaptureScript>
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
---
|
||||||
|
import CaptureScript from '../CaptureScript.astro'
|
||||||
|
|
||||||
|
interface Props {
|
||||||
|
id: string
|
||||||
|
services?: string[]
|
||||||
|
days?: number
|
||||||
|
seed?: number
|
||||||
|
class?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
const { id, services = ['API', 'Dashboard', 'Webhooks', 'Email delivery'], days = 60, seed = 18, class: className } = Astro.props
|
||||||
|
|
||||||
|
const cardId = `system-status-${id}`
|
||||||
|
---
|
||||||
|
|
||||||
|
<div class:list={['card', className]} id={cardId}>
|
||||||
|
<div class="card-header">
|
||||||
|
<h3 class="card-title">System status</h3>
|
||||||
|
<div class="card-actions">
|
||||||
|
<span class="status status-green" data-status>
|
||||||
|
<span class="status-dot status-dot-animated"></span>
|
||||||
|
<span data-status-label>All systems operational</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="list-group list-group-flush">
|
||||||
|
{
|
||||||
|
services.map((service) => (
|
||||||
|
<div class="list-group-item">
|
||||||
|
<div class="d-flex align-items-baseline mb-2">
|
||||||
|
<div class="fw-medium">{service}</div>
|
||||||
|
<div class="ms-auto text-secondary">
|
||||||
|
<span data-uptime-value>–</span> uptime
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="tracking" data-uptime={service} />
|
||||||
|
</div>
|
||||||
|
))
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
<div class="card-footer">
|
||||||
|
<div class="d-flex align-items-center text-secondary">
|
||||||
|
<div>{days} days ago</div>
|
||||||
|
<div class="legend-list mx-auto">
|
||||||
|
<span class="legend legend-green"><span class="legend-dot"></span>Operational</span>
|
||||||
|
<span class="legend legend-yellow"><span class="legend-dot"></span>Degraded</span>
|
||||||
|
<span class="legend legend-red"><span class="legend-dot"></span>Outage</span>
|
||||||
|
</div>
|
||||||
|
<div>Today</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<CaptureScript>
|
||||||
|
<!-- BEGIN SYSTEM STATUS -->
|
||||||
|
<script is:inline define:vars={{ cardId, days, seed }}>
|
||||||
|
// Share of days with an outage / degraded performance, and how much a degraded day counts
|
||||||
|
const OUTAGE_RATE = 0.02
|
||||||
|
const DEGRADED_RATE = 0.04
|
||||||
|
const DEGRADED_WEIGHT = 0.5
|
||||||
|
|
||||||
|
const STATUSES = {
|
||||||
|
up: { label: 'Operational', color: 'bg-green' },
|
||||||
|
degraded: { label: 'Degraded performance', color: 'bg-yellow' },
|
||||||
|
down: { label: 'Outage', color: 'bg-red' },
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mulberry32: tiny seeded PRNG, so every load draws the same history
|
||||||
|
function createRandom(seed) {
|
||||||
|
return function () {
|
||||||
|
seed = (seed + 0x6d2b79f5) | 0
|
||||||
|
let t = Math.imul(seed ^ (seed >>> 15), 1 | seed)
|
||||||
|
t = (t + Math.imul(t ^ (t >>> 7), 61 | t)) ^ t
|
||||||
|
return ((t ^ (t >>> 14)) >>> 0) / 4294967296
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function initSystemStatus() {
|
||||||
|
const card = document.getElementById(cardId)
|
||||||
|
const random = createRandom(seed)
|
||||||
|
const today = new Date()
|
||||||
|
let allOperational = true
|
||||||
|
|
||||||
|
card.querySelectorAll('[data-uptime]').forEach((container) => {
|
||||||
|
let score = 0
|
||||||
|
|
||||||
|
for (let i = days - 1; i >= 0; i--) {
|
||||||
|
const roll = random()
|
||||||
|
const status = roll < OUTAGE_RATE ? 'down' : roll < OUTAGE_RATE + DEGRADED_RATE ? 'degraded' : 'up'
|
||||||
|
const date = new Date(today.getFullYear(), today.getMonth(), today.getDate() - i)
|
||||||
|
|
||||||
|
const bar = document.createElement('div')
|
||||||
|
bar.className = 'tracking-block ' + STATUSES[status].color
|
||||||
|
bar.title = date.toLocaleDateString(undefined, { year: 'numeric', month: 'short', day: 'numeric' }) + ' – ' + STATUSES[status].label
|
||||||
|
container.appendChild(bar)
|
||||||
|
|
||||||
|
score += status === 'up' ? 1 : status === 'degraded' ? DEGRADED_WEIGHT : 0
|
||||||
|
}
|
||||||
|
|
||||||
|
if (score < days) allOperational = false
|
||||||
|
|
||||||
|
container.parentElement.querySelector('[data-uptime-value]').textContent = ((score / days) * 100).toFixed(2) + '%'
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!allOperational) {
|
||||||
|
card.querySelector('[data-status]').classList.replace('status-green', 'status-yellow')
|
||||||
|
card.querySelector('[data-status-label]').textContent = 'Some systems affected'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
document.readyState !== 'loading' ? initSystemStatus() : document.addEventListener('DOMContentLoaded', initSystemStatus, { once: true })
|
||||||
|
</script>
|
||||||
|
<!-- END SYSTEM STATUS -->
|
||||||
|
</CaptureScript>
|
||||||
@@ -6,7 +6,7 @@ import PageTitle from '@ui/PageTitle.astro'
|
|||||||
|
|
||||||
<!-- BEGIN HEADER UPTIME -->
|
<!-- BEGIN HEADER UPTIME -->
|
||||||
<div class="page-header d-print-none">
|
<div class="page-header d-print-none">
|
||||||
<div class="container">
|
<div class="container-xl">
|
||||||
<div class="row g-3 align-items-center">
|
<div class="row g-3 align-items-center">
|
||||||
<div class="col-auto">
|
<div class="col-auto">
|
||||||
<span class="status-indicator status-green status-indicator-animated">
|
<span class="status-indicator status-green status-indicator-animated">
|
||||||
|
|||||||
Reference in new issue
Block a user