add(crm): implement page reorder api, list pages by selfID
This commit is contained in:
@@ -48,6 +48,7 @@ CRM module pages
|
||||
|
||||
| Parameter | Type | Method | Description | Default | Required? |
|
||||
| --------- | ---- | ------ | ----------- | ------- | --------- |
|
||||
| selfID | uint64 | GET | Parent page ID | N/A | NO |
|
||||
|
||||
## Create page
|
||||
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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())
|
||||
|
||||
+46
-9
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
+5
-1
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
+9
-3
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user