From 4b58544300847e5faf19be5baa4eb177a86b2b0f Mon Sep 17 00:00:00 2001 From: Leonardo Bishop Date: Thu, 17 Jul 2025 21:52:26 +0100 Subject: Add automatic index --- web/command/html/authenticate.go | 5 +- web/command/html/create.go | 11 ++- web/command/html/delete.go | 11 ++- web/command/html/error.go | 7 +- web/command/html/flags.go | 12 +-- web/command/html/home.go | 11 ++- web/command/html/host.go | 11 ++- web/command/html/site.go | 25 ++--- web/command/html/skeleton.go | 57 ------------ web/command/html/style.css | 183 ------------------------------------ web/command/html/upload.go | 11 ++- web/skeleton/skeleton.go | 58 ++++++++++++ web/skeleton/style.css | 195 +++++++++++++++++++++++++++++++++++++++ web/status/404.html | 11 --- 14 files changed, 309 insertions(+), 299 deletions(-) delete mode 100644 web/command/html/skeleton.go delete mode 100644 web/command/html/style.css create mode 100644 web/skeleton/skeleton.go create mode 100644 web/skeleton/style.css delete mode 100644 web/status/404.html (limited to 'web') diff --git a/web/command/html/authenticate.go b/web/command/html/authenticate.go index c077529..3d85325 100644 --- a/web/command/html/authenticate.go +++ b/web/command/html/authenticate.go @@ -1,15 +1,16 @@ package html import ( + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) func AuthenticatePage(err string) Node { - return page("Authenticate", + return Page("Authenticate", H1(Text("Welcome to scrapbook")), - If(err != "", alertError(err)), + If(err != "", AlertError(err)), Form( Action("/authenticate"), diff --git a/web/command/html/create.go b/web/command/html/create.go index 8b76776..47de92f 100644 --- a/web/command/html/create.go +++ b/web/command/html/create.go @@ -1,6 +1,7 @@ package html import ( + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) @@ -11,19 +12,19 @@ type CreatePageForm struct { } func CreatePage(success, err string, formValues CreatePageForm) Node { - return page("Create site", + return Page("Create site", H1(Text("Create site")), If(success != "", Group{ - alertSuccess(success), + AlertSuccess(success), Div( Class("control-group group-right"), - navButton("OK", "/"), + NavButton("OK", "/"), ), }), If(success == "", Group{ - If(err != "", alertError(err)), + If(err != "", AlertError(err)), Form( Action("/create"), @@ -62,7 +63,7 @@ func CreatePage(success, err string, formValues CreatePageForm) Node { Div( Class("control-group group-right"), - navButton("Go back", "/"), + NavButton("Go back", "/"), Input( Type("submit"), Value("Submit"), diff --git a/web/command/html/delete.go b/web/command/html/delete.go index a2059f5..54764c3 100644 --- a/web/command/html/delete.go +++ b/web/command/html/delete.go @@ -3,24 +3,25 @@ package html import ( "fmt" + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) func DeletePage(success, err string, siteName string) Node { - return page("Delete "+siteName, + return Page("Delete "+siteName, H1(Text("Delete "+siteName)), If(success != "", Group{ - alertSuccess(success), + AlertSuccess(success), Div( Class("control-group group-right"), - navButton("OK", "/"), + NavButton("OK", "/"), ), }), If(success == "", Group{ - If(err != "", alertError(err)), + If(err != "", AlertError(err)), Form( Method("post"), @@ -46,7 +47,7 @@ func DeletePage(success, err string, siteName string) Node { Div( Class("control-group group-right"), - navButton("Go back", fmt.Sprintf("/site/%s/", siteName)), + NavButton("Go back", fmt.Sprintf("/site/%s/", siteName)), Input( Type("submit"), Value("Submit"), diff --git a/web/command/html/error.go b/web/command/html/error.go index b39cc19..20b49f3 100644 --- a/web/command/html/error.go +++ b/web/command/html/error.go @@ -1,13 +1,14 @@ package html import ( + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" ) func ErrorPage(err string) Node { - return page("Error", - alertError(err), + return Page("Error", + AlertError(err), - navButton("Home", "/"), + NavButton("Home", "/"), ) } diff --git a/web/command/html/flags.go b/web/command/html/flags.go index 728b415..61a1f50 100644 --- a/web/command/html/flags.go +++ b/web/command/html/flags.go @@ -4,24 +4,25 @@ import ( "fmt" "github.com/LMBishop/scrapbook/pkg/config" + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) func FlagsPage(success, err string, siteName string, flags config.SiteFlag) Node { - return page("Set flags for "+siteName, + return Page("Set flags for "+siteName, H1(Text("Set flags for "+siteName)), If(success != "", Group{ - alertSuccess(success), + AlertSuccess(success), Div( Class("control-group group-right"), - navButton("OK", fmt.Sprintf("/site/%s/", siteName)), + NavButton("OK", fmt.Sprintf("/site/%s/", siteName)), ), }), If(success == "", Group{ - If(err != "", alertError(err)), + If(err != "", AlertError(err)), Form( Method("post"), @@ -70,7 +71,6 @@ func FlagsPage(success, err string, siteName string, flags config.SiteFlag) Node ID("index"), Name("index"), Type("checkbox"), - Disabled(), If(flags&config.FlagIndex != 0, Checked()), ), Label( @@ -121,7 +121,7 @@ func FlagsPage(success, err string, siteName string, flags config.SiteFlag) Node Div( Class("control-group group-right"), - navButton("Go back", fmt.Sprintf("/site/%s/", siteName)), + NavButton("Go back", fmt.Sprintf("/site/%s/", siteName)), Input( Type("submit"), Value("Submit"), diff --git a/web/command/html/home.go b/web/command/html/home.go index 5dc236a..6de30bd 100644 --- a/web/command/html/home.go +++ b/web/command/html/home.go @@ -5,16 +5,17 @@ import ( "github.com/LMBishop/scrapbook/pkg/index" "github.com/LMBishop/scrapbook/pkg/site" + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) func HomePage(siteIndex *index.SiteIndex) Node { - return page("All sites", + return Page("All sites", H1(Text("All sites")), Div( - Class("sites-table"), + Class("table sites-table"), Group{ Span( Class("header name"), @@ -58,18 +59,18 @@ func HomePage(siteIndex *index.SiteIndex) Node { ), Span( Class("actions"), - navButton("Details", fmt.Sprintf("/site/%s/", site.Name)), + NavButton("Details", fmt.Sprintf("/site/%s/", site.Name)), ), } }), ), - If(len(siteIndex.GetSites()) == 0, alert("There are no sites to display", "")), + If(len(siteIndex.GetSites()) == 0, Alert("There are no sites to display", "")), Div( Class("control-group group-right"), - navButton("Create new", "/create"), + NavButton("Create new", "/create"), ), ) } diff --git a/web/command/html/host.go b/web/command/html/host.go index 36f0e6b..cd1c75a 100644 --- a/web/command/html/host.go +++ b/web/command/html/host.go @@ -3,24 +3,25 @@ package html import ( "fmt" + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) func HostPage(success, err, siteName, hostValue string) Node { - return page("Change host for "+siteName, + return Page("Change host for "+siteName, H1(Text("Change host for "+siteName)), If(success != "", Group{ - alertSuccess(success), + AlertSuccess(success), Div( Class("control-group group-right"), - navButton("OK", fmt.Sprintf("/site/%s/", siteName)), + NavButton("OK", fmt.Sprintf("/site/%s/", siteName)), ), }), If(success == "", Group{ - If(err != "", alertError(err)), + If(err != "", AlertError(err)), Form( Method("post"), @@ -40,7 +41,7 @@ func HostPage(success, err, siteName, hostValue string) Node { Div( Class("control-group group-right"), - navButton("Go back", fmt.Sprintf("/site/%s/", siteName)), + NavButton("Go back", fmt.Sprintf("/site/%s/", siteName)), Input( Type("submit"), Value("Submit"), diff --git a/web/command/html/site.go b/web/command/html/site.go index cb1fa31..e9bfbac 100644 --- a/web/command/html/site.go +++ b/web/command/html/site.go @@ -5,6 +5,7 @@ import ( "github.com/LMBishop/scrapbook/pkg/config" "github.com/LMBishop/scrapbook/pkg/site" + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) @@ -13,10 +14,10 @@ func SitePage(mainConfig *config.MainConfig, site *site.Site) Node { versions, err := site.GetAllVersions() currentVersion, _ := site.GetCurrentVersion() - return page("Site "+site.Name, + return Page("Site "+site.Name, H1(Text("Site "+site.Name)), - If(site.EvaluateSiteStatus() != "live", alertError(site.EvaluateSiteStatusReason())), + If(site.EvaluateSiteStatus() != "live", AlertError(site.EvaluateSiteStatusReason())), FieldSet( Legend(Text("Site actions")), @@ -24,19 +25,19 @@ func SitePage(mainConfig *config.MainConfig, site *site.Site) Node { Div( Class("control-group"), - navButton("Change host", "host"), - navButton("Set flags", "flags"), - navButton("Delete site", "delete"), + NavButton("Change host", "host"), + NavButton("Set flags", "flags"), + NavButton("Delete site", "delete"), ), ), H2(Text("Version history")), - If(len(versions) == 0, Span(Class("span"), alert("There are no versions to display", ""))), - If(err != nil, Span(Class("span"), alertError(fmt.Errorf("Cannot show site versions: %w", err).Error()))), + If(len(versions) == 0, Span(Class("span"), Alert("There are no versions to display", ""))), + If(err != nil, Span(Class("span"), AlertError(fmt.Errorf("Cannot show site versions: %w", err).Error()))), If(len(versions) > 0 && err == nil, Group{ Div( - Class("versions-table"), + Class("table versions-table"), Group{ Span( Class("header date"), @@ -57,8 +58,8 @@ func SitePage(mainConfig *config.MainConfig, site *site.Site) Node { ), Span( Class("actions"), - If(currentVersion != version, navButton("Set current", fmt.Sprintf("/site/%s/", site.Name))), - navButton("Details", fmt.Sprintf("version/%s/", version)), + If(currentVersion != version, NavButton("Set current", fmt.Sprintf("/site/%s/", site.Name))), + NavButton("Details", fmt.Sprintf("version/%s/", version)), ), } }), @@ -67,7 +68,7 @@ func SitePage(mainConfig *config.MainConfig, site *site.Site) Node { Div( Class("control-group group-right"), - navButton("Upload new version", "upload"), + NavButton("Upload new version", "upload"), ), H2(Text("Information")), @@ -78,6 +79,6 @@ func SitePage(mainConfig *config.MainConfig, site *site.Site) Node { Br(), - navButton("Go back", "/"), + NavButton("Go back", "/"), ) } diff --git a/web/command/html/skeleton.go b/web/command/html/skeleton.go deleted file mode 100644 index 9e17475..0000000 --- a/web/command/html/skeleton.go +++ /dev/null @@ -1,57 +0,0 @@ -package html - -import ( - _ "embed" - - . "maragu.dev/gomponents" - . "maragu.dev/gomponents/components" - . "maragu.dev/gomponents/html" -) - -//go:embed style.css -var styles string - -func page(title string, children ...Node) Node { - return HTML5(HTML5Props{ - Title: title, - Language: "en", - Head: []Node{ - StyleEl(Raw(styles)), - }, - Body: []Node{ - Div(Class("container"), - Group(children), - footer(), - ), - }, - }) -} - -func footer() Node { - return Footer( - Hr(), - Text("scrapbook"), - ) -} - -func navButton(label string, dest string) Node { - return A( - Href(dest), - Text(label), - ) -} - -func alert(label string, class string) Node { - return Div( - Class("alert "+class), - Text(label), - ) -} - -func alertError(label string) Node { - return alert(label, "error") -} - -func alertSuccess(label string) Node { - return alert(label, "success") -} diff --git a/web/command/html/style.css b/web/command/html/style.css deleted file mode 100644 index e8db90c..0000000 --- a/web/command/html/style.css +++ /dev/null @@ -1,183 +0,0 @@ -html, body { - font-family: sans-serif; - -} -table { - border-collapse: collapse; -} - -th, td { - text-align: left; - padding: 8px; - border: black 1px solid; -} - -th { - background-color: #f2f2f2; -} - -a, input[type=submit] { - /* font-weight: bold; */ - border: 1px solid #000!important; - color: #000; - /* border: 2px solid #0074D9!important; - color: #0074D9; */ - padding: 3px 6px!important; - text-decoration: none; -} - -a :visited{ - color: #fff; -} - -form { - display: flex; - flex-direction: column; -} - -fieldset { - display: flex; - flex-direction: column; - gap: 0.5rem; - margin-bottom: 1rem;; -} - -legend { - background-color: #000; - color: #fff; - padding: 3px 6px; - font-style: italic; -} - -label:not(input[type=checkbox]+label) { - font-weight: bold; -} - -input[type=checkbox] { - margin: 0 0.25rem 0 0; -} - -footer { - margin-top: 2rem; - color: gray; - font-size: smaller; -} - -button, input[type=submit] { - background: none!important; - font-family: sans-serif; - font-size: medium; - cursor: pointer; -} - -a:hover, button:hover, input[type=submit]:hover, button:active, a:active, input[type=submit]:active { - background: #000!important; - color: #fff!important; -} - -.form-help { - font-size: smaller; -} - -.container { - max-width: 800px; - margin: 0 auto; -} - -.control-group { - display: flex; - gap: 0.5rem; - flex-direction: row; -} - -.control-group.group-right { - justify-content: flex-end; -} - -.control-group a, .control-group button, .control-group input[type=submit] { - text-decoration: none; - width: initial; -} - -.sites-table { - width: 100%; - display: grid; - grid-template-columns: 40% 1fr 1fr 1fr; - align-items: center; - gap: 1rem; - margin-bottom: 1rem; -} - -.sites-table > .header, .versions-table > .header { - font-weight: bold; -} - -.sites-table > .name { - display: flex; - flex-direction: column; -} - -.sites-table > .flags:not(.header) { - font-family: monospace; -} - -.sites-table > .name > span:nth-child(2) { - font-size: smaller; -} - -.sites-table > .actions, .versions-table > .actions { - display: flex; - gap: 0.5rem; - justify-self: flex-end; -} - -.versions-table { - width: 100%; - display: grid; - grid-template-columns: 1fr 1fr; - align-items: center; - gap: 1rem; - margin-bottom: 1rem; -} - -.versions-table > .span { - grid-column: 1 / span 2; -} - -.versions-table > .date { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.versions-table > .date > .current { - color: #0dbe22; - font-size: smaller; - font-style: italic; -} - -.alert { - background-color: #f2f2f2; - padding: 0.5rem 1rem; - border: 1px solid #e7e7e7; - margin-bottom: 1rem; - font-style: italic; -} - -.alert.success { - background-color: #aaffaa; - border: 1px solid #90ee90; -} - -.alert.error { - background-color: #ffcccb; - border: 1px solid #ff6666; -} - -.text-good { - color: #0dbe22; -} - -.text-bad { - color: #c02020; -} \ No newline at end of file diff --git a/web/command/html/upload.go b/web/command/html/upload.go index 1225d0f..5810b19 100644 --- a/web/command/html/upload.go +++ b/web/command/html/upload.go @@ -3,24 +3,25 @@ package html import ( "fmt" + . "github.com/LMBishop/scrapbook/web/skeleton" . "maragu.dev/gomponents" . "maragu.dev/gomponents/html" ) func UploadPage(success, err string, siteName string) Node { - return page("Upload new version to "+siteName, + return Page("Upload new version to "+siteName, H1(Text("Upload new version to "+siteName)), If(success != "", Group{ - alertSuccess(success), + AlertSuccess(success), Div( Class("control-group group-right"), - navButton("OK", fmt.Sprintf("/site/%s/", siteName)), + NavButton("OK", fmt.Sprintf("/site/%s/", siteName)), ), }), If(success == "", Group{ - If(err != "", alertError(err)), + If(err != "", AlertError(err)), Form( Method("post"), @@ -41,7 +42,7 @@ func UploadPage(success, err string, siteName string) Node { Div( Class("control-group group-right"), - navButton("Go back", fmt.Sprintf("/site/%s/", siteName)), + NavButton("Go back", fmt.Sprintf("/site/%s/", siteName)), Input( Type("submit"), Value("Submit"), diff --git a/web/skeleton/skeleton.go b/web/skeleton/skeleton.go new file mode 100644 index 0000000..a3ba73e --- /dev/null +++ b/web/skeleton/skeleton.go @@ -0,0 +1,58 @@ +package skeleton + +import ( + _ "embed" + + . "maragu.dev/gomponents" + . "maragu.dev/gomponents/components" + . "maragu.dev/gomponents/html" +) + +//go:embed style.css +var styles string + +func Page(title string, children ...Node) Node { + return HTML5(HTML5Props{ + Title: title, + Language: "en", + Head: []Node{ + StyleEl(Raw(styles)), + }, + Body: []Node{ + Div(Class("container"), + Group(children), + footer(), + ), + }, + }) +} + +func footer() Node { + return Footer( + Hr(), + Text("scrapbook"), + ) +} + +func NavButton(label string, dest string) Node { + return A( + Class("button"), + Href(dest), + Text(label), + ) +} + +func Alert(label string, class string) Node { + return Div( + Class("alert "+class), + Text(label), + ) +} + +func AlertError(label string) Node { + return Alert(label, "error") +} + +func AlertSuccess(label string) Node { + return Alert(label, "success") +} diff --git a/web/skeleton/style.css b/web/skeleton/style.css new file mode 100644 index 0000000..b4cd0eb --- /dev/null +++ b/web/skeleton/style.css @@ -0,0 +1,195 @@ +html, body { + font-family: sans-serif; + +} +table { + border-collapse: collapse; +} + +th, td { + text-align: left; + padding: 8px; + border: black 1px solid; +} + +th { + background-color: #f2f2f2; +} + +a.button, input[type=submit] { + /* font-weight: bold; */ + border: 1px solid #000!important; + color: #000; + /* border: 2px solid #0074D9!important; + color: #0074D9; */ + padding: 3px 6px!important; + text-decoration: none; +} + +a.button:visited{ + color: #000; +} + +form { + display: flex; + flex-direction: column; +} + +fieldset { + display: flex; + flex-direction: column; + gap: 0.5rem; + margin-bottom: 1rem;; +} + +legend { + background-color: #000; + color: #fff; + padding: 3px 6px; + font-style: italic; +} + +label:not(input[type=checkbox]+label) { + font-weight: bold; +} + +input[type=checkbox] { + margin: 0 0.25rem 0 0; +} + +footer { + margin-top: 2rem; + color: gray; + font-size: smaller; +} + +button, input[type=submit] { + background: none!important; + font-family: sans-serif; + font-size: medium; + cursor: pointer; +} + +a.button:hover, button:hover, input[type=submit]:hover, button:active, a.button:active, input[type=submit]:active { + background: #000!important; + color: #fff!important; +} + +.form-help { + font-size: smaller; +} + +.container { + max-width: 800px; + margin: 0 auto; +} + +.control-group { + display: flex; + gap: 0.5rem; + flex-direction: row; +} + +.control-group.group-right { + justify-content: flex-end; +} + +.control-group a.button, .control-group button, .control-group input[type=submit] { + text-decoration: none; + width: initial; +} + +.table { + width: 100%; + align-items: center; + display: grid; + gap: 1rem; + margin-bottom: 1rem; +} + +.table > .header { + font-weight: bold; +} + +.files-table { + grid-template-columns: 1fr 1fr 1fr; + gap: 0.5rem; +} + +.files-table > a.name { + width: 100%; + border: none !important; + color: #0074D9 !important; + padding: 0 !important; + margin: 0 !important; + text-decoration: none; +} + +.sites-table { + grid-template-columns: 40% 1fr 1fr 1fr; +} + +.sites-table > .name { + display: flex; + flex-direction: column; +} + +.sites-table > .flags:not(.header) { + font-family: monospace; +} + +.sites-table > .name > span:nth-child(2) { + font-size: smaller; +} + +.sites-table > .actions, .versions-table > .actions { + display: flex; + gap: 0.5rem; + justify-self: flex-end; +} + +.versions-table { + grid-template-columns: 1fr 1fr; +} + +.versions-table > .span { + grid-column: 1 / span 2; +} + +.versions-table > .date { + display: flex; + align-items: center; + gap: 0.5rem; +} + +.versions-table > .date > .current { + color: #0dbe22; + font-size: smaller; + font-style: italic; +} + +.alert { + background-color: #f2f2f2; + padding: 0.5rem 1rem; + border: 1px solid #e7e7e7; + margin-bottom: 1rem; + font-style: italic; +} + +.alert.success { + background-color: #aaffaa; + border: 1px solid #90ee90; +} + +.alert.error { + background-color: #ffcccb; + border: 1px solid #ff6666; +} + +.text-good { + color: #0dbe22; +} + +.text-bad { + color: #c02020; +} \ No newline at end of file diff --git a/web/status/404.html b/web/status/404.html deleted file mode 100644 index a094ccd..0000000 --- a/web/status/404.html +++ /dev/null @@ -1,11 +0,0 @@ - - - - 404 Not Found - - -

The request page could not be found.

-
-

scrapbook

- - -- cgit v1.2.3-70-g09d2