Skip to content

Commit dad642b

Browse files
committed
fix: combinde excluded and included tags, simplify tag checking
1 parent 09d830f commit dad642b

File tree

8 files changed

+61
-115
lines changed

8 files changed

+61
-115
lines changed

dashboard/convert/dashboardtag.go

Lines changed: 13 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,54 +5,31 @@ import (
55
"github.com/traggo/server/model"
66
)
77

8-
func excludedTagsToExternal(tags []model.DashboardExcludedTag) []*gqlmodel.TimeSpanTag {
8+
func tagFiltersToExternal(tags []model.DashboardTagFilter, include bool) []*gqlmodel.TimeSpanTag {
99
result := []*gqlmodel.TimeSpanTag{}
1010
for _, tag := range tags {
11-
result = append(result, &gqlmodel.TimeSpanTag{
12-
Key: tag.Key,
13-
Value: tag.StringValue,
14-
})
11+
if tag.Include == include {
12+
result = append(result, &gqlmodel.TimeSpanTag{
13+
Key: tag.Key,
14+
Value: tag.StringValue,
15+
})
16+
}
1517
}
1618
return result
1719
}
1820

19-
func ExcludedTagsToInternal(gqls []*gqlmodel.InputTimeSpanTag) []model.DashboardExcludedTag {
20-
result := make([]model.DashboardExcludedTag, 0)
21+
func TagFiltersToInternal(gqls []*gqlmodel.InputTimeSpanTag, include bool) []model.DashboardTagFilter {
22+
result := make([]model.DashboardTagFilter, 0)
2123
for _, tag := range gqls {
22-
result = append(result, excludedTagToInternal(*tag))
24+
result = append(result, tagFilterToInternal(*tag, include))
2325
}
2426
return result
2527
}
2628

27-
func excludedTagToInternal(gqls gqlmodel.InputTimeSpanTag) model.DashboardExcludedTag {
28-
return model.DashboardExcludedTag{
29-
Key: gqls.Key,
30-
StringValue: gqls.Value,
31-
}
32-
}
33-
34-
func includedTagsToExternal(tags []model.DashboardIncludedTag) []*gqlmodel.TimeSpanTag {
35-
result := []*gqlmodel.TimeSpanTag{}
36-
for _, tag := range tags {
37-
result = append(result, &gqlmodel.TimeSpanTag{
38-
Key: tag.Key,
39-
Value: tag.StringValue,
40-
})
41-
}
42-
return result
43-
}
44-
45-
func IncludedTagsToInternal(gqls []*gqlmodel.InputTimeSpanTag) []model.DashboardIncludedTag {
46-
result := make([]model.DashboardIncludedTag, 0)
47-
for _, tag := range gqls {
48-
result = append(result, includedTagToInternal(*tag))
49-
}
50-
return result
51-
}
52-
53-
func includedTagToInternal(gqls gqlmodel.InputTimeSpanTag) model.DashboardIncludedTag {
54-
return model.DashboardIncludedTag{
29+
func tagFilterToInternal(gqls gqlmodel.InputTimeSpanTag, include bool) model.DashboardTagFilter {
30+
return model.DashboardTagFilter{
5531
Key: gqls.Key,
5632
StringValue: gqls.Value,
33+
Include: include,
5734
}
5835
}

dashboard/convert/entry.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ func ToExternalEntry(entry model.DashboardEntry) (*gqlmodel.DashboardEntry, erro
4141
Interval: ExternalInterval(entry.Interval),
4242
Tags: strings.Split(entry.Keys, ","),
4343
Range: dateRange,
44-
ExcludeTags: excludedTagsToExternal(entry.ExcludedTags),
45-
IncludeTags: includedTagsToExternal(entry.IncludedTags),
44+
ExcludeTags: tagFiltersToExternal(entry.TagFilters, false),
45+
IncludeTags: tagFiltersToExternal(entry.TagFilters, true),
4646
}
4747
if entry.RangeID != model.NoRangeIDDefined {
4848
stats.RangeID = &entry.RangeID

dashboard/entry/add.go

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,11 @@ func (r *ResolverForEntry) AddDashboardEntry(ctx context.Context, dashboardID in
2424
return nil, err
2525
}
2626

27-
if tag := tagsDuplicates(stats.ExcludeTags, stats.IncludeTags); tag != nil {
28-
return nil, fmt.Errorf("tag '%s' is present in both exclude tags and include tags", tag.Key+":"+tag.Value)
29-
}
30-
31-
if err := tagsExist(r.DB, auth.GetUser(ctx).ID, stats.ExcludeTags); err != nil {
32-
return nil, fmt.Errorf("exclude tags: %s", err.Error())
33-
}
27+
tagFilters := convert.TagFiltersToInternal(stats.ExcludeTags, false)
28+
tagFilters = append(tagFilters, convert.TagFiltersToInternal(stats.IncludeTags, true)...)
3429

35-
if err := tagsExist(r.DB, auth.GetUser(ctx).ID, stats.IncludeTags); err != nil {
36-
return nil, fmt.Errorf("include tags: %s", err.Error())
30+
if err := tagsDuplicates(tagFilters); err != nil {
31+
return nil, err
3732
}
3833

3934
entry := model.DashboardEntry{
@@ -46,8 +41,7 @@ func (r *ResolverForEntry) AddDashboardEntry(ctx context.Context, dashboardID in
4641
MobilePosition: convert.EmptyPos(),
4742
DesktopPosition: convert.EmptyPos(),
4843
RangeID: -1,
49-
ExcludedTags: convert.ExcludedTagsToInternal(stats.ExcludeTags),
50-
IncludedTags: convert.IncludedTagsToInternal(stats.IncludeTags),
44+
TagFilters: tagFilters,
5145
}
5246

5347
if len(stats.Tags) == 0 {

dashboard/entry/tagcheck.go

Lines changed: 18 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,41 +3,31 @@ package entry
33
import (
44
"fmt"
55

6-
"github.com/jinzhu/gorm"
7-
"github.com/traggo/server/generated/gqlmodel"
86
"github.com/traggo/server/model"
97
)
108

11-
func tagsDuplicates(src []*gqlmodel.InputTimeSpanTag, dst []*gqlmodel.InputTimeSpanTag) *gqlmodel.InputTimeSpanTag {
12-
existingTags := make(map[string]struct{})
13-
for _, tag := range src {
14-
existingTags[tag.Key+":"+tag.Value] = struct{}{}
15-
}
16-
17-
for _, tag := range dst {
18-
if _, ok := existingTags[tag.Key+":"+tag.Value]; ok {
19-
return tag
20-
}
21-
22-
existingTags[tag.Key] = struct{}{}
23-
}
24-
25-
return nil
26-
}
27-
28-
func tagsExist(db *gorm.DB, userID int, tags []*gqlmodel.InputTimeSpanTag) error {
29-
existingTags := make(map[string]struct{})
9+
func tagsDuplicates(tags []model.DashboardTagFilter) error {
10+
existingTags := make(map[model.DashboardTagFilter]struct{})
3011

3112
for _, tag := range tags {
32-
if _, ok := existingTags[tag.Key]; ok {
33-
return fmt.Errorf("tag '%s' is present multiple times", tag.Key)
13+
if _, ok := existingTags[tag]; ok {
14+
tagType := "exclude"
15+
if tag.Include {
16+
tagType = "include"
17+
}
18+
19+
return fmt.Errorf("%s tags: tag '%s' is present multiple times", tagType, tag.Key+":"+tag.StringValue)
20+
} else {
21+
copyTag := tag
22+
copyTag.Include = !copyTag.Include
23+
24+
if _, ok := existingTags[copyTag]; ok {
25+
return fmt.Errorf("tag '%s' is present in both exclude tags and include tags", tag.Key+":"+tag.StringValue)
26+
}
3427
}
3528

36-
if db.Where("key = ?", tag.Key).Where("user_id = ?", userID).Find(new(model.TagDefinition)).RecordNotFound() {
37-
return fmt.Errorf("tag '%s' does not exist", tag.Key)
38-
}
39-
40-
existingTags[tag.Key] = struct{}{}
29+
existingTags[tag] = struct{}{}
4130
}
31+
4232
return nil
4333
}

dashboard/entry/update.go

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -54,24 +54,18 @@ func (r *ResolverForEntry) UpdateDashboardEntry(ctx context.Context, id int, ent
5454
entry.RangeTo = stats.Range.To
5555
}
5656

57-
if tag := tagsDuplicates(stats.ExcludeTags, stats.IncludeTags); tag != nil {
58-
return nil, fmt.Errorf("tag '%s' is present in both exclude tags and include tags", tag.Key+":"+tag.Value)
59-
}
60-
61-
r.DB.Where("dashboard_entry_id = ?", id).Delete(new(model.DashboardExcludedTag))
62-
r.DB.Where("dashboard_entry_id = ?", id).Delete(new(model.DashboardIncludedTag))
57+
tagFilters := convert.TagFiltersToInternal(stats.ExcludeTags, false)
58+
tagFilters = append(tagFilters, convert.TagFiltersToInternal(stats.IncludeTags, true)...)
6359

64-
if err := tagsExist(r.DB, auth.GetUser(ctx).ID, stats.ExcludeTags); err != nil {
65-
return nil, fmt.Errorf("exclude tags: %s", err.Error())
60+
if err := tagsDuplicates(tagFilters); err != nil {
61+
return nil, err
6662
}
6763

68-
if err := tagsExist(r.DB, auth.GetUser(ctx).ID, stats.IncludeTags); err != nil {
69-
return nil, fmt.Errorf("include tags: %s", err.Error())
64+
if err := r.DB.Where("dashboard_entry_id = ?", id).Delete(new(model.DashboardTagFilter)).Error; err != nil {
65+
return nil, fmt.Errorf("failed to update tag filters: %s", err)
7066
}
7167

72-
entry.ExcludedTags = convert.ExcludedTagsToInternal(stats.ExcludeTags)
73-
entry.IncludedTags = convert.IncludedTagsToInternal(stats.IncludeTags)
74-
68+
entry.TagFilters = tagFilters
7569
entry.Keys = strings.Join(stats.Tags, ",")
7670
entry.Interval = convert.InternalInterval(stats.Interval)
7771
}

dashboard/get.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,7 @@ func (r *ResolverForDashboard) Dashboards(ctx context.Context) ([]*gqlmodel.Dash
1818

1919
q := r.DB
2020
q = q.Preload("Entries")
21-
q = q.Preload("Entries.ExcludedTags")
22-
q = q.Preload("Entries.IncludedTags")
21+
q = q.Preload("Entries.TagFilters")
2322
q = q.Preload("Ranges")
2423

2524
find := q.Where(&model.Dashboard{UserID: userID}).Find(&dashboards)

model/all.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,7 @@ func All() []interface{} {
1111
new(UserSetting),
1212
new(Dashboard),
1313
new(DashboardEntry),
14-
new(DashboardExcludedTag),
15-
new(DashboardIncludedTag),
14+
new(DashboardTagFilter),
1615
new(DashboardRange),
1716
}
1817
}

model/dashboard.go

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -26,35 +26,28 @@ type Dashboard struct {
2626

2727
// DashboardEntry an entry which represents a diagram in a dashboard.
2828
type DashboardEntry struct {
29-
ID int `gorm:"primary_key;unique_index;AUTO_INCREMENT"`
30-
DashboardID int `gorm:"type:int REFERENCES dashboards(id) ON DELETE CASCADE"`
31-
Title string
32-
Total bool `gorm:"default:false"`
33-
Type DashboardType
34-
Keys string
35-
Interval Interval
36-
RangeID int
37-
RangeFrom string
38-
RangeTo string
39-
ExcludedTags []DashboardExcludedTag
40-
IncludedTags []DashboardIncludedTag
29+
ID int `gorm:"primary_key;unique_index;AUTO_INCREMENT"`
30+
DashboardID int `gorm:"type:int REFERENCES dashboards(id) ON DELETE CASCADE"`
31+
Title string
32+
Total bool `gorm:"default:false"`
33+
Type DashboardType
34+
Keys string
35+
Interval Interval
36+
RangeID int
37+
RangeFrom string
38+
RangeTo string
39+
TagFilters []DashboardTagFilter
4140

4241
MobilePosition string
4342
DesktopPosition string
4443
}
4544

46-
// DashboardExcludedTag a tag for filtering timespans
47-
type DashboardExcludedTag struct {
48-
DashboardEntryID int `gorm:"type:int REFERENCES dashboard_entries(id) ON DELETE CASCADE"`
49-
Key string
50-
StringValue string
51-
}
52-
53-
// DashboardIncludedTag a tag for filtering timespans
54-
type DashboardIncludedTag struct {
45+
// DashboardTagFilter a tag for filtering timespans
46+
type DashboardTagFilter struct {
5547
DashboardEntryID int `gorm:"type:int REFERENCES dashboard_entries(id) ON DELETE CASCADE"`
5648
Key string
5749
StringValue string
50+
Include bool
5851
}
5952

6053
// DashboardType the dashboard type

0 commit comments

Comments
 (0)