diff --git a/assets/style.css b/assets/style.css index 218d15d..9b51a95 100644 --- a/assets/style.css +++ b/assets/style.css @@ -33,4 +33,8 @@ section { grid-template-columns: repeat(2, 1fr); grid-gap: 1em; } -} \ No newline at end of file +} + +.field { margin-bottom: 1rem; max-width: 500px; } +.field > label { margin-bottom: .25rem; } +.field > * { display: block; width: 100%; box-sizing: border-box; } \ No newline at end of file diff --git a/model/user.go b/model/user.go index 9374aab..c649e2e 100644 --- a/model/user.go +++ b/model/user.go @@ -8,10 +8,12 @@ import ( ) type User struct { - Name string - Password string - Hash []byte - CreatedAt time.Time + Name string + Password string + Hash []byte + Homepage string + About string + CreatedAt time.Time } func (u User) Validate() error { diff --git a/storage/migration.go b/storage/migration.go index f799c5e..e89fd82 100644 --- a/storage/migration.go +++ b/storage/migration.go @@ -7,7 +7,7 @@ import ( "strconv" ) -const schemaVersion = 2 +const schemaVersion = 3 func Migrate(db *sql.DB) { var currentVersion int diff --git a/storage/sql.go b/storage/sql.go index 71017dc..65dbcad 100644 --- a/storage/sql.go +++ b/storage/sql.go @@ -27,5 +27,9 @@ create table statuses `, "schema_version_2": `alter table users add column status_id int references statuses(id); +`, + "schema_version_3": `alter table users + add column homepage varchar(500) not null DEFAULT '', + add column about varchar(500) not null DEFAULT ''; `, } diff --git a/storage/sql/schema_version_3.sql b/storage/sql/schema_version_3.sql new file mode 100644 index 0000000..f5f2b0f --- /dev/null +++ b/storage/sql/schema_version_3.sql @@ -0,0 +1,3 @@ +alter table users + add column homepage varchar(500) not null DEFAULT '', + add column about varchar(500) not null DEFAULT ''; diff --git a/storage/user.go b/storage/user.go index e6eca0f..0aaaf1b 100644 --- a/storage/user.go +++ b/storage/user.go @@ -4,11 +4,10 @@ import ( "status/model" ) -const queryFindName = `SELECT name, hash, created_at FROM users WHERE name=lower($1);` -const queryFindDomain = `SELECT name, hash, created_at FROM users WHERE domain=$1;` +const queryFindName = `SELECT name, hash, created_at, homepage, about FROM users WHERE name=lower($1);` func (s *Storage) queryUser(q string, params ...interface{}) (user model.User, err error) { - err = s.db.QueryRow(q, params...).Scan(&user.Name, &user.Hash, &user.CreatedAt) + err = s.db.QueryRow(q, params...).Scan(&user.Name, &user.Hash, &user.CreatedAt, &user.Homepage, &user.About) return } @@ -77,3 +76,12 @@ func (s *Storage) DeleteUser(username string) error { _, err = stmt.Exec(username) return err } + +func (s *Storage) UpdateSettings(username, homepage, about string) error { + stmt, err := s.db.Prepare(`UPDATE users SET homepage = $1, about = $2 WHERE name = $3;`) + if err != nil { + return err + } + _, err = stmt.Exec(homepage, about, username) + return err +} diff --git a/web/handler/form/settings.go b/web/handler/form/settings.go new file mode 100644 index 0000000..6cd85db --- /dev/null +++ b/web/handler/form/settings.go @@ -0,0 +1,17 @@ +package form + +import ( + "net/http" +) + +type SettingsForm struct { + Homepage string + About string +} + +func NewSettingsForm(r *http.Request) *SettingsForm { + return &SettingsForm{ + Homepage: r.FormValue("homepage"), + About: r.FormValue("about"), + } +} diff --git a/web/handler/handler.go b/web/handler/handler.go index 7326314..6c6433a 100644 --- a/web/handler/handler.go +++ b/web/handler/handler.go @@ -70,6 +70,9 @@ func New(cfg *config.Config, sess *session.Session, data *storage.Storage) (http router.HandleFunc("/register", h.handleRegister) router.HandleFunc("/logout", h.logout).Methods(http.MethodGet) + router.HandleFunc("/settings", h.showSettingsView).Methods(http.MethodGet) + router.HandleFunc("/settings-update", h.updateSettings).Methods(http.MethodPost) + router.HandleFunc("/status-new", h.showNewStatusView).Methods(http.MethodGet) router.HandleFunc("/status-save", h.saveStatus).Methods(http.MethodPost) router.HandleFunc("/statuses/{id}/edit", h.showEditStatusView).Methods(http.MethodGet) diff --git a/web/handler/html.go b/web/handler/html.go index 22aafc8..0a06b28 100644 --- a/web/handler/html.go +++ b/web/handler/html.go @@ -86,7 +86,6 @@ Are you sure you you want to delete the following status?
-

Update status with bookmarklet

Drag to your bookmarks to update from anywhere: Set status

@@ -142,12 +141,44 @@ Are you sure you you want to delete the following status? {{ end }}`, - "user": `{{ define "content" }} + "settings": `{{ define "content" }}
-

{{ .user }}

- {{ range .statuses }} - {{ template "status" . }} +

Settings

+ {{ if .flash }} +

{{ .flash }}

{{ end }} +
+
+ + +
+ +
+ + +
+ + +
+{{ end }}`, + "user": `{{ define "content" }} +
+
+

{{ .user }}

+
+
Homepage
+
{{ .homepage }}
+
About
+
{{ .about }}
+
+
+
+

Statuses

+ {{ range .statuses }} + {{ template "status" . }} + {{ end }} +
+
{{ end }}`, } diff --git a/web/handler/html/index.html b/web/handler/html/index.html index 88df678..f30508f 100644 --- a/web/handler/html/index.html +++ b/web/handler/html/index.html @@ -12,7 +12,6 @@
-

Update status with bookmarklet

Drag to your bookmarks to update from anywhere: Set status

diff --git a/web/handler/html/settings.html b/web/handler/html/settings.html new file mode 100644 index 0000000..9ae8789 --- /dev/null +++ b/web/handler/html/settings.html @@ -0,0 +1,21 @@ +{{ define "content" }} +
+

Settings

+ {{ if .flash }} +

{{ .flash }}

+ {{ end }} +
+
+ + +
+ +
+ + +
+ + +
+
+{{ end }} \ No newline at end of file diff --git a/web/handler/html/user.html b/web/handler/html/user.html index 40601c0..bab2a1d 100644 --- a/web/handler/html/user.html +++ b/web/handler/html/user.html @@ -1,8 +1,19 @@ {{ define "content" }} -
-

{{ .user }}

- {{ range .statuses }} - {{ template "status" . }} - {{ end }} -
+
+
+

{{ .user }}

+
+
Homepage
+
{{ .homepage }}
+
About
+
{{ .about }}
+
+
+
+

Statuses

+ {{ range .statuses }} + {{ template "status" . }} + {{ end }} +
+
{{ end }} \ No newline at end of file diff --git a/web/handler/settings-update.go b/web/handler/settings-update.go new file mode 100644 index 0000000..bd7a9a5 --- /dev/null +++ b/web/handler/settings-update.go @@ -0,0 +1,28 @@ +package handler + +import ( + "fmt" + "net/http" + "status/web/handler/form" +) + +func (h *Handler) updateSettings(w http.ResponseWriter, r *http.Request) { + user, err := h.getUser(r) + if err != nil { + unauthorized(w) + return + } + f := form.NewSettingsForm(r) + if err := h.storage.UpdateSettings(user, f.Homepage, f.About); err != nil { + serverError(w, err) + return + } + session, err := h.sess.Store.Get(r, "ichi") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + session.AddFlash("Status edited!") + err = session.Save(r, w) + http.Redirect(w, r, fmt.Sprintf("/settings"), http.StatusFound) +} diff --git a/web/handler/settings_show.go b/web/handler/settings_show.go new file mode 100644 index 0000000..5c69480 --- /dev/null +++ b/web/handler/settings_show.go @@ -0,0 +1,31 @@ +package handler + +import "net/http" + +func (h *Handler) showSettingsView(w http.ResponseWriter, r *http.Request) { + username, err := h.getUser(r) + if err != nil { + unauthorized(w) + return + } + user, err := h.storage.UserByName(username) + if err != nil { + unauthorized(w) + return + } + session, err := h.sess.Store.Get(r, "ichi") + if err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + return + } + flash := "" + if flashes := session.Flashes(); len(flashes) > 0 { + flash = flashes[0].(string) + } + session.Save(r, w) + h.renderLayout(w, "settings", map[string]interface{}{ + "flash": flash, + "About": user.About, + "Homepage": user.Homepage, + }, username) +} diff --git a/web/handler/user_view.go b/web/handler/user_show.go similarity index 94% rename from web/handler/user_view.go rename to web/handler/user_show.go index 75ebf15..7fcda58 100644 --- a/web/handler/user_view.go +++ b/web/handler/user_show.go @@ -17,8 +17,9 @@ import ( ) func (h *Handler) showUserView(w http.ResponseWriter, r *http.Request) { - user := mux.Vars(r)["user"] - if !h.storage.UserExists(user) { + username := mux.Vars(r)["user"] + user, err := h.storage.UserByName(username) + if err != nil { notFound(w) return } @@ -28,9 +29,11 @@ func (h *Handler) showUserView(w http.ResponseWriter, r *http.Request) { return } h.renderLayout(w, "user", map[string]interface{}{ - "user": user, + "user": username, "statuses": statuses, - }, "") + "homepage": user.Homepage, + "about": user.About, + }, username) } type statusjson struct {