Merge pull request #143 from writeas/collection-404

Style collection 404 page like rest of blog

Resolves T493
This commit is contained in:
Matt Baer 2019-08-07 10:39:38 -04:00 committed by GitHub
commit b06d1c2762
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 46 additions and 7 deletions

View file

@ -721,6 +721,10 @@ func (h *Handler) handleHTTPError(w http.ResponseWriter, r *http.Request, err er
return return
} else if err.Status == http.StatusNotFound { } else if err.Status == http.StatusNotFound {
w.WriteHeader(err.Status) w.WriteHeader(err.Status)
if strings.Contains(r.Header.Get("Accept"), "application/activity+json") {
// This is a fediverse request; simply return the header
return
}
h.errors.NotFound.ExecuteTemplate(w, "base", pageForReq(h.app.App(), r)) h.errors.NotFound.ExecuteTemplate(w, "base", pageForReq(h.app.App(), r))
return return
} else if err.Status == http.StatusInternalServerError { } else if err.Status == http.StatusInternalServerError {

View file

@ -1295,14 +1295,32 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error
coll.Owner = owner coll.Owner = owner
} }
postFound := true
p, err := app.db.GetPost(slug, coll.ID) p, err := app.db.GetPost(slug, coll.ID)
if err != nil { if err != nil {
if err == ErrCollectionPageNotFound && slug == "feed" { if err == ErrCollectionPageNotFound {
// User tried to access blog feed without a trailing slash, and postFound = false
// there's no post with a slug "feed"
return impart.HTTPError{http.StatusFound, c.CanonicalURL() + "/feed/"} if slug == "feed" {
// User tried to access blog feed without a trailing slash, and
// there's no post with a slug "feed"
return impart.HTTPError{http.StatusFound, c.CanonicalURL() + "/feed/"}
}
po := &Post{
Slug: null.NewString(slug, true),
Font: "norm",
Language: zero.NewString("en", true),
RTL: zero.NewBool(false, true),
Content: `<p class="msg">This page is missing.</p>
Are you sure it was ever here?`,
}
pp := po.processPost()
p = &pp
} else {
return err
} }
return err
} }
p.IsOwner = owner != nil && p.OwnerID.Valid && owner.ID == p.OwnerID.Int64 p.IsOwner = owner != nil && p.OwnerID.Valid && owner.ID == p.OwnerID.Int64
p.Collection = coll p.Collection = coll
@ -1324,11 +1342,20 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error
contentType = "text/markdown" contentType = "text/markdown"
} }
w.Header().Set("Content-Type", fmt.Sprintf("%s; charset=utf-8", contentType)) w.Header().Set("Content-Type", fmt.Sprintf("%s; charset=utf-8", contentType))
if !postFound {
w.WriteHeader(http.StatusNotFound)
fmt.Fprintf(w, "Post not found.")
// TODO: return error instead, so status is correctly reflected in logs
return nil
}
if isMarkdown && p.Title.String != "" { if isMarkdown && p.Title.String != "" {
fmt.Fprintf(w, "# %s\n\n", p.Title.String) fmt.Fprintf(w, "# %s\n\n", p.Title.String)
} }
fmt.Fprint(w, p.Content) fmt.Fprint(w, p.Content)
} else if strings.Contains(r.Header.Get("Accept"), "application/activity+json") { } else if strings.Contains(r.Header.Get("Accept"), "application/activity+json") {
if !postFound {
return ErrCollectionPageNotFound
}
p.extractData() p.extractData()
ap := p.ActivityObject() ap := p.ActivityObject()
ap.Context = []interface{}{activitystreams.Namespace} ap.Context = []interface{}{activitystreams.Namespace}
@ -1345,14 +1372,20 @@ func viewCollectionPost(app *App, w http.ResponseWriter, r *http.Request) error
IsPinned bool IsPinned bool
IsCustomDomain bool IsCustomDomain bool
PinnedPosts *[]PublicPost PinnedPosts *[]PublicPost
IsFound bool
}{ }{
PublicPost: p, PublicPost: p,
StaticPage: pageForReq(app, r), StaticPage: pageForReq(app, r),
IsOwner: cr.isCollOwner, IsOwner: cr.isCollOwner,
IsCustomDomain: cr.isCustomDomain, IsCustomDomain: cr.isCustomDomain,
IsFound: postFound,
} }
tp.PinnedPosts, _ = app.db.GetPinnedPosts(coll) tp.PinnedPosts, _ = app.db.GetPinnedPosts(coll)
tp.IsPinned = len(*tp.PinnedPosts) > 0 && PostsContains(tp.PinnedPosts, p) tp.IsPinned = len(*tp.PinnedPosts) > 0 && PostsContains(tp.PinnedPosts, p)
if !postFound {
w.WriteHeader(http.StatusNotFound)
}
if err := templates["collection-post"].ExecuteTemplate(w, "post", tp); err != nil { if err := templates["collection-post"].ExecuteTemplate(w, "post", tp); err != nil {
log.Error("Error in collection-post template: %v", err) log.Error("Error in collection-post template: %v", err)
} }

View file

@ -8,6 +8,7 @@
<link rel="stylesheet" type="text/css" href="/css/write.css" /> <link rel="stylesheet" type="text/css" href="/css/write.css" />
<link rel="shortcut icon" href="/favicon.ico" /> <link rel="shortcut icon" href="/favicon.ico" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" />
{{ if .IsFound }}
<link rel="canonical" href="{{.CanonicalURL}}" /> <link rel="canonical" href="{{.CanonicalURL}}" />
<meta name="generator" content="WriteFreely"> <meta name="generator" content="WriteFreely">
<meta name="title" content="{{.PlainDisplayTitle}} {{localhtml "title dash" .Language.String}} {{if .Collection.Title}}{{.Collection.Title}}{{else}}{{.Collection.Alias}}{{end}}"> <meta name="title" content="{{.PlainDisplayTitle}} {{localhtml "title dash" .Language.String}} {{if .Collection.Title}}{{.Collection.Title}}{{else}}{{.Collection.Alias}}{{end}}">
@ -29,6 +30,7 @@
<meta property="og:updated_time" content="{{.Created8601}}" /> <meta property="og:updated_time" content="{{.Created8601}}" />
{{range .Images}}<meta property="og:image" content="{{.}}" />{{else}}<meta property="og:image" content="{{.Collection.AvatarURL}}">{{end}} {{range .Images}}<meta property="og:image" content="{{.}}" />{{else}}<meta property="og:image" content="{{.Collection.AvatarURL}}">{{end}}
<meta property="article:published_time" content="{{.Created8601}}"> <meta property="article:published_time" content="{{.Created8601}}">
{{ end }}
{{if .Collection.StyleSheet}}<style type="text/css">{{.Collection.StyleSheetDisplay}}</style>{{end}} {{if .Collection.StyleSheet}}<style type="text/css">{{.Collection.StyleSheetDisplay}}</style>{{end}}
{{if .Collection.RenderMathJax}} {{if .Collection.RenderMathJax}}
@ -50,14 +52,14 @@
{{if .PinnedPosts}} {{if .PinnedPosts}}
{{range .PinnedPosts}}<a class="pinned{{if eq .Slug.String $.Slug.String}} selected{{end}}" href="{{if not $.SingleUser}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}} {{range .PinnedPosts}}<a class="pinned{{if eq .Slug.String $.Slug.String}} selected{{end}}" href="{{if not $.SingleUser}}/{{$.Collection.Alias}}/{{.Slug.String}}{{else}}{{.CanonicalURL}}{{end}}">{{.PlainDisplayTitle}}</a>{{end}}
{{end}} {{end}}
{{ if .IsOwner }}<span class="views" dir="ltr"><strong>{{largeNumFmt .Views}}</strong> {{pluralize "view" "views" .Views}}</span> {{ if and .IsOwner .IsFound }}<span class="views" dir="ltr"><strong>{{largeNumFmt .Views}}</strong> {{pluralize "view" "views" .Views}}</span>
<a class="xtra-feature" href="/{{if not .SingleUser}}{{.Collection.Alias}}/{{end}}{{.Slug.String}}/edit" dir="{{.Direction}}">Edit</a> <a class="xtra-feature" href="/{{if not .SingleUser}}{{.Collection.Alias}}/{{end}}{{.Slug.String}}/edit" dir="{{.Direction}}">Edit</a>
{{if .IsPinned}}<a class="xtra-feature unpin" href="/{{.Collection.Alias}}/{{.Slug.String}}/unpin" dir="{{.Direction}}" onclick="unpinPost(event, '{{.ID}}')">Unpin</a>{{end}} {{if .IsPinned}}<a class="xtra-feature unpin" href="/{{.Collection.Alias}}/{{.Slug.String}}/unpin" dir="{{.Direction}}" onclick="unpinPost(event, '{{.ID}}')">Unpin</a>{{end}}
{{ end }} {{ end }}
</nav> </nav>
</header> </header>
<article id="post-body" class="{{.Font}} h-entry">{{if .IsScheduled}}<p class="badge">Scheduled</p>{{end}}{{if .Title.String}}<h2 id="title" class="p-name">{{.FormattedDisplayTitle}}</h2>{{end}}<div class="e-content">{{.HTMLContent}}</div></article> <article id="post-body" class="{{.Font}} h-entry {{if not .IsFound}}error-page{{end}}">{{if .IsScheduled}}<p class="badge">Scheduled</p>{{end}}{{if .Title.String}}<h2 id="title" class="p-name">{{.FormattedDisplayTitle}}</h2>{{end}}<div class="e-content">{{.HTMLContent}}</div></article>
{{ if .Collection.ShowFooterBranding }} {{ if .Collection.ShowFooterBranding }}
<footer dir="ltr"><hr><nav><p style="font-size: 0.9em">{{localhtml "published with write.as" .Language.String}}</p></nav></footer> <footer dir="ltr"><hr><nav><p style="font-size: 0.9em">{{localhtml "published with write.as" .Language.String}}</p></nav></footer>