- commit
- b49c843
- parent
- 7a2ff35
- author
- Eric Bower
- date
- 2022-08-22 20:56:55 +0000 UTC
refactor(imgs): redesign blog page for imgs After chatting with the pico members, it became clear that the photo album direction I was heading in was not going to super useful. Instead we decided to revert the design back to how the other pico services function. So now it's just a stream of images not grouped by tags.
3 files changed,
+28,
-312
+23,
-287
1@@ -6,7 +6,6 @@ import (
2 "html/template"
3 "net/http"
4 "net/url"
5- "sort"
6 "strings"
7 "time"
8
9@@ -23,32 +22,12 @@ type PageData struct {
10 }
11
12 type PostItemData struct {
13- URL template.URL
14- BlogURL template.URL
15- Username string
16- Title string
17- Description string
18- PublishAtISO string
19- PublishAt string
20- UpdatedAtISO string
21- UpdatedTimeAgo string
22- Tags []string
23-}
24-
25-type TagPageData struct {
26- BlogURL template.URL
27- PageTitle string
28- Username string
29- URL template.URL
30- Site shared.SitePageData
31- Tag string
32- Posts []TagPostData
33-}
34-
35-type TagPostData struct {
36- URL template.URL
37- ImgURL template.URL
38- Caption string
39+ BlogURL template.URL
40+ URL template.URL
41+ ImgURL template.URL
42+ PublishAtISO string
43+ PublishAt string
44+ Caption string
45 }
46
47 type BlogPageData struct {
48@@ -59,7 +38,7 @@ type BlogPageData struct {
49 Username string
50 Readme *ReadmeTxt
51 Header *HeaderTxt
52- Posts []*PostTagData
53+ Posts []*PostItemData
54 HasFilter bool
55 }
56
57@@ -105,14 +84,6 @@ type ReadmeTxt struct {
58 Contents template.HTML
59 }
60
61-type MergePost struct {
62- Db db.DB
63- UserID string
64- Space string
65-}
66-
67-var allTag = "all"
68-
69 func GetPostTitle(post *db.Post) string {
70 if post.Description == "" {
71 return post.Title
72@@ -129,13 +100,6 @@ func isRequestTrackable(r *http.Request) bool {
73 return true
74 }
75
76-type PostTagData struct {
77- URL template.URL
78- ImgURL template.URL
79- Tag string
80- PublishAt *time.Time
81-}
82-
83 func blogHandler(w http.ResponseWriter, r *http.Request) {
84 username := shared.GetUsernameFromRequest(r)
85 dbpool := shared.GetDB(r)
86@@ -149,7 +113,13 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
87 return
88 }
89
90- posts, err := dbpool.FindPostsForUser(user.ID, cfg.Space)
91+ tag := r.URL.Query().Get("tag")
92+ var posts []*db.Post
93+ if tag == "" {
94+ posts, err = dbpool.FindPostsForUser(user.ID, cfg.Space)
95+ } else {
96+ posts, err = dbpool.FindUserPostsByTag(tag, user.ID, cfg.Space)
97+ }
98
99 if err != nil {
100 logger.Error(err)
101@@ -179,46 +149,27 @@ func blogHandler(w http.ResponseWriter, r *http.Request) {
102 }
103 readmeTxt := &ReadmeTxt{}
104
105- tagMap := make(map[string]*db.Post, len(posts))
106+ postCollection := make([]*PostItemData, 0, len(posts))
107 for _, post := range posts {
108- if post.Hidden {
109- continue
110- }
111-
112- for _, tag := range post.Tags {
113- if tagMap[tag] == nil {
114- tagMap[tag] = post
115- }
116- }
117-
118- if tagMap[allTag] == nil {
119- tagMap[allTag] = post
120- }
121- }
122-
123- postCollection := make([]*PostTagData, 0, len(tagMap))
124- for key, post := range tagMap {
125- postCollection = append(postCollection, &PostTagData{
126- Tag: key,
127- URL: template.URL(cfg.TagURL(post.Username, key, onSubdomain, withUserName)),
128- ImgURL: template.URL(cfg.ImgURL(post.Username, post.Filename, onSubdomain, withUserName)),
129- PublishAt: post.PublishAt,
130+ postCollection = append(postCollection, &PostItemData{
131+ ImgURL: template.URL(cfg.ImgURL(post.Username, post.Filename, onSubdomain, withUserName)),
132+ URL: template.URL(cfg.ImgURL(post.Username, post.Slug, onSubdomain, withUserName)),
133+ Caption: post.Title,
134+ PublishAt: post.PublishAt.Format("02 Jan, 2006"),
135+ PublishAtISO: post.PublishAt.Format(time.RFC3339),
136 })
137 }
138
139- sort.Slice(postCollection, func(i, j int) bool {
140- return postCollection[i].PublishAt.After(*postCollection[j].PublishAt)
141- })
142-
143 data := BlogPageData{
144 Site: *cfg.GetSiteData(),
145 PageTitle: headerTxt.Title,
146 URL: template.URL(cfg.FullBlogURL(username, onSubdomain, withUserName)),
147- RSSURL: template.URL(cfg.RssBlogURL(username, onSubdomain, withUserName, "")),
148+ RSSURL: template.URL(cfg.RssBlogURL(username, onSubdomain, withUserName, tag)),
149 Readme: readmeTxt,
150 Header: headerTxt,
151 Username: username,
152 Posts: postCollection,
153+ HasFilter: tag != "",
154 }
155
156 err = ts.Execute(w, data)
157@@ -286,219 +237,6 @@ func imgHandler(w http.ResponseWriter, r *http.Request) {
158 }
159 }
160
161-func tagHandler(w http.ResponseWriter, r *http.Request) {
162- username := shared.GetUsernameFromRequest(r)
163- subdomain := shared.GetSubdomain(r)
164- cfg := shared.GetCfg(r)
165-
166- tag := ""
167- if !cfg.IsSubdomains() || subdomain == "" {
168- tag, _ = url.PathUnescape(shared.GetField(r, 1))
169- } else {
170- tag, _ = url.PathUnescape(shared.GetField(r, 0))
171- }
172-
173- dbpool := shared.GetDB(r)
174- logger := shared.GetLogger(r)
175-
176- user, err := dbpool.FindUserForName(username)
177- if err != nil {
178- logger.Infof("blog not found: %s", username)
179- http.Error(w, "blog not found", http.StatusNotFound)
180- return
181- }
182-
183- hostDomain := strings.Split(r.Host, ":")[0]
184- appDomain := strings.Split(cfg.ConfigCms.Domain, ":")[0]
185-
186- onSubdomain := cfg.IsSubdomains() && strings.Contains(hostDomain, appDomain)
187- withUserName := (!onSubdomain && hostDomain == appDomain) || !cfg.IsCustomdomains()
188-
189- posts, err := dbpool.FindPostsForUser(user.ID, cfg.Space)
190- if err != nil {
191- logger.Infof("tag not found: %s/%s", username, tag)
192- http.Error(w, "tag not found", http.StatusNotFound)
193- return
194- }
195-
196- mergedPosts := make([]TagPostData, 0)
197- for _, post := range posts {
198- if post.Hidden {
199- continue
200- }
201-
202- if tag != allTag && !slices.Contains(post.Tags, tag) {
203- continue
204- }
205- mergedPosts = append(mergedPosts, TagPostData{
206- URL: template.URL(cfg.TagPostURL(username, tag, post.Slug, onSubdomain, withUserName)),
207- ImgURL: template.URL(cfg.ImgURL(username, post.Filename, onSubdomain, withUserName)),
208- Caption: post.Title,
209- })
210- }
211-
212- data := TagPageData{
213- BlogURL: template.URL(cfg.FullBlogURL(username, onSubdomain, withUserName)),
214- Username: username,
215- PageTitle: fmt.Sprintf("%s -- %s", tag, username),
216- Site: *cfg.GetSiteData(),
217- Tag: tag,
218- Posts: mergedPosts,
219- URL: template.URL(cfg.TagURL(username, tag, onSubdomain, withUserName)),
220- }
221-
222- ts, err := shared.RenderTemplate(cfg, []string{
223- cfg.StaticPath("html/tag.page.tmpl"),
224- })
225-
226- if err != nil {
227- http.Error(w, err.Error(), http.StatusInternalServerError)
228- }
229-
230- err = ts.Execute(w, data)
231- if err != nil {
232- logger.Error(err)
233- http.Error(w, err.Error(), http.StatusInternalServerError)
234- }
235-}
236-
237-func tagPostHandler(w http.ResponseWriter, r *http.Request) {
238- username := shared.GetUsernameFromRequest(r)
239- subdomain := shared.GetSubdomain(r)
240- cfg := shared.GetCfg(r)
241-
242- tag := ""
243- slug := ""
244- if !cfg.IsSubdomains() || subdomain == "" {
245- tag, _ = url.PathUnescape(shared.GetField(r, 1))
246- slug, _ = url.PathUnescape(shared.GetField(r, 2))
247- } else {
248- tag, _ = url.PathUnescape(shared.GetField(r, 0))
249- slug, _ = url.PathUnescape(shared.GetField(r, 1))
250- }
251-
252- dbpool := shared.GetDB(r)
253- logger := shared.GetLogger(r)
254-
255- user, err := dbpool.FindUserForName(username)
256- if err != nil {
257- logger.Infof("blog not found: %s", username)
258- http.Error(w, "blog not found", http.StatusNotFound)
259- return
260- }
261-
262- blogName := GetBlogName(username)
263- hostDomain := strings.Split(r.Host, ":")[0]
264- appDomain := strings.Split(cfg.ConfigCms.Domain, ":")[0]
265-
266- onSubdomain := cfg.IsSubdomains() && strings.Contains(hostDomain, appDomain)
267- withUserName := (!onSubdomain && hostDomain == appDomain) || !cfg.IsCustomdomains()
268-
269- posts, err := dbpool.FindPostsForUser(user.ID, cfg.Space)
270- if err != nil {
271- logger.Infof("tag not found: %s/%s", username, tag)
272- http.Error(w, "tag not found", http.StatusNotFound)
273- return
274- }
275-
276- mergedPosts := make([]db.Post, 0)
277- for _, post := range posts {
278- if post.Hidden {
279- continue
280- }
281-
282- if !slices.Contains(post.Tags, tag) {
283- continue
284- }
285- mergedPosts = append(mergedPosts, *post)
286- }
287-
288- prevPage := ""
289- nextPage := ""
290- for i, post := range mergedPosts {
291- if post.Slug != slug {
292- continue
293- }
294-
295- if i+1 < len(mergedPosts) {
296- nextPage = cfg.TagPostURL(
297- username,
298- tag,
299- mergedPosts[i+1].Slug,
300- onSubdomain,
301- withUserName,
302- )
303- }
304-
305- if i-1 >= 0 {
306- prevPage = cfg.TagPostURL(
307- username,
308- tag,
309- mergedPosts[i-1].Slug,
310- onSubdomain,
311- withUserName,
312- )
313- }
314- }
315-
316- post, err := dbpool.FindPostWithSlug(slug, user.ID, cfg.Space)
317- if err != nil {
318- logger.Infof("post not found: %s/%s", username, slug)
319- http.Error(w, "post not found", http.StatusNotFound)
320- return
321- }
322-
323- parsed, err := shared.ParseText(post.Text, cfg.ImgURL(username, "", true, false))
324- if err != nil {
325- logger.Error(err)
326- }
327- text := ""
328- if parsed != nil {
329- text = parsed.Html
330- }
331-
332- tagLinks := make([]Link, 0, len(post.Tags))
333- for _, tag := range post.Tags {
334- tagLinks = append(tagLinks, Link{
335- URL: template.URL(cfg.TagURL(username, tag, onSubdomain, withUserName)),
336- Text: tag,
337- })
338- }
339-
340- data := PostPageData{
341- Site: *cfg.GetSiteData(),
342- PageTitle: GetPostTitle(post),
343- URL: template.URL(cfg.FullPostURL(post.Username, post.Slug, onSubdomain, withUserName)),
344- BlogURL: template.URL(cfg.FullBlogURL(username, onSubdomain, withUserName)),
345- Caption: post.Description,
346- Title: post.Title,
347- Slug: post.Slug,
348- PublishAt: post.PublishAt.Format("02 Jan, 2006"),
349- PublishAtISO: post.PublishAt.Format(time.RFC3339),
350- Username: username,
351- BlogName: blogName,
352- Contents: template.HTML(text),
353- ImgURL: template.URL(cfg.ImgURL(username, post.Filename, onSubdomain, withUserName)),
354- Tags: tagLinks,
355- PrevPage: template.URL(prevPage),
356- NextPage: template.URL(nextPage),
357- }
358-
359- ts, err := shared.RenderTemplate(cfg, []string{
360- cfg.StaticPath("html/tag_post.page.tmpl"),
361- })
362-
363- if err != nil {
364- http.Error(w, err.Error(), http.StatusInternalServerError)
365- }
366-
367- err = ts.Execute(w, data)
368- if err != nil {
369- logger.Error(err)
370- http.Error(w, err.Error(), http.StatusInternalServerError)
371- }
372-}
373-
374 func postHandler(w http.ResponseWriter, r *http.Request) {
375 username := shared.GetUsernameFromRequest(r)
376 subdomain := shared.GetSubdomain(r)
377@@ -864,8 +602,6 @@ func createSubdomainRoutes(staticRoutes []shared.Route) []shared.Route {
378 routes = append(
379 routes,
380 shared.NewRoute("GET", "/([^/]+\\..+)", imgHandler),
381- shared.NewRoute("GET", "/t/([^/]+)", tagHandler),
382- shared.NewRoute("GET", "/([^/]+)/([^/]+)", tagPostHandler),
383 shared.NewRoute("GET", "/([^/]+)", postHandler),
384 )
385
+4,
-3
1@@ -47,13 +47,14 @@
2 </section>
3 {{end}}
4
5+ {{if .HasFilter}}
6+ <a href={{.URL}}>clear filters</a>
7+ {{end}}
8 <section class="albums">
9 {{range .Posts}}
10 <article class="thumbnail-container">
11 <a href="{{.URL}}" class="thumbnail-link">
12- <div class="tag-overlay"></div>
13- <div class="tag-text text-2xl">{{.Tag}}</div>
14- <img class="thumbnail" src="{{.ImgURL}}" alt="{{.Tag}}" />
15+ <img class="thumbnail" src="{{.ImgURL}}" alt="{{.Caption}}" />
16 </a>
17 </article>
18 {{end}}
1@@ -158,28 +158,7 @@ func (c *ConfigSite) ImgURL(username string, slug string, onSubdomain bool, with
2
3 func (c *ConfigSite) TagURL(username, tag string, onSubdomain, withUserName bool) string {
4 tg := url.PathEscape(tag)
5- if c.IsSubdomains() && onSubdomain {
6- return fmt.Sprintf("%s://%s.%s/t/%s", c.Protocol, username, c.Domain, tg)
7- }
8-
9- if withUserName {
10- return fmt.Sprintf("/%s/t/%s", username, tg)
11- }
12-
13- return fmt.Sprintf("/t/%s", tg)
14-}
15-
16-func (c *ConfigSite) TagPostURL(username, tag, slug string, onSubdomain, withUserName bool) string {
17- fname := url.PathEscape(strings.TrimLeft(slug, "/"))
18- if c.IsSubdomains() && onSubdomain {
19- return fmt.Sprintf("%s://%s.%s/%s/%s", c.Protocol, username, c.Domain, tag, fname)
20- }
21-
22- if withUserName {
23- return fmt.Sprintf("/%s/%s/%s", username, tag, fname)
24- }
25-
26- return fmt.Sprintf("/%s/%s", tag, fname)
27+ return fmt.Sprintf("%s?tag=%s", c.FullBlogURL(username, onSubdomain, withUserName), tg)
28 }
29
30 func CreateLogger() *zap.SugaredLogger {