diff --git a/config.go b/config.go index 839168a..a9f2634 100644 --- a/config.go +++ b/config.go @@ -115,6 +115,7 @@ type configSection struct { Description string `mapstructure:"description"` PathTemplate string `mapstructure:"pathtemplate"` ShowFull bool `mapstructure:"showFull"` + HideOnStart bool `mapstructure:"hideOnStart"` Name string } diff --git a/dbmigrations/00035.sql b/dbmigrations/00035.sql new file mode 100644 index 0000000..d33299d --- /dev/null +++ b/dbmigrations/00035.sql @@ -0,0 +1 @@ +alter table sections add hideonstart boolean not null default false; \ No newline at end of file diff --git a/go.mod b/go.mod index 22ef931..71b9093 100644 --- a/go.mod +++ b/go.mod @@ -63,8 +63,8 @@ require ( github.com/yuin/goldmark v1.5.4 // master github.com/yuin/goldmark-emoji v1.0.2-0.20210607094911-0487583eca38 - golang.org/x/crypto v0.7.0 - golang.org/x/net v0.8.0 + golang.org/x/crypto v0.8.0 + golang.org/x/net v0.9.0 golang.org/x/sync v0.1.0 golang.org/x/text v0.9.0 gopkg.in/yaml.v3 v3.0.1 @@ -124,8 +124,8 @@ require ( github.com/valyala/fastjson v1.6.4 // indirect go.uber.org/multierr v1.11.0 // indirect golang.org/x/exp v0.0.0-20230321023759-10a507213a29 // indirect - golang.org/x/image v0.6.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/image v0.7.0 // indirect + golang.org/x/oauth2 v0.7.0 // indirect golang.org/x/sys v0.7.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.30.0 // indirect diff --git a/go.sum b/go.sum index 52728d6..d594948 100644 --- a/go.sum +++ b/go.sum @@ -453,8 +453,8 @@ golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ= +golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -470,8 +470,8 @@ golang.org/x/exp v0.0.0-20230321023759-10a507213a29/go.mod h1:CxIveKay+FTh1D0yPZ golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4= -golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0= +golang.org/x/image v0.7.0 h1:gzS29xtG1J5ybQlv0PuyfE3nmc6R4qB73m6LUUmvFuw= +golang.org/x/image v0.7.0/go.mod h1:nd/q4ef1AKKYl/4kft7g+6UyGbdiqWqTP1ZAbRoV7Rg= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -535,8 +535,8 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM= +golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -546,8 +546,8 @@ golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= -golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= +golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= +golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -611,7 +611,7 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -621,7 +621,6 @@ golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/posts.go b/posts.go index 692d043..275becc 100644 --- a/posts.go +++ b/posts.go @@ -162,7 +162,7 @@ func (a *goBlog) serveHome(w http.ResponseWriter, r *http.Request) { } a.serveIndex(w, r.WithContext(context.WithValue(r.Context(), indexConfigKey, &indexConfig{ path: a.getRelativePath(blog, ""), - sections: lo.Values(bc.Sections), + sections: lo.Filter(lo.Values(bc.Sections), func(s *configSection, _ int) bool { return !s.HideOnStart }), }))) } diff --git a/settings.go b/settings.go index e8d359a..0de111f 100644 --- a/settings.go +++ b/settings.go @@ -88,33 +88,7 @@ func (a *goBlog) settingsDeleteSection(w http.ResponseWriter, r *http.Request) { const settingsCreateSectionPath = "/createsection" func (a *goBlog) settingsCreateSection(w http.ResponseWriter, r *http.Request) { - blog, bc := a.getBlog(r) - // Read values - sectionName := r.FormValue("sectionname") - sectionTitle := r.FormValue("sectiontitle") - if sectionName == "" || sectionTitle == "" { - a.serveError(w, r, "Missing values for name or title", http.StatusBadRequest) - return - } - // Create section - section := &configSection{ - Name: sectionName, - Title: sectionTitle, - } - err := a.saveSection(blog, section) - if err != nil { - a.serveError(w, r, "Failed to insert section into database", http.StatusInternalServerError) - return - } - // Reload sections - err = a.loadSections() - if err != nil { - a.serveError(w, r, "Failed to reload section configuration from the database", http.StatusInternalServerError) - return - } - a.reloadRouter() - a.cache.purge() - http.Redirect(w, r, bc.getRelativePath(settingsPath), http.StatusFound) + a.settingsUpdateSection(w, r) } const settingsUpdateSectionPath = "/updatesection" @@ -131,6 +105,7 @@ func (a *goBlog) settingsUpdateSection(w http.ResponseWriter, r *http.Request) { sectionDescription := r.FormValue("sectiondescription") sectionPathTemplate := r.FormValue("sectionpathtemplate") sectionShowFull := r.FormValue("sectionshowfull") == "on" + sectionHideOnStart := r.FormValue("sectionhideonstart") == "on" // Create section section := &configSection{ Name: sectionName, @@ -138,6 +113,7 @@ func (a *goBlog) settingsUpdateSection(w http.ResponseWriter, r *http.Request) { Description: sectionDescription, PathTemplate: sectionPathTemplate, ShowFull: sectionShowFull, + HideOnStart: sectionHideOnStart, } err := a.saveSection(blog, section) if err != nil { diff --git a/settingsDb.go b/settingsDb.go index 845d828..7ba22fb 100644 --- a/settingsDb.go +++ b/settingsDb.go @@ -78,14 +78,14 @@ func (a *goBlog) loadSections() error { } func (a *goBlog) getSections(blog string) (map[string]*configSection, error) { - rows, err := a.db.Query("select name, title, description, pathtemplate, showfull from sections where blog = @blog", sql.Named("blog", blog)) + rows, err := a.db.Query("select name, title, description, pathtemplate, showfull, hideonstart from sections where blog = @blog", sql.Named("blog", blog)) if err != nil { return nil, err } sections := map[string]*configSection{} for rows.Next() { section := &configSection{} - err = rows.Scan(§ion.Name, §ion.Title, §ion.Description, §ion.PathTemplate, §ion.ShowFull) + err = rows.Scan(§ion.Name, §ion.Title, §ion.Description, §ion.PathTemplate, §ion.ShowFull, §ion.HideOnStart) if err != nil { return nil, err } @@ -109,8 +109,8 @@ func (a *goBlog) saveAllSections() error { func (a *goBlog) saveSection(blog string, section *configSection) error { _, err := a.db.Exec( ` - insert into sections (blog, name, title, description, pathtemplate, showfull) values (@blog, @name, @title, @description, @pathtemplate, @showfull) - on conflict (blog, name) do update set title = @title2, description = @description2, pathtemplate = @pathtemplate2, showfull = @showfull2 + insert into sections (blog, name, title, description, pathtemplate, showfull, hideonstart) values (@blog, @name, @title, @description, @pathtemplate, @showfull, @hideonstart) + on conflict (blog, name) do update set title = @title2, description = @description2, pathtemplate = @pathtemplate2, showfull = @showfull2, hideonstart = @hideonstart2 `, sql.Named("blog", blog), sql.Named("name", section.Name), @@ -118,10 +118,12 @@ func (a *goBlog) saveSection(blog string, section *configSection) error { sql.Named("description", section.Description), sql.Named("pathtemplate", section.PathTemplate), sql.Named("showfull", section.ShowFull), + sql.Named("hideonstart", section.HideOnStart), sql.Named("title2", section.Title), sql.Named("description2", section.Description), sql.Named("pathtemplate2", section.PathTemplate), sql.Named("showfull2", section.ShowFull), + sql.Named("hideonstart2", section.HideOnStart), ) return err } diff --git a/strings/de.yaml b/strings/de.yaml index a2f365b..ab923c7 100644 --- a/strings/de.yaml +++ b/strings/de.yaml @@ -68,6 +68,7 @@ scheduledposts: "Geplante Posts" scheduledpostsdesc: "Beiträge mit dem Status `scheduled`, die veröffentlicht werden, wenn das `published`-Datum erreicht ist." search: "Suchen" sectiondescription: "Beschreibung" +sectionhideonstart: "Im Hauptindex ausblenden" sectionname: "Name" sectionpathtemplate: "Pfadvorlage" sectionshowfull: "Vollständigen Inhalt in der Zusammenfassung anzeigen" diff --git a/strings/default.yaml b/strings/default.yaml index 991cbbc..f25b6d2 100644 --- a/strings/default.yaml +++ b/strings/default.yaml @@ -83,6 +83,7 @@ scheduledpostsdesc: "Posts with status `scheduled` that are published when the ` scopes: "Scopes" search: "Search" sectiondescription: "Description" +sectionhideonstart: "Hide on main index" sectionname: "Name" sectionpathtemplate: "Path template" sectionshowfull: "Show full content in summary" diff --git a/uiComponents.go b/uiComponents.go index 8e4e31d..9ad31c5 100644 --- a/uiComponents.go +++ b/uiComponents.go @@ -593,6 +593,12 @@ func (a *goBlog) renderPostSectionSettings(hb *htmlbuilder.HtmlBuilder, rd *rend hb.WriteElementOpen("label", "for", "showfull-"+section.Name) hb.WriteEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectionshowfull")) hb.WriteElementClose("label") + hb.WriteElementsClose("br") + // Hide on start + hb.WriteElementOpen("input", "type", "checkbox", "name", "sectionhideonstart", "id", "hideonstart-"+section.Name, lo.If(section.HideOnStart, "checked").Else(""), "") + hb.WriteElementOpen("label", "for", "hideonstart-"+section.Name) + hb.WriteEscaped(a.ts.GetTemplateStringVariant(rd.Blog.Lang, "sectionhideonstart")) + hb.WriteElementClose("label") // Actions hb.WriteElementOpen("div", "class", "p")