Skip to content
This repository has been archived by the owner on Feb 3, 2023. It is now read-only.

Commit

Permalink
add host node to tui
Browse files Browse the repository at this point in the history
  • Loading branch information
ingbyr committed Sep 6, 2022
1 parent d681a5d commit 4f3e3c2
Show file tree
Hide file tree
Showing 12 changed files with 369 additions and 19 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
.idea/
*.exe
gohost*

66 changes: 66 additions & 0 deletions gohost/group.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package gohost

import (
"errors"
"github.com/timshannon/bolthold"
)

var (
ErrGroupExist = errors.New("group is already existed")
)

type Group struct {
ID uint `boltholdKey:"ID"`
ParentID uint
Name string
Desc string
}

func (g Group) Title() string {
return g.Name
}
func (g Group) Description() string {
return g.Desc
}
func (g Group) FilterValue() string {
return g.Name
}

func (g Group) GetID() uint {
return g.ID
}

func (g Group) GetParentID() uint {
return g.ParentID
}

func (s *Service) loadGroups() []Group {
var groups []Group
if err := s.store.FindNullable(&groups, &bolthold.Query{}); err != nil {
panic(err)
}
return groups
}

func (s *Service) loadGroupNodes() []*Node[TreeNode] {
groups := s.loadGroups()

groupNodes := make([]*Node[TreeNode], 0, len(groups))
for _, group := range groups {
groupNodes = append(groupNodes, NewNode[TreeNode](group, 0))
}
return groupNodes
}

func (s *Service) SaveGroup(group Group) error {
if _, exist := s.nodes[group.ID]; exist {
return ErrGroupExist
}
err := s.store.Insert(group.ID, group)
if err != nil {
return err
}
// FIXME set correct depth
s.nodes[group.ID] = NewNode[TreeNode](&group, 0)
return nil
}
34 changes: 34 additions & 0 deletions gohost/group_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package gohost

import (
"github.com/stretchr/testify/assert"
"gohost/db"
"testing"
)

func TestGroupService_Save(t *testing.T) {
store := db.Instance()
defer store.Close()
a := assert.New(t)
service := GetService()
groups := []Group{
{ID: 1, ParentID: 0, Name: "g-1", Desc: "desc1"},
{ID: 11, ParentID: 1, Name: "g-1-1", Desc: "desc11"},
{ID: 111, ParentID: 11, Name: "g-1-1-1", Desc: "desc111"},
{ID: 112, ParentID: 11, Name: "g-1-1-2", Desc: "desc112"},
{ID: 12, ParentID: 1, Name: "g-1-2", Desc: "desc12"},
{ID: 13, ParentID: 1, Name: "g-1-3", Desc: "desc13"},
{ID: 131, ParentID: 13, Name: "g-1-3-1", Desc: "desc131"},
{ID: 132, ParentID: 13, Name: "g-1-3-2", Desc: "desc132"},
{ID: 2, ParentID: 0, Name: "g-2", Desc: "desc2"},
{ID: 3, ParentID: 0, Name: "g-3", Desc: "desc3"},
{ID: 31, ParentID: 3, Name: "g-3-1", Desc: "desc31"},
{ID: 32, ParentID: 3, Name: "g-3-2", Desc: "desc32"},
{ID: 4, ParentID: 0, Name: "g-4", Desc: "desc4"},
}
for _, g := range groups {
if err := service.SaveGroup(g); err != nil {
a.NoError(err)
}
}
}
49 changes: 49 additions & 0 deletions gohost/host.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package gohost

import (
"github.com/timshannon/bolthold"
"gohost/util"
)

type Host interface {
TreeNode
GetID() uint
GetName() string
GetContent() []byte
GetDesc() string
GetGroupID() uint
}

func (s *Service) SaveHost(host Host) error {
if err := s.store.Insert(host.GetDesc(), host); err != nil {
return err
}
return nil
}

func (s *Service) LoadHosts(groupID uint) []Host {
return s.loadLocalHosts(groupID)
}

func (s *Service) LoadHostNodes(groupID uint) []*Node[TreeNode] {
groupNode := s.nodes[groupID]
if groupNode == nil {
return nil
}
hostNodeDepth := groupNode.Depth + 1
hosts := s.LoadHosts(groupID)
hostNodes := make([]*Node[TreeNode], 0, len(hosts))
for _, host := range hosts {
node := NewNode[TreeNode](host, hostNodeDepth)
hostNodes = append(hostNodes, node)
}
return hostNodes
}

func (s *Service) loadLocalHosts(groupID uint) []Host {
var hosts []*LocalHost
if err := s.store.FindNullable(&hosts, bolthold.Where("GroupID").Eq(groupID)); err != nil {
panic(err)
}
return util.WrapSlice[Host](hosts)
}
33 changes: 33 additions & 0 deletions gohost/host_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package gohost

import (
"fmt"
"github.com/stretchr/testify/assert"
"testing"
)

func TestService_SaveHost(t *testing.T) {
a := assert.New(t)
hosts := []Host{
&LocalHost{
ID: 1000,
Name: "host-1000",
Content: []byte("127.0.0.1 localhost"),
Desc: "host1000",
GroupID: 3,
},
}

for _, host := range hosts {
if err := GetService().SaveHost(host); err != nil {
a.NoError(err)
}
}
}

func TestService_LoadHost(t *testing.T) {
hosts := GetService().loadLocalHosts(3)
for _, host := range hosts {
fmt.Println(host)
}
}
41 changes: 41 additions & 0 deletions gohost/local_host.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package gohost

type LocalHost struct {
ID uint
Name string
Content []byte
Desc string
GroupID uint
}

// Implement of Host

func (h *LocalHost) GetID() uint {
return h.ID
}

func (h *LocalHost) GetName() string {
return h.Name
}

func (h *LocalHost) GetContent() []byte {
return h.Content
}

func (h *LocalHost) GetDesc() string {
return h.Desc
}

func (h *LocalHost) GetGroupID() uint {
return h.GroupID
}

// Implement of TreeNode

func (h *LocalHost) FilterValue() string {
return h.Name
}

func (h *LocalHost) GetParentID() uint {
return h.GroupID
}
37 changes: 37 additions & 0 deletions gohost/node.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package gohost

import "github.com/charmbracelet/bubbles/list"

type TreeNode interface {
list.Item
GetID() uint
GetParentID() uint
}

type Node[T TreeNode] struct {
Data T
Children []*Node[T]
Depth int
IsFolded bool
}

func NewNode[T TreeNode](data T, depth int) *Node[T] {
return &Node[T]{
Data: data,
Children: make([]*Node[T], 0),
Depth: depth,
IsFolded: true,
}
}

func (n *Node[T]) FilterValue() string {
return n.Data.FilterValue()
}

func (n *Node[T]) GetID() uint {
return n.Data.GetID()
}

func (n *Node[T]) GetParentID() uint {
return n.Data.GetParentID()
}
4 changes: 4 additions & 0 deletions gohost/remote_host.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
package gohost

type RemoteHost struct {
}
84 changes: 84 additions & 0 deletions gohost/service.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package gohost

import (
"gohost/db"
"sort"
"sync"
)

var (
service *Service
serviceOnce sync.Once
)

func GetService() *Service {
serviceOnce.Do(func() {
service = NewService()
})
return service
}

func NewService() *Service {
return &Service{
store: db.Instance(),
nodes: make(map[uint]*Node[TreeNode], 0),
tree: make([]*Node[TreeNode], 0),
}
}

type Service struct {
store *db.Store
nodes map[uint]*Node[TreeNode]
tree []*Node[TreeNode]
}

func (s *Service) Tree() []*Node[TreeNode] {
return s.tree
}

func (s *Service) cacheNodes(nodes []*Node[TreeNode]) {
for _, node := range nodes {
s.nodes[node.GetID()] = node
}
}

func (s *Service) buildTree() {
// Build tree
for _, node := range s.nodes {
p, exist := s.nodes[node.Data.GetParentID()]
if !exist {
s.tree = append(s.tree, node)
continue
}
node.Depth = p.Depth + 1
p.Children = append(p.Children, node)
}
// Bfs to set depth
sort.Slice(s.tree, func(i, j int) bool {
return s.tree[i].Data.GetID() < s.tree[j].GetID()
})
nodes := s.tree
depth := 0
for len(nodes) > 0 {
for _, node := range nodes {
node.Depth = depth
sort.Slice(node.Children, func(i, j int) bool {
return node.Children[i].GetID() < node.Children[j].GetID()
})
nodes = append(nodes, node.Children...)
nodes = nodes[1:]
}
depth++
}
}

func (s *Service) Load() {
nodes := make([]*Node[TreeNode], 0)
nodes = append(nodes, s.loadGroupNodes()...)
s.cacheNodes(nodes)
s.buildTree()
}

func (s *Service) ChildNodes(nodeID uint) []*Node[TreeNode] {
return s.nodes[nodeID].Children
}
5 changes: 5 additions & 0 deletions gohost/sys_host.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package gohost

type SysHost struct {
HostsEnable map[int]struct{}
}

0 comments on commit 4f3e3c2

Please sign in to comment.