Compare commits
2 commits
a67a3fdc87
...
b7aac5d59d
| Author | SHA1 | Date | |
|---|---|---|---|
|
b7aac5d59d |
|||
|
fbd2eb5797 |
10 changed files with 205 additions and 3 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
|
@ -1,3 +1,5 @@
|
|||
/borgmatic-monitor
|
||||
/env.sh
|
||||
/example.json
|
||||
/build
|
||||
|
||||
|
|
|
|||
BIN
build/bgm-client
BIN
build/bgm-client
Binary file not shown.
BIN
build/bgm-server
BIN
build/bgm-server
Binary file not shown.
|
|
@ -23,6 +23,9 @@ func main() {
|
|||
|
||||
e.GET("/", web.Hosts)
|
||||
e.GET("/host/:id", web.Host)
|
||||
e.Any("/host/new", web.HostCreate)
|
||||
e.Any("/host/:id/edit", web.HostUpdate)
|
||||
e.POST("/host/:id/delete", web.HostDelete)
|
||||
e.POST("/api/v1/borgmatic/infos", web.ApiBorgmaticInfos)
|
||||
|
||||
docs.SwaggerInfo.Title = "Borgmatic monitor"
|
||||
|
|
|
|||
4
go.mod
4
go.mod
|
|
@ -21,11 +21,13 @@ require (
|
|||
github.com/go-openapi/swag/typeutils v0.25.4 // indirect
|
||||
github.com/go-openapi/swag/yamlutils v0.25.4 // indirect
|
||||
github.com/go-sql-driver/mysql v1.8.1 // indirect
|
||||
github.com/iancoleman/strcase v0.3.0 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/labstack/echo/v5 v5.0.4 // indirect
|
||||
github.com/mailru/easyjson v0.9.1 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0 // indirect
|
||||
|
|
@ -37,6 +39,8 @@ require (
|
|||
github.com/swaggo/swag/v2 v2.0.0-rc5 // indirect
|
||||
github.com/urfave/cli/v2 v2.27.5 // indirect
|
||||
github.com/urfave/cli/v3 v3.6.2 // indirect
|
||||
github.com/yassinebenaid/godump v0.11.1 // indirect
|
||||
gitnet.fr/deblan/go-form v1.5.0 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.3 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/mod v0.33.0 // indirect
|
||||
|
|
|
|||
8
go.sum
8
go.sum
|
|
@ -50,6 +50,8 @@ github.com/go-openapi/swag/yamlutils v0.25.4 h1:6jdaeSItEUb7ioS9lFoCZ65Cne1/RZtP
|
|||
github.com/go-openapi/swag/yamlutils v0.25.4/go.mod h1:MNzq1ulQu+yd8Kl7wPOut/YHAAU/H6hL91fF+E2RFwc=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/iancoleman/strcase v0.3.0 h1:nTXanmYxhfFAMjZL34Ov6gkzEsSJZ5DbhxWjvSASxEI=
|
||||
github.com/iancoleman/strcase v0.3.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
|
||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
|
|
@ -68,6 +70,8 @@ github.com/mailru/easyjson v0.7.6 h1:8yTIVnZgCoiM1TgqoeTl+LfU5Jg6/xL3QhGQnimLYnA
|
|||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||
github.com/mailru/easyjson v0.9.1 h1:LbtsOm5WAswyWbvTEOqhypdPeZzHavpZx96/n553mR8=
|
||||
github.com/mailru/easyjson v0.9.1/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
|
|
@ -98,6 +102,10 @@ github.com/urfave/cli/v2 v2.27.5 h1:WoHEJLdsXr6dDWoJgMq/CboDmyY/8HMMH1fTECbih+w=
|
|||
github.com/urfave/cli/v2 v2.27.5/go.mod h1:3Sevf16NykTbInEnD0yKkjDAeZDS0A6bzhBH5hrMvTQ=
|
||||
github.com/urfave/cli/v3 v3.6.2 h1:lQuqiPrZ1cIz8hz+HcrG0TNZFxU70dPZ3Yl+pSrH9A8=
|
||||
github.com/urfave/cli/v3 v3.6.2/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso=
|
||||
github.com/yassinebenaid/godump v0.11.1 h1:SPujx/XaYqGDfmNh7JI3dOyCUVrG0bG2duhO3Eh2EhI=
|
||||
github.com/yassinebenaid/godump v0.11.1/go.mod h1:dc/0w8wmg6kVIvNGAzbKH1Oa54dXQx8SNKh4dPRyW44=
|
||||
gitnet.fr/deblan/go-form v1.5.0 h1:DHRP8kXTMYVtBsTBej6f+oLfpOxp3Ga3PcNpEwm9eqc=
|
||||
gitnet.fr/deblan/go-form v1.5.0/go.mod h1:jE0cvyDshY1XKmPbjm2ywRl245iSl+ghWj8ANUqU0Fg=
|
||||
go.yaml.in/yaml/v2 v2.4.3 h1:6gvOSjQoTB3vt1l+CU+tSyi/HOjfOjRLJ4YwYZGwRO0=
|
||||
go.yaml.in/yaml/v2 v2.4.3/go.mod h1:zSxWcmIDjOzPXpjlTTbAsKokqkDNAVtZO0WOMiT90s8=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
|
|
|
|||
51
pkg/types/host.go
Normal file
51
pkg/types/host.go
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
"gitnet.fr/deblan/borgmatic-monitor/pkg/database/model"
|
||||
"gitnet.fr/deblan/go-form/form"
|
||||
"gitnet.fr/deblan/go-form/validation"
|
||||
)
|
||||
|
||||
func NewHostForm() *form.Form {
|
||||
f := form.NewForm(
|
||||
form.
|
||||
NewFieldText("Name").
|
||||
WithOptions(form.NewOption("label", "Name")).
|
||||
WithConstraints(validation.NewNotBlank()),
|
||||
form.
|
||||
NewSubmit("submit").
|
||||
WithOptions(form.NewOption("attr", form.Attrs{
|
||||
"class": "mt-2 btn btn-primary",
|
||||
})),
|
||||
)
|
||||
|
||||
f.
|
||||
WithName("form").
|
||||
WithMethod(http.MethodPost).
|
||||
End()
|
||||
|
||||
return f
|
||||
}
|
||||
|
||||
func NewHostDeleteForm(host *model.Host) *form.Form {
|
||||
btn := form.
|
||||
NewSubmit("delete").
|
||||
WithOptions(form.NewOption("attr", form.Attrs{
|
||||
"class": "btn btn-danger",
|
||||
"onclick": "return confirm('Are you sure?')",
|
||||
}))
|
||||
|
||||
btn.Data = "Delete"
|
||||
|
||||
f := form.NewForm(btn)
|
||||
|
||||
f.
|
||||
WithMethod(http.MethodPost).
|
||||
WithAction(fmt.Sprintf("/host/%d/delete", host.ID)).
|
||||
End()
|
||||
|
||||
return f
|
||||
}
|
||||
128
pkg/web/host.go
128
pkg/web/host.go
|
|
@ -8,7 +8,11 @@ import (
|
|||
"github.com/labstack/echo/v5"
|
||||
"github.com/spf13/cast"
|
||||
"gitnet.fr/deblan/borgmatic-monitor/pkg/database"
|
||||
"gitnet.fr/deblan/borgmatic-monitor/pkg/database/model"
|
||||
"gitnet.fr/deblan/borgmatic-monitor/pkg/types"
|
||||
"gitnet.fr/deblan/borgmatic-monitor/pkg/web/partial"
|
||||
"gitnet.fr/deblan/go-form/theme"
|
||||
"gorm.io/gorm/clause"
|
||||
|
||||
. "maragu.dev/gomponents"
|
||||
. "maragu.dev/gomponents/html"
|
||||
|
|
@ -69,8 +73,18 @@ func Host(c *echo.Context) error {
|
|||
Div(
|
||||
Class("container-fluid"),
|
||||
Div(
|
||||
Class("d-flex justify-content-end"),
|
||||
partial.Paginate(fmt.Sprintf("/host/%d?page=%%page%%", host.ID), page, maxPages),
|
||||
Class("d-flex justify-content-end mb-3"),
|
||||
Div(
|
||||
A(
|
||||
Class("btn btn-primary"),
|
||||
Href(fmt.Sprintf("/host/%d/edit", host.ID)),
|
||||
Text("Edit"),
|
||||
),
|
||||
),
|
||||
Div(
|
||||
Class("ms-2"),
|
||||
partial.Paginate(fmt.Sprintf("/host/%d?page=%%page%%", host.ID), page, maxPages),
|
||||
),
|
||||
),
|
||||
Div(
|
||||
Class("row"),
|
||||
|
|
@ -81,3 +95,113 @@ func Host(c *echo.Context) error {
|
|||
),
|
||||
))
|
||||
}
|
||||
|
||||
func HostCreate(c *echo.Context) error {
|
||||
host := new(model.Host)
|
||||
|
||||
f := types.NewHostForm()
|
||||
f.WithAction(c.Request().RequestURI)
|
||||
f.Mount(host)
|
||||
render := theme.NewRenderer(theme.Bootstrap5)
|
||||
|
||||
if c.Request().Method == f.Method {
|
||||
f.HandleRequest(c.Request())
|
||||
|
||||
if f.IsSubmitted() && f.IsValid() {
|
||||
f.Bind(host)
|
||||
|
||||
database.GetDb().Save(&host)
|
||||
|
||||
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/host/%d", host.ID))
|
||||
}
|
||||
}
|
||||
|
||||
return c.HTML(http.StatusOK, Page(
|
||||
"home",
|
||||
"New host",
|
||||
Div(
|
||||
Class("container-fluid"),
|
||||
Div(
|
||||
Class("d-flex justify-content-end"),
|
||||
),
|
||||
Div(
|
||||
Class("row"),
|
||||
Div(
|
||||
Class("col-12"),
|
||||
Raw(string(render.RenderForm(f))),
|
||||
),
|
||||
),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
func HostUpdate(c *echo.Context) error {
|
||||
id := cast.ToInt(c.Param("id"))
|
||||
|
||||
if id == 0 {
|
||||
return c.HTML(http.StatusNotFound, "Not found.")
|
||||
}
|
||||
|
||||
host := database.Host(id)
|
||||
|
||||
if host == nil {
|
||||
return c.HTML(http.StatusNotFound, "Not found.")
|
||||
}
|
||||
|
||||
f := types.NewHostForm()
|
||||
f.WithAction(c.Request().RequestURI)
|
||||
f.Mount(host)
|
||||
render := theme.NewRenderer(theme.Bootstrap5)
|
||||
|
||||
if c.Request().Method == f.Method {
|
||||
f.HandleRequest(c.Request())
|
||||
|
||||
if f.IsSubmitted() && f.IsValid() {
|
||||
f.Bind(host)
|
||||
|
||||
database.GetDb().Save(&host)
|
||||
|
||||
return c.Redirect(http.StatusSeeOther, fmt.Sprintf("/host/%d", host.ID))
|
||||
}
|
||||
}
|
||||
|
||||
return c.HTML(http.StatusOK, Page(
|
||||
fmt.Sprintf("host_%d", host.ID),
|
||||
host.Name,
|
||||
Div(
|
||||
Class("container-fluid"),
|
||||
Div(
|
||||
Class("d-flex justify-content-end mb-3"),
|
||||
Raw(string(render.RenderForm(types.NewHostDeleteForm(host)))),
|
||||
),
|
||||
Div(
|
||||
Class("row"),
|
||||
Div(
|
||||
Class("col-12"),
|
||||
Raw(string(render.RenderForm(f))),
|
||||
),
|
||||
),
|
||||
),
|
||||
))
|
||||
}
|
||||
|
||||
func HostDelete(c *echo.Context) error {
|
||||
id := cast.ToInt(c.Param("id"))
|
||||
|
||||
if id == 0 {
|
||||
return c.HTML(http.StatusNotFound, "Not found.")
|
||||
}
|
||||
|
||||
host := database.Host(id)
|
||||
|
||||
if host == nil {
|
||||
return c.HTML(http.StatusNotFound, "Not found.")
|
||||
}
|
||||
|
||||
database.GetDb().
|
||||
Unscoped().
|
||||
Select(clause.Associations).
|
||||
Delete(&host)
|
||||
|
||||
return c.Redirect(http.StatusSeeOther, "/")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,6 +22,16 @@ func Hosts(c *echo.Context) error {
|
|||
"Hosts",
|
||||
Div(
|
||||
Class("container-fluid"),
|
||||
Div(
|
||||
Class("d-flex justify-content-end mb-3"),
|
||||
Div(
|
||||
A(
|
||||
Class("btn btn-primary"),
|
||||
Href("/host/new"),
|
||||
Text("Create"),
|
||||
),
|
||||
),
|
||||
),
|
||||
Div(
|
||||
Class("row"),
|
||||
Group(nodes),
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ func Paginate(path string, currentPage int, pages int) Node {
|
|||
return Nav(
|
||||
Attr("arial-label", "Pagination"),
|
||||
Ul(
|
||||
Class("pagination"),
|
||||
Class("pagination mb-0"),
|
||||
If(
|
||||
currentPage > 1,
|
||||
Li(
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue