150 lines
4.0 KiB
Go
150 lines
4.0 KiB
Go
package menuService
|
|
|
|
import (
|
|
"sort"
|
|
|
|
"git.ma-al.com/goc_daniel/b2b/app/model"
|
|
"git.ma-al.com/goc_daniel/b2b/app/repos/categoriesRepo"
|
|
routesRepo "git.ma-al.com/goc_daniel/b2b/app/repos/routesRepo"
|
|
"git.ma-al.com/goc_daniel/b2b/app/utils/responseErrors"
|
|
)
|
|
|
|
type MenuService struct {
|
|
categoriesRepo categoriesRepo.UICategoriesRepo
|
|
routesRepo routesRepo.UIRoutesRepo
|
|
}
|
|
|
|
func New() *MenuService {
|
|
return &MenuService{
|
|
categoriesRepo: categoriesRepo.New(),
|
|
routesRepo: routesRepo.New(),
|
|
}
|
|
}
|
|
|
|
func (s *MenuService) GetCategoryTree(root_category_id uint, id_lang uint) (*model.Category, error) {
|
|
all_categories, err := s.categoriesRepo.GetAllCategories(id_lang)
|
|
if err != nil {
|
|
return &model.Category{}, err
|
|
}
|
|
|
|
// find the root
|
|
root_index := 0
|
|
root_found := false
|
|
for i := 0; i < len(all_categories); i++ {
|
|
if all_categories[i].CategoryID == root_category_id {
|
|
root_index = i
|
|
root_found = true
|
|
break
|
|
}
|
|
}
|
|
if !root_found {
|
|
return &model.Category{}, responseErrors.ErrNoRootFound
|
|
}
|
|
|
|
// now create the children and reorder them according to position
|
|
id_to_index := make(map[uint]int)
|
|
for i := 0; i < len(all_categories); i++ {
|
|
all_categories[i].Visited = false
|
|
id_to_index[all_categories[i].CategoryID] = i
|
|
}
|
|
|
|
children_indices := make(map[int][]ChildWithPosition)
|
|
for i := 0; i < len(all_categories); i++ {
|
|
parent_index := id_to_index[all_categories[i].ParentID]
|
|
children_indices[parent_index] = append(children_indices[parent_index], ChildWithPosition{Index: i, Position: all_categories[i].Position})
|
|
}
|
|
|
|
for key := range children_indices {
|
|
sort.Sort(ByPosition(children_indices[key]))
|
|
}
|
|
|
|
// finally, create the tree
|
|
tree, success := s.createTree(root_index, &all_categories, &children_indices)
|
|
if !success {
|
|
return &tree, responseErrors.ErrCircularDependency
|
|
}
|
|
|
|
return &tree, nil
|
|
}
|
|
|
|
func (s *MenuService) createTree(index int, all_categories *([]model.ScannedCategory), children_indices *(map[int][]ChildWithPosition)) (model.Category, bool) {
|
|
node := s.scannedToNormalCategory((*all_categories)[index])
|
|
|
|
if (*all_categories)[index].Visited {
|
|
return node, false
|
|
}
|
|
(*all_categories)[index].Visited = true
|
|
|
|
for i := 0; i < len((*children_indices)[index]); i++ {
|
|
next_child, success := s.createTree((*children_indices)[index][i].Index, all_categories, children_indices)
|
|
if !success {
|
|
return node, false
|
|
}
|
|
node.Children = append(node.Children, next_child)
|
|
}
|
|
|
|
(*all_categories)[index].Visited = false // just in case we have a "diamond" diagram
|
|
return node, true
|
|
}
|
|
|
|
func (s *MenuService) GetRoutes(id_lang uint) ([]model.Route, error) {
|
|
return s.routesRepo.GetRoutes(id_lang)
|
|
}
|
|
|
|
func (s *MenuService) scannedToNormalCategory(scanned model.ScannedCategory) model.Category {
|
|
var normal model.Category
|
|
// normal.Active = scanned.Active
|
|
normal.CategoryID = scanned.CategoryID
|
|
normal.Label = scanned.Name
|
|
// normal.Active = scanned.Active == 1
|
|
normal.Params = model.CategoryParams{CategoryID: normal.CategoryID, LinkRewrite: scanned.LinkRewrite, Locale: scanned.IsoCode}
|
|
normal.Children = []model.Category{}
|
|
return normal
|
|
}
|
|
|
|
type ChildWithPosition struct {
|
|
Index int
|
|
Position uint
|
|
}
|
|
type ByPosition []ChildWithPosition
|
|
|
|
func (a ByPosition) Len() int { return len(a) }
|
|
func (a ByPosition) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
|
|
func (a ByPosition) Less(i, j int) bool { return a[i].Position < a[j].Position }
|
|
|
|
func (s *MenuService) GetTopMenu(id uint) ([]*model.B2BTopMenu, error) {
|
|
items, err := s.routesRepo.GetTopMenu(id)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
menuMap := make(map[int]*model.B2BTopMenu, len(items))
|
|
roots := make([]*model.B2BTopMenu, 0)
|
|
|
|
for i := range items {
|
|
menu := &items[i]
|
|
menu.Children = make([]*model.B2BTopMenu, 0)
|
|
menuMap[menu.MenuID] = menu
|
|
}
|
|
|
|
for i := range items {
|
|
menu := &items[i]
|
|
|
|
if menu.ParentID == nil {
|
|
roots = append(roots, menu)
|
|
continue
|
|
}
|
|
|
|
parent, ok := menuMap[*menu.ParentID]
|
|
if !ok {
|
|
// fallback for orphaned nodes
|
|
roots = append(roots, menu)
|
|
continue
|
|
}
|
|
|
|
parent.Children = append(parent.Children, menu)
|
|
}
|
|
|
|
return roots, nil
|
|
}
|