Merge pull request #351 from boreq/list-notices-as-json
Add a way to list notices as JSON
This commit is contained in:
commit
641069a8f1
|
@ -329,12 +329,13 @@ func New(
|
|||
|
||||
// notices (the mini-CMS)
|
||||
var nh = noticeHandler{
|
||||
render: r,
|
||||
flashes: flashHelper,
|
||||
|
||||
notices: dbs.Notices,
|
||||
pinned: dbs.PinnedNotices,
|
||||
}
|
||||
m.Get(router.CompleteNoticeList).Handler(r.HTML("notice/list.tmpl", nh.list))
|
||||
m.Get(router.CompleteNoticeList).HandlerFunc(nh.list)
|
||||
m.Get(router.CompleteNoticeShow).Handler(r.HTML("notice/show.tmpl", nh.show))
|
||||
|
||||
// public aliases
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
package handlers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"go.mindeco.de/http/render"
|
||||
"html/template"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
@ -16,6 +18,7 @@ import (
|
|||
)
|
||||
|
||||
type noticeHandler struct {
|
||||
render *render.Renderer
|
||||
flashes *errors.FlashHelper
|
||||
|
||||
pinned roomdb.PinnedNoticesService
|
||||
|
@ -27,22 +30,33 @@ type noticesListData struct {
|
|||
Flashes []errors.FlashMessage
|
||||
}
|
||||
|
||||
func (h noticeHandler) list(rw http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
func (h noticeHandler) list(rw http.ResponseWriter, req *http.Request) {
|
||||
var responder listNoticesResponder
|
||||
switch req.URL.Query().Get("encoding") {
|
||||
case "json":
|
||||
responder = newListNoticesJSONResponder(rw)
|
||||
default:
|
||||
responder = newListNoticesHTMLResponder(h.render, rw, req)
|
||||
}
|
||||
|
||||
lst, err := h.pinned.List(req.Context())
|
||||
if err != nil {
|
||||
return nil, err
|
||||
responder.RenderError(err)
|
||||
return
|
||||
}
|
||||
|
||||
flashes, err := h.flashes.GetAll(rw, req)
|
||||
if err != nil {
|
||||
responder.RenderError(err)
|
||||
return
|
||||
}
|
||||
|
||||
pageData := noticesListData{
|
||||
AllNotices: lst.Sorted(),
|
||||
}
|
||||
pageData.Flashes, err = h.flashes.GetAll(rw, req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
Flashes: flashes,
|
||||
}
|
||||
|
||||
return pageData, nil
|
||||
responder.Render(pageData)
|
||||
}
|
||||
|
||||
type noticeShowData struct {
|
||||
|
@ -80,3 +94,86 @@ func (h noticeHandler) show(rw http.ResponseWriter, req *http.Request) (interfac
|
|||
|
||||
return pageData, nil
|
||||
}
|
||||
|
||||
type listNoticesResponder interface {
|
||||
Render(noticesListData)
|
||||
RenderError(error)
|
||||
}
|
||||
|
||||
type listNoticesJSONResponder struct {
|
||||
rw http.ResponseWriter
|
||||
}
|
||||
|
||||
func newListNoticesJSONResponder(rw http.ResponseWriter) *listNoticesJSONResponder {
|
||||
return &listNoticesJSONResponder{rw: rw}
|
||||
}
|
||||
|
||||
func (l listNoticesJSONResponder) Render(data noticesListData) {
|
||||
l.rw.Header().Set("Content-Type", "application/json")
|
||||
var pinnedNotices []listNoticesJSONResponsePinnedNotice
|
||||
for _, pinnedNotice := range data.AllNotices {
|
||||
v := listNoticesJSONResponsePinnedNotice{
|
||||
Name: string(pinnedNotice.Name),
|
||||
Notices: nil,
|
||||
}
|
||||
for _, notice := range pinnedNotice.Notices {
|
||||
v.Notices = append(v.Notices, listNoticesJSONResponseNotice{
|
||||
ID: notice.ID,
|
||||
Title: notice.Title,
|
||||
Content: notice.Content,
|
||||
Language: notice.Language,
|
||||
})
|
||||
}
|
||||
pinnedNotices = append(pinnedNotices, v)
|
||||
}
|
||||
|
||||
var resp = listNoticesJSONResponse{
|
||||
PinnedNotices: pinnedNotices,
|
||||
}
|
||||
json.NewEncoder(l.rw).Encode(resp)
|
||||
}
|
||||
|
||||
func (l listNoticesJSONResponder) RenderError(err error) {
|
||||
l.rw.Header().Set("Content-Type", "application/json")
|
||||
l.rw.WriteHeader(http.StatusInternalServerError)
|
||||
json.NewEncoder(l.rw).Encode(struct {
|
||||
Status string `json:"status"`
|
||||
Error string `json:"error"`
|
||||
}{"error", err.Error()})
|
||||
}
|
||||
|
||||
type listNoticesHTMLResponder struct {
|
||||
renderer *render.Renderer
|
||||
rw http.ResponseWriter
|
||||
req *http.Request
|
||||
}
|
||||
|
||||
func newListNoticesHTMLResponder(renderer *render.Renderer, rw http.ResponseWriter, req *http.Request) *listNoticesHTMLResponder {
|
||||
return &listNoticesHTMLResponder{renderer: renderer, rw: rw, req: req}
|
||||
}
|
||||
|
||||
func (l listNoticesHTMLResponder) Render(data noticesListData) {
|
||||
l.renderer.HTML("notice/list.tmpl", func(w http.ResponseWriter, req *http.Request) (interface{}, error) {
|
||||
return data, nil
|
||||
})(l.rw, l.req)
|
||||
}
|
||||
|
||||
func (l listNoticesHTMLResponder) RenderError(err error) {
|
||||
l.renderer.Error(l.rw, l.req, http.StatusInternalServerError, err)
|
||||
}
|
||||
|
||||
type listNoticesJSONResponse struct {
|
||||
PinnedNotices []listNoticesJSONResponsePinnedNotice `json:"pinned_notices"`
|
||||
}
|
||||
|
||||
type listNoticesJSONResponsePinnedNotice struct {
|
||||
Name string `json:"name"`
|
||||
Notices []listNoticesJSONResponseNotice `json:"notices"`
|
||||
}
|
||||
|
||||
type listNoticesJSONResponseNotice struct {
|
||||
ID int64 `json:"id"`
|
||||
Title string `json:"title"`
|
||||
Content string `json:"content"`
|
||||
Language string `json:"language"`
|
||||
}
|
||||
|
|
|
@ -223,3 +223,74 @@ func TestNoticesCreateOnlyModsAndHigherInRestricted(t *testing.T) {
|
|||
webassert.HasFlashMessages(t, ts.Client, noticeListURL, "ErrorNotAuthorized")
|
||||
|
||||
}
|
||||
|
||||
func TestNoticesListReturnsJSONWhenCorrectParameterIsSet(t *testing.T) {
|
||||
ts := setup(t)
|
||||
a := assert.New(t)
|
||||
|
||||
ts.PinnedDB.ListReturns(roomdb.PinnedNotices{
|
||||
"name1": {
|
||||
{
|
||||
ID: 1,
|
||||
Title: "title1",
|
||||
Content: "content1",
|
||||
Language: "language1",
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Title: "title2",
|
||||
Content: "content2",
|
||||
Language: "language2",
|
||||
},
|
||||
},
|
||||
"name2": {
|
||||
{
|
||||
ID: 3,
|
||||
Title: "title3",
|
||||
Content: "content3",
|
||||
Language: "language3",
|
||||
},
|
||||
},
|
||||
}, nil)
|
||||
|
||||
noticeURL := ts.URLTo(router.CompleteNoticeList)
|
||||
values := noticeURL.Query()
|
||||
values.Set("encoding", "json")
|
||||
noticeURL.RawQuery = values.Encode()
|
||||
|
||||
var response listNoticesJSONResponse
|
||||
res := ts.Client.GetJSON(noticeURL, &response)
|
||||
a.Equal(http.StatusOK, res.Code, "wrong HTTP status code")
|
||||
a.Equal(listNoticesJSONResponse{
|
||||
PinnedNotices: []listNoticesJSONResponsePinnedNotice{
|
||||
{
|
||||
Name: "name1",
|
||||
Notices: []listNoticesJSONResponseNotice{
|
||||
{
|
||||
ID: 1,
|
||||
Title: "title1",
|
||||
Content: "content1",
|
||||
Language: "language1",
|
||||
},
|
||||
{
|
||||
ID: 2,
|
||||
Title: "title2",
|
||||
Content: "content2",
|
||||
Language: "language2",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "name2",
|
||||
Notices: []listNoticesJSONResponseNotice{
|
||||
{
|
||||
ID: 3,
|
||||
Title: "title3",
|
||||
Content: "content3",
|
||||
Language: "language3",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}, response)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue