Skip to content

Commit 5432979

Browse files
committed
Add charts to summary
1 parent 14fc3c4 commit 5432979

13 files changed

+232
-30
lines changed
+8-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package backups
22

3-
import "context"
3+
import (
4+
"context"
45

5-
func (s *Service) GetBackupsQty(ctx context.Context) (int64, error) {
6+
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
7+
)
8+
9+
func (s *Service) GetBackupsQty(
10+
ctx context.Context,
11+
) (dbgen.BackupsServiceGetBackupsQtyRow, error) {
612
return s.dbgen.BackupsServiceGetBackupsQty(ctx)
713
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
-- name: BackupsServiceGetBackupsQty :one
2-
SELECT COUNT(*) FROM backups;
2+
SELECT
3+
COUNT(*) AS all,
4+
SUM(CASE WHEN is_active = true THEN 1 ELSE 0 END) AS active,
5+
SUM(CASE WHEN is_active = false THEN 1 ELSE 0 END) AS inactive
6+
FROM backups;
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package databases
22

3-
import "context"
3+
import (
4+
"context"
45

5-
func (s *Service) GetDatabasesQty(ctx context.Context) (int64, error) {
6+
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
7+
)
8+
9+
func (s *Service) GetDatabasesQty(
10+
ctx context.Context,
11+
) (dbgen.DatabasesServiceGetDatabasesQtyRow, error) {
612
return s.dbgen.DatabasesServiceGetDatabasesQty(ctx)
713
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
-- name: DatabasesServiceGetDatabasesQty :one
2-
SELECT COUNT(*) FROM databases;
2+
SELECT
3+
COUNT(*) AS all,
4+
SUM(CASE WHEN test_ok = true THEN 1 ELSE 0 END) AS healthy,
5+
SUM(CASE WHEN test_ok = false THEN 1 ELSE 0 END) AS unhealthy
6+
FROM databases;
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package destinations
22

3-
import "context"
3+
import (
4+
"context"
45

5-
func (s *Service) GetDestinationsQty(ctx context.Context) (int64, error) {
6+
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
7+
)
8+
9+
func (s *Service) GetDestinationsQty(
10+
ctx context.Context,
11+
) (dbgen.DestinationsServiceGetDestinationsQtyRow, error) {
612
return s.dbgen.DestinationsServiceGetDestinationsQty(ctx)
713
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,6 @@
11
-- name: DestinationsServiceGetDestinationsQty :one
2-
SELECT COUNT(*) FROM destinations;
2+
SELECT
3+
COUNT(*) AS all,
4+
SUM(CASE WHEN test_ok = true THEN 1 ELSE 0 END) AS healthy,
5+
SUM(CASE WHEN test_ok = false THEN 1 ELSE 0 END) AS unhealthy
6+
FROM destinations;
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package executions
22

3-
import "context"
3+
import (
4+
"context"
45

5-
func (s *Service) GetExecutionsQty(ctx context.Context) (int64, error) {
6+
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
7+
)
8+
9+
func (s *Service) GetExecutionsQty(
10+
ctx context.Context,
11+
) (dbgen.ExecutionsServiceGetExecutionsQtyRow, error) {
612
return s.dbgen.ExecutionsServiceGetExecutionsQty(ctx)
713
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,8 @@
11
-- name: ExecutionsServiceGetExecutionsQty :one
2-
SELECT COUNT(*) FROM executions;
2+
SELECT
3+
COUNT(*) AS all,
4+
SUM(CASE WHEN status = 'running' THEN 1 ELSE 0 END) AS running,
5+
SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) AS success,
6+
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed,
7+
SUM(CASE WHEN status = 'deleted' THEN 1 ELSE 0 END) AS deleted
8+
FROM executions;
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,13 @@
11
package restorations
22

3-
import "context"
3+
import (
4+
"context"
45

5-
func (s *Service) GetRestorationsQty(ctx context.Context) (int64, error) {
6+
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
7+
)
8+
9+
func (s *Service) GetRestorationsQty(
10+
ctx context.Context,
11+
) (dbgen.RestorationsServiceGetRestorationsQtyRow, error) {
612
return s.dbgen.RestorationsServiceGetRestorationsQty(ctx)
713
}
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
-- name: RestorationsServiceGetRestorationsQty :one
2-
SELECT COUNT(*) FROM restorations;
2+
SELECT
3+
COUNT(*) AS all,
4+
SUM(CASE WHEN status = 'running' THEN 1 ELSE 0 END) AS running,
5+
SUM(CASE WHEN status = 'success' THEN 1 ELSE 0 END) AS success,
6+
SUM(CASE WHEN status = 'failed' THEN 1 ELSE 0 END) AS failed
7+
FROM restorations;

internal/view/static/libs/chartjs/chartjs-4.4.3.umd.min.js

+20
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/view/web/dashboard/summary/index.go

+143-15
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
package summary
22

33
import (
4+
"fmt"
45
"net/http"
56

67
lucide "github.com/eduardolat/gomponents-lucide"
8+
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
79
"github.com/eduardolat/pgbackweb/internal/util/echoutil"
810
"github.com/eduardolat/pgbackweb/internal/view/web/alpine"
911
"github.com/eduardolat/pgbackweb/internal/view/web/component"
1012
"github.com/eduardolat/pgbackweb/internal/view/web/layout"
13+
"github.com/google/uuid"
1114
"github.com/labstack/echo/v4"
1215
"github.com/maragudk/gomponents"
1316
"github.com/maragudk/gomponents/html"
@@ -46,35 +49,160 @@ func (h *handlers) indexPageHandler(c echo.Context) error {
4649
}
4750

4851
func indexPage(
49-
databasesQty, destinationsQty, backupsQty, executionsQty, restorationsQty int64,
52+
databasesQty dbgen.DatabasesServiceGetDatabasesQtyRow,
53+
destinationsQty dbgen.DestinationsServiceGetDestinationsQtyRow,
54+
backupsQty dbgen.BackupsServiceGetBackupsQtyRow,
55+
executionsQty dbgen.ExecutionsServiceGetExecutionsQtyRow,
56+
restorationsQty dbgen.RestorationsServiceGetRestorationsQtyRow,
5057
) gomponents.Node {
51-
countCard := func(title string, count int64) gomponents.Node {
58+
type ChartData struct {
59+
Label string
60+
Labels []string
61+
Data []int64
62+
BgColors []string
63+
}
64+
65+
countCard := func(
66+
title string,
67+
count int64,
68+
chartData ChartData,
69+
) gomponents.Node {
70+
var chart gomponents.Node
71+
if len(chartData.Data) > 0 {
72+
chartID := "chart-" + uuid.NewString()
73+
74+
labels := ""
75+
for _, label := range chartData.Labels {
76+
labels += fmt.Sprintf("'%s',", label)
77+
}
78+
79+
areAllZero := true
80+
for _, d := range chartData.Data {
81+
if d != 0 {
82+
areAllZero = false
83+
break
84+
}
85+
}
86+
87+
data := ""
88+
for _, d := range chartData.Data {
89+
if areAllZero {
90+
data += "-1,"
91+
continue
92+
}
93+
data += fmt.Sprintf("%d,", d)
94+
}
95+
96+
bgColors := ""
97+
for _, color := range chartData.BgColors {
98+
if areAllZero {
99+
bgColors += "'#e5e6e6',"
100+
continue
101+
}
102+
bgColors += fmt.Sprintf("'%s',", color)
103+
}
104+
105+
chart = html.Div(
106+
html.Class("mt-2"),
107+
html.Div(html.Canvas(html.ID(chartID))),
108+
html.Script(gomponents.Raw(`
109+
new Chart(document.getElementById('`+chartID+`'), {
110+
type: 'doughnut',
111+
data: {
112+
labels: [`+labels+`],
113+
datasets: [{
114+
label: '`+chartData.Label+`',
115+
data: [`+data+`],
116+
backgroundColor: [`+bgColors+`],
117+
borderColor: 'rgba(0, 0, 0, 0)',
118+
borderWidth: 0
119+
}]
120+
},
121+
options: {
122+
plugins: {
123+
legend: {
124+
position: 'bottom'
125+
},
126+
tooltip: {
127+
callbacks: {
128+
label: function(tooltipItem) {
129+
let value = tooltipItem.raw;
130+
if (value === -1) {
131+
value = 0;
132+
}
133+
return tooltipItem.label + ': ' + value;
134+
}
135+
}
136+
}
137+
}
138+
}
139+
});
140+
`)),
141+
)
142+
}
143+
52144
return component.CardBox(component.CardBoxParams{
53-
Class: "text-center",
145+
Class: "text-center max-w-[250px]",
54146
Children: []gomponents.Node{
55-
component.H2Text(title),
56-
html.Span(
57-
html.Class("text-5xl font-bold"),
58-
gomponents.Textf("%d", count),
59-
),
147+
component.H2Text(fmt.Sprintf("%d %s", count, title)),
148+
chart,
60149
},
61150
})
62151
}
63152

153+
const (
154+
greenColor = "#00a96e"
155+
redColor = "#ff5861"
156+
yellowColor = "#ffbe00"
157+
blueColor = "#00b6ff"
158+
)
159+
64160
content := []gomponents.Node{
65161
component.H1Text("Summary"),
66162
html.Div(
67-
html.Class("mt-4 grid grid-cols-5 gap-4"),
68-
countCard("Databases", databasesQty),
69-
countCard("Destinations", destinationsQty),
70-
countCard("Backups", backupsQty),
71-
countCard("Executions", executionsQty),
72-
countCard("Restorations", restorationsQty),
163+
html.Class("mt-4 flex justify-start flex-wrap gap-4"),
164+
165+
countCard("Databases", databasesQty.All, ChartData{
166+
Label: "Quantity",
167+
Labels: []string{"Healthy", "Unhealthy"},
168+
Data: []int64{databasesQty.Healthy, databasesQty.Unhealthy},
169+
BgColors: []string{greenColor, redColor},
170+
}),
171+
countCard("Destinations", destinationsQty.All, ChartData{
172+
Label: "Quantity",
173+
Labels: []string{"Healthy", "Unhealthy"},
174+
Data: []int64{destinationsQty.Healthy, destinationsQty.Unhealthy},
175+
BgColors: []string{greenColor, redColor},
176+
}),
177+
countCard("Backups", backupsQty.All, ChartData{
178+
Label: "Quantity",
179+
Labels: []string{"Active", "Inactive"},
180+
Data: []int64{backupsQty.Active, backupsQty.Inactive},
181+
BgColors: []string{greenColor, redColor},
182+
}),
183+
countCard("Executions", executionsQty.All, ChartData{
184+
Label: "Status",
185+
Labels: []string{"Running", "Success", "Failed", "Deleted"},
186+
Data: []int64{
187+
executionsQty.Running, executionsQty.Success, executionsQty.Failed,
188+
executionsQty.Deleted,
189+
},
190+
BgColors: []string{blueColor, greenColor, redColor, yellowColor},
191+
}),
192+
countCard("Restorations", restorationsQty.All, ChartData{
193+
Label: "Status",
194+
Labels: []string{"Running", "Success", "Failed"},
195+
Data: []int64{
196+
restorationsQty.Running, restorationsQty.Success,
197+
restorationsQty.Failed,
198+
},
199+
BgColors: []string{blueColor, greenColor, redColor},
200+
}),
73201
),
74202
html.Div(
75203
alpine.XData("genericSlider(4)"),
76204
alpine.XCloak(),
77-
html.Class("mt-6 flex flex-col justify-center items-center"),
205+
html.Class("mt-6 flex flex-col justify-center items-start"),
78206
component.H2Text("How to use PG Back Web"),
79207

80208
component.CardBox(component.CardBoxParams{

internal/view/web/layout/dashboard.go

+1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ func Dashboard(params DashboardParams) gomponents.Node {
2727

2828
html.Script(html.Src("/libs/htmx/htmx-2.0.1.min.js"), html.Defer()),
2929
html.Script(html.Src("/libs/alpinejs/alpinejs-3.14.1.min.js"), html.Defer()),
30+
html.Script(html.Src("/libs/chartjs/chartjs-4.4.3.umd.min.js")),
3031
html.Script(html.Src("/libs/theme-change/theme-change-2.0.2.min.js")),
3132

3233
html.Link(html.Rel("stylesheet"), html.Href("/libs/notyf/notyf-3.10.0.min.css")),

0 commit comments

Comments
 (0)