From 697d01e30613d639fcbfcc32c785a067804a356c Mon Sep 17 00:00:00 2001 From: boojack Date: Fri, 8 Jul 2022 22:23:27 +0800 Subject: [PATCH] feat: add `visibility` field to memo (#109) * feat: add `visibility` field to memo * chore: fix typo --- api/memo.go | 32 +++++++++++-- server/memo.go | 3 ++ .../db/migration/0.2/01__memo_visibility.sql | 1 + store/db/migration/LATEST__SCHEMA.sql | 1 + store/db/seed/10002__memo.sql | 8 ++-- store/memo.go | 46 ++++++++++++------- 6 files changed, 67 insertions(+), 24 deletions(-) create mode 100644 store/db/migration/0.2/01__memo_visibility.sql diff --git a/api/memo.go b/api/memo.go index bfb7b940..43d8f773 100644 --- a/api/memo.go +++ b/api/memo.go @@ -1,5 +1,25 @@ package api +// Visibility is the type of a visibility. +type Visibility string + +const ( + // Public is the PUBLIC visibility. + Public Visibility = "PUBLIC" + // Privite is the PRIVATE visibility. + Privite Visibility = "PRIVATE" +) + +func (e Visibility) String() string { + switch e { + case Public: + return "PUBLIC" + case Privite: + return "PRIVATE" + } + return "PRIVATE" +} + type Memo struct { ID int `json:"id"` @@ -10,8 +30,9 @@ type Memo struct { UpdatedTs int64 `json:"updatedTs"` // Domain specific fields - Content string `json:"content"` - Pinned bool `json:"pinned"` + Content string `json:"content"` + Visibility Visibility `json:"visibility"` + Pinned bool `json:"pinned"` } type MemoCreate struct { @@ -21,7 +42,8 @@ type MemoCreate struct { CreatedTs *int64 `json:"createdTs"` // Domain specific fields - Content string `json:"content"` + Content string `json:"content"` + Visibility Visibility `json:"visibility"` } type MemoPatch struct { @@ -31,7 +53,8 @@ type MemoPatch struct { RowStatus *RowStatus `json:"rowStatus"` // Domain specific fields - Content *string `json:"content"` + Content *string `json:"content"` + Visibility *Visibility `json:"visibility"` } type MemoFind struct { @@ -44,6 +67,7 @@ type MemoFind struct { // Domain specific fields Pinned *bool ContentSearch *string + Visibility *Visibility // Pagination Limit int diff --git a/server/memo.go b/server/memo.go index 144d5d01..14b8bc52 100644 --- a/server/memo.go +++ b/server/memo.go @@ -22,6 +22,9 @@ func (s *Server) registerMemoRoutes(g *echo.Group) { return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post memo request").SetInternal(err) } + // TODO(steven): remove this line after frontend is ready + memoCreate.Visibility = api.Privite + memo, err := s.Store.CreateMemo(memoCreate) if err != nil { return echo.NewHTTPError(http.StatusInternalServerError, "Failed to create memo").SetInternal(err) diff --git a/store/db/migration/0.2/01__memo_visibility.sql b/store/db/migration/0.2/01__memo_visibility.sql new file mode 100644 index 00000000..5e1122d3 --- /dev/null +++ b/store/db/migration/0.2/01__memo_visibility.sql @@ -0,0 +1 @@ +ALTER TABLE memo ADD visibility TEXT NOT NULL CHECK (visibility IN ('PUBLIC', 'PRIVATE')) DEFAULT 'PRIVATE'; diff --git a/store/db/migration/LATEST__SCHEMA.sql b/store/db/migration/LATEST__SCHEMA.sql index e27d4ca9..4f5c33b6 100644 --- a/store/db/migration/LATEST__SCHEMA.sql +++ b/store/db/migration/LATEST__SCHEMA.sql @@ -44,6 +44,7 @@ CREATE TABLE memo ( updated_ts BIGINT NOT NULL DEFAULT (strftime('%s', 'now')), row_status TEXT NOT NULL CHECK (row_status IN ('NORMAL', 'ARCHIVED')) DEFAULT 'NORMAL', content TEXT NOT NULL DEFAULT '', + visibility TEXT NOT NULL CHECK (visibility IN ('PUBLIC', 'PRIVATE')) DEFAULT 'PRIVATE', FOREIGN KEY(creator_id) REFERENCES user(id) ON DELETE CASCADE ); diff --git a/store/db/seed/10002__memo.sql b/store/db/seed/10002__memo.sql index 2604d382..352c8e91 100644 --- a/store/db/seed/10002__memo.sql +++ b/store/db/seed/10002__memo.sql @@ -34,13 +34,15 @@ INSERT INTO memo ( `id`, `content`, - `creator_id` + `creator_id`, + `visibility` ) VALUES ( 103, - '好好学习,天天向上。🤜🤛', - 101 + '好好学习,天天向上。🤜🤛', + 101, + 'PUBLIC' ); INSERT INTO diff --git a/store/memo.go b/store/memo.go index faf1f7cb..5b40782e 100644 --- a/store/memo.go +++ b/store/memo.go @@ -21,7 +21,8 @@ type memoRaw struct { UpdatedTs int64 // Domain specific fields - Content string + Content string + Visibility api.Visibility } // toMemo creates an instance of Memo based on the memoRaw. @@ -37,7 +38,8 @@ func (raw *memoRaw) toMemo() *api.Memo { UpdatedTs: raw.UpdatedTs, // Domain specific fields - Content: raw.Content, + Content: raw.Content, + Visibility: raw.Visibility, } } @@ -116,21 +118,21 @@ func (s *Store) DeleteMemo(delete *api.MemoDelete) error { } func createMemoRaw(db *sql.DB, create *api.MemoCreate) (*memoRaw, error) { - set := []string{"creator_id", "content"} - placeholder := []string{"?", "?"} - args := []interface{}{create.CreatorID, create.Content} + set := []string{"creator_id", "content", "visibility"} + placeholder := []string{"?", "?", "?"} + args := []interface{}{create.CreatorID, create.Content, create.Visibility} if v := create.CreatedTs; v != nil { set, placeholder, args = append(set, "created_ts"), append(placeholder, "?"), append(args, *v) } - row, err := db.Query(` - INSERT INTO memo ( - `+strings.Join(set, ", ")+` - ) - VALUES (`+strings.Join(placeholder, ",")+`) - RETURNING id, creator_id, created_ts, updated_ts, content, row_status - `, + query := ` + INSERT INTO memo ( + ` + strings.Join(set, ", ") + ` + ) + VALUES (` + strings.Join(placeholder, ",") + `) + RETURNING id, creator_id, created_ts, updated_ts, row_status, content, visibility` + row, err := db.Query(query, args..., ) if err != nil { @@ -145,8 +147,9 @@ func createMemoRaw(db *sql.DB, create *api.MemoCreate) (*memoRaw, error) { &memoRaw.CreatorID, &memoRaw.CreatedTs, &memoRaw.UpdatedTs, - &memoRaw.Content, &memoRaw.RowStatus, + &memoRaw.Content, + &memoRaw.Visibility, ); err != nil { return nil, FormatError(err) } @@ -163,6 +166,9 @@ func patchMemoRaw(db *sql.DB, patch *api.MemoPatch) (*memoRaw, error) { if v := patch.RowStatus; v != nil { set, args = append(set, "row_status = ?"), append(args, *v) } + if v := patch.Visibility; v != nil { + set, args = append(set, "visibility = ?"), append(args, *v) + } args = append(args, patch.ID) @@ -170,7 +176,7 @@ func patchMemoRaw(db *sql.DB, patch *api.MemoPatch) (*memoRaw, error) { UPDATE memo SET `+strings.Join(set, ", ")+` WHERE id = ? - RETURNING id, creator_id, created_ts, updated_ts, content, row_status + RETURNING id, creator_id, created_ts, updated_ts, row_status, content, visibility `, args...) if err != nil { return nil, FormatError(err) @@ -187,8 +193,9 @@ func patchMemoRaw(db *sql.DB, patch *api.MemoPatch) (*memoRaw, error) { &memoRaw.CreatorID, &memoRaw.CreatedTs, &memoRaw.UpdatedTs, - &memoRaw.Content, &memoRaw.RowStatus, + &memoRaw.Content, + &memoRaw.Visibility, ); err != nil { return nil, FormatError(err) } @@ -214,6 +221,9 @@ func findMemoRawList(db *sql.DB, find *api.MemoFind) ([]*memoRaw, error) { if v := find.ContentSearch; v != nil { where, args = append(where, "content LIKE ?"), append(args, "%"+*v+"%") } + if v := find.Visibility; v != nil { + where, args = append(where, "visibility = ?"), append(args, *v) + } pagination := "" if find.Limit > 0 { @@ -229,8 +239,9 @@ func findMemoRawList(db *sql.DB, find *api.MemoFind) ([]*memoRaw, error) { creator_id, created_ts, updated_ts, + row_status, content, - row_status + visibility FROM memo WHERE `+strings.Join(where, " AND ")+` ORDER BY created_ts DESC`+pagination, @@ -249,8 +260,9 @@ func findMemoRawList(db *sql.DB, find *api.MemoFind) ([]*memoRaw, error) { &memoRaw.CreatorID, &memoRaw.CreatedTs, &memoRaw.UpdatedTs, - &memoRaw.Content, &memoRaw.RowStatus, + &memoRaw.Content, + &memoRaw.Visibility, ); err != nil { return nil, FormatError(err) }