Add /page/tree, generated set types

This commit is contained in:
Denis Arh
2018-11-21 05:50:07 +01:00
parent 297533e03c
commit 02eebb5cfc
11 changed files with 266 additions and 11 deletions
+13
View File
@@ -265,6 +265,19 @@ CRM module pages
| --------- | ---- | ------ | ----------- | ------- | --------- |
| pageID | uint64 | PATH | Page ID | N/A | YES |
## Get page all pages, hierarchically
#### Method
| URI | Protocol | Method | Authentication |
| --- | -------- | ------ | -------------- |
| `/page/tree` | HTTP/S | GET | |
#### Request parameters
| Parameter | Type | Method | Description | Default | Required? |
| --------- | ---- | ------ | ----------- | ------- | --------- |
## Edit page
#### Method
+7
View File
@@ -141,6 +141,13 @@
]
}
},
{
"name": "tree",
"path": "/tree",
"method": "GET",
"title": "Get page all pages, hierarchically",
"parameters": {}
},
{
"name": "edit",
"method": "POST",
+7
View File
@@ -87,6 +87,13 @@
]
}
},
{
"Name": "tree",
"Method": "GET",
"Title": "Get page all pages, hierarchically",
"Path": "/tree",
"Parameters": {}
},
{
"Name": "edit",
"Method": "POST",
+3 -3
View File
@@ -19,7 +19,7 @@ type (
Chart(r *request.ModuleChart) (interface{}, error)
FindByID(id uint64) (*types.Module, error)
Find() ([]*types.Module, error)
Find() (types.ModuleSet, error)
Create(mod *types.Module) (*types.Module, error)
Update(mod *types.Module) (*types.Module, error)
DeleteByID(id uint64) error
@@ -56,8 +56,8 @@ func (r *module) FindByID(id uint64) (*types.Module, error) {
return mod, nil
}
func (r *module) Find() ([]*types.Module, error) {
mod := make([]*types.Module, 0)
func (r *module) Find() (types.ModuleSet, error) {
mod := types.ModuleSet{}
return mod, r.db().Select(&mod, "SELECT * FROM crm_module ORDER BY id ASC")
}
+11 -5
View File
@@ -13,9 +13,10 @@ type (
PageRepository interface {
With(ctx context.Context, db *factory.DB) PageRepository
Find(selfID uint64) ([]*types.Page, error)
FindByID(id uint64) (*types.Page, error)
FindByModuleID(id uint64) (*types.Page, error)
FindBySelfID(selfID uint64) (types.PageSet, error)
FindAll() (types.PageSet, error)
Create(mod *types.Page) (*types.Page, error)
Update(mod *types.Page) (*types.Page, error)
@@ -58,9 +59,9 @@ func (r *page) FindByModuleID(id uint64) (*types.Page, error) {
return page, nil
}
func (r *page) Find(selfID uint64) ([]*types.Page, error) {
pages := make([]*types.Page, 0)
if err := r.db().Select(&pages, "SELECT * FROM crm_page where self_id=? ORDER BY weight ASC", selfID); err != nil {
func (r *page) FindBySelfID(selfID uint64) (types.PageSet, error) {
pages := types.PageSet{}
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 {
@@ -71,9 +72,14 @@ func (r *page) Find(selfID uint64) ([]*types.Page, error) {
return pages, nil
}
func (r *page) FindAll() (types.PageSet, error) {
pages := types.PageSet{}
return pages, r.db().Select(&pages, "SELECT * FROM crm_page ORDER BY self_id, weight ASC")
}
func (r *page) Reorder(selfID uint64, pageIDs []uint64) error {
pageMap := map[uint64]bool{}
if pages, err := r.Find(selfID); err != nil {
if pages, err := r.FindBySelfID(selfID); err != nil {
return nil
} else {
for _, page := range pages {
+10
View File
@@ -30,6 +30,7 @@ type PageAPI interface {
List(context.Context, *request.PageList) (interface{}, error)
Create(context.Context, *request.PageCreate) (interface{}, error)
Read(context.Context, *request.PageRead) (interface{}, error)
Tree(context.Context, *request.PageTree) (interface{}, error)
Edit(context.Context, *request.PageEdit) (interface{}, error)
Reorder(context.Context, *request.PageReorder) (interface{}, error)
Delete(context.Context, *request.PageDelete) (interface{}, error)
@@ -40,6 +41,7 @@ type Page struct {
List func(http.ResponseWriter, *http.Request)
Create func(http.ResponseWriter, *http.Request)
Read func(http.ResponseWriter, *http.Request)
Tree func(http.ResponseWriter, *http.Request)
Edit func(http.ResponseWriter, *http.Request)
Reorder func(http.ResponseWriter, *http.Request)
Delete func(http.ResponseWriter, *http.Request)
@@ -68,6 +70,13 @@ func NewPage(ph PageAPI) *Page {
return ph.Read(r.Context(), params)
})
},
Tree: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewPageTree()
resputil.JSON(w, params.Fill(r), func() (interface{}, error) {
return ph.Tree(r.Context(), params)
})
},
Edit: func(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
params := request.NewPageEdit()
@@ -99,6 +108,7 @@ func (ph *Page) MountRoutes(r chi.Router, middlewares ...func(http.Handler) http
r.Get("/", ph.List)
r.Post("/", ph.Create)
r.Get("/{pageID}", ph.Read)
r.Get("/tree", ph.Tree)
r.Post("/{pageID}", ph.Edit)
r.Post("/{selfID}/reorder", ph.Reorder)
r.Delete("/{pageID}", ph.Delete)
+4
View File
@@ -25,6 +25,10 @@ func (ctrl *Page) List(ctx context.Context, r *request.PageList) (interface{}, e
return ctrl.page.With(ctx).Find(r.SelfID)
}
func (ctrl *Page) Tree(ctx context.Context, r *request.PageTree) (interface{}, error) {
return ctrl.page.With(ctx).Tree()
}
func (ctrl *Page) Create(ctx context.Context, r *request.PageCreate) (interface{}, error) {
p := &types.Page{
SelfID: r.SelfID,
+40
View File
@@ -192,6 +192,46 @@ func (p *PageRead) Fill(r *http.Request) (err error) {
var _ RequestFiller = NewPageRead()
// Page tree request parameters
type PageTree struct {
}
func NewPageTree() *PageTree {
return &PageTree{}
}
func (p *PageTree) Fill(r *http.Request) (err error) {
if strings.ToLower(r.Header.Get("content-type")) == "application/json" {
err = json.NewDecoder(r.Body).Decode(p)
switch {
case err == io.EOF:
err = nil
case err != nil:
return errors.Wrap(err, "error parsing http request body")
}
}
if err = r.ParseForm(); err != nil {
return err
}
get := map[string]string{}
post := map[string]string{}
urlQuery := r.URL.Query()
for name, param := range urlQuery {
get[name] = string(param[0])
}
postVars := r.Form
for name, param := range postVars {
post[name] = string(param[0])
}
return err
}
var _ RequestFiller = NewPageTree()
// Page edit request parameters
type PageEdit struct {
PageID uint64 `json:",string"`
+62 -3
View File
@@ -14,13 +14,15 @@ type (
db *factory.DB
ctx context.Context
repository repository.PageRepository
moduleRepo repository.ModuleRepository
}
PageService interface {
With(ctx context.Context) PageService
FindByID(pageID uint64) (*types.Page, error)
Find(selfID uint64) ([]*types.Page, error)
Find(selfID uint64) (pages types.PageSet, err error)
Tree() (pages types.PageSet, err error)
Create(page *types.Page) (*types.Page, error)
Update(page *types.Page) (*types.Page, error)
@@ -40,6 +42,7 @@ func (s *page) With(ctx context.Context) PageService {
db: db,
ctx: ctx,
repository: repository.Page(ctx, db),
moduleRepo: repository.Module(ctx, db),
}
}
@@ -47,8 +50,50 @@ func (s *page) FindByID(id uint64) (*types.Page, error) {
return s.repository.FindByID(id)
}
func (s *page) Find(selfID uint64) ([]*types.Page, error) {
return s.repository.Find(selfID)
func (s *page) Find(selfID uint64) (pages types.PageSet, err error) {
return pages, s.db.Transaction(func() (err error) {
if pages, err = s.repository.FindBySelfID(selfID); err != nil {
return
}
if err = s.preload(pages); err != nil {
return
}
return nil
})
}
func (s *page) Tree() (pages types.PageSet, err error) {
var tree types.PageSet
return tree, s.db.Transaction(func() (err error) {
if pages, err = s.repository.FindAll(); err != nil {
return
}
if err = s.preload(pages); err != nil {
return
}
_ = pages.Walk(func(p *types.Page) error {
if p.SelfID == 0 {
tree = append(tree, p)
} else if c := pages.FindByID(p.SelfID); c != nil {
if c.Children == nil {
c.Children = types.PageSet{}
}
c.Children = append(c.Children, p)
} else {
// Ignore orphans :(
}
return nil
})
return nil
})
}
func (s *page) Reorder(selfID uint64, pageIDs []uint64) error {
@@ -66,3 +111,17 @@ func (s *page) Update(mod *types.Page) (*types.Page, error) {
func (s *page) DeleteByID(id uint64) error {
return s.repository.DeleteByID(id)
}
// Preloads modules for all pages
func (s *page) preload(pages types.PageSet) error {
if modules, err := s.moduleRepo.Find(); err != nil {
return err
} else {
_ = pages.Walk(func(page *types.Page) error {
page.Module = modules.FindByID(page.ModuleID)
return nil
})
}
return nil
}
+105
View File
@@ -0,0 +1,105 @@
package types
type (
// ModuleSet slice of Module
ModuleSet []*Module
// PageSet slice of Page
PageSet []*Page
)
// Walk iterates through every slice item and calls w(Module) err
func (set ModuleSet) Walk(w func(*Module) error) (err error) {
for i := range set {
if err = w(set[i]); err != nil {
return
}
}
return
}
// Filter iterates through every slice item, calls f(Module) (bool, err) and return filtered slice
func (set ModuleSet) Filter(f func(*Module) (bool, error)) (out ModuleSet, err error) {
var ok bool
out = ModuleSet{}
for i := range set {
if ok, err = f(set[i]); err != nil {
return
} else if ok {
out = append(out, set[i])
}
}
return
}
// Finds slice item by its ID property
func (set ModuleSet) FindByID(ID uint64) *Module {
for i := range set {
if set[i].ID == ID {
return set[i]
}
}
return nil
}
// Returns a slice of uint64s from all items in the set
func (set ModuleSet) IDs() (IDs []uint64) {
IDs = make([]uint64, len(set))
for i := range set {
IDs[i] = set[i].ID
}
return
}
// Walk iterates through every slice item and calls w(Page) err
func (set PageSet) Walk(w func(*Page) error) (err error) {
for i := range set {
if err = w(set[i]); err != nil {
return
}
}
return
}
// Filter iterates through every slice item, calls f(Page) (bool, err) and return filtered slice
func (set PageSet) Filter(f func(*Page) (bool, error)) (out PageSet, err error) {
var ok bool
out = PageSet{}
for i := range set {
if ok, err = f(set[i]); err != nil {
return
} else if ok {
out = append(out, set[i])
}
}
return
}
// Finds slice item by its ID property
func (set PageSet) FindByID(ID uint64) *Page {
for i := range set {
if set[i].ID == ID {
return set[i]
}
}
return nil
}
// Returns a slice of uint64s from all items in the set
func (set PageSet) IDs() (IDs []uint64) {
IDs = make([]uint64, len(set))
for i := range set {
IDs[i] = set[i].ID
}
return
}
+4
View File
@@ -1,5 +1,7 @@
package types
//go:generate go run ../../codegen/v2/type-set.go Module Page type-sets.gen.go
import (
"time"
@@ -80,6 +82,8 @@ type (
Blocks types.JSONText `json:"blocks" db:"blocks"`
Children PageSet `json:"children,omitempty" db:"-"`
Visible bool `json:"visible" db:"visible"`
Weight int `json:"-" db:"weight"`
}