-
Notifications
You must be signed in to change notification settings - Fork 0
/
table.go
109 lines (91 loc) · 2.72 KB
/
table.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package twf
import (
"fmt"
"github.com/pkg/errors"
"github.com/tochk/twf/datastruct"
"reflect"
"strings"
)
// processParameters replaces {field} in value
func processParameters(value string, fields map[string]string) interface{} {
for k, v := range fields {
value = strings.Replace(value, "{"+k+"}", v, -1)
}
return value
}
// filterTableFields filters fields is TWF.NotShowOnTable flag is enabled
func filterTableFields(fields []datastruct.Field) []datastruct.Field {
res := make([]datastruct.Field, 0, len(fields))
for _, field := range fields {
if field.NotShowOnTable {
continue
}
res = append(res, field)
}
return res
}
// Table return table with contents of given slice
func (t *TWF) Table(title string, slice interface{}, fks ...interface{}) (string, error) {
if reflect.TypeOf(slice).Kind() != reflect.Slice {
return "", fmt.Errorf("twf.Table: expected slice, got %s", reflect.TypeOf(slice).Kind().String())
}
for i, fkSlice := range fks {
if reflect.TypeOf(fkSlice).Kind() != reflect.Slice {
return "", fmt.Errorf("twf.Table: error on fks idx %d expected slice, got %s", i, reflect.TypeOf(fkSlice).Kind().String())
}
}
item, err := getSliceElementPtrType(slice)
if err != nil {
return "", errors.Wrap(err, "twf.Table")
}
fields, err := getFieldDescription(item)
if err != nil {
return "", errors.Wrap(err, "twf.Table")
}
res := strings.Builder{}
res.WriteString(t.HeadFunc(title))
res.WriteString(t.MenuFunc())
content := strings.Builder{}
s := reflect.ValueOf(slice)
for i := 0; i < s.Len(); i++ {
itemsSlice, err := generateTableItemsSlice(s, fields, i, fks)
if err != nil {
return "", err
}
content.WriteString(t.ListItemFunc(itemsSlice))
}
fields = filterTableFields(fields)
res.WriteString(t.ListFunc(fields, content.String()))
res.WriteString(t.FooterFunc())
return res.String(), nil
}
func generateTableItemsSlice(s reflect.Value, fields []datastruct.Field, i int, fks []interface{}) ([]interface{}, error) {
itemsSlice := make([]interface{}, 0, s.Index(i).NumField())
data := map[string]string{}
for j := 0; j < s.Index(i).NumField(); j++ {
var value interface{}
if fields[j].ProcessParameters {
value = processParameters(fields[j].Value, data)
} else {
tmp := s.Index(i).Field(j)
value = getFieldValue(tmp)
}
var fkValue interface{}
fkValue, value, err := getFKValue(fields[j].FkInfo, value, fks)
if err != nil {
return nil, err
}
if fkValue != nil {
data[fields[j].Name] = fmt.Sprint(fkValue)
if !fields[j].NotShowOnTable {
itemsSlice = append(itemsSlice, fkValue)
}
continue
}
data[fields[j].Name] = fmt.Sprint(value)
if !fields[j].NotShowOnTable {
itemsSlice = append(itemsSlice, value)
}
}
return itemsSlice, nil
}