Update the way statuses work
This commit is contained in:
parent
c0922e3fb9
commit
56427140b5
9 changed files with 109 additions and 19 deletions
|
|
@ -2,13 +2,14 @@ package model
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type Status struct {
|
type Status struct {
|
||||||
Id int64
|
Id int64
|
||||||
User string
|
User string
|
||||||
Content string
|
Content string
|
||||||
CreatedAt time.Time
|
CreatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -22,3 +23,34 @@ func (s Status) Validate() error {
|
||||||
func (s Status) Date() string {
|
func (s Status) Date() string {
|
||||||
return s.CreatedAt.Format("2006-01-02")
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
const schemaVersion = 1
|
const schemaVersion = 2
|
||||||
|
|
||||||
func Migrate(db *sql.DB) {
|
func Migrate(db *sql.DB) {
|
||||||
var currentVersion int
|
var currentVersion int
|
||||||
|
|
|
||||||
|
|
@ -24,5 +24,8 @@ create table statuses
|
||||||
content VARCHAR(500) NOT NULL CHECK (content <> ''),
|
content VARCHAR(500) NOT NULL CHECK (content <> ''),
|
||||||
created_at timestamp with time zone DEFAULT now()
|
created_at timestamp with time zone DEFAULT now()
|
||||||
);
|
);
|
||||||
|
`,
|
||||||
|
"schema_version_2": `alter table users
|
||||||
|
add column status_id int references statuses(id);
|
||||||
`,
|
`,
|
||||||
}
|
}
|
||||||
|
|
|
||||||
2
storage/sql/schema_version_2.sql
Normal file
2
storage/sql/schema_version_2.sql
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
alter table users
|
||||||
|
add column status_id int references statuses(id);
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
package storage
|
package storage
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"status/model"
|
"status/model"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
@ -37,11 +38,25 @@ func (s *Storage) populateStatus(rows *sql.Rows) (model.Status, error) {
|
||||||
return status, nil
|
return status, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) CreateStatus(status model.Status) (int64, error) {
|
func (s *Storage) CreateStatus(status model.Status) error {
|
||||||
var lid int64
|
var statusId int64
|
||||||
err := s.db.QueryRow(`INSERT INTO statuses (author, content) VALUES ($1, $2) RETURNING id`,
|
ctx := context.Background()
|
||||||
status.User, status.Content).Scan(&lid)
|
tx, err := s.db.BeginTx(ctx, nil)
|
||||||
return lid, err
|
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) {
|
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
|
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 {
|
func (s *Storage) UpdateStatus(status model.Status) error {
|
||||||
stmt, err := s.db.Prepare(`UPDATE statuses SET content = $1 WHERE id = $2 and author = $3;`)
|
stmt, err := s.db.Prepare(`UPDATE statuses SET content = $1 WHERE id = $2 and author = $3;`)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,13 @@ Are you sure you you want to delete the following status?
|
||||||
</form>
|
</form>
|
||||||
{{ end }}`,
|
{{ end }}`,
|
||||||
"index": `{{ define "content" }}
|
"index": `{{ define "content" }}
|
||||||
<p>This is the index</p>
|
<p><a href="javascript:void(open('http://localhost:8000/statuses/new','status.cafe','resizable,scrollbars,width=360,height=200'))">Update your status</a></p>
|
||||||
|
{{ range .statuses }}
|
||||||
|
<article class="status">
|
||||||
|
<div class="username"><a href="/{{ .User }}">{{ .User }}</a>, {{ .TimeAgo }}</div>
|
||||||
|
<p>{{ .Content }}</p>
|
||||||
|
</article>
|
||||||
|
{{ end }}
|
||||||
{{ end }}`,
|
{{ end }}`,
|
||||||
"login": `{{ define "content" }}
|
"login": `{{ define "content" }}
|
||||||
<h1>Login</h1>
|
<h1>Login</h1>
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,9 @@
|
||||||
{{ define "content" }}
|
{{ define "content" }}
|
||||||
<p>This is the index</p>
|
<p><a href="javascript:void(open('http://localhost:8000/statuses/new','status.cafe','resizable,scrollbars,width=360,height=200'))">Update your status</a></p>
|
||||||
|
{{ range .statuses }}
|
||||||
|
<article class="status">
|
||||||
|
<div class="username"><a href="/{{ .User }}">{{ .User }}</a>, {{ .TimeAgo }}</div>
|
||||||
|
<p>{{ .Content }}</p>
|
||||||
|
</article>
|
||||||
|
{{ end }}
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
@ -10,13 +10,12 @@ type Update struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (h *Handler) showIndexView(w http.ResponseWriter, r *http.Request) {
|
func (h *Handler) showIndexView(w http.ResponseWriter, r *http.Request) {
|
||||||
// user, _ := h.sess.Get(r)
|
statuses, err := h.storage.LatestStatuses()
|
||||||
|
if err != nil {
|
||||||
//h.renderLayout(w, "index", map[string]interface{}{
|
serverError(w, err)
|
||||||
// "Pages": pages,
|
return
|
||||||
// "Files": files,
|
}
|
||||||
// "News": news,
|
h.renderLayout(w, "index", map[string]interface{}{
|
||||||
//}, user)
|
"statuses": statuses,
|
||||||
|
}, "")
|
||||||
h.renderLayout(w, "index", nil, "")
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func (h *Handler) saveStatus(w http.ResponseWriter, r *http.Request) {
|
||||||
}, "")
|
}, "")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if _, err := h.storage.CreateStatus(status); err != nil {
|
if err := h.storage.CreateStatus(status); err != nil {
|
||||||
serverError(w, err)
|
serverError(w, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue