summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitaly Minko <vitaly.minko@gmail.com>2019-06-04 07:22:01 +0300
committerVitaly Minko <vitaly.minko@gmail.com>2019-06-04 07:22:01 +0300
commitba92d3e6cc48f562cc957984081201ccf2047174 (patch)
tree61b6cc4940c458e9a753acd93cfa3e8f9f0ced8a
parent25cb058452154c9e6e3b41343ba47839edf0596f (diff)
Non-functional improvements,
* Introduced common data types for controller handlers. * Introduced custom 404 handler.
-rw-r--r--cmd/dscuss-web/controller/board_handlers.go2
-rw-r--r--cmd/dscuss-web/controller/controller.go65
-rw-r--r--cmd/dscuss-web/controller/login_handlers.go10
-rw-r--r--cmd/dscuss-web/controller/reply_handlers.go44
-rw-r--r--cmd/dscuss-web/controller/thread_handlers.go44
-rw-r--r--cmd/dscuss-web/main.go1
-rw-r--r--cmd/dscuss-web/static/css.go4
-rw-r--r--cmd/dscuss-web/view/board.go2
-rw-r--r--cmd/dscuss-web/view/login.go17
-rw-r--r--cmd/dscuss-web/view/reply.go2
-rw-r--r--cmd/dscuss-web/view/templates.go1
-rw-r--r--cmd/dscuss-web/view/thread.go4
-rw-r--r--dscuss.go8
13 files changed, 110 insertions, 94 deletions
diff --git a/cmd/dscuss-web/controller/board_handlers.go b/cmd/dscuss-web/controller/board_handlers.go
index 1faae95..6fdb436 100644
--- a/cmd/dscuss-web/controller/board_handlers.go
+++ b/cmd/dscuss-web/controller/board_handlers.go
@@ -41,7 +41,7 @@ func boardHandler(w http.ResponseWriter, r *http.Request, l *dscuss.LoginHandle,
var validURI = regexp.MustCompile("^/board(topic=[a-z,]*)?$")
m := validURI.FindStringSubmatch(r.URL.Path)
if m == nil {
- http.NotFound(w, r)
+ NotFoundHandler(w, r)
return
}
topicStr := r.URL.Query().Get("topic")
diff --git a/cmd/dscuss-web/controller/controller.go b/cmd/dscuss-web/controller/controller.go
index fa59edf..8cf2b48 100644
--- a/cmd/dscuss-web/controller/controller.go
+++ b/cmd/dscuss-web/controller/controller.go
@@ -24,6 +24,7 @@ import (
"io"
"net/http"
"runtime/debug"
+ "time"
"vminko.org/dscuss"
"vminko.org/dscuss/cmd/dscuss-web/static"
"vminko.org/dscuss/entity"
@@ -31,13 +32,8 @@ import (
"vminko.org/dscuss/log"
)
-func InternalServerErrorHandler(w http.ResponseWriter, r *http.Request) {
- if r := recover(); r != nil {
- log.Errorf("[INFO] Recovered from panic: %s\n[INFO] Debug stack: %s\n",
- r, debug.Stack())
- http.Error(w, "Internal server error. This event has been logged.",
- http.StatusInternalServerError)
- }
+func NotFoundHandler(w http.ResponseWriter, r *http.Request) {
+ http.NotFound(w, r)
}
func BadRequestHandler(w http.ResponseWriter, r *http.Request, msg string) {
@@ -49,6 +45,15 @@ func ForbiddenHandler(w http.ResponseWriter, r *http.Request) {
http.Error(w, "403 Forbidden", http.StatusForbidden)
}
+func InternalServerErrorHandler(w http.ResponseWriter, r *http.Request) {
+ if r := recover(); r != nil {
+ log.Errorf("[INFO] Recovered from panic: %s\n[INFO] Debug stack: %s\n",
+ r, debug.Stack())
+ http.Error(w, "Internal server error. This event has been logged.",
+ http.StatusInternalServerError)
+ }
+}
+
func CSSHandler(w http.ResponseWriter, r *http.Request) {
defer InternalServerErrorHandler(w, r)
w.Header().Set("Content-Type", "text/css")
@@ -100,3 +105,49 @@ func userName(l *dscuss.LoginHandle, id *entity.ID) string {
return u.Nickname
}
}
+
+type Message struct {
+ ID string
+ Subject string
+ Text string
+ DateWritten string
+ AuthorName string
+ AuthorID string
+ AuthorShortID string
+}
+
+func (m *Message) Assign(em *entity.Message, l *dscuss.LoginHandle) {
+ m.ID = em.ID().String()
+ m.Subject = em.Subject
+ m.Text = em.Text
+ m.DateWritten = em.DateWritten.Format(time.RFC3339)
+ m.AuthorID = em.AuthorID.String()
+ m.AuthorShortID = em.AuthorID.Shorten()
+ m.AuthorName = userName(l, &em.AuthorID)
+}
+
+type RootMessage struct {
+ Message
+ Topic string
+}
+
+func (rm *RootMessage) Assign(em *entity.Message, l *dscuss.LoginHandle) {
+ rm.Message.Assign(em, l)
+ rm.Topic = em.Topic.String()
+}
+
+type Thread struct {
+ RootMessage
+ Replies []Message
+}
+
+type ComposedReply struct {
+ Subject string
+ Text string
+}
+
+type ComposedRootMessage struct {
+ Topic string
+ Subject string
+ Text string
+}
diff --git a/cmd/dscuss-web/controller/login_handlers.go b/cmd/dscuss-web/controller/login_handlers.go
index 9fc4141..bd1c907 100644
--- a/cmd/dscuss-web/controller/login_handlers.go
+++ b/cmd/dscuss-web/controller/login_handlers.go
@@ -31,17 +31,17 @@ const (
)
func loginHandler(w http.ResponseWriter, r *http.Request, l *dscuss.LoginHandle, s *Session) {
- var validURI = regexp.MustCompile("^/login(next=[a-zA-Z0-9\\/+=]+)?$")
+ var validURI = regexp.MustCompile("^/login(\\?next=[a-zA-Z0-9\\/+=]+)?$")
m := validURI.FindStringSubmatch(r.URL.Path)
if m == nil {
- http.NotFound(w, r)
+ NotFoundHandler(w, r)
return
}
var err error
redirectURL := r.FormValue("next")
- // FormValue() returns URL-decoded value for GET methods
if r.Method == "POST" {
- redirectURL, err = url.QueryUnescape(r.FormValue("next"))
+ // FormValue() returns URL-decoded value for GET methods
+ redirectURL, err = url.QueryUnescape(redirectURL)
}
if err != nil || redirectURL == "" || redirectURL[0] != '/' {
redirectURL = "/"
@@ -76,7 +76,7 @@ func MakeLoginHandler(l *dscuss.LoginHandle) http.HandlerFunc {
func LogoutHandler(w http.ResponseWriter, r *http.Request) {
if r.URL.Path != "/logout" {
- http.NotFound(w, r)
+ NotFoundHandler(w, r)
return
}
defer InternalServerErrorHandler(w, r)
diff --git a/cmd/dscuss-web/controller/reply_handlers.go b/cmd/dscuss-web/controller/reply_handlers.go
index 11d2237..ceb6744 100644
--- a/cmd/dscuss-web/controller/reply_handlers.go
+++ b/cmd/dscuss-web/controller/reply_handlers.go
@@ -20,7 +20,6 @@ import (
"net/http"
"net/url"
"regexp"
- "time"
"vminko.org/dscuss"
"vminko.org/dscuss/cmd/dscuss-web/view"
"vminko.org/dscuss/entity"
@@ -33,29 +32,10 @@ const (
maxTextLength = 1024
)
-type Thread1 struct {
- ID string
- Topic string
- Subject string
-}
-type ParentMessage1 struct {
- ID string
- Subject string
- Text string
- DateWritten string
- AuthorName string
- AuthorID string
- AuthorShortID string
-}
-type Reply1 struct {
- Subject string
- Text string
-}
-
func replyHandler(w http.ResponseWriter, r *http.Request, l *dscuss.LoginHandle, s *Session) {
var validURI = regexp.MustCompile("^/reply(\\?id=[a-zA-Z0-9\\/+=]+)?$")
if validURI.FindStringSubmatch(r.URL.Path) == nil {
- http.NotFound(w, r)
+ NotFoundHandler(w, r)
return
}
if !s.IsAuthenticated {
@@ -80,32 +60,24 @@ func replyHandler(w http.ResponseWriter, r *http.Request, l *dscuss.LoginHandle,
var msg string
var showSubj bool
- var t Thread1
- var pm ParentMessage1
- var rpl Reply1
+ var rm RootMessage
+ var pm Message
+ var rpl ComposedReply
m, err := l.GetMessage(&pid)
if err == errors.NoSuchEntity {
- http.NotFound(w, r)
+ NotFoundHandler(w, r)
} else if err != nil {
log.Fatalf("Got an error while fetching msg %s from DB: %v",
pid.Shorten(), err)
}
- pm.ID = m.ID().String()
- pm.Subject = m.Subject
- pm.Text = m.Text
- pm.DateWritten = m.DateWritten.Format(time.RFC3339)
- pm.AuthorID = m.AuthorID.String()
- pm.AuthorShortID = m.AuthorID.Shorten()
- pm.AuthorName = userName(l, &m.AuthorID)
+ pm.Assign(m, l)
root, err := l.GetRootMessage(m)
if err != nil {
log.Fatalf("Got an error while fetching root for msg %s from DB: %v",
pid.Shorten(), err)
}
- t.ID = root.ID().String()
- t.Topic = root.Topic.String()
- t.Subject = root.Subject
+ rm.Assign(root, l)
if r.Method == "POST" {
rpl.Subject = r.PostFormValue("subject")
@@ -128,7 +100,7 @@ func replyHandler(w http.ResponseWriter, r *http.Request, l *dscuss.LoginHandle,
render:
view.Render(w, "reply.html", map[string]interface{}{
"Common": readCommonData(r, s, l),
- "Thread": t,
+ "Thread": rm,
"Parent": pm,
"Reply": rpl,
"ShowParentSubject": showSubj,
diff --git a/cmd/dscuss-web/controller/thread_handlers.go b/cmd/dscuss-web/controller/thread_handlers.go
index da41b67..dbcf023 100644
--- a/cmd/dscuss-web/controller/thread_handlers.go
+++ b/cmd/dscuss-web/controller/thread_handlers.go
@@ -19,7 +19,6 @@ package controller
import (
"net/http"
"regexp"
- "time"
"vminko.org/dscuss"
"vminko.org/dscuss/cmd/dscuss-web/view"
"vminko.org/dscuss/entity"
@@ -27,28 +26,6 @@ import (
"vminko.org/dscuss/thread"
)
-type Thread struct {
- ID string
- Topic string
- Subject string
- Text string
- DateWritten string
- AuthorName string
- AuthorID string
- AuthorShortID string
- Replies []Reply
-}
-
-type Reply struct {
- ID string
- Subject string
- Text string
- DateWritten string
- AuthorName string
- AuthorID string
- AuthorShortID string
-}
-
type ThreadComposer struct {
t *Thread
l *dscuss.LoginHandle
@@ -60,24 +37,11 @@ func (tc *ThreadComposer) Handle(n *thread.Node) bool {
return true
}
if n.IsRoot() {
- tc.t.ID = m.ID().String()
- tc.t.Topic = m.Topic.String()
- tc.t.Subject = m.Subject
- tc.t.Text = m.Text
- tc.t.DateWritten = m.DateWritten.Format(time.RFC3339)
- tc.t.AuthorID = m.AuthorID.String()
- tc.t.AuthorShortID = m.AuthorID.Shorten()
- tc.t.AuthorName = userName(tc.l, &m.AuthorID)
+ tc.t.RootMessage.Assign(m, tc.l)
} else {
- tc.t.Replies = append(tc.t.Replies, Reply{})
+ tc.t.Replies = append(tc.t.Replies, Message{})
r := &tc.t.Replies[len(tc.t.Replies)-1]
- r.ID = m.ID().String()
- r.Subject = m.Subject
- r.Text = m.Text
- r.DateWritten = m.DateWritten.Format(time.RFC3339)
- r.AuthorID = m.AuthorID.String()
- r.AuthorShortID = m.AuthorID.Shorten()
- r.AuthorName = userName(tc.l, &m.AuthorID)
+ r.Assign(m, tc.l)
}
return true
}
@@ -86,7 +50,7 @@ func threadHandler(w http.ResponseWriter, r *http.Request, l *dscuss.LoginHandle
var validURI = regexp.MustCompile("^/thread(id=[a-zA-Z0-9\\/+=]{32})?$")
m := validURI.FindStringSubmatch(r.URL.Path)
if m == nil {
- http.NotFound(w, r)
+ NotFoundHandler(w, r)
return
}
idStr := r.URL.Query().Get("id")
diff --git a/cmd/dscuss-web/main.go b/cmd/dscuss-web/main.go
index d3fa3b4..ef06eb7 100644
--- a/cmd/dscuss-web/main.go
+++ b/cmd/dscuss-web/main.go
@@ -123,6 +123,7 @@ func main() {
http.HandleFunc("/login", controller.MakeLoginHandler(loginHandle))
http.HandleFunc("/logout", controller.LogoutHandler)
http.HandleFunc("/thread", controller.MakeThreadHandler(loginHandle))
+ http.HandleFunc("/reply", controller.MakeReplyHandler(loginHandle))
http.HandleFunc("/", controller.MakeRootHandler(loginHandle))
log.Debugf("Starting HTTP server on port %d\n", webPort)
diff --git a/cmd/dscuss-web/static/css.go b/cmd/dscuss-web/static/css.go
index 2c8314c..f84611f 100644
--- a/cmd/dscuss-web/static/css.go
+++ b/cmd/dscuss-web/static/css.go
@@ -204,8 +204,10 @@ textarea {
#subtitle {
margin-top: 0px;
}
-.message p:first-child {
+.message-text {
margin-top: 10px;
+ white-space: pre-wrap;
+ font-family: monospace;
}
.message-row, .thread-row {
margin-bottom: 30px;
diff --git a/cmd/dscuss-web/view/board.go b/cmd/dscuss-web/view/board.go
index ba35297..38e42a4 100644
--- a/cmd/dscuss-web/view/board.go
+++ b/cmd/dscuss-web/view/board.go
@@ -38,7 +38,7 @@ all topics
<span class="topic">in <a class="topic" href="/board?topic={{ .Topic }}">{{ .Topic }}</a></span>
{{ end }}
</div>
- <div class="message">{{ .Text }}</div>
+ <div class="message-text">{{ .Text }}</div>
<div class="dimmed underline">
by {{ .AuthorName }}-{{ .AuthorShortID }} {{ .DateWritten }}
</div>
diff --git a/cmd/dscuss-web/view/login.go b/cmd/dscuss-web/view/login.go
index 3a4ec25..b55cf4a 100644
--- a/cmd/dscuss-web/view/login.go
+++ b/cmd/dscuss-web/view/login.go
@@ -1,3 +1,20 @@
+/*
+This file is part of Dscuss.
+Copyright (C) 2019 Vitaly Minko
+
+This program is free software: you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free Software
+Foundation, either version 3 of the License, or (at your option) any later
+version.
+
+This program is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+PARTICULAR PURPOSE. See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License along with
+this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
package view
const loginHTML = `
diff --git a/cmd/dscuss-web/view/reply.go b/cmd/dscuss-web/view/reply.go
index 31bda7f..22450c1 100644
--- a/cmd/dscuss-web/view/reply.go
+++ b/cmd/dscuss-web/view/reply.go
@@ -34,7 +34,7 @@ const replyHTML = `
<form action="/reply" method="POST" enctype="multipart/form-data">
<input type="hidden" name="csrf" value="{{ .Common.CSRF }}">
<input type="hidden" name="id" value="{{ .Parent.ID }}">
- <input type="text" name="subject" value="{{ .Reply.Subject }}">
+ Subject: <input type="text" name="subject" value="{{ .Reply.Subject }}" placeholder="Re: {{.Parent.Subject}}">
<textarea name="text" rows="12">{{ .Reply.Text }}</textarea>
{{ if .Message }}
<span class="alert">{{ .Message }}</span>
diff --git a/cmd/dscuss-web/view/templates.go b/cmd/dscuss-web/view/templates.go
index 7a7c5be..14508d3 100644
--- a/cmd/dscuss-web/view/templates.go
+++ b/cmd/dscuss-web/view/templates.go
@@ -39,6 +39,7 @@ func init() {
templates.Add(base, "login", loginHTML)
templates.Add(base, "board", boardHTML)
templates.Add(base, "thread", threadHTML)
+ templates.Add(base, "reply", replyHTML)
}
func Render(w http.ResponseWriter, tmplName string, data interface{}) {
diff --git a/cmd/dscuss-web/view/thread.go b/cmd/dscuss-web/view/thread.go
index cfd8f4c..d241e2e 100644
--- a/cmd/dscuss-web/view/thread.go
+++ b/cmd/dscuss-web/view/thread.go
@@ -29,7 +29,7 @@ const threadHTML = `
<h2 id="title"><a href="/thread?id={{ .ThreadID }}">{{ .Subject }}</a></h2>
<span class="topic">in <a href="/board?topic={{ .Topic }}">{{ .Topic }}</a></span>
<div class="message-row">
- <div class="message">{{ .Text }}</div>
+ <div class="message-text">{{ .Text }}</div>
<div class="dimmed underline">
by <a href="/user?u={{ .AuthorID }}">{{ .AuthorName }}-{{ .AuthorShortID }}</a> {{ .DateWritten }}
{{ if .Common.IsWritingPermitted }}
@@ -45,7 +45,7 @@ const threadHTML = `
<hr class="sep">
<div class="message-row" id="message-{{ .ID }}">
<b>{{ .Subject }}</b>
- <div class="message">{{ .Text }}</div>
+ <div class="message-text">{{ .Text }}</div>
<div class="dimmed underline">
by <a href="/user?u={{ .AuthorID }}">{{ .AuthorName }}-{{ .AuthorShortID }}</a>
<a href="/lsop?id={{ .ID }}">{{ .DateWritten }}</a>
diff --git a/dscuss.go b/dscuss.go
index f5c0440..2706f1b 100644
--- a/dscuss.go
+++ b/dscuss.go
@@ -257,6 +257,14 @@ func (lh *LoginHandle) GetUser(id *entity.ID) (*entity.User, error) {
return lh.owner.Storage.GetUser(id)
}
+func (lh *LoginHandle) GetMessage(id *entity.ID) (*entity.Message, error) {
+ return lh.owner.Storage.GetMessage(id)
+}
+
+func (lh *LoginHandle) GetRootMessage(m *entity.Message) (*entity.Message, error) {
+ return lh.owner.Storage.GetRoot(m)
+}
+
func (lh *LoginHandle) ListOperationsOnUser(id *entity.ID) ([]*entity.Operation, error) {
return lh.owner.Storage.GetOperationsOnUser(id)
}