From 0055693f33a883703d07907168ed13c2aec54fca Mon Sep 17 00:00:00 2001
From: Steven Orvis
-
-
- 🐘 Effortless PostgreSQL backups with a user-friendly web interface! 🌐💾
- PG Back Web
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-## Reset password
-
-You can reset your PG Back Web password by running the following command in the server where PG Back Web is running:
-
-```bash
-docker exec -it +
+
+
+ 🐘 Effortless PostgreSQL backups with a user-friendly web interface! 🌐💾 +
+ +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+## Reset password
+
+You can reset your PG Back Web password by running the following command in the server where PG Back Web is running:
+
+```bash
+docker exec -it bar
` - - assert.Equal(t, expected, got.String()) - }) -} +package component + +import ( + "bytes" + "testing" + + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/html" + "github.com/stretchr/testify/assert" +) + +func TestRenderableGroupRenderer(t *testing.T) { + t.Run("renders a group of string nodes without a parent element", func(t *testing.T) { + gotRenderer := RenderableGroup([]gomponents.Node{ + gomponents.Text("foo"), + gomponents.Text("bar"), + }) + + got := bytes.Buffer{} + err := gotRenderer.Render(&got) + assert.NoError(t, err) + + expected := "foobar" + + assert.Equal(t, expected, got.String()) + }) + + t.Run("renders a group of tag nodes without a parent element", func(t *testing.T) { + gotRenderer := RenderableGroup([]gomponents.Node{ + html.Span( + gomponents.Text("foo"), + ), + html.P( + gomponents.Text("bar"), + ), + }) + + got := bytes.Buffer{} + err := gotRenderer.Render(&got) + assert.NoError(t, err) + + expected := `foobar
` + + assert.Equal(t, expected, got.String()) + }) +} diff --git a/internal/view/web/component/select_control.go b/internal/view/web/component/select_control.go index e022aac0..c26a5482 100644 --- a/internal/view/web/component/select_control.go +++ b/internal/view/web/component/select_control.go @@ -1,91 +1,91 @@ -package component - -import ( - lucide "github.com/eduardolat/gomponents-lucide" - "github.com/google/uuid" - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/components" - "github.com/maragudk/gomponents/html" -) - -type SelectControlParams struct { - ID string - Name string - Label string - Placeholder string - Required bool - HelpText string - Color color - AutoComplete string - Children []gomponents.Node - HelpButtonChildren []gomponents.Node -} - -func SelectControl(params SelectControlParams) gomponents.Node { - id := params.ID - if id == "" { - id = "select-control-" + uuid.NewString() - } - - return html.Div( - components.Classes{ - "form-control w-full": true, - getTextColorClass(params.Color): true, - }, - html.Div( - html.Class("label flex justify-start"), - html.Label( - html.For(id), - html.Class("flex justify-start items-center space-x-1"), - SpanText(params.Label), - gomponents.If( - params.Required, - lucide.Asterisk(html.Class("text-error")), - ), - ), - gomponents.If( - len(params.HelpButtonChildren) > 0, - HelpButtonModal(HelpButtonModalParams{ - ModalTitle: params.Label, - Children: params.HelpButtonChildren, - }), - ), - ), - html.Select( - components.Classes{ - "w-full": true, - }, - html.ID(id), - html.Name(params.Name), - gomponents.If( - params.Required, - html.Required(), - ), - gomponents.If( - params.AutoComplete != "", - html.AutoComplete(params.AutoComplete), - ), - gomponents.If( - params.Placeholder != "", - html.Option( - html.Value(""), - html.Disabled(), - html.Selected(), - gomponents.Text(params.Placeholder), - ), - ), - gomponents.Group(params.Children), - ), - gomponents.If( - params.HelpText != "", - html.Label( - html.Class("label"), - html.For(id), - SpanText(params.HelpText), - ), - ), - html.Script(gomponents.Raw(` - new SlimSelect({select: '#`+id+`'}) - `)), - ) -} +package component + +import ( + lucide "github.com/eduardolat/gomponents-lucide" + "github.com/google/uuid" + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/components" + "github.com/maragudk/gomponents/html" +) + +type SelectControlParams struct { + ID string + Name string + Label string + Placeholder string + Required bool + HelpText string + Color color + AutoComplete string + Children []gomponents.Node + HelpButtonChildren []gomponents.Node +} + +func SelectControl(params SelectControlParams) gomponents.Node { + id := params.ID + if id == "" { + id = "select-control-" + uuid.NewString() + } + + return html.Div( + components.Classes{ + "form-control w-full": true, + getTextColorClass(params.Color): true, + }, + html.Div( + html.Class("label flex justify-start"), + html.Label( + html.For(id), + html.Class("flex justify-start items-center space-x-1"), + SpanText(params.Label), + gomponents.If( + params.Required, + lucide.Asterisk(html.Class("text-error")), + ), + ), + gomponents.If( + len(params.HelpButtonChildren) > 0, + HelpButtonModal(HelpButtonModalParams{ + ModalTitle: params.Label, + Children: params.HelpButtonChildren, + }), + ), + ), + html.Select( + components.Classes{ + "w-full": true, + }, + html.ID(id), + html.Name(params.Name), + gomponents.If( + params.Required, + html.Required(), + ), + gomponents.If( + params.AutoComplete != "", + html.AutoComplete(params.AutoComplete), + ), + gomponents.If( + params.Placeholder != "", + html.Option( + html.Value(""), + html.Disabled(), + html.Selected(), + gomponents.Text(params.Placeholder), + ), + ), + gomponents.Group(params.Children), + ), + gomponents.If( + params.HelpText != "", + html.Label( + html.Class("label"), + html.For(id), + SpanText(params.HelpText), + ), + ), + html.Script(gomponents.Raw(` + new SlimSelect({select: '#`+id+`'}) + `)), + ) +} diff --git a/internal/view/web/component/spinner.go b/internal/view/web/component/spinner.go index d8432deb..7483e48a 100644 --- a/internal/view/web/component/spinner.go +++ b/internal/view/web/component/spinner.go @@ -1,66 +1,66 @@ -package component - -import ( - "fmt" - - lucide "github.com/eduardolat/gomponents-lucide" - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/components" - "github.com/maragudk/gomponents/html" -) - -func spinner(size size) gomponents.Node { - return lucide.LoaderCircle(components.Classes{ - "animate-spin inline-block": true, - "size-5": size == SizeSm, - "size-8": size == SizeMd, - "size-12": size == SizeLg, - }) -} - -func SpinnerSm() gomponents.Node { - return spinner(SizeSm) -} - -func SpinnerMd() gomponents.Node { - return spinner(SizeMd) -} - -func SpinnerLg() gomponents.Node { - return spinner(SizeLg) -} - -func spinnerContainer(size size, height string) gomponents.Node { - return html.Div( - components.Classes{ - "flex justify-center": true, - "items-center w-full": true, - }, - html.Style(fmt.Sprintf("height: %s;", height)), - spinner(size), - ) -} - -func SpinnerContainerSm(height ...string) gomponents.Node { - pickedHeight := "300px" - if len(height) > 0 { - pickedHeight = height[0] - } - return spinnerContainer(SizeSm, pickedHeight) -} - -func SpinnerContainerMd(height ...string) gomponents.Node { - pickedHeight := "300px" - if len(height) > 0 { - pickedHeight = height[0] - } - return spinnerContainer(SizeMd, pickedHeight) -} - -func SpinnerContainerLg(height ...string) gomponents.Node { - pickedHeight := "300px" - if len(height) > 0 { - pickedHeight = height[0] - } - return spinnerContainer(SizeLg, pickedHeight) -} +package component + +import ( + "fmt" + + lucide "github.com/eduardolat/gomponents-lucide" + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/components" + "github.com/maragudk/gomponents/html" +) + +func spinner(size size) gomponents.Node { + return lucide.LoaderCircle(components.Classes{ + "animate-spin inline-block": true, + "size-5": size == SizeSm, + "size-8": size == SizeMd, + "size-12": size == SizeLg, + }) +} + +func SpinnerSm() gomponents.Node { + return spinner(SizeSm) +} + +func SpinnerMd() gomponents.Node { + return spinner(SizeMd) +} + +func SpinnerLg() gomponents.Node { + return spinner(SizeLg) +} + +func spinnerContainer(size size, height string) gomponents.Node { + return html.Div( + components.Classes{ + "flex justify-center": true, + "items-center w-full": true, + }, + html.Style(fmt.Sprintf("height: %s;", height)), + spinner(size), + ) +} + +func SpinnerContainerSm(height ...string) gomponents.Node { + pickedHeight := "300px" + if len(height) > 0 { + pickedHeight = height[0] + } + return spinnerContainer(SizeSm, pickedHeight) +} + +func SpinnerContainerMd(height ...string) gomponents.Node { + pickedHeight := "300px" + if len(height) > 0 { + pickedHeight = height[0] + } + return spinnerContainer(SizeMd, pickedHeight) +} + +func SpinnerContainerLg(height ...string) gomponents.Node { + pickedHeight := "300px" + if len(height) > 0 { + pickedHeight = height[0] + } + return spinnerContainer(SizeLg, pickedHeight) +} diff --git a/internal/view/web/component/star_on_github.go b/internal/view/web/component/star_on_github.go index 3943094e..3c24cc41 100644 --- a/internal/view/web/component/star_on_github.go +++ b/internal/view/web/component/star_on_github.go @@ -1,29 +1,29 @@ -package component - -import ( - lucide "github.com/eduardolat/gomponents-lucide" - "github.com/eduardolat/pgbackweb/internal/view/web/alpine" - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/components" - "github.com/maragudk/gomponents/html" -) - -func StarOnGithub(size size) gomponents.Node { - return html.A( - alpine.XData("githubRepoInfo"), - alpine.XCloak(), - components.Classes{ - "btn btn-neutral": true, - "btn-sm": size == SizeSm, - "btn-lg": size == SizeLg, - }, - html.Href("https://github.com/eduardolat/pgbackweb"), - html.Target("_blank"), - lucide.Github(), - SpanText("Star on Github"), - html.Span( - alpine.XShow("stars"), - alpine.XText("'( ' + stars + ' )'"), - ), - ) -} +package component + +import ( + lucide "github.com/eduardolat/gomponents-lucide" + "github.com/eduardolat/pgbackweb/internal/view/web/alpine" + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/components" + "github.com/maragudk/gomponents/html" +) + +func StarOnGithub(size size) gomponents.Node { + return html.A( + alpine.XData("githubRepoInfo"), + alpine.XCloak(), + components.Classes{ + "btn btn-neutral": true, + "btn-sm": size == SizeSm, + "btn-lg": size == SizeLg, + }, + html.Href("https://github.com/eduardolat/pgbackweb"), + html.Target("_blank"), + lucide.Github(), + SpanText("Star on Github"), + html.Span( + alpine.XShow("stars"), + alpine.XText("'( ' + stars + ' )'"), + ), + ) +} diff --git a/internal/view/web/component/status_badge.go b/internal/view/web/component/status_badge.go index 308397dd..23835c71 100644 --- a/internal/view/web/component/status_badge.go +++ b/internal/view/web/component/status_badge.go @@ -1,31 +1,31 @@ -package component - -import ( - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/components" - "github.com/maragudk/gomponents/html" -) - -func StatusBadge(status string) gomponents.Node { - class := "" - switch status { - case "running": - class = "badge-info" - case "success": - class = "badge-success" - case "failed": - class = "badge-error" - case "deleted": - class = "badge-warning" - default: - class = "badge-neutral" - } - - return html.Span( - components.Classes{ - "badge": true, - class: true, - }, - gomponents.Text(status), - ) -} +package component + +import ( + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/components" + "github.com/maragudk/gomponents/html" +) + +func StatusBadge(status string) gomponents.Node { + class := "" + switch status { + case "running": + class = "badge-info" + case "success": + class = "badge-success" + case "failed": + class = "badge-error" + case "deleted": + class = "badge-warning" + default: + class = "badge-neutral" + } + + return html.Span( + components.Classes{ + "badge": true, + class: true, + }, + gomponents.Text(status), + ) +} diff --git a/internal/view/web/component/textarea_control.go b/internal/view/web/component/textarea_control.go index 5c448de3..93728a8f 100644 --- a/internal/view/web/component/textarea_control.go +++ b/internal/view/web/component/textarea_control.go @@ -1,109 +1,109 @@ -package component - -import ( - lucide "github.com/eduardolat/gomponents-lucide" - "github.com/google/uuid" - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/components" - "github.com/maragudk/gomponents/html" -) - -type TextareaControlParams struct { - ID string - Name string - Label string - Placeholder string - Required bool - HelpText string - Color color - AutoComplete string - Pattern string - Children []gomponents.Node - HelpButtonChildren []gomponents.Node -} - -func TextareaControl(params TextareaControlParams) gomponents.Node { - id := params.ID - if id == "" { - id = "textarea-control-" + uuid.NewString() - } - - return html.Div( - components.Classes{ - "form-control w-full": true, - getTextColorClass(params.Color): true, - }, - html.Div( - html.Class("label flex justify-start"), - html.Label( - html.For(id), - html.Class("flex justify-start items-center space-x-1"), - SpanText(params.Label), - gomponents.If( - params.Required, - lucide.Asterisk(html.Class("text-error")), - ), - ), - gomponents.If( - len(params.HelpButtonChildren) > 0, - HelpButtonModal(HelpButtonModalParams{ - ModalTitle: params.Label, - Children: params.HelpButtonChildren, - }), - ), - ), - html.Textarea( - components.Classes{ - "textarea textarea-bordered w-full": true, - getTextareaColorClass(params.Color): true, - }, - html.ID(id), - html.Name(params.Name), - html.Placeholder(params.Placeholder), - gomponents.If( - params.Required, - html.Required(), - ), - gomponents.If( - params.AutoComplete != "", - html.AutoComplete(params.AutoComplete), - ), - gomponents.If( - params.Pattern != "", - html.Pattern(params.Pattern), - ), - gomponents.Group(params.Children), - ), - gomponents.If( - params.HelpText != "", - html.Label( - html.Class("label"), - html.For(id), - SpanText(params.HelpText), - ), - ), - ) -} - -func getTextareaColorClass(color color) string { - switch color { - case ColorPrimary: - return "textarea-primary" - case ColorSecondary: - return "textarea-secondary" - case ColorAccent: - return "textarea-accent" - case ColorNeutral: - return "textarea-neutral" - case ColorInfo: - return "textarea-info" - case ColorSuccess: - return "textarea-success" - case ColorWarning: - return "textarea-warning" - case ColorError: - return "textarea-error" - default: - return "textarea-neutral" - } -} +package component + +import ( + lucide "github.com/eduardolat/gomponents-lucide" + "github.com/google/uuid" + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/components" + "github.com/maragudk/gomponents/html" +) + +type TextareaControlParams struct { + ID string + Name string + Label string + Placeholder string + Required bool + HelpText string + Color color + AutoComplete string + Pattern string + Children []gomponents.Node + HelpButtonChildren []gomponents.Node +} + +func TextareaControl(params TextareaControlParams) gomponents.Node { + id := params.ID + if id == "" { + id = "textarea-control-" + uuid.NewString() + } + + return html.Div( + components.Classes{ + "form-control w-full": true, + getTextColorClass(params.Color): true, + }, + html.Div( + html.Class("label flex justify-start"), + html.Label( + html.For(id), + html.Class("flex justify-start items-center space-x-1"), + SpanText(params.Label), + gomponents.If( + params.Required, + lucide.Asterisk(html.Class("text-error")), + ), + ), + gomponents.If( + len(params.HelpButtonChildren) > 0, + HelpButtonModal(HelpButtonModalParams{ + ModalTitle: params.Label, + Children: params.HelpButtonChildren, + }), + ), + ), + html.Textarea( + components.Classes{ + "textarea textarea-bordered w-full": true, + getTextareaColorClass(params.Color): true, + }, + html.ID(id), + html.Name(params.Name), + html.Placeholder(params.Placeholder), + gomponents.If( + params.Required, + html.Required(), + ), + gomponents.If( + params.AutoComplete != "", + html.AutoComplete(params.AutoComplete), + ), + gomponents.If( + params.Pattern != "", + html.Pattern(params.Pattern), + ), + gomponents.Group(params.Children), + ), + gomponents.If( + params.HelpText != "", + html.Label( + html.Class("label"), + html.For(id), + SpanText(params.HelpText), + ), + ), + ) +} + +func getTextareaColorClass(color color) string { + switch color { + case ColorPrimary: + return "textarea-primary" + case ColorSecondary: + return "textarea-secondary" + case ColorAccent: + return "textarea-accent" + case ColorNeutral: + return "textarea-neutral" + case ColorInfo: + return "textarea-info" + case ColorSuccess: + return "textarea-success" + case ColorWarning: + return "textarea-warning" + case ColorError: + return "textarea-error" + default: + return "textarea-neutral" + } +} diff --git a/internal/view/web/component/typography.go b/internal/view/web/component/typography.go index c0d7530b..5cab61df 100644 --- a/internal/view/web/component/typography.go +++ b/internal/view/web/component/typography.go @@ -1,127 +1,127 @@ -package component - -import ( - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/html" -) - -// getTextColorClass returns the text color class for a text that -// is written on top of a base-100, base-200 or base-300 background. -func getTextColorClass(color color) string { - switch color { - case ColorPrimary: - return "text-primary" - case ColorSecondary: - return "text-secondary" - case ColorAccent: - return "text-accent" - case ColorNeutral: - return "text-base-content" - case ColorInfo: - return "text-info" - case ColorSuccess: - return "text-success" - case ColorWarning: - return "text-warning" - case ColorError: - return "text-error" - default: - return "text-base-content" - } -} - -func H1(children ...gomponents.Node) gomponents.Node { - return html.H1( - html.Class("text-2xl font-bold desk:text-4xl"), - gomponents.Group(children), - ) -} - -func H2(children ...gomponents.Node) gomponents.Node { - return html.H2( - html.Class("text-xl font-bold desk:text-2xl"), - gomponents.Group(children), - ) -} - -func H3(children ...gomponents.Node) gomponents.Node { - return html.H3( - html.Class("text-lg font-bold desk:text-xl"), - gomponents.Group(children), - ) -} - -func H4(children ...gomponents.Node) gomponents.Node { - return html.H4( - html.Class("text-base font-bold desk:text-lg"), - gomponents.Group(children), - ) -} - -func H5(children ...gomponents.Node) gomponents.Node { - return html.H5( - html.Class("text-sm font-bold desk:text-base"), - gomponents.Group(children), - ) -} - -func H6(children ...gomponents.Node) gomponents.Node { - return html.H6( - html.Class("text-xs font-bold desk:text-sm"), - gomponents.Group(children), - ) -} - -// H1Text is a convenience function to create an H1 element with a -// simple text node as its child. -func H1Text(text string) gomponents.Node { - return H1(gomponents.Text(text)) -} - -// H2Text is a convenience function to create an H2 element with a -// simple text node as its child. -func H2Text(text string) gomponents.Node { - return H2(gomponents.Text(text)) -} - -// H3Text is a convenience function to create an H3 element with a -// simple text node as its child. -func H3Text(text string) gomponents.Node { - return H3(gomponents.Text(text)) -} - -// H4Text is a convenience function to create an H4 element with a -// simple text node as its child. -func H4Text(text string) gomponents.Node { - return H4(gomponents.Text(text)) -} - -// H5Text is a convenience function to create an H5 element with a -// simple text node as its child. -func H5Text(text string) gomponents.Node { - return H5(gomponents.Text(text)) -} - -// H6Text is a convenience function to create an H6 element with a -// simple text node as its child. -func H6Text(text string) gomponents.Node { - return H6(gomponents.Text(text)) -} - -// PText is a convenience function to create a P element with a -// simple text node as its child. -func PText(text string) gomponents.Node { - return html.P(gomponents.Text(text)) -} - -// SpanText is a convenience function to create a Span element with a -// simple text node as its child. -func SpanText(text string) gomponents.Node { - return html.Span(gomponents.Text(text)) -} - -// BText is a convenience function to create a B element with a -// simple text node as its child. -func BText(text string) gomponents.Node { - return html.B(gomponents.Text(text)) -} +package component + +import ( + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/html" +) + +// getTextColorClass returns the text color class for a text that +// is written on top of a base-100, base-200 or base-300 background. +func getTextColorClass(color color) string { + switch color { + case ColorPrimary: + return "text-primary" + case ColorSecondary: + return "text-secondary" + case ColorAccent: + return "text-accent" + case ColorNeutral: + return "text-base-content" + case ColorInfo: + return "text-info" + case ColorSuccess: + return "text-success" + case ColorWarning: + return "text-warning" + case ColorError: + return "text-error" + default: + return "text-base-content" + } +} + +func H1(children ...gomponents.Node) gomponents.Node { + return html.H1( + html.Class("text-2xl font-bold desk:text-4xl"), + gomponents.Group(children), + ) +} + +func H2(children ...gomponents.Node) gomponents.Node { + return html.H2( + html.Class("text-xl font-bold desk:text-2xl"), + gomponents.Group(children), + ) +} + +func H3(children ...gomponents.Node) gomponents.Node { + return html.H3( + html.Class("text-lg font-bold desk:text-xl"), + gomponents.Group(children), + ) +} + +func H4(children ...gomponents.Node) gomponents.Node { + return html.H4( + html.Class("text-base font-bold desk:text-lg"), + gomponents.Group(children), + ) +} + +func H5(children ...gomponents.Node) gomponents.Node { + return html.H5( + html.Class("text-sm font-bold desk:text-base"), + gomponents.Group(children), + ) +} + +func H6(children ...gomponents.Node) gomponents.Node { + return html.H6( + html.Class("text-xs font-bold desk:text-sm"), + gomponents.Group(children), + ) +} + +// H1Text is a convenience function to create an H1 element with a +// simple text node as its child. +func H1Text(text string) gomponents.Node { + return H1(gomponents.Text(text)) +} + +// H2Text is a convenience function to create an H2 element with a +// simple text node as its child. +func H2Text(text string) gomponents.Node { + return H2(gomponents.Text(text)) +} + +// H3Text is a convenience function to create an H3 element with a +// simple text node as its child. +func H3Text(text string) gomponents.Node { + return H3(gomponents.Text(text)) +} + +// H4Text is a convenience function to create an H4 element with a +// simple text node as its child. +func H4Text(text string) gomponents.Node { + return H4(gomponents.Text(text)) +} + +// H5Text is a convenience function to create an H5 element with a +// simple text node as its child. +func H5Text(text string) gomponents.Node { + return H5(gomponents.Text(text)) +} + +// H6Text is a convenience function to create an H6 element with a +// simple text node as its child. +func H6Text(text string) gomponents.Node { + return H6(gomponents.Text(text)) +} + +// PText is a convenience function to create a P element with a +// simple text node as its child. +func PText(text string) gomponents.Node { + return html.P(gomponents.Text(text)) +} + +// SpanText is a convenience function to create a Span element with a +// simple text node as its child. +func SpanText(text string) gomponents.Node { + return html.Span(gomponents.Text(text)) +} + +// BText is a convenience function to create a B element with a +// simple text node as its child. +func BText(text string) gomponents.Node { + return html.B(gomponents.Text(text)) +} diff --git a/internal/view/web/dashboard/about/index.go b/internal/view/web/dashboard/about/index.go index bf162f23..fe151bb3 100644 --- a/internal/view/web/dashboard/about/index.go +++ b/internal/view/web/dashboard/about/index.go @@ -1,87 +1,87 @@ -package about - -import ( - "net/http" - - "github.com/eduardolat/pgbackweb/internal/config" - "github.com/eduardolat/pgbackweb/internal/util/echoutil" - "github.com/eduardolat/pgbackweb/internal/view/web/component" - "github.com/eduardolat/pgbackweb/internal/view/web/layout" - "github.com/labstack/echo/v4" - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/html" -) - -func (h *handlers) indexPageHandler(c echo.Context) error { - return echoutil.RenderGomponent(c, http.StatusOK, indexPage()) -} - -func indexPage() gomponents.Node { - content := []gomponents.Node{ - component.H1Text("About PG Back Web"), - component.H2Text(config.Version), - - html.Div( - html.Class("grid grid-cols-2 gap-4 mt-4"), - - component.CardBox(component.CardBoxParams{ - Children: []gomponents.Node{ - component.PText(` - PG Back Web was born in July 2024 out of a need for a simple and - user-friendly backup solution for self-hosted PostgreSQL databases. - After searching extensively for an easy-to-use backup tool and not - finding one, I decided to create my own. Its mission is to provide a - straightforward web interface that makes managing PostgreSQL backups - effortless and efficient. - `), - }, - }), - - component.CardBox(component.CardBoxParams{ - Children: []gomponents.Node{ - html.Table( - html.Class("table"), - html.Tr( - html.Th(component.SpanText("License")), - html.Td( - html.A( - html.Class("link"), - html.Href("https://github.com/eduardolat/pgbackweb/blob/main/LICENSE"), - html.Target("_blank"), - component.SpanText("MIT"), - ), - ), - ), - html.Tr( - html.Th(component.SpanText("About the author")), - html.Td( - html.A( - html.Class("link"), - html.Href("https://eduardo.lat"), - html.Target("_blank"), - component.SpanText("https://eduardo.lat"), - ), - ), - ), - html.Tr( - html.Th(component.SpanText("Repository")), - html.Td( - html.A( - html.Class("link"), - html.Href("https://github.com/eduardolat/pgbackweb"), - html.Target("_blank"), - component.SpanText("https://github.com/eduardolat/pgbackweb"), - ), - ), - ), - ), - }, - }), - ), - } - - return layout.Dashboard(layout.DashboardParams{ - Title: "About", - Body: content, - }) -} +package about + +import ( + "net/http" + + "github.com/eduardolat/pgbackweb/internal/config" + "github.com/eduardolat/pgbackweb/internal/util/echoutil" + "github.com/eduardolat/pgbackweb/internal/view/web/component" + "github.com/eduardolat/pgbackweb/internal/view/web/layout" + "github.com/labstack/echo/v4" + "github.com/maragudk/gomponents" + "github.com/maragudk/gomponents/html" +) + +func (h *handlers) indexPageHandler(c echo.Context) error { + return echoutil.RenderGomponent(c, http.StatusOK, indexPage()) +} + +func indexPage() gomponents.Node { + content := []gomponents.Node{ + component.H1Text("About PG Back Web"), + component.H2Text(config.Version), + + html.Div( + html.Class("grid grid-cols-2 gap-4 mt-4"), + + component.CardBox(component.CardBoxParams{ + Children: []gomponents.Node{ + component.PText(` + PG Back Web was born in July 2024 out of a need for a simple and + user-friendly backup solution for self-hosted PostgreSQL databases. + After searching extensively for an easy-to-use backup tool and not + finding one, I decided to create my own. Its mission is to provide a + straightforward web interface that makes managing PostgreSQL backups + effortless and efficient. + `), + }, + }), + + component.CardBox(component.CardBoxParams{ + Children: []gomponents.Node{ + html.Table( + html.Class("table"), + html.Tr( + html.Th(component.SpanText("License")), + html.Td( + html.A( + html.Class("link"), + html.Href("https://github.com/eduardolat/pgbackweb/blob/main/LICENSE"), + html.Target("_blank"), + component.SpanText("MIT"), + ), + ), + ), + html.Tr( + html.Th(component.SpanText("About the author")), + html.Td( + html.A( + html.Class("link"), + html.Href("https://eduardo.lat"), + html.Target("_blank"), + component.SpanText("https://eduardo.lat"), + ), + ), + ), + html.Tr( + html.Th(component.SpanText("Repository")), + html.Td( + html.A( + html.Class("link"), + html.Href("https://github.com/eduardolat/pgbackweb"), + html.Target("_blank"), + component.SpanText("https://github.com/eduardolat/pgbackweb"), + ), + ), + ), + ), + }, + }), + ), + } + + return layout.Dashboard(layout.DashboardParams{ + Title: "About", + Body: content, + }) +} diff --git a/internal/view/web/dashboard/backups/common.go b/internal/view/web/dashboard/backups/common.go index b01d43f4..78bd50f1 100644 --- a/internal/view/web/dashboard/backups/common.go +++ b/internal/view/web/dashboard/backups/common.go @@ -1,185 +1,185 @@ -package backups - -import ( - "time" - - lucide "github.com/eduardolat/gomponents-lucide" - "github.com/eduardolat/pgbackweb/internal/view/web/component" - "github.com/maragudk/gomponents" - "github.com/maragudk/gomponents/components" - "github.com/maragudk/gomponents/html" -) - -func localBackupsHelp() []gomponents.Node { - return []gomponents.Node{ - component.H3Text("Local backups"), - component.PText(` - Local backups are stored in the server where PG Back Web is running. - They are stored under /backups directory so you can mount a docker - volume to this directory to persist the backups in any way you want. - `), - - html.Div( - html.Class("mt-2"), - component.H3Text("Remote backups"), - component.PText(` - Remote backups are stored in a destination. A destination is a remote - S3 compatible storage. With this option you don't need to worry about - creating and managing docker volumes. - `), - ), - } -} - -func cronExpressionHelp() []gomponents.Node { - return []gomponents.Node{ - component.PText(` - A cron expression is a string used to define a schedule for running tasks - in Unix-like operating systems. It consists of five fields representing - the minute, hour, day of the month, month, and day of the week. - Cron expressions enable precise scheduling of periodic tasks. - `), - - html.Div( - html.Class("mt-4 flex justify-end items-center space-x-1"), - html.A( - html.Href("https://en.wikipedia.org/wiki/Cron"), - html.Target("_blank"), - html.Class("btn btn-ghost"), - component.SpanText("Learn more"), - lucide.ExternalLink(), - ), - html.A( - html.Href("https://crontab.guru/examples.html"), - html.Target("_blank"), - html.Class("btn btn-ghost"), - component.SpanText("Examples & common expressions"), - lucide.ExternalLink(), - ), - ), - } -} - -func timezoneFilenamesHelp() []gomponents.Node { - serverTimezone := time.Now().Location().String() - - return []gomponents.Node{ - component.PText(` - This is the time zone in which the cron expression will be evaluated. - `), - html.P( - component.SpanText(` - Backup filenames will always use the server timezone (currently - `), - component.BText(serverTimezone), - component.SpanText(")."), - ), - - html.Div( - html.Class("mt-4 flex justify-end items-center"), - html.A( - html.Href("https://github.com/eduardolat/pgbackweb?tab=readme-ov-file#configuration"), - html.Target("_blank"), - html.Class("btn btn-ghost"), - component.SpanText("Learn more in project README"), - lucide.ExternalLink(), - ), - ), - } -} - -func destinationDirectoryHelp() []gomponents.Node { - return []gomponents.Node{ - component.PText(` - The destination directory is the directory where the backups will be - stored. This directory is relative to the base directory of the - destination. It should start with a slash, should not contain any - spaces, and should not end with a slash. - `), - - html.Div( - html.Class("mt-2"), - component.H3Text("Local backups"), - component.PText(` - For local backups, the base directory is /backups. So, the backup files - will be stored in: - `), - html.Div( - components.Classes{ - "whitespace-nowrap p-1": true, - "overflow-x-scroll": true, - "font-mono": true, - }, - component.BText( - "/backups/