Skip to content

Commit 5455592

Browse files
authored
Merge pull request #1 from gochore/dev
update style; support map dataset
2 parents 1537c8e + 2876d3c commit 5455592

File tree

4 files changed

+83
-34
lines changed

4 files changed

+83
-34
lines changed

email.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ func (e *Email) Render(writer io.Writer) error {
2222
<title></title>
2323
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
2424
</head>
25-
<body style="margin: 0; padding: 0;">
25+
<body>
2626
`)
2727

2828
for _, element := range e.elements {

email_test.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,16 +26,16 @@ func TestEmail_Render(t *testing.T) {
2626
fields: fields{
2727
elements: []Element{
2828
Table{
29-
Dataset: []interface{}{
30-
TestStruct1{
29+
Dataset: []TestStruct1{
30+
{
3131
A: "a1",
3232
B: 1,
3333
},
34-
TestStruct1{
34+
{
3535
A: "a2",
3636
B: 2,
3737
},
38-
TestStruct1{
38+
{
3939
A: "a3",
4040
B: 3,
4141
},

table.go

Lines changed: 48 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,12 @@ import (
55
"html/template"
66
"io"
77
"reflect"
8+
"sort"
89
"strings"
910
)
1011

1112
type Table struct {
12-
Dataset []interface{}
13+
Dataset interface{}
1314
Columns []Column
1415
Attr Attributes
1516
HeaderAttr Attributes
@@ -24,7 +25,7 @@ func NewTable() Table {
2425
}
2526
}
2627

27-
func (t Table) WithDataset(dataset []interface{}) Table {
28+
func (t Table) WithDataset(dataset interface{}) Table {
2829
t.Dataset = dataset
2930
return t
3031
}
@@ -35,31 +36,58 @@ func (t Table) WithColumns(columns []Column) Table {
3536
}
3637

3738
func (t Table) Render(writer io.Writer) error {
38-
if len(t.Dataset) == 0 {
39+
dataset := reflect.ValueOf(t.Dataset)
40+
if dataset.Kind() != reflect.Slice {
41+
return fmt.Errorf("%v is not a slice", dataset.Type())
42+
}
43+
44+
if dataset.Len() == 0 {
3945
return fmt.Errorf("empty data")
4046
}
4147

42-
typ := reflect.TypeOf(t.Dataset[0])
43-
if typ.Kind() != reflect.Struct {
48+
mapItem := false
49+
typ := dataset.Index(0).Type()
50+
switch typ.Kind() {
51+
case reflect.Map:
52+
mapItem = true
53+
case reflect.Struct:
54+
// do nothing
55+
default:
56+
return fmt.Errorf("unsupported slice item type: %v", typ)
57+
}
58+
if typ.Kind() != reflect.Struct && typ.Kind() != reflect.Map {
4459
return fmt.Errorf("%v is not a struct", typ)
4560
}
4661

47-
for i, v := range t.Dataset {
48-
t := reflect.TypeOf(v)
49-
if t != typ {
62+
for i := 0; i < dataset.Len(); i++ {
63+
if t := dataset.Index(i).Type(); t != typ {
5064
return fmt.Errorf("item %v is %v, not %v", i, t, typ)
5165
}
5266
}
5367

5468
columns := t.Columns
5569
if len(columns) == 0 {
56-
numField := typ.NumField()
57-
for i := 0; i < numField; i++ {
58-
field := typ.Field(i)
59-
columns = append(columns, Column{
60-
Name: field.Name,
61-
Template: fmt.Sprintf("{{.%s}}", field.Name),
62-
})
70+
if mapItem {
71+
var keys []string
72+
for _, v := range dataset.Index(0).MapKeys() {
73+
keys = append(keys, fmt.Sprint(v.Interface()))
74+
}
75+
sort.Strings(keys)
76+
for _, key := range keys {
77+
columns = append(columns, Column{
78+
Name: key,
79+
Template: fmt.Sprintf("{{.%s}}", key),
80+
})
81+
}
82+
} else {
83+
numField := typ.NumField()
84+
for i := 0; i < numField; i++ {
85+
field := typ.Field(i)
86+
columns = append(columns, Column{
87+
Name: field.Name,
88+
Template: fmt.Sprintf("{{.%s}}", field.Name),
89+
})
90+
}
6391
}
6492
}
6593
var rowTemplate *template.Template
@@ -88,8 +116,8 @@ func (t Table) Render(writer io.Writer) error {
88116
}
89117
render.Println("</tr>")
90118

91-
for _, row := range t.Dataset {
92-
if err := rowTemplate.Execute(render, row); err != nil {
119+
for i := 0; i < dataset.Len(); i++ {
120+
if err := rowTemplate.Execute(render, dataset.Index(i)); err != nil {
93121
return fmt.Errorf("Execute: %w", err)
94122
}
95123
render.Println()
@@ -107,12 +135,12 @@ type Column struct {
107135

108136
var (
109137
DefaultTableAttr = Attributes{
110-
{Name: "style", Value: "font-family: verdana,arial,sans-serif;font-size:14px;color:#333333;border-width: 1px;border-color: #666666;border-collapse: collapse;"},
138+
{Name: "style", Value: "border:1px black solid; padding:3px 3px 3px 3px; border-collapse:collapse;"},
111139
}
112140
DefaultTableHeaderAttr = Attributes{
113-
{Name: "style", Value: "border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #dedede;"},
141+
{Name: "style", Value: "border:1px black solid; padding:3px 3px 3px 3px; border-collapse:collapse; background-color:#dedede;"},
114142
}
115143
DefaultTableDataAttr = Attributes{
116-
{Name: "style", Value: "border-width: 1px;padding: 8px;border-style: solid;border-color: #666666;background-color: #ffffff"},
144+
{Name: "style", Value: "border:1px black solid; padding:3px 3px 3px 3px; border-collapse:collapse;"},
117145
}
118146
)

table_test.go

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import (
1313

1414
func TestTable_Render(t1 *testing.T) {
1515
type fields struct {
16-
Dataset []interface{}
16+
Dataset interface{}
1717
Columns []Column
1818
}
1919
tests := []struct {
@@ -24,16 +24,16 @@ func TestTable_Render(t1 *testing.T) {
2424
{
2525
name: "regular",
2626
fields: fields{
27-
Dataset: []interface{}{
28-
TestStruct1{
27+
Dataset: []TestStruct1{
28+
{
2929
A: "a1",
3030
B: 1,
3131
},
32-
TestStruct1{
32+
{
3333
A: "a2",
3434
B: 2,
3535
},
36-
TestStruct1{
36+
{
3737
A: "a3",
3838
B: 3,
3939
},
@@ -45,16 +45,16 @@ func TestTable_Render(t1 *testing.T) {
4545
{
4646
name: "with_columns",
4747
fields: fields{
48-
Dataset: []interface{}{
49-
TestStruct1{
48+
Dataset: []TestStruct1{
49+
{
5050
A: "a1",
5151
B: 1,
5252
},
53-
TestStruct1{
53+
{
5454
A: "a2",
5555
B: 2,
5656
},
57-
TestStruct1{
57+
{
5858
A: "a3",
5959
B: 3,
6060
},
@@ -76,6 +76,27 @@ func TestTable_Render(t1 *testing.T) {
7676
},
7777
wantErr: false,
7878
},
79+
{
80+
name: "map_dataset",
81+
fields: fields{
82+
Dataset: []map[string]interface{}{
83+
{
84+
"A": "a1",
85+
"B": 1,
86+
},
87+
{
88+
"A": "a2",
89+
"B": 2,
90+
},
91+
{
92+
"A": "a3",
93+
"B": 3,
94+
},
95+
},
96+
Columns: nil,
97+
},
98+
wantErr: false,
99+
},
79100
}
80101
for _, tt := range tests {
81102
t1.Run(tt.name, func(t1 *testing.T) {

0 commit comments

Comments
 (0)