Skip to content

Commit e8c4cd7

Browse files
authored
Allow admins to view additional quote details (#11)
* Allow admins to see who submitted a quote and when * Adjust error positioning
1 parent 032e97c commit e8c4cd7

File tree

6 files changed

+104
-34
lines changed

6 files changed

+104
-34
lines changed

internal/server/http/frontend/page.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,15 @@ func (PrivacyPage) viewName() string {
2828

2929
// QuotesPage lists all quotes by year
3030
type QuotesPage struct {
31+
// RenderAdmin is true if the page should render admin controls / info
32+
RenderAdmin bool
33+
3134
Error error
3235
Quote model.Quote
3336
Quotes []model.Quote
37+
38+
// Users is a map of user ID to user, and should only be populated if RenderAdmin is true
39+
Users map[string]model.User
3440
}
3541

3642
func (QuotesPage) viewName() string {

internal/server/http/frontend/public/styles/app.css

Lines changed: 21 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/server/http/frontend/templates/components/error.gohtml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{{define "error"}}
22
{{with getIssues .}}
3-
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4" role="alert">
3+
<div class="bg-red-100 border-l-4 border-red-500 text-red-700 p-4 my-3" role="alert">
44
<p class="font-bold">Error: </p>
55
{{range .}}
66
<p>{{ . }}</p>

internal/server/http/frontend/templates/views/quotes.gohtml

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
{{template "base" .}}
1+
{{ template "base" . }}
22

3-
{{define "body"}}
3+
{{ define "body" }}
44
<div class="section text-center">
55
<h1 class="h1">💬 {{.Title}}</h1>
66
</div>
77
<div class="section my-8 max-w-md">
88
<form action="{{.Paths.Quotes}}" method="post">
99
<h2 class="text-3xl font-semibold text-center">Submit a new quote:</h2>
1010

11-
{{ template "error" .Page.Error }}
12-
1311
<div class="mt-8">
1412
<div class="grid grid-cols-1 gap-6">
1513
<label class="block">
@@ -27,30 +25,41 @@
2725
<input name="quotee" type="text" class="mt-1 block w-full dark:bg-gray-800"
2826
placeholder="Jaustin Ross" value="{{.Page.Quote.Quotee}}" />
2927
</label>
28+
29+
{{ template "error" .Page.Error }}
30+
3031
<input class="button" type="submit" value="Submit" />
3132
</div>
3233
</div>
3334
</form>
3435
</div>
3536
<div class="wide-section my-12">
37+
{{ $renderAdmin := .Page.RenderAdmin }}
38+
{{ $users := .Page.Users }}
3639
{{ $byYear := quotesByYear .Page.Quotes }}
3740
{{ range $year := orderedYearKeys $byYear }}
3841
<h3 class="text-3xl mb-4">{{ $year }}</h3>
3942
<hr class="mb-4" />
4043
<div class="masonry-container mb-6">
41-
{{ range index $byYear $year }}
42-
<div class="bg-gray-100 dark:bg-gray-900 p-4">
43-
{{with .Context}}<p class="text-lg dark:text-white font-light lowercase mb-3">{{.}}</p>{{end}}
44-
<p class="text-xl text-gray-800 dark:text-gray-200 font-medium mb-3">{{.Quote}}</p>
45-
<p class="text-xl text-gray-600 dark:text-gray-300 font-medium text-right">- {{.Quotee}}</p>
44+
{{ range (index $byYear $year) }}
45+
<div>
46+
<div class="bg-gray-100 dark:bg-gray-900 p-4">
47+
{{ with .Context }}<p class="text-lg dark:text-white font-light lowercase mb-3">{{ . }}</p>{{end}}
48+
<p class="text-xl text-gray-800 dark:text-gray-200 font-medium mb-3">{{ .Quote }}</p>
49+
<p class="text-xl text-gray-600 dark:text-gray-300 font-medium text-right">- {{ .Quotee }}</p>
50+
</div>
51+
{{ if $renderAdmin }}
52+
<p class="mt-2 text-gray-500 dark:text-gray-500">Submitted by {{ (index $users .SubmitterID).Name }} on {{
53+
.Created.Format "2006-01-02 (Mon) at 15:04" }}</p>
54+
{{ end }}
4655
</div>
4756
{{ end }}
4857
</div>
49-
{{end}}
58+
{{ end }}
5059
</div>
51-
{{end}}
60+
{{ end }}
5261

53-
{{define "scripts"}}
62+
{{ define "scripts" }}
5463
<script src="/static/scripts/macy.js"></script>
5564
<script>
5665
var macyInstances = []
@@ -69,4 +78,4 @@
6978
}))
7079
});
7180
</script>
72-
{{end}}
81+
{{ end }}

internal/server/http/frontend/templating_test.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,23 @@ func Test_TemplateEngine_RenderPage(t *testing.T) {
2828
},
2929
},
3030
},
31+
QuotesPage{
32+
RenderAdmin: true,
33+
Quotes: []model.Quote{
34+
{
35+
Quotee: "Test Quotee",
36+
Quote: "Test Quote",
37+
Context: "Test Context",
38+
SubmitterID: "x123",
39+
},
40+
},
41+
Users: map[string]model.User{
42+
"x123": {
43+
ID: "x123",
44+
Name: "Test User",
45+
},
46+
},
47+
},
3148
QuizPage{
3249
Questions: []service.QuizQuestion{
3350
{

internal/server/http/quotes_handler.go

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,53 @@
11
package http
22

33
import (
4+
"context"
45
"net/http"
56

7+
"github.com/willbicks/epigram/internal/ctxval"
68
"github.com/willbicks/epigram/internal/model"
79
"github.com/willbicks/epigram/internal/server/http/frontend"
810
)
911

12+
func (s *QuoteServer) getQuotesPage(ctx context.Context) (frontend.QuotesPage, error) {
13+
quotes, err := s.QuoteService.GetAllQuotes(ctx)
14+
if err != nil {
15+
return frontend.QuotesPage{}, err
16+
}
17+
18+
page := frontend.QuotesPage{
19+
Quotes: quotes,
20+
}
21+
22+
if ctxval.UserFromContext(ctx).Admin {
23+
page.RenderAdmin = true
24+
25+
users, err := s.UserService.GetAllUsers(ctx)
26+
if err != nil {
27+
return frontend.QuotesPage{}, err
28+
}
29+
30+
page.Users = make(map[string]model.User)
31+
for _, u := range users {
32+
page.Users[u.ID] = u
33+
}
34+
}
35+
36+
return page, nil
37+
}
38+
1039
// quotesHandler handles requests to the quotes page, either GET requests to render
1140
// quotes, or POST requests to submit a new quote
1241
func (s *QuoteServer) quotesHandler(w http.ResponseWriter, r *http.Request) {
1342
switch r.Method {
1443
case "GET":
15-
quotes, err := s.QuoteService.GetAllQuotes(r.Context())
44+
page, err := s.getQuotesPage(r.Context())
1645
if err != nil {
1746
s.serverError(w, r, err)
1847
return
1948
}
20-
err = s.tmpl.RenderPage(w, frontend.QuotesPage{
21-
Quotes: quotes,
22-
})
49+
50+
err = s.tmpl.RenderPage(w, page)
2351
if err != nil {
2452
s.serverError(w, r, err)
2553
s.Logger.Warn(err.Error())
@@ -38,16 +66,15 @@ func (s *QuoteServer) quotesHandler(w http.ResponseWriter, r *http.Request) {
3866
createErr := s.QuoteService.CreateQuote(r.Context(), &q)
3967

4068
if createErr != nil {
41-
quotes, err := s.QuoteService.GetAllQuotes(r.Context())
69+
page, err := s.getQuotesPage(r.Context())
4270
if err != nil {
4371
s.serverError(w, r, err)
4472
return
4573
}
46-
err = s.tmpl.RenderPage(w, frontend.QuotesPage{
47-
Error: createErr,
48-
Quote: q,
49-
Quotes: quotes,
50-
})
74+
page.Quote = q
75+
page.Error = createErr
76+
77+
err = s.tmpl.RenderPage(w, page)
5178
if err != nil {
5279
s.serverError(w, r, err)
5380
return

0 commit comments

Comments
 (0)