You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
2.0 KiB
110 lines
2.0 KiB
package tag
|
|
|
|
import (
|
|
"git.aiterp.net/rpdata2-take2/rpdata2/auth"
|
|
"git.aiterp.net/rpdata2-take2/rpdata2/internal/genutils"
|
|
)
|
|
|
|
type Node struct {
|
|
Tag
|
|
|
|
Children []Node `json:"children"`
|
|
}
|
|
|
|
func (n Node) WithoutSecret(reqUser *auth.UserInfo) *Node {
|
|
return n.filter(func(n Node) bool {
|
|
if !n.Secret {
|
|
return false
|
|
}
|
|
|
|
return reqUser != nil && reqUser.HasIDOrPermission(n.OwnerID, "tag", "view_secret")
|
|
})
|
|
}
|
|
|
|
func (n Node) WithoutUnlisted() *Node {
|
|
return n.filter(func(n Node) bool { return n.Listed })
|
|
}
|
|
|
|
func (n Node) filter(cb func(n Node) bool) *Node {
|
|
if !cb(n) {
|
|
return nil
|
|
}
|
|
|
|
filtered := make([]Node, 0, len(n.Children))
|
|
for _, child := range n.Children {
|
|
pruned := child.filter(cb)
|
|
if pruned == nil {
|
|
continue
|
|
}
|
|
|
|
filtered = append(filtered, *pruned)
|
|
}
|
|
|
|
n.Children = filtered
|
|
return &n
|
|
}
|
|
|
|
func (n Node) Less(n2 Node) bool {
|
|
if n.Kind < n2.Kind {
|
|
return true
|
|
}
|
|
|
|
return n.Name < n2.Name
|
|
}
|
|
|
|
func BuildForest(tags []Tag) []Node {
|
|
nodes := make(map[string]*Node)
|
|
for _, tag := range tags {
|
|
nodes[tag.ID] = &Node{Tag: tag, Children: []Node{}}
|
|
}
|
|
|
|
children := make(map[string][]*Node, len(tags))
|
|
for _, node := range nodes {
|
|
if node.ParentID != nil {
|
|
children[*node.ParentID] = append(children[*node.ParentID], node)
|
|
}
|
|
}
|
|
|
|
cleared := make(map[string]bool)
|
|
for len(cleared) < len(nodes) {
|
|
anyCleared := false
|
|
for _, node := range nodes {
|
|
if cleared[node.ID] {
|
|
continue
|
|
}
|
|
|
|
good := true
|
|
for _, child := range children[node.ID] {
|
|
if !cleared[child.ID] {
|
|
good = false
|
|
break
|
|
}
|
|
}
|
|
|
|
if good {
|
|
genutils.SortSlice(node.Children)
|
|
|
|
cleared[node.ID] = true
|
|
anyCleared = true
|
|
if node.ParentID != nil {
|
|
nodes[*node.ParentID].Children = append(nodes[*node.ParentID].Children, *node)
|
|
}
|
|
}
|
|
}
|
|
|
|
if !anyCleared {
|
|
panic("deadlock in tag.BuildForest")
|
|
}
|
|
}
|
|
|
|
res := make([]Node, 0, 8)
|
|
for _, node := range nodes {
|
|
if node.ParentID == nil {
|
|
res = append(res, *node)
|
|
}
|
|
}
|
|
|
|
genutils.SortSlice(res)
|
|
|
|
return res
|
|
}
|