From d0ea7cf3c631512ea6b3afba61a25c83aaded6c8 Mon Sep 17 00:00:00 2001 From: "Daniel J. Summers" Date: Mon, 18 Jun 2018 20:25:00 -0500 Subject: [PATCH] Added "snoozedUntil" column to API Also added a "snooze" route (working on #17 ) --- src/api/data/data.go | 44 ++++++++++++++++++++++++++++++-------- src/api/data/entities.go | 20 +++++++++-------- src/api/routes/handlers.go | 10 +++++++++ src/api/routes/routes.go | 7 ++++++ 4 files changed, 63 insertions(+), 18 deletions(-) diff --git a/src/api/data/data.go b/src/api/data/data.go index abc44eb..5ca71d5 100644 --- a/src/api/data/data.go +++ b/src/api/data/data.go @@ -14,10 +14,10 @@ import ( const ( currentRequestSQL = ` - SELECT "requestId", "text", "asOf", "lastStatus" + SELECT "requestId", "text", "asOf", "lastStatus", "snoozedUntil" FROM mpj.journal` journalSQL = ` - SELECT "requestId", "text", "asOf", "lastStatus" + SELECT "requestId", "text", "asOf", "lastStatus", "snoozedUntil" FROM mpj.journal WHERE "userId" = $1 AND "lastStatus" <> 'Answered'` @@ -41,11 +41,11 @@ type Settings struct { func retrieveRequest(reqID, userID string) (*Request, bool) { req := Request{} err := db.QueryRow(` - SELECT "requestId", "enteredOn" + SELECT "requestId", "enteredOn", "snoozedUntil" FROM mpj.request WHERE "requestId" = $1 AND "userId" = $2`, reqID, userID).Scan( - &req.ID, &req.EnteredOn, + &req.ID, &req.EnteredOn, &req.SnoozedUntil, ) if err != nil { if err != sql.ErrNoRows { @@ -67,7 +67,7 @@ func makeJournal(rows *sql.Rows, userID string) []JournalRequest { var out []JournalRequest for rows.Next() { req := JournalRequest{} - err := rows.Scan(&req.RequestID, &req.Text, &req.AsOf, &req.LastStatus) + err := rows.Scan(&req.RequestID, &req.Text, &req.AsOf, &req.LastStatus, &req.SnoozedUntil) if err != nil { log.Print(err) continue @@ -117,7 +117,7 @@ func AddNew(userID, text string) (*JournalRequest, bool) { } }() _, err = tx.Exec( - `INSERT INTO mpj.request ("requestId", "enteredOn", "userId") VALUES ($1, $2, $3)`, + `INSERT INTO mpj.request ("requestId", "enteredOn", "userId", "snoozedUntil") VALUES ($1, $2, $3, 0)`, id, now, userID) if err != nil { return nil, false @@ -128,7 +128,7 @@ func AddNew(userID, text string) (*JournalRequest, bool) { if err != nil { return nil, false } - return &JournalRequest{RequestID: id, Text: text, AsOf: now, LastStatus: `Created`}, true + return &JournalRequest{RequestID: id, Text: text, AsOf: now, LastStatus: `Created`, SnoozedUntil: 0}, true } // AddNote adds a note to a prayer request. @@ -171,7 +171,7 @@ func ByID(userID, reqID string) (*JournalRequest, bool) { ` WHERE "requestId" = $1 AND "userId" = $2`, reqID, userID).Scan( - &req.RequestID, &req.Text, &req.AsOf, &req.LastStatus, + &req.RequestID, &req.Text, &req.AsOf, &req.LastStatus, &req.SnoozedUntil, ) if err != nil { if err == sql.ErrNoRows { @@ -284,6 +284,23 @@ func NotesByID(userID, reqID string) ([]Note, error) { return notes, nil } +// SnoozeByID sets a request to not show until a specified time +func SnoozeByID(userID, reqID string, until int64) int { + if _, ok := retrieveRequest(reqID, userID); !ok { + return 404 + } + _, err := db.Exec(` + UPDATE mpj.request + SET "snoozedUntil" = $2 + WHERE "requestId" = $1`, + reqID, until) + if err != nil { + log.Print(err) + return 500 + } + return 204 +} + /* DDL */ // EnsureDB makes sure we have a known state of data structures. @@ -291,6 +308,11 @@ func EnsureDB() { tableSQL := func(table string) string { return fmt.Sprintf(`SELECT 1 FROM pg_tables WHERE schemaname='mpj' AND tablename='%s'`, table) } + columnSQL := func(table, column string) string { + return fmt.Sprintf( + `SELECT 1 FROM information_schema.columns WHERE table_schema='mpj' AND table_name='%s' AND column_name='%s'`, + table, column) + } indexSQL := func(table, index string) string { return fmt.Sprintf(`SELECT 1 FROM pg_indexes WHERE schemaname='mpj' AND tablename='%s' AND indexname='%s'`, table, index) @@ -322,6 +344,9 @@ func EnsureDB() { "enteredOn" bigint NOT NULL, "userId" varchar(100) NOT NULL); COMMENT ON TABLE mpj.request IS 'Requests'`) + check(`request.snoozedUntil Column`, columnSQL(`request`, `snoozedUntil`), + `ALTER TABLE mpj.request + ADD COLUMN "snoozedUntil" bigint NOT NULL DEFAULT 0`) check(`history Table`, tableSQL(`history`), `CREATE TABLE mpj.history ( "requestId" varchar(25) NOT NULL REFERENCES mpj.request, @@ -360,7 +385,8 @@ func EnsureDB() { FROM mpj.history WHERE history."requestId" = request."requestId" ORDER BY "asOf" DESC - LIMIT 1) AS "lastStatus" + LIMIT 1) AS "lastStatus", + request."snoozedUntil" FROM mpj.request; COMMENT ON VIEW mpj.journal IS 'Requests with latest text'`) } diff --git a/src/api/data/entities.go b/src/api/data/entities.go index 2fad45b..d85aa60 100644 --- a/src/api/data/entities.go +++ b/src/api/data/entities.go @@ -17,18 +17,20 @@ type Note struct { // Request is the identifying record for a prayer request. type Request struct { - ID string `json:"requestId"` - EnteredOn int64 `json:"enteredOn"` - UserID string `json:"userId"` + ID string `json:"requestId"` + EnteredOn int64 `json:"enteredOn"` + UserID string `json:"userId"` + SnoozedUntil int64 `json:"snoozedUntil"` } // JournalRequest is the form of a prayer request returned for the request journal display. It also contains // properties that may be filled for history and notes. type JournalRequest struct { - RequestID string `json:"requestId"` - Text string `json:"text"` - AsOf int64 `json:"asOf"` - LastStatus string `json:"lastStatus"` - History []History `json:"history,omitempty"` - Notes []Note `json:"notes,omitempty"` + RequestID string `json:"requestId"` + Text string `json:"text"` + AsOf int64 `json:"asOf"` + LastStatus string `json:"lastStatus"` + SnoozedUntil int64 `json:"snoozedUntil"` + History []History `json:"history,omitempty"` + Notes []Note `json:"notes,omitempty"` } diff --git a/src/api/routes/handlers.go b/src/api/routes/handlers.go index ef97190..bd05b3d 100644 --- a/src/api/routes/handlers.go +++ b/src/api/routes/handlers.go @@ -155,6 +155,16 @@ func requestGetNotes(c *routing.Context) error { return sendJSON(c, notes) } +// POST: /api/request//snooze +func requestSnooze(c *routing.Context) error { + payload, err := parseJSON(c) + if err != nil { + return sendError(c, err) + } + c.Response.WriteHeader(data.SnoozeByID(userID(c), c.Param("id"), payload["until"].(int64))) + return nil +} + // GET: /api/request/answered func requestsAnswered(c *routing.Context) error { reqs := data.Answered(userID(c)) diff --git a/src/api/routes/routes.go b/src/api/routes/routes.go index 38c9da5..27dd92b 100644 --- a/src/api/routes/routes.go +++ b/src/api/routes/routes.go @@ -85,6 +85,13 @@ var routes = Routes{ requestGetNotes, false, }, + Route{ + "SnoozeRequest", + http.MethodPost, + "/api/request//snooze", + requestSnooze, + false, + }, // keep this route last Route{ "StaticFiles",