diff --git a/admin.go b/admin.go index 7d21abd..227d363 100644 --- a/admin.go +++ b/admin.go @@ -299,6 +299,7 @@ func handleViewAdminPage(app *App, u *User, w http.ResponseWriter, r *http.Reque Config config.AppCfg Message string + Banner *instanceContent Content *instanceContent }{ Config: app.cfg.App, @@ -311,6 +312,13 @@ func handleViewAdminPage(app *App, u *User, w http.ResponseWriter, r *http.Reque p.Content, err = getAboutPage(app) } else if slug == "privacy" { p.Content, err = getPrivacyPage(app) + } else if slug == "landing" { + p.Banner, err = getLandingBanner(app) + if err != nil { + return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not get banner: %v", err)} + } + p.Content, err = getLandingPage(app) + p.Content.ID = "landing" } else { p.Content, err = app.db.GetDynamicContent(slug) } @@ -334,13 +342,24 @@ func handleAdminUpdateSite(app *App, u *User, w http.ResponseWriter, r *http.Req id := vars["page"] // Validate - if id != "about" && id != "privacy" { + if id != "about" && id != "privacy" && id != "landing" { return impart.HTTPError{http.StatusNotFound, "No such page."} } - // Update page + var err error m := "" - err := app.db.UpdateDynamicContent(id, r.FormValue("title"), r.FormValue("content"), "page") + if id == "landing" { + // Handle special landing page + err = app.db.UpdateDynamicContent("landing-banner", "", r.FormValue("banner"), "section") + if err != nil { + m = "?m=" + err.Error() + return impart.HTTPError{http.StatusFound, "/admin/page/" + id + m} + } + err = app.db.UpdateDynamicContent("landing-body", "", r.FormValue("content"), "section") + } else { + // Update page + err = app.db.UpdateDynamicContent(id, r.FormValue("title"), r.FormValue("content"), "page") + } if err != nil { m = "?m=" + err.Error() } diff --git a/app.go b/app.go index 61db4e1..ad2c451 100644 --- a/app.go +++ b/app.go @@ -203,6 +203,8 @@ func handleViewHome(app *App, w http.ResponseWriter, r *http.Request) error { p := struct { page.StaticPage Flashes []template.HTML + Banner template.HTML + Content template.HTML ForcedLanding bool }{ @@ -210,6 +212,20 @@ func handleViewHome(app *App, w http.ResponseWriter, r *http.Request) error { ForcedLanding: forceLanding, } + banner, err := getLandingBanner(app) + if err != nil { + log.Error("unable to get landing banner: %v", err) + return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not get banner: %v", err)} + } + p.Banner = template.HTML(applyMarkdown([]byte(banner.Content), "")) + + content, err := getLandingPage(app) + if err != nil { + log.Error("unable to get landing content: %v", err) + return impart.HTTPError{http.StatusInternalServerError, fmt.Sprintf("Could not get content: %v", err)} + } + p.Content = template.HTML(applyMarkdown([]byte(content.Content), "")) + // Get error messages session, err := app.sessionStore.Get(r, cookieName) if err != nil { diff --git a/pages.go b/pages.go index 29ba07a..7ec20df 100644 --- a/pages.go +++ b/pages.go @@ -79,3 +79,59 @@ We store log files, or data about what happens on our servers. We also use cooki Beyond this, it's important that you trust whoever runs **` + cfg.App.SiteName + `**. Software can only do so much to protect you -- your level of privacy protections will ultimately fall on the humans that run this particular service.` } + +func getLandingBanner(app *App) (*instanceContent, error) { + c, err := app.db.GetDynamicContent("landing-banner") + if err != nil { + return nil, err + } + if c == nil { + c = &instanceContent{ + ID: "landing-banner", + Type: "section", + Content: defaultLandingBanner(app.cfg), + Updated: defaultPageUpdatedTime, + } + } + return c, nil +} + +func getLandingPage(app *App) (*instanceContent, error) { + c, err := app.db.GetDynamicContent("landing-body") + if err != nil { + return nil, err + } + if c == nil { + c = &instanceContent{ + ID: "landing-body", + Type: "section", + Content: defaultLandingBody(app.cfg), + Updated: defaultPageUpdatedTime, + } + } + return c, nil +} + +func defaultLandingBanner(cfg *config.Config) string { + if cfg.App.Federation { + return "# Start your blog in the fediverse" + } + return "# Start your blog" +} + +func defaultLandingBody(cfg *config.Config) string { + if cfg.App.Federation { + return `## Join the Fediverse + +The fediverse is a large network of platforms that all speak a common language. Imagine if you could reply to Instagram posts from Twitter, or interact with your favorite Medium blogs from Facebook -- federated alternatives like [PixelFed](https://pixelfed.org), [Mastodon](https://joinmastodon.org), and WriteFreely enable you to do these types of things. + +
+ +
+ +## Write More Socially + +WriteFreely can communicate with other federated platforms like Mastodon, so people can follow your blogs, bookmark their favorite posts, and boost them to their followers. Sign up above to create a blog and join the fediverse.` + } + return "" +} diff --git a/pages/landing.tmpl b/pages/landing.tmpl index fc4be05..d3867a9 100644 --- a/pages/landing.tmpl +++ b/pages/landing.tmpl @@ -53,15 +53,22 @@ tr.subscription { form dd { margin: 0; } +.banner-container { + text-align: left; +} +.banner-container h1 { + margin-top: 0; + max-width: 8em; +} {{end}} {{define "content"}}
-
-

{{if .Federation}}Start your blog in the fediverse{{else}}Start your blog{{end}}

-

Learn more...

+ @@ -101,24 +108,14 @@ form dd {
-{{if .Federation}} +{{if .Content}}
{{end}}
-{{ if .Federation }} +{{ if .Content }}
- -

Join the Fediverse

-

The fediverse is a large network of platforms that all speak a common language. Imagine if you could reply to Instagram posts from Twitter, or interact with your favorite Medium blogs from Facebook — federated alternatives like PixelFed, Mastodon, and WriteFreely enable you to do these types of things.

- -
- -
- -

Write More Socially

-

WriteFreely can communicate with other federated platforms like Mastodon, so people can follow your blogs, bookmark their favorite posts, and boost them to their followers. Sign up above to create a blog and join the fediverse.

- + {{.Content}}
{{ end }} diff --git a/templates/user/admin/pages.tmpl b/templates/user/admin/pages.tmpl index 9842287..25f7984 100644 --- a/templates/user/admin/pages.tmpl +++ b/templates/user/admin/pages.tmpl @@ -17,6 +17,9 @@ table.classy.export .disabled, table.classy.export a { Page Last Modified + + Home + {{range .Pages}} {{if .Title.Valid}}{{.Title.String}}{{else}}{{.ID}}{{end}} diff --git a/templates/user/admin/view-page.tmpl b/templates/user/admin/view-page.tmpl index 3b1acbd..2ed0658 100644 --- a/templates/user/admin/view-page.tmpl +++ b/templates/user/admin/view-page.tmpl @@ -25,23 +25,33 @@ input[type=text] {
{{template "admin-header" .}} -

{{.Content.ID}} page

+

{{if eq .Content.ID "landing"}}Home page{{else}}{{.Content.ID}} page{{end}}

{{if eq .Content.ID "about"}}

Describe what your instance is about.

{{else if eq .Content.ID "privacy"}}

Outline your privacy policy.

+ {{else if eq .Content.ID "landing"}} +

Customize your home page.

{{end}} {{if .Message}}

{{.Message}}

{{end}}
+ {{if eq .Content.Type "section"}} + + +

We suggest a header (e.g. # Welcome), optionally followed by a small bit of text. Accepts Markdown and HTML.

+ {{else}} + {{end}}