From 56427140b55efa2266e2af0200ef5dd4e39ea28a Mon Sep 17 00:00:00 2001 From: m15o Date: Mon, 22 Nov 2021 18:12:07 +0100 Subject: [PATCH] Update the way statuses work --- model/status.go | 34 ++++++++++++++++++++- storage/migration.go | 2 +- storage/sql.go | 3 ++ storage/sql/schema_version_2.sql | 2 ++ storage/status.go | 52 +++++++++++++++++++++++++++++--- web/handler/html.go | 8 ++++- web/handler/html/index.html | 8 ++++- web/handler/index_show.go | 17 +++++------ web/handler/status_save.go | 2 +- 9 files changed, 109 insertions(+), 19 deletions(-) create mode 100644 storage/sql/schema_version_2.sql diff --git a/model/status.go b/model/status.go index 079426a..1929413 100644 --- a/model/status.go +++ b/model/status.go @@ -2,13 +2,14 @@ package model import ( "errors" + "fmt" "time" ) type Status struct { Id int64 User string - Content string + Content string CreatedAt time.Time } @@ -22,3 +23,34 @@ func (s Status) Validate() error { func (s Status) Date() string { return s.CreatedAt.Format("2006-01-02") } + +func (s Status) TimeAgo() string { + // Taken from flounder.online <3 + // https://github.com/alexwennerberg/flounder + d := time.Since(s.CreatedAt) + if d.Seconds() < 60 { + seconds := int(d.Seconds()) + if seconds == 1 { + return "1 second ago" + } + return fmt.Sprintf("%d seconds ago", seconds) + } else if d.Minutes() < 60 { + minutes := int(d.Minutes()) + if minutes == 1 { + return "1 minute ago" + } + return fmt.Sprintf("%d minutes ago", minutes) + } else if d.Hours() < 24 { + hours := int(d.Hours()) + if hours == 1 { + return "1 hour ago" + } + return fmt.Sprintf("%d hours ago", hours) + } else { + days := int(d.Hours()) / 24 + if days == 1 { + return "1 day ago" + } + return fmt.Sprintf("%d days ago", days) + } +} diff --git a/storage/migration.go b/storage/migration.go index efe581d..f799c5e 100644 --- a/storage/migration.go +++ b/storage/migration.go @@ -7,7 +7,7 @@ import ( "strconv" ) -const schemaVersion = 1 +const schemaVersion = 2 func Migrate(db *sql.DB) { var currentVersion int diff --git a/storage/sql.go b/storage/sql.go index 55f70c2..71017dc 100644 --- a/storage/sql.go +++ b/storage/sql.go @@ -24,5 +24,8 @@ create table statuses content VARCHAR(500) NOT NULL CHECK (content <> ''), created_at timestamp with time zone DEFAULT now() ); +`, + "schema_version_2": `alter table users + add column status_id int references statuses(id); `, } diff --git a/storage/sql/schema_version_2.sql b/storage/sql/schema_version_2.sql new file mode 100644 index 0000000..926f310 --- /dev/null +++ b/storage/sql/schema_version_2.sql @@ -0,0 +1,2 @@ +alter table users + add column status_id int references statuses(id); diff --git a/storage/status.go b/storage/status.go index 76bde82..81ee7e7 100644 --- a/storage/status.go +++ b/storage/status.go @@ -1,6 +1,7 @@ package storage import ( + "context" "database/sql" "status/model" "strconv" @@ -37,11 +38,25 @@ func (s *Storage) populateStatus(rows *sql.Rows) (model.Status, error) { return status, nil } -func (s *Storage) CreateStatus(status model.Status) (int64, error) { - var lid int64 - err := s.db.QueryRow(`INSERT INTO statuses (author, content) VALUES ($1, $2) RETURNING id`, - status.User, status.Content).Scan(&lid) - return lid, err +func (s *Storage) CreateStatus(status model.Status) error { + var statusId int64 + ctx := context.Background() + tx, err := s.db.BeginTx(ctx, nil) + if err != nil { + return err + } + if err := tx.QueryRowContext(ctx, `INSERT INTO statuses (author, content) VALUES ($1, $2) RETURNING id`, + status.User, status.Content).Scan(&statusId); err != nil { + tx.Rollback() + return err + } + + if _, err := tx.ExecContext(ctx, `UPDATE users set status_id=$1 where name=$2`, statusId, status.User); err != nil { + tx.Rollback() + return err + } + err = tx.Commit() + return err } func (s *Storage) StatusById(id int64) (model.Status, error) { @@ -100,6 +115,33 @@ func (s *Storage) Statuses(page int64, perPage int) ([]model.Status, bool, error return statuses, false, err } +func (s *Storage) LatestStatuses() ([]model.Status, error) { + rows, err := s.db.Query(` + select + statuses.id, + users.name, + statuses.content, + statuses.created_at + from + users + inner join statuses + on users.status_id = statuses.id + order by statuses.created_at desc; + `) + if err != nil { + return nil, err + } + var statuses []model.Status + for rows.Next() { + post, err := s.populateStatus(rows) + if err != nil { + return statuses, err + } + statuses = append(statuses, post) + } + return statuses, err +} + func (s *Storage) UpdateStatus(status model.Status) error { stmt, err := s.db.Prepare(`UPDATE statuses SET content = $1 WHERE id = $2 and author = $3;`) if err != nil { diff --git a/web/handler/html.go b/web/handler/html.go index d776d1e..48ef973 100644 --- a/web/handler/html.go +++ b/web/handler/html.go @@ -41,7 +41,13 @@ Are you sure you you want to delete the following status? {{ end }}`, "index": `{{ define "content" }} -

This is the index

+

Update your status

+{{ range .statuses }} +
+
{{ .User }}, {{ .TimeAgo }}
+

{{ .Content }}

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

Login

diff --git a/web/handler/html/index.html b/web/handler/html/index.html index 1f75611..3b7e997 100644 --- a/web/handler/html/index.html +++ b/web/handler/html/index.html @@ -1,3 +1,9 @@ {{ define "content" }} -

This is the index

+

Update your status

+{{ range .statuses }} +
+
{{ .User }}, {{ .TimeAgo }}
+

{{ .Content }}

+
+{{ end }} {{ end }} \ No newline at end of file diff --git a/web/handler/index_show.go b/web/handler/index_show.go index dd6e4d1..3835aa7 100644 --- a/web/handler/index_show.go +++ b/web/handler/index_show.go @@ -10,13 +10,12 @@ type Update struct { } func (h *Handler) showIndexView(w http.ResponseWriter, r *http.Request) { - // user, _ := h.sess.Get(r) - - //h.renderLayout(w, "index", map[string]interface{}{ - // "Pages": pages, - // "Files": files, - // "News": news, - //}, user) - - h.renderLayout(w, "index", nil, "") + statuses, err := h.storage.LatestStatuses() + if err != nil { + serverError(w, err) + return + } + h.renderLayout(w, "index", map[string]interface{}{ + "statuses": statuses, + }, "") } diff --git a/web/handler/status_save.go b/web/handler/status_save.go index 9b05aaa..7522fe0 100644 --- a/web/handler/status_save.go +++ b/web/handler/status_save.go @@ -24,7 +24,7 @@ func (h *Handler) saveStatus(w http.ResponseWriter, r *http.Request) { }, "") return } - if _, err := h.storage.CreateStatus(status); err != nil { + if err := h.storage.CreateStatus(status); err != nil { serverError(w, err) return }