From 068af15e4060630645e140b0f1691d148d4d585d Mon Sep 17 00:00:00 2001 From: Tit Petric Date: Thu, 25 Oct 2018 11:52:11 +0200 Subject: [PATCH] add(crm): implement page reorder api, list pages by selfID --- crm/docs/README.md | 1 + crm/docs/src/spec.json | 7 ++++- crm/docs/src/spec/page.json | 11 +++++++- crm/repository/main_test.go | 2 +- crm/repository/page.go | 55 ++++++++++++++++++++++++++++++------ crm/repository/page_test.go | 56 ++++++++++++++++++++++++++++++++----- crm/rest/page.go | 6 +++- crm/rest/request/page.go | 6 ++++ crm/service/page.go | 12 ++++++-- 9 files changed, 133 insertions(+), 23 deletions(-) diff --git a/crm/docs/README.md b/crm/docs/README.md index 539abe119..1483a7222 100644 --- a/crm/docs/README.md +++ b/crm/docs/README.md @@ -48,6 +48,7 @@ CRM module pages | Parameter | Type | Method | Description | Default | Required? | | --------- | ---- | ------ | ----------- | ------- | --------- | +| selfID | uint64 | GET | Parent page ID | N/A | NO | ## Create page diff --git a/crm/docs/src/spec.json b/crm/docs/src/spec.json index 42cb08b38..3ac174fab 100644 --- a/crm/docs/src/spec.json +++ b/crm/docs/src/spec.json @@ -49,7 +49,12 @@ "name": "list", "method": "GET", "path": "/", - "title": "List available pages" + "title": "List available pages", + "parameters": { + "get": [ + { "type": "uint64", "name": "selfID", "required": false, "title": "Parent page ID" } + ] + } }, { "name": "create", diff --git a/crm/docs/src/spec/page.json b/crm/docs/src/spec/page.json index 3ca3c3c5f..cce969987 100644 --- a/crm/docs/src/spec/page.json +++ b/crm/docs/src/spec/page.json @@ -14,7 +14,16 @@ "Method": "GET", "Title": "List available pages", "Path": "/", - "Parameters": null + "Parameters": { + "get": [ + { + "name": "selfID", + "required": false, + "title": "Parent page ID", + "type": "uint64" + } + ] + } }, { "Name": "create", diff --git a/crm/repository/main_test.go b/crm/repository/main_test.go index f597ca28a..dc17d509c 100644 --- a/crm/repository/main_test.go +++ b/crm/repository/main_test.go @@ -33,7 +33,7 @@ func TestMain(m *testing.M) { // clean up tables { - for _, name := range []string{"crm_module", "crm_content", "crm_content_column"} { + for _, name := range []string{"crm_module", "crm_module_form", "crm_content", "crm_content_column", "crm_page"} { _, err := db.Exec("truncate " + name) if err != nil { panic("Error when clearing " + name + ": " + err.Error()) diff --git a/crm/repository/page.go b/crm/repository/page.go index bbe0970a8..2b5ec1b0a 100644 --- a/crm/repository/page.go +++ b/crm/repository/page.go @@ -13,13 +13,15 @@ type ( PageRepository interface { With(ctx context.Context, db *factory.DB) PageRepository - Find() ([]*types.Page, error) + Find(selfID uint64) ([]*types.Page, error) FindByID(id uint64) (*types.Page, error) FindByModuleID(id uint64) (*types.Page, error) Create(mod *types.Page) (*types.Page, error) Update(mod *types.Page) (*types.Page, error) DeleteByID(id uint64) error + + Reorder(selfID uint64, pageIDs []uint64) error } page struct { @@ -56,9 +58,9 @@ func (r *page) FindByModuleID(id uint64) (*types.Page, error) { return page, nil } -func (r *page) Find() ([]*types.Page, error) { +func (r *page) Find(selfID uint64) ([]*types.Page, error) { pages := make([]*types.Page, 0) - if err := r.db().Select(&pages, "SELECT * FROM crm_page ORDER BY id ASC"); err != nil { + if err := r.db().Select(&pages, "SELECT * FROM crm_page where self_id=? ORDER BY weight ASC", selfID); err != nil { return pages, err } for _, page := range pages { @@ -69,15 +71,50 @@ func (r *page) Find() ([]*types.Page, error) { return pages, nil } -func (r *page) Create(page *types.Page) (*types.Page, error) { +func (r *page) Reorder(selfID uint64, pageIDs []uint64) error { + pageMap := map[uint64]bool{} + if pages, err := r.Find(selfID); err != nil { + return nil + } else { + for _, page := range pages { + pageMap[page.ID] = true + } + } + weight := 1 + db := r.db() + // honor parameter first + for _, pageID := range pageIDs { + if pageMap[pageID] { + pageMap[pageID] = false + if _, err := db.Exec("UPDATE crm_page set weight=? where id=? and self_id=?", weight, pageID, selfID); err != nil { + return err + } + weight++ + } + } + for pageID, update := range pageMap { + if update { + if _, err := db.Exec("UPDATE crm_page set weight=? where id=? and self_id=?", weight, pageID, selfID); err != nil { + return err + } + weight++ + } + } + return nil +} + +func (r *page) Create(item *types.Page) (*types.Page, error) { + page := &types.Page{} + *page = *item + page.ID = factory.Sonyflake.NextID() if page.ModuleID > 0 { - check, err := r.FindByModuleID(page.ModuleID) - if err != nil { + if check, err := r.FindByModuleID(page.ModuleID); err != nil { return nil, err - } - if check.ID > 0 { - return nil, errors.New("Page for module already exists") + } else { + if check.ID > 0 { + return nil, errors.New("Page for module already exists") + } } } return page, r.db().Insert("crm_page", page) diff --git a/crm/repository/page_test.go b/crm/repository/page_test.go index 4d17a96af..941a50ece 100644 --- a/crm/repository/page_test.go +++ b/crm/repository/page_test.go @@ -2,8 +2,12 @@ package repository import ( "context" - "github.com/crusttech/crust/crm/types" "testing" + + "github.com/davecgh/go-spew/spew" + "github.com/pkg/errors" + + "github.com/crusttech/crust/crm/types" ) func TestPage(t *testing.T) { @@ -24,12 +28,29 @@ func TestPage(t *testing.T) { assert(t, err == nil, "Error when creating page: %+v", err) assert(t, m.ID > 0, "Expected auto generated ID") + page.SelfID = m.ID + + { + _, err := repository.Create(page) + assert(t, err != nil, "%+v", errors.Errorf("Expected error when creating duplicate moduleID page")) + } + + { + page.ModuleID = 0 + _, err := repository.Create(page) + assert(t, err == nil, "Unexpected error when creating page, %+v", err) + } + { + _, err := repository.Create(page) + assert(t, err == nil, "Unexpected error when creating page, %+v", err) + } + // fetch created page { ms, err := repository.FindByID(m.ID) assert(t, err == nil, "Error when retrieving page by id: %+v", err) - assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID) - assert(t, ms.Title == m.Title, "Expected Title from database to match, %s != %s", m.Title, ms.Title) + assert(t, ms.ID == m.ID, "Expected ID from database to match, %+v", errors.Errorf("%d != %d", m.ID, ms.ID)) + assert(t, ms.Title == m.Title, "Expected Title from database to match, %+v", errors.Errorf("%s != %s", m.Title, ms.Title)) } // update created page @@ -43,7 +64,7 @@ func TestPage(t *testing.T) { { ms, err := repository.FindByID(m.ID) assert(t, err == nil, "Error when retrieving page by id: %+v", err) - assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID) + assert(t, ms.ID == m.ID, "re-fetch: Expected ID from database to match, %d != %d", m.ID, ms.ID) assert(t, ms.Title == m.Title, "Expected Title from database to match, %s != %s", m.Title, ms.Title) } @@ -51,18 +72,39 @@ func TestPage(t *testing.T) { { ms, err := repository.FindByModuleID(m.ModuleID) assert(t, err == nil, "Error when retrieving page by id: %+v", err) - assert(t, ms.ID == m.ID, "Expected ID from database to match, %d != %d", m.ID, ms.ID) + assert(t, ms.ID == m.ID, "fetch-module: Expected ID from database to match, %d != %d", m.ID, ms.ID) assert(t, ms.Title == m.Title, "Expected Title from database to match, %s != %s", m.Title, ms.Title) } // fetch all pages { - ms, err := repository.Find() + ms, err := repository.Find(0) assert(t, err == nil, "Error when retrieving pages: %+v", err) assert(t, len(ms) >= 1, "Expected at least one page, got %d", len(ms)) prevPageCount = len(ms) } + // fetch all pages + { + ms, err := repository.Find(m.ID) + assert(t, err == nil, "Error when retrieving pages: %+v", err) + assert(t, len(ms) == 2, "Expected two pages with selfID=%d, got %v", m.ID, spew.Sdump(ms)) + prevPageCount = len(ms) + + parent := m.ID + ids := []uint64{ms[0].ID, ms[1].ID} + + { + err := repository.Reorder(parent, ids) + assert(t, err == nil, "Error when reordering pages: %+v", err) + + ms, err = repository.Find(m.ID) + assert(t, err == nil, "Error when retrieving pages: %+v", err) + assert(t, len(ms) == 2, "Expected two pages with selfID=%d, got %v", m.ID, spew.Sdump(ms)) + assert(t, ms[0].Weight < ms[1].Weight, "Expected ascending order, %+v", errors.Errorf("%d < %d", ms[0].Weight, ms[1].Weight)) + } + } + // re-fetch page { err := repository.DeleteByID(m.ID) @@ -71,7 +113,7 @@ func TestPage(t *testing.T) { // fetch all pages { - ms, err := repository.Find() + ms, err := repository.Find(0) assert(t, err == nil, "Error when retrieving pages: %+v", err) assert(t, len(ms) < prevPageCount, "Expected pages count to decrease after deletion, %d < %d", len(ms), prevPageCount) } diff --git a/crm/rest/page.go b/crm/rest/page.go index e5628f47f..ee56a3024 100644 --- a/crm/rest/page.go +++ b/crm/rest/page.go @@ -21,7 +21,7 @@ func (Page) New(pageSvc service.PageService) *Page { } func (ctrl *Page) List(ctx context.Context, r *request.PageList) (interface{}, error) { - return ctrl.page.With(ctx).Find() + return ctrl.page.With(ctx).Find(r.SelfID) } func (ctrl *Page) Create(ctx context.Context, r *request.PageCreate) (interface{}, error) { @@ -40,6 +40,10 @@ func (ctrl *Page) Read(ctx context.Context, r *request.PageRead) (interface{}, e return ctrl.page.With(ctx).FindByID(r.ID) } +func (ctrl *Page) Reorder(ctx context.Context, r *request.PageReorder) (interface{}, error) { + return resputil.OK(), ctrl.page.With(ctx).Reorder(r.SelfID, r.PageIDs) +} + func (ctrl *Page) Edit(ctx context.Context, r *request.PageEdit) (interface{}, error) { p := &types.Page{ ID: r.ID, diff --git a/crm/rest/request/page.go b/crm/rest/request/page.go index f3f9ce57d..f4a1f3302 100644 --- a/crm/rest/request/page.go +++ b/crm/rest/request/page.go @@ -32,6 +32,7 @@ var _ = multipart.FileHeader{} // Page list request parameters type PageList struct { + SelfID uint64 `json:",string"` } func NewPageList() *PageList { @@ -65,6 +66,11 @@ func (p *PageList) Fill(r *http.Request) (err error) { post[name] = string(param[0]) } + if val, ok := get["selfID"]; ok { + + p.SelfID = parseUInt64(val) + } + return err } diff --git a/crm/service/page.go b/crm/service/page.go index 3a346aacb..19ed222a8 100644 --- a/crm/service/page.go +++ b/crm/service/page.go @@ -20,11 +20,13 @@ type ( With(ctx context.Context) PageService FindByID(pageID uint64) (*types.Page, error) - Find() ([]*types.Page, error) + Find(selfID uint64) ([]*types.Page, error) Create(page *types.Page) (*types.Page, error) Update(page *types.Page) (*types.Page, error) DeleteByID(pageID uint64) error + + Reorder(selfID uint64, pageIDs []uint64) error } ) @@ -45,8 +47,12 @@ func (s *page) FindByID(id uint64) (*types.Page, error) { return s.repository.FindByID(id) } -func (s *page) Find() ([]*types.Page, error) { - return s.repository.Find() +func (s *page) Find(selfID uint64) ([]*types.Page, error) { + return s.repository.Find(selfID) +} + +func (s *page) Reorder(selfID uint64, pageIDs []uint64) error { + return s.repository.Reorder(selfID, pageIDs) } func (s *page) Create(mod *types.Page) (*types.Page, error) {