use javascript chart instead of svg
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"vctp/components/core"
|
||||
)
|
||||
import "vctp/components/core"
|
||||
|
||||
type SnapshotEntry struct {
|
||||
Label string
|
||||
@@ -18,10 +15,10 @@ type VcenterLink struct {
|
||||
}
|
||||
|
||||
type VcenterTotalsEntry struct {
|
||||
Snapshot string
|
||||
RawTime int64
|
||||
VmCount int64
|
||||
VcpuTotal int64
|
||||
Snapshot string
|
||||
RawTime int64
|
||||
VmCount int64
|
||||
VcpuTotal int64
|
||||
RamTotalGB int64
|
||||
}
|
||||
|
||||
@@ -37,20 +34,7 @@ type VcenterTotalsMeta struct {
|
||||
}
|
||||
|
||||
type VcenterChartData struct {
|
||||
PointsVm string
|
||||
PointsVcpu string
|
||||
PointsRam string
|
||||
Width int
|
||||
Height int
|
||||
GridX []float64
|
||||
GridY []float64
|
||||
YTicks []ChartTick
|
||||
XTicks []ChartTick
|
||||
}
|
||||
|
||||
type ChartTick struct {
|
||||
Pos float64
|
||||
Label string
|
||||
ConfigJSON string
|
||||
}
|
||||
|
||||
templ SnapshotHourlyList(entries []SnapshotEntry) {
|
||||
@@ -75,17 +59,16 @@ templ SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) {
|
||||
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<div class="web2-pill">Snapshot Library</div>
|
||||
<h1 class="mt-3 text-4xl font-bold">{title}</h1>
|
||||
<p class="mt-2 text-sm text-slate-600">{subtitle}</p>
|
||||
<h1 class="mt-3 text-4xl font-bold">{ title }</h1>
|
||||
<p class="mt-2 text-sm text-slate-600">{ subtitle }</p>
|
||||
</div>
|
||||
<a class="web2-button" href="/">Back to Dashboard</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="web2-card">
|
||||
<div class="flex items-center justify-between gap-3 mb-4 flex-wrap">
|
||||
<h2 class="text-lg font-semibold">Available Exports</h2>
|
||||
<span class="web2-badge">{len(entries)} files</span>
|
||||
<span class="web2-badge">{ len(entries) } files</span>
|
||||
</div>
|
||||
<div class="overflow-hidden border border-slate-200 rounded">
|
||||
<table class="web2-table">
|
||||
@@ -100,20 +83,20 @@ templ SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) {
|
||||
for i, entry := range entries {
|
||||
if entry.Group != "" && (i == 0 || entries[i-1].Group != entry.Group) {
|
||||
<tr class="web2-group-row">
|
||||
<td colspan="3" class="font-semibold text-slate-700">{entry.Group}</td>
|
||||
<td colspan="3" class="font-semibold text-slate-700">{ entry.Group }</td>
|
||||
</tr>
|
||||
}
|
||||
<tr>
|
||||
<td>
|
||||
<div class="flex flex-col">
|
||||
<span class="text-sm font-semibold text-slate-700">{entry.Label}</span>
|
||||
<span class="text-sm font-semibold text-slate-700">{ entry.Label }</span>
|
||||
</div>
|
||||
</td>
|
||||
<td>
|
||||
<span class="web2-badge">{entry.Count} records</span>
|
||||
<span class="web2-badge">{ entry.Count } records</span>
|
||||
</td>
|
||||
<td class="text-right">
|
||||
<a class="web2-link" href={entry.Link}>Download XLSX</a>
|
||||
<a class="web2-link" href={ entry.Link }>Download XLSX</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@@ -143,11 +126,10 @@ templ VcenterList(links []VcenterLink) {
|
||||
<a class="web2-button" href="/">Back to Dashboard</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="web2-card">
|
||||
<div class="flex items-center justify-between gap-3 mb-4 flex-wrap">
|
||||
<h2 class="text-lg font-semibold">vCenters</h2>
|
||||
<span class="web2-badge">{len(links)} total</span>
|
||||
<span class="web2-badge">{ len(links) } total</span>
|
||||
</div>
|
||||
<div class="overflow-hidden border border-slate-200 rounded">
|
||||
<table class="web2-table">
|
||||
@@ -160,9 +142,9 @@ templ VcenterList(links []VcenterLink) {
|
||||
<tbody>
|
||||
for _, link := range links {
|
||||
<tr>
|
||||
<td class="font-semibold text-slate-700">{link.Name}</td>
|
||||
<td class="font-semibold text-slate-700">{ link.Name }</td>
|
||||
<td class="text-right">
|
||||
<a class="web2-link" href={link.Link}>View Totals</a>
|
||||
<a class="web2-link" href={ link.Link }>View Totals</a>
|
||||
</td>
|
||||
</tr>
|
||||
}
|
||||
@@ -177,84 +159,48 @@ templ VcenterList(links []VcenterLink) {
|
||||
}
|
||||
|
||||
templ VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart VcenterChartData, meta VcenterTotalsMeta) {
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@core.Header()
|
||||
<body class="flex flex-col min-h-screen web2-bg">
|
||||
<main class="flex-grow web2-shell space-y-8 max-w-screen-2xl mx-auto" style="max-width: 1400px;">
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
@core.Header()
|
||||
<body class="flex flex-col min-h-screen web2-bg">
|
||||
<main class="flex-grow web2-shell web2-shell-wide space-y-8 max-w-screen-2xl mx-auto" style="max-width: 1400px; width: 100%;">
|
||||
<section class="web2-header">
|
||||
<div class="flex flex-col gap-4 md:flex-row md:items-center md:justify-between">
|
||||
<div>
|
||||
<div class="web2-pill">vCenter Totals</div>
|
||||
<h1 class="mt-3 text-4xl font-bold">Totals for {vcenter}</h1>
|
||||
<p class="mt-2 text-sm text-slate-600">{meta.TypeLabel} snapshots of VM count, vCPU, and RAM over time.</p>
|
||||
</div>
|
||||
<div class="flex gap-3">
|
||||
<a class="web2-button secondary" href="/vcenters">All vCenters</a>
|
||||
<a class="web2-button" href="/">Dashboard</a>
|
||||
</div>
|
||||
<div class="web2-pill">vCenter Totals</div>
|
||||
<h1 class="mt-3 text-4xl font-bold">Totals for { vcenter }</h1>
|
||||
<p class="mt-2 text-sm text-slate-600">{ meta.TypeLabel } snapshots of VM count, vCPU, and RAM over time.</p>
|
||||
</div>
|
||||
<div class="web3-button-group mt-8 mb-3">
|
||||
<a class={meta.HourlyClass} href={meta.HourlyLink}>Hourly</a>
|
||||
<a class={meta.DailyClass} href={meta.DailyLink}>Daily</a>
|
||||
<a class={meta.MonthlyClass} href={meta.MonthlyLink}>Monthly</a>
|
||||
<div class="flex gap-3">
|
||||
<a class="web2-button secondary" href="/vcenters">All vCenters</a>
|
||||
<a class="web2-button" href="/">Dashboard</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="web2-card">
|
||||
<div class="flex items-center justify-between gap-3 mb-4 flex-wrap">
|
||||
<h2 class="text-lg font-semibold">{meta.TypeLabel} Snapshots</h2>
|
||||
<span class="web2-badge">{len(entries)} records</span>
|
||||
</div>
|
||||
if chart.PointsVm != "" {
|
||||
</div>
|
||||
<div class="web3-button-group mt-8 mb-3">
|
||||
<a class={ meta.HourlyClass } href={ meta.HourlyLink }>Hourly</a>
|
||||
<a class={ meta.DailyClass } href={ meta.DailyLink }>Daily</a>
|
||||
<a class={ meta.MonthlyClass } href={ meta.MonthlyLink }>Monthly</a>
|
||||
</div>
|
||||
</section>
|
||||
<section class="web2-card">
|
||||
<div class="flex items-center justify-between gap-3 mb-4 flex-wrap">
|
||||
<h2 class="text-lg font-semibold">{ meta.TypeLabel } Snapshots</h2>
|
||||
<span class="web2-badge">{ len(entries) } records</span>
|
||||
</div>
|
||||
if chart.ConfigJSON != "" {
|
||||
<div class="mb-6 overflow-auto">
|
||||
<svg width="100%" height={fmt.Sprintf("%d", chart.Height+80)} viewBox={"0 0 " + fmt.Sprintf("%d", chart.Width) + " " + fmt.Sprintf("%d", chart.Height+70)} role="img" aria-label="Totals over time">
|
||||
<defs>
|
||||
<linearGradient id="grid" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#e2e8f0" stop-opacity="0.6"></stop>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<rect x="40" y="10" width={fmt.Sprintf("%d", chart.Width-60)} height={fmt.Sprintf("%d", chart.Height)} fill="white" stroke="#e2e8f0"></rect>
|
||||
<!-- grid lines -->
|
||||
<g stroke="#e2e8f0" stroke-width="1" stroke-dasharray="2,4">
|
||||
for _, y := range chart.GridY {
|
||||
<line x1="40" y1={fmt.Sprintf("%.1f", y)} x2={fmt.Sprintf("%d", chart.Width-20)} y2={fmt.Sprintf("%.1f", y)} />
|
||||
}
|
||||
for _, x := range chart.GridX {
|
||||
<line x1={fmt.Sprintf("%.1f", x)} y1="10" x2={fmt.Sprintf("%.1f", x)} y2={fmt.Sprintf("%d", chart.Height+10)} />
|
||||
}
|
||||
</g>
|
||||
<!-- axes -->
|
||||
<line x1="40" y1={fmt.Sprintf("%d", chart.Height+10)} x2={fmt.Sprintf("%d", chart.Width-20)} y2={fmt.Sprintf("%d", chart.Height+10)} stroke="#94a3b8" stroke-width="1.5"></line>
|
||||
<line x1="40" y1="10" x2="40" y2={fmt.Sprintf("%d", chart.Height+10)} stroke="#94a3b8" stroke-width="1.5"></line>
|
||||
<!-- data -->
|
||||
<polyline points={chart.PointsVm} fill="none" stroke="#2563eb" stroke-width="2.5"></polyline>
|
||||
<polyline points={chart.PointsVcpu} fill="none" stroke="#16a34a" stroke-width="2.5"></polyline>
|
||||
<polyline points={chart.PointsRam} fill="none" stroke="#ea580c" stroke-width="2.5"></polyline>
|
||||
<!-- tick labels -->
|
||||
<g font-size="10" fill="#475569" text-anchor="end">
|
||||
for _, tick := range chart.YTicks {
|
||||
<text x="36" y={fmt.Sprintf("%.1f", tick.Pos+3)}>{tick.Label}</text>
|
||||
}
|
||||
</g>
|
||||
<g font-size="10" fill="#475569" text-anchor="middle">
|
||||
for _, tick := range chart.XTicks {
|
||||
<text x={fmt.Sprintf("%.1f", tick.Pos)} y={fmt.Sprintf("%d", chart.Height+24)}>{tick.Label}</text>
|
||||
}
|
||||
</g>
|
||||
<!-- legend -->
|
||||
<g font-size="12" fill="#475569" transform={"translate(40 " + fmt.Sprintf("%d", chart.Height+54) + ")"}>
|
||||
<rect x="0" y="0" width="14" height="8" fill="#2563eb"></rect><text x="22" y="12">VMs</text>
|
||||
<rect x="90" y="0" width="14" height="8" fill="#16a34a"></rect><text x="112" y="12">vCPU</text>
|
||||
<rect x="180" y="0" width="14" height="8" fill="#ea580c"></rect><text x="202" y="12">RAM (GB)</text>
|
||||
</g>
|
||||
<!-- axis labels -->
|
||||
<text x="15" y="20" transform={"rotate(-90 15 20)"} font-size="12" fill="#475569">Totals</text>
|
||||
<text x={fmt.Sprintf("%d", chart.Width/2)} y={fmt.Sprintf("%d", chart.Height+70)} font-size="12" fill="#475569">Snapshot sequence (newest right)</text>
|
||||
</svg>
|
||||
<div class="web3-chart-frame">
|
||||
<canvas id="vcenter-totals-chart" class="web3-chart-canvas" role="img" aria-label="Totals over time" data-chart-config={ chart.ConfigJSON }></canvas>
|
||||
<div id="vcenter-totals-tooltip" class="web3-chart-tooltip" aria-hidden="true"></div>
|
||||
</div>
|
||||
<script>
|
||||
window.Web3Charts.renderFromDataset({
|
||||
canvasId: "vcenter-totals-chart",
|
||||
tooltipId: "vcenter-totals-tooltip",
|
||||
})
|
||||
</script>
|
||||
</div>
|
||||
}
|
||||
|
||||
<div class="overflow-hidden border border-slate-200 rounded">
|
||||
<table class="web2-table">
|
||||
<thead>
|
||||
@@ -268,10 +214,10 @@ templ VcenterTotalsPage(vcenter string, entries []VcenterTotalsEntry, chart Vcen
|
||||
<tbody>
|
||||
for _, entry := range entries {
|
||||
<tr>
|
||||
<td>{entry.Snapshot}</td>
|
||||
<td class="text-right">{entry.VmCount}</td>
|
||||
<td class="text-right">{entry.VcpuTotal}</td>
|
||||
<td class="text-right">{entry.RamTotalGB}</td>
|
||||
<td>{ entry.Snapshot }</td>
|
||||
<td class="text-right">{ entry.VmCount }</td>
|
||||
<td class="text-right">{ entry.VcpuTotal }</td>
|
||||
<td class="text-right">{ entry.RamTotalGB }</td>
|
||||
</tr>
|
||||
}
|
||||
</tbody>
|
||||
|
||||
Reference in New Issue
Block a user