mirror of
https://github.com/eduardolat/pgbackweb.git
synced 2026-05-12 22:48:27 -05:00
Add destinations functionality to dashboard
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
package destinations
|
||||
|
||||
import (
|
||||
lucide "github.com/eduardolat/gomponents-lucide"
|
||||
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
|
||||
"github.com/eduardolat/pgbackweb/internal/validate"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/component"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/htmx"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/maragudk/gomponents"
|
||||
"github.com/maragudk/gomponents/html"
|
||||
)
|
||||
|
||||
type createDestinationDTO struct {
|
||||
Name string `form:"name" validate:"required"`
|
||||
BucketName string `form:"bucket_name" validate:"required"`
|
||||
AccessKey string `form:"access_key" validate:"required"`
|
||||
SecretKey string `form:"secret_key" validate:"required"`
|
||||
Region string `form:"region" validate:"required"`
|
||||
Endpoint string `form:"endpoint" validate:"required"`
|
||||
}
|
||||
|
||||
func (h *handlers) testDestinationHandler(c echo.Context) error {
|
||||
var formData createDestinationDTO
|
||||
if err := c.Bind(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
if err := validate.Struct(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
err := h.servs.DestinationsService.TestDestination(
|
||||
formData.AccessKey, formData.SecretKey, formData.Region, formData.Endpoint,
|
||||
formData.BucketName,
|
||||
)
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
return htmx.RespondToastSuccess(c, "Connection successful")
|
||||
}
|
||||
|
||||
func (h *handlers) createDestinationHandler(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
|
||||
var formData createDestinationDTO
|
||||
if err := c.Bind(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
if err := validate.Struct(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
_, err := h.servs.DestinationsService.CreateDestination(
|
||||
ctx, dbgen.DestinationsServiceCreateDestinationParams{
|
||||
Name: formData.Name,
|
||||
AccessKey: formData.AccessKey,
|
||||
SecretKey: formData.SecretKey,
|
||||
Region: formData.Region,
|
||||
Endpoint: formData.Endpoint,
|
||||
BucketName: formData.BucketName,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
return htmx.RespondRedirect(c, "/dashboard/destinations")
|
||||
}
|
||||
|
||||
func createDestinationButton() gomponents.Node {
|
||||
htmxAttributes := func(url string) gomponents.Node {
|
||||
return gomponents.Group([]gomponents.Node{
|
||||
htmx.HxPost(url),
|
||||
htmx.HxInclude("#create-destination-form"),
|
||||
htmx.HxDisabledELT(".create-destination-btn"),
|
||||
htmx.HxIndicator("#create-destination-loading"),
|
||||
htmx.HxValidate("true"),
|
||||
})
|
||||
}
|
||||
|
||||
mo := component.Modal(component.ModalParams{
|
||||
Size: component.SizeMd,
|
||||
Title: "Create destination",
|
||||
Content: []gomponents.Node{
|
||||
html.Form(
|
||||
html.ID("create-destination-form"),
|
||||
html.Class("space-y-2"),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "name",
|
||||
Label: "Name",
|
||||
Placeholder: "My destination",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
HelpText: "A name to easily identify the destination",
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "bucket_name",
|
||||
Label: "Bucket name",
|
||||
Placeholder: "my-bucket",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "endpoint",
|
||||
Label: "Endpoint",
|
||||
Placeholder: "s3-us-west-1.amazonaws.com",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "region",
|
||||
Label: "Region",
|
||||
Placeholder: "us-west-1",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "access_key",
|
||||
Label: "Access key",
|
||||
Placeholder: "Access key",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
HelpText: "It will be stored securely using PGP encryption.",
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "secret_key",
|
||||
Label: "Secret key",
|
||||
Placeholder: "Secret key",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
HelpText: "It will be stored securely using PGP encryption.",
|
||||
}),
|
||||
),
|
||||
|
||||
html.Div(
|
||||
html.Class("flex justify-between items-center pt-4"),
|
||||
html.Div(
|
||||
html.Button(
|
||||
htmxAttributes("/dashboard/destinations/test"),
|
||||
html.Class("create-destination-btn btn btn-neutral btn-outline"),
|
||||
html.Type("button"),
|
||||
component.SpanText("Test connection"),
|
||||
lucide.PlugZap(),
|
||||
),
|
||||
),
|
||||
html.Div(
|
||||
html.Class("flex justify-end items-center space-x-2"),
|
||||
component.HxLoadingMd("create-destination-loading"),
|
||||
html.Button(
|
||||
htmxAttributes("/dashboard/destinations"),
|
||||
html.Class("create-destination-btn btn btn-primary"),
|
||||
html.Type("button"),
|
||||
component.SpanText("Save"),
|
||||
lucide.Save(),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
})
|
||||
|
||||
button := html.Button(
|
||||
mo.OpenerAttr,
|
||||
html.Class("btn btn-primary"),
|
||||
component.SpanText("Create destination"),
|
||||
lucide.Plus(),
|
||||
)
|
||||
|
||||
return html.Div(
|
||||
html.Class("inline-block"),
|
||||
mo.HTML,
|
||||
button,
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package destinations
|
||||
|
||||
import (
|
||||
lucide "github.com/eduardolat/gomponents-lucide"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/htmx"
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/maragudk/gomponents"
|
||||
"github.com/maragudk/gomponents/html"
|
||||
)
|
||||
|
||||
func (h *handlers) deleteDestinationHandler(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
|
||||
destinationID, err := uuid.Parse(c.Param("destinationID"))
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
err = h.servs.DestinationsService.DeleteDestination(ctx, destinationID)
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
return htmx.RespondRefresh(c)
|
||||
}
|
||||
|
||||
func deleteDestinationButton(destinationID uuid.UUID) gomponents.Node {
|
||||
return html.Div(
|
||||
html.Class("inline-block tooltip tooltip-right"),
|
||||
html.Data("tip", "Delete destination"),
|
||||
html.Button(
|
||||
htmx.HxDelete("/dashboard/destinations/"+destinationID.String()),
|
||||
htmx.HxConfirm("Are you sure you want to delete this destination?"),
|
||||
html.Class("btn btn-error btn-square btn-sm btn-ghost"),
|
||||
lucide.Trash(),
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
package destinations
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
|
||||
lucide "github.com/eduardolat/gomponents-lucide"
|
||||
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
|
||||
"github.com/eduardolat/pgbackweb/internal/validate"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/component"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/htmx"
|
||||
"github.com/google/uuid"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/maragudk/gomponents"
|
||||
"github.com/maragudk/gomponents/components"
|
||||
"github.com/maragudk/gomponents/html"
|
||||
)
|
||||
|
||||
func (h *handlers) editDestinationHandler(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
|
||||
destinationID, err := uuid.Parse(c.Param("destinationID"))
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
var formData createDestinationDTO
|
||||
if err := c.Bind(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
if err := validate.Struct(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
_, err = h.servs.DestinationsService.UpdateDestination(
|
||||
ctx, dbgen.DestinationsServiceUpdateDestinationParams{
|
||||
ID: destinationID,
|
||||
Name: sql.NullString{String: formData.Name, Valid: true},
|
||||
BucketName: sql.NullString{String: formData.BucketName, Valid: true},
|
||||
Region: sql.NullString{String: formData.Region, Valid: true},
|
||||
Endpoint: sql.NullString{String: formData.Endpoint, Valid: true},
|
||||
AccessKey: sql.NullString{String: formData.AccessKey, Valid: true},
|
||||
SecretKey: sql.NullString{String: formData.SecretKey, Valid: true},
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
return htmx.RespondToastSuccess(c, "Destination updated")
|
||||
}
|
||||
|
||||
func editDestinationButton(
|
||||
destination dbgen.DestinationsServicePaginateDestinationsRow,
|
||||
) gomponents.Node {
|
||||
idPref := "edit-destination-" + destination.ID.String()
|
||||
formID := idPref + "-form"
|
||||
btnClass := idPref + "-btn"
|
||||
loadingID := idPref + "-loading"
|
||||
|
||||
htmxAttributes := func(url string) gomponents.Node {
|
||||
return gomponents.Group([]gomponents.Node{
|
||||
htmx.HxPost(url),
|
||||
htmx.HxInclude("#" + formID),
|
||||
htmx.HxDisabledELT("." + btnClass),
|
||||
htmx.HxIndicator("#" + loadingID),
|
||||
htmx.HxValidate("true"),
|
||||
})
|
||||
}
|
||||
|
||||
mo := component.Modal(component.ModalParams{
|
||||
Size: component.SizeMd,
|
||||
Title: "Edit destination",
|
||||
Content: []gomponents.Node{
|
||||
html.Form(
|
||||
html.ID(formID),
|
||||
html.Class("space-y-2"),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "name",
|
||||
Label: "Name",
|
||||
Placeholder: "My destination",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
HelpText: "A name to easily identify the destination",
|
||||
Children: []gomponents.Node{
|
||||
html.Value(destination.Name),
|
||||
},
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "bucket_name",
|
||||
Label: "Bucket name",
|
||||
Placeholder: "my-bucket",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
Children: []gomponents.Node{
|
||||
html.Value(destination.BucketName),
|
||||
},
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "endpoint",
|
||||
Label: "Endpoint",
|
||||
Placeholder: "s3-us-west-1.amazonaws.com",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
Children: []gomponents.Node{
|
||||
html.Value(destination.Endpoint),
|
||||
},
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "region",
|
||||
Label: "Region",
|
||||
Placeholder: "us-west-1",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
Children: []gomponents.Node{
|
||||
html.Value(destination.Region),
|
||||
},
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "access_key",
|
||||
Label: "Access key",
|
||||
Placeholder: "Access key",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
HelpText: "It will be stored securely using PGP encryption.",
|
||||
Children: []gomponents.Node{
|
||||
html.Value(destination.DecryptedAccessKey),
|
||||
},
|
||||
}),
|
||||
|
||||
component.InputControl(component.InputControlParams{
|
||||
Name: "secret_key",
|
||||
Label: "Secret key",
|
||||
Placeholder: "Secret key",
|
||||
Required: true,
|
||||
Type: component.InputTypeText,
|
||||
HelpText: "It will be stored securely using PGP encryption.",
|
||||
Children: []gomponents.Node{
|
||||
html.Value(destination.DecryptedSecretKey),
|
||||
},
|
||||
}),
|
||||
),
|
||||
|
||||
html.Div(
|
||||
html.Class("flex justify-between items-center pt-4"),
|
||||
html.Div(
|
||||
html.Button(
|
||||
htmxAttributes("/dashboard/destinations/test"),
|
||||
components.Classes{
|
||||
btnClass: true,
|
||||
"btn btn-neutral btn-outline": true,
|
||||
},
|
||||
html.Type("button"),
|
||||
component.SpanText("Test connection"),
|
||||
lucide.PlugZap(),
|
||||
),
|
||||
),
|
||||
html.Div(
|
||||
html.Class("flex justify-end items-center space-x-2"),
|
||||
component.HxLoadingMd(loadingID),
|
||||
html.Button(
|
||||
htmxAttributes("/dashboard/destinations/"+destination.ID.String()+"/edit"),
|
||||
components.Classes{
|
||||
btnClass: true,
|
||||
"btn btn-primary": true,
|
||||
},
|
||||
html.Type("button"),
|
||||
component.SpanText("Save"),
|
||||
lucide.Save(),
|
||||
),
|
||||
),
|
||||
),
|
||||
},
|
||||
})
|
||||
|
||||
button := html.Button(
|
||||
mo.OpenerAttr,
|
||||
html.Class("btn btn-neutral btn-sm btn-square btn-ghost"),
|
||||
lucide.Pencil(),
|
||||
)
|
||||
|
||||
return html.Div(
|
||||
html.Class("inline-block"),
|
||||
mo.HTML,
|
||||
html.Div(
|
||||
html.Class("inline-block tooltip tooltip-right"),
|
||||
html.Data("tip", "Edit destination"),
|
||||
button,
|
||||
),
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package destinations
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/eduardolat/pgbackweb/internal/util/echoutil"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/component"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/htmx"
|
||||
"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{
|
||||
html.Div(
|
||||
html.Class("flex justify-between items-start"),
|
||||
component.H1Text("Destinations"),
|
||||
createDestinationButton(),
|
||||
),
|
||||
html.Div(
|
||||
html.Div(
|
||||
html.Class("mt-4 overflow-x-auto"),
|
||||
html.Table(
|
||||
html.Class("table"),
|
||||
html.THead(
|
||||
html.Tr(
|
||||
html.Th(),
|
||||
html.Th(component.SpanText("Name")),
|
||||
html.Th(component.SpanText("Bucket name")),
|
||||
html.Th(component.SpanText("Endpoint")),
|
||||
html.Th(component.SpanText("Region")),
|
||||
html.Th(component.SpanText("Access key")),
|
||||
html.Th(component.SpanText("Secret key")),
|
||||
html.Th(component.SpanText("Created at")),
|
||||
),
|
||||
),
|
||||
html.TBody(
|
||||
htmx.HxGet("/dashboard/destinations/list?page=1"),
|
||||
htmx.HxTrigger("load"),
|
||||
htmx.HxIndicator("#list-destinations-loading"),
|
||||
),
|
||||
),
|
||||
),
|
||||
html.Div(
|
||||
html.Class("flex justify-center mt-4"),
|
||||
component.HxLoadingLg("list-destinations-loading"),
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
return layout.Dashboard(layout.DashboardParams{
|
||||
Title: "Destinations",
|
||||
Body: content,
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
package destinations
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
|
||||
lucide "github.com/eduardolat/gomponents-lucide"
|
||||
"github.com/eduardolat/pgbackweb/internal/database/dbgen"
|
||||
"github.com/eduardolat/pgbackweb/internal/service/destinations"
|
||||
"github.com/eduardolat/pgbackweb/internal/util/echoutil"
|
||||
"github.com/eduardolat/pgbackweb/internal/util/paginateutil"
|
||||
"github.com/eduardolat/pgbackweb/internal/util/timeutil"
|
||||
"github.com/eduardolat/pgbackweb/internal/validate"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/component"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/htmx"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/maragudk/gomponents"
|
||||
"github.com/maragudk/gomponents/html"
|
||||
)
|
||||
|
||||
func (h *handlers) listDestinationsHandler(c echo.Context) error {
|
||||
ctx := c.Request().Context()
|
||||
|
||||
var formData struct {
|
||||
Page int `query:"page" validate:"required,min=1"`
|
||||
}
|
||||
if err := c.Bind(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
if err := validate.Struct(&formData); err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
pagination, destinations, err := h.servs.DestinationsService.PaginateDestinations(
|
||||
ctx, destinations.PaginateDestinationsParams{
|
||||
Page: formData.Page,
|
||||
Limit: 8,
|
||||
},
|
||||
)
|
||||
if err != nil {
|
||||
return htmx.RespondToastError(c, err.Error())
|
||||
}
|
||||
|
||||
return echoutil.RenderGomponent(
|
||||
c, http.StatusOK, listDestinations(pagination, destinations),
|
||||
)
|
||||
}
|
||||
|
||||
func listDestinations(
|
||||
pagination paginateutil.PaginateResponse,
|
||||
destinations []dbgen.DestinationsServicePaginateDestinationsRow,
|
||||
) gomponents.Node {
|
||||
trs := []gomponents.Node{}
|
||||
for _, destination := range destinations {
|
||||
trs = append(trs, html.Tr(
|
||||
html.Td(
|
||||
html.Class("w-[40px]"),
|
||||
html.Div(
|
||||
html.Class("flex justify-start space-x-1"),
|
||||
editDestinationButton(destination),
|
||||
html.Form(
|
||||
html.Class("inline-block tooltip tooltip-right"),
|
||||
html.Data("tip", "Test connection"),
|
||||
htmx.HxPost("/dashboard/destinations/test"),
|
||||
html.Input(
|
||||
html.Type("hidden"),
|
||||
html.Name("name"),
|
||||
html.Value(destination.Name),
|
||||
),
|
||||
html.Input(
|
||||
html.Type("hidden"),
|
||||
html.Name("bucket_name"),
|
||||
html.Value(destination.BucketName),
|
||||
),
|
||||
html.Input(
|
||||
html.Type("hidden"),
|
||||
html.Name("endpoint"),
|
||||
html.Value(destination.Endpoint),
|
||||
),
|
||||
html.Input(
|
||||
html.Type("hidden"),
|
||||
html.Name("region"),
|
||||
html.Value(destination.Region),
|
||||
),
|
||||
html.Input(
|
||||
html.Type("hidden"),
|
||||
html.Name("access_key"),
|
||||
html.Value(destination.DecryptedAccessKey),
|
||||
),
|
||||
html.Input(
|
||||
html.Type("hidden"),
|
||||
html.Name("secret_key"),
|
||||
html.Value(destination.DecryptedSecretKey),
|
||||
),
|
||||
html.Button(
|
||||
html.Class("btn btn-neutral btn-square btn-ghost btn-sm"),
|
||||
lucide.PlugZap(),
|
||||
),
|
||||
),
|
||||
deleteDestinationButton(destination.ID),
|
||||
),
|
||||
),
|
||||
html.Td(component.SpanText(destination.Name)),
|
||||
html.Td(component.SpanText(destination.BucketName)),
|
||||
html.Td(component.SpanText(destination.Endpoint)),
|
||||
html.Td(component.SpanText(destination.Region)),
|
||||
html.Td(
|
||||
html.Class("space-x-1"),
|
||||
component.CopyButtonSm(destination.DecryptedAccessKey),
|
||||
component.SpanText("**********"),
|
||||
),
|
||||
html.Td(
|
||||
html.Class("space-x-1"),
|
||||
component.CopyButtonSm(destination.DecryptedSecretKey),
|
||||
component.SpanText("**********"),
|
||||
),
|
||||
html.Td(component.SpanText(
|
||||
destination.CreatedAt.Format(timeutil.LayoutYYYYMMDDHHMMSSPretty),
|
||||
)),
|
||||
))
|
||||
}
|
||||
|
||||
if pagination.HasNextPage {
|
||||
trs = append(trs, html.Tr(
|
||||
htmx.HxGet(fmt.Sprintf(
|
||||
"/dashboard/destinations/list?page=%d", pagination.NextPage,
|
||||
)),
|
||||
htmx.HxTrigger("intersect once"),
|
||||
htmx.HxSwap("afterend"),
|
||||
htmx.HxIndicator("#list-destinations-loading"),
|
||||
))
|
||||
}
|
||||
|
||||
return component.RenderableGroup(trs)
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package destinations
|
||||
|
||||
import (
|
||||
"github.com/eduardolat/pgbackweb/internal/service"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/middleware"
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
type handlers struct {
|
||||
servs *service.Service
|
||||
}
|
||||
|
||||
func newHandlers(servs *service.Service) *handlers {
|
||||
return &handlers{servs: servs}
|
||||
}
|
||||
|
||||
func MountRouter(
|
||||
parent *echo.Group, mids *middleware.Middleware, servs *service.Service,
|
||||
) {
|
||||
h := newHandlers(servs)
|
||||
|
||||
parent.GET("", h.indexPageHandler)
|
||||
parent.GET("/list", h.listDestinationsHandler)
|
||||
parent.POST("", h.createDestinationHandler)
|
||||
parent.POST("/test", h.testDestinationHandler)
|
||||
parent.DELETE("/:destinationID", h.deleteDestinationHandler)
|
||||
parent.POST("/:destinationID/edit", h.editDestinationHandler)
|
||||
}
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"github.com/eduardolat/pgbackweb/internal/view/middleware"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/dashboard/about"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/dashboard/databases"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/dashboard/destinations"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/dashboard/profile"
|
||||
"github.com/eduardolat/pgbackweb/internal/view/web/dashboard/summary"
|
||||
"github.com/labstack/echo/v4"
|
||||
@@ -15,6 +16,7 @@ func MountRouter(
|
||||
) {
|
||||
summary.MountRouter(parent.Group(""), mids, servs)
|
||||
databases.MountRouter(parent.Group("/databases"), mids, servs)
|
||||
destinations.MountRouter(parent.Group("/destinations"), mids, servs)
|
||||
profile.MountRouter(parent.Group("/profile"), mids, servs)
|
||||
about.MountRouter(parent.Group("/about"), mids, servs)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user