diff --git a/internal/view/web/component/empty_results.go b/internal/view/web/component/empty_results.go index 4e1419d..dba33b2 100644 --- a/internal/view/web/component/empty_results.go +++ b/internal/view/web/component/empty_results.go @@ -42,3 +42,13 @@ func EmptyResults(params EmptyResultsParams) gomponents.Node { ), ) } + +func EmptyResultsTr(params EmptyResultsParams) gomponents.Node { + return html.Tr( + html.Td( + html.ColSpan("100%"), + html.Class("py-10"), + EmptyResults(params), + ), + ) +} diff --git a/internal/view/web/dashboard/backups/list_backups.go b/internal/view/web/dashboard/backups/list_backups.go index 1226672..22e7549 100644 --- a/internal/view/web/dashboard/backups/list_backups.go +++ b/internal/view/web/dashboard/backups/list_backups.go @@ -50,6 +50,14 @@ func listBackups( pagination paginateutil.PaginateResponse, backups []dbgen.BackupsServicePaginateBackupsRow, ) gomponents.Node { + if len(backups) < 1 { + return component.EmptyResultsTr(component.EmptyResultsParams{ + IsLarge: true, + Title: "No backups found", + Subtitle: "Wait for the first backup to appear here", + }) + } + yesNoSpan := func(b bool) gomponents.Node { if b { return component.SpanText("Yes") diff --git a/internal/view/web/dashboard/databases/list_databases.go b/internal/view/web/dashboard/databases/list_databases.go index 6a85a08..69386a8 100644 --- a/internal/view/web/dashboard/databases/list_databases.go +++ b/internal/view/web/dashboard/databases/list_databases.go @@ -50,6 +50,14 @@ func listDatabases( pagination paginateutil.PaginateResponse, databases []dbgen.DatabasesServicePaginateDatabasesRow, ) gomponents.Node { + if len(databases) < 1 { + return component.EmptyResultsTr(component.EmptyResultsParams{ + IsLarge: true, + Title: "No databases found", + Subtitle: "Wait for the first database to appear here", + }) + } + trs := []gomponents.Node{} for _, database := range databases { trs = append(trs, html.Tr( diff --git a/internal/view/web/dashboard/destinations/index.go b/internal/view/web/dashboard/destinations/index.go index dbe062c..a827d6c 100644 --- a/internal/view/web/dashboard/destinations/index.go +++ b/internal/view/web/dashboard/destinations/index.go @@ -21,16 +21,20 @@ func (h *handlers) indexPageHandler(c echo.Context) error { func indexPage(reqCtx reqctx.Ctx) gomponents.Node { content := []gomponents.Node{ html.Div( - html.Class("flex justify-between items-start"), - component.H1Text("S3 Destinations"), - createDestinationButton(), + html.Class("flex justify-between items-start space-x-2"), + html.Div( + component.H1Text("S3 Destinations"), + component.PText(` + Here you can manage your S3 destinations. You can skip creating a S3 + destination if you want to use the local storage for your backups. + `), + ), + html.Div( + html.Class("flex-none"), + createDestinationButton(), + ), ), - component.PText(` - Here you can manage your S3 destinations. You can skip creating a S3 - destination if you want to use the local storage for your backups. - `), - component.CardBox(component.CardBoxParams{ Class: "mt-4", Children: []gomponents.Node{ diff --git a/internal/view/web/dashboard/destinations/list_destinations.go b/internal/view/web/dashboard/destinations/list_destinations.go index ad262d1..931efd0 100644 --- a/internal/view/web/dashboard/destinations/list_destinations.go +++ b/internal/view/web/dashboard/destinations/list_destinations.go @@ -50,6 +50,14 @@ func listDestinations( pagination paginateutil.PaginateResponse, destinations []dbgen.DestinationsServicePaginateDestinationsRow, ) gomponents.Node { + if len(destinations) < 1 { + return component.EmptyResultsTr(component.EmptyResultsParams{ + IsLarge: true, + Title: "No destinations found", + Subtitle: "Wait for the first destination to appear here", + }) + } + trs := []gomponents.Node{} for _, destination := range destinations { trs = append(trs, html.Tr( diff --git a/internal/view/web/dashboard/executions/list_executions.go b/internal/view/web/dashboard/executions/list_executions.go index 5fab3f8..6ae1a87 100644 --- a/internal/view/web/dashboard/executions/list_executions.go +++ b/internal/view/web/dashboard/executions/list_executions.go @@ -66,6 +66,14 @@ func listExecutions( pagination paginateutil.PaginateResponse, executions []dbgen.ExecutionsServicePaginateExecutionsRow, ) gomponents.Node { + if len(executions) < 1 { + return component.EmptyResultsTr(component.EmptyResultsParams{ + IsLarge: true, + Title: "No executions found", + Subtitle: "Wait for the first execution to appear here", + }) + } + trs := []gomponents.Node{} for _, execution := range executions { trs = append(trs, html.Tr( diff --git a/internal/view/web/dashboard/restorations/list_restorations.go b/internal/view/web/dashboard/restorations/list_restorations.go index 62935bf..0a35769 100644 --- a/internal/view/web/dashboard/restorations/list_restorations.go +++ b/internal/view/web/dashboard/restorations/list_restorations.go @@ -62,6 +62,14 @@ func listRestorations( pagination paginateutil.PaginateResponse, restorations []dbgen.RestorationsServicePaginateRestorationsRow, ) gomponents.Node { + if len(restorations) < 1 { + return component.EmptyResultsTr(component.EmptyResultsParams{ + IsLarge: true, + Title: "No restorations found", + Subtitle: "Wait for the first restoration to appear here", + }) + } + trs := []gomponents.Node{} for _, restoration := range restorations { trs = append(trs, html.Tr( diff --git a/internal/view/web/dashboard/webhooks/list_webhooks.go b/internal/view/web/dashboard/webhooks/list_webhooks.go index 0527ed1..2378466 100644 --- a/internal/view/web/dashboard/webhooks/list_webhooks.go +++ b/internal/view/web/dashboard/webhooks/list_webhooks.go @@ -50,6 +50,14 @@ func listWebhooks( pagination paginateutil.PaginateResponse, whooks []dbgen.Webhook, ) gomponents.Node { + if len(whooks) < 1 { + return component.EmptyResultsTr(component.EmptyResultsParams{ + IsLarge: true, + Title: "No webhooks found", + Subtitle: "Wait for the first webhook to appear here", + }) + } + trs := []gomponents.Node{} for _, whook := range whooks { trs = append(trs, html.Tr( diff --git a/internal/view/web/dashboard/webhooks/webhook_executions.go b/internal/view/web/dashboard/webhooks/webhook_executions.go index 12a0798..2076928 100644 --- a/internal/view/web/dashboard/webhooks/webhook_executions.go +++ b/internal/view/web/dashboard/webhooks/webhook_executions.go @@ -61,16 +61,10 @@ func webhookExecutionsList( execs []dbgen.WebhookExecution, ) gomponents.Node { if len(execs) == 0 { - return html.Tr( - html.Td( - html.ColSpan("4"), - html.Class("py-10"), - component.EmptyResults(component.EmptyResultsParams{ - Title: "No executions found", - Subtitle: "Wait for the first execution to appear here", - }), - ), - ) + return component.EmptyResultsTr(component.EmptyResultsParams{ + Title: "No executions found", + Subtitle: "Wait for the first execution to appear here", + }) } trs := []gomponents.Node{} @@ -136,106 +130,100 @@ func webhookExecutionDetailsButton( }`), alpine.XOn("mouseenter.once", "processTextareas()"), - component.CardBoxSimple( - html.Table( - html.Class("table [&_th]:text-nowrap"), - html.Tr( - html.Td( - html.ColSpan("2"), - component.H3Text("General"), - ), + html.Table( + html.Class("table [&_th]:text-nowrap"), + html.Tr( + html.Td( + html.ColSpan("100%"), + component.H3Text("General"), ), - html.Tr( - html.Th(component.SpanText("ID")), - html.Td(component.SpanText(exec.ID.String())), + ), + html.Tr( + html.Th(component.SpanText("ID")), + html.Td(component.SpanText(exec.ID.String())), + ), + html.Tr( + html.Th(component.SpanText("Date")), + html.Td(component.SpanText( + exec.CreatedAt.Local().Format(timeutil.LayoutYYYYMMDDHHMMSSPretty), + )), + ), + ), + + html.Table( + html.Class("table [&_th]:text-nowrap"), + html.Tr( + html.Td( + html.ColSpan("100%"), + component.H3Text("Request"), ), - html.Tr( - html.Th(component.SpanText("Date")), - html.Td(component.SpanText( - exec.CreatedAt.Local().Format(timeutil.LayoutYYYYMMDDHHMMSSPretty), - )), + ), + html.Tr( + html.Th(component.SpanText("Method")), + html.Td(component.SpanText(exec.ReqMethod.String)), + ), + html.Tr( + html.Th(component.SpanText("Headers")), + html.Td( + component.TextareaControl(component.TextareaControlParams{ + Children: []gomponents.Node{ + alpine.XRef("reqHeadersTextarea"), + gomponents.Text(exec.ReqHeaders.String), + }, + }), + ), + ), + html.Tr( + html.Th(component.SpanText("Body")), + html.Td( + component.TextareaControl(component.TextareaControlParams{ + Children: []gomponents.Node{ + alpine.XRef("reqBodyTextarea"), + gomponents.Text(exec.ReqBody.String), + }, + }), ), ), ), - component.CardBoxSimple( - html.Table( - html.Class("table [&_th]:text-nowrap"), - html.Tr( - html.Td( - html.ColSpan("2"), - component.H3Text("Request"), - ), - ), - html.Tr( - html.Th(component.SpanText("Method")), - html.Td(component.SpanText(exec.ReqMethod.String)), - ), - html.Tr( - html.Th(component.SpanText("Headers")), - html.Td( - component.TextareaControl(component.TextareaControlParams{ - Children: []gomponents.Node{ - alpine.XRef("reqHeadersTextarea"), - gomponents.Text(exec.ReqHeaders.String), - }, - }), - ), - ), - html.Tr( - html.Th(component.SpanText("Body")), - html.Td( - component.TextareaControl(component.TextareaControlParams{ - Children: []gomponents.Node{ - alpine.XRef("reqBodyTextarea"), - gomponents.Text(exec.ReqBody.String), - }, - }), - ), + html.Table( + html.Class("table [&_th]:text-nowrap"), + html.Tr( + html.Td( + html.ColSpan("100%"), + component.H3Text("Response"), ), ), - ), - - component.CardBoxSimple( - html.Table( - html.Class("table [&_th]:text-nowrap"), - html.Tr( - html.Td( - html.ColSpan("2"), - component.H3Text("Response"), - ), + html.Tr( + html.Th(component.SpanText("Status")), + html.Td(component.SpanText( + fmt.Sprintf("%d", exec.ResStatus.Int16), + )), + ), + html.Tr( + html.Th(component.SpanText("Duration")), + html.Td(component.SpanText(duration.String())), + ), + html.Tr( + html.Th(component.SpanText("Headers")), + html.Td( + component.TextareaControl(component.TextareaControlParams{ + Children: []gomponents.Node{ + alpine.XRef("resHeadersTextarea"), + gomponents.Text(exec.ResHeaders.String), + }, + }), ), - html.Tr( - html.Th(component.SpanText("Status")), - html.Td(component.SpanText( - fmt.Sprintf("%d", exec.ResStatus.Int16), - )), - ), - html.Tr( - html.Th(component.SpanText("Duration")), - html.Td(component.SpanText(duration.String())), - ), - html.Tr( - html.Th(component.SpanText("Headers")), - html.Td( - component.TextareaControl(component.TextareaControlParams{ - Children: []gomponents.Node{ - alpine.XRef("resHeadersTextarea"), - gomponents.Text(exec.ResHeaders.String), - }, - }), - ), - ), - html.Tr( - html.Th(component.SpanText("Body")), - html.Td( - component.TextareaControl(component.TextareaControlParams{ - Children: []gomponents.Node{ - alpine.XRef("resBodyTextarea"), - gomponents.Text(exec.ResBody.String), - }, - }), - ), + ), + html.Tr( + html.Th(component.SpanText("Body")), + html.Td( + component.TextareaControl(component.TextareaControlParams{ + Children: []gomponents.Node{ + alpine.XRef("resBodyTextarea"), + gomponents.Text(exec.ResBody.String), + }, + }), ), ), ),