Skip to content

Commit

Permalink
Make stringValue required
Browse files Browse the repository at this point in the history
  • Loading branch information
jmattheis committed Dec 3, 2019
1 parent 0977de0 commit 9f323d0
Show file tree
Hide file tree
Showing 33 changed files with 114 additions and 203 deletions.
24 changes: 7 additions & 17 deletions hack/datagen/datagen.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,37 +40,31 @@ func main() {
log.Info().Msg("Creating Tags ...")

db.Create(&model.TagDefinition{
Type: model.TypeSingleValue,
Key: "type",
UserID: uID,
Color: "#fff",
})
db.Create(&model.TagDefinition{
Type: model.TypeSingleValue,
Key: "issue",
UserID: uID,
Color: "#fff",
})
db.Create(&model.TagDefinition{
Type: model.TypeSingleValue,
Key: "meeting",
UserID: uID,
Color: "#fff",
})
db.Create(&model.TagDefinition{
Type: model.TypeSingleValue,
Key: "with",
UserID: uID,
Color: "#fff",
})
db.Create(&model.TagDefinition{
Type: model.TypeSingleValue,
Key: "misc",
UserID: uID,
Color: "#fff",
})
db.Create(&model.TagDefinition{
Type: model.TypeSingleValue,
Key: "proj",
UserID: uID,
Color: "#fff",
Expand Down Expand Up @@ -164,9 +158,9 @@ func generateIssueType(proj, t string) []timeSpan {
for _, number := range numbers {
result = append(result, timeSpan{
Tags: []model.TimeSpanTag{
{Key: "proj", StringValue: &proj},
{Key: "type", StringValue: p(t)},
{Key: "issue", StringValue: p(fmt.Sprintf("%X-%d", proj, number))},
{Key: "proj", StringValue: proj},
{Key: "type", StringValue: t},
{Key: "issue", StringValue: fmt.Sprintf("%X-%d", proj, number)},
},
Runtime: gotime.Hour * 24 * 12,
})
Expand All @@ -181,8 +175,8 @@ func generateMeeting() []timeSpan {
for _, name := range names {
result = append(result, timeSpan{
Tags: []model.TimeSpanTag{
{Key: "type", StringValue: p("meeting")},
{Key: "meeting", StringValue: &name},
{Key: "type", StringValue: "meeting"},
{Key: "meeting", StringValue: name},
},
Runtime: gotime.Duration(-1),
})
Expand All @@ -197,8 +191,8 @@ func generateSupport() []timeSpan {
for _, name := range names {
result = append(result, timeSpan{
Tags: []model.TimeSpanTag{
{Key: "type", StringValue: p("support")},
{Key: "with", StringValue: &name},
{Key: "type", StringValue: "support"},
{Key: "with", StringValue: name},
},
Runtime: gotime.Duration(-1),
})
Expand Down Expand Up @@ -228,7 +222,3 @@ func noErr(err error) {
func randInt(min int, max int) int {
return min + rand.Intn(max-min)
}

func p(s string) *string {
return &s
}
11 changes: 0 additions & 11 deletions model/tagdefinition.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,5 @@ type TagDefinition struct {
Key string
UserID int `gorm:"type:int REFERENCES users(id) ON DELETE CASCADE"`
Color string
Type TagDefinitionType
Usages int `gorm:"-"`
}

// TagDefinitionType describes a tag type.
type TagDefinitionType string

const (
// TypeNoValue used for tags without values
TypeNoValue TagDefinitionType = "novalue"
// TypeSingleValue used for tags with one value
TypeSingleValue TagDefinitionType = "singlevalue"
)
2 changes: 1 addition & 1 deletion model/timespan.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,5 @@ type TimeSpan struct {
type TimeSpanTag struct {
TimeSpanID int `gorm:"type:int REFERENCES time_spans(id) ON DELETE CASCADE"`
Key string
StringValue *string
StringValue string
}
17 changes: 6 additions & 11 deletions schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ schema {
}

type RootMutation {
createTag(key: String!, color: String!, type: TagDefinitionType!): TagDefinition @hasRole(role: USER)
updateTag(key: String!, newKey: String, color: String!, type: TagDefinitionType!): TagDefinition @hasRole(role: USER)
createTag(key: String!, color: String!): TagDefinition @hasRole(role: USER)
updateTag(key: String!, newKey: String, color: String!): TagDefinition @hasRole(role: USER)
removeTag(key: String!): TagDefinition @hasRole(role: USER)

createUser(name: String!, pass: String!, admin: Boolean!): User @hasRole(role: ADMIN)
Expand Down Expand Up @@ -138,16 +138,10 @@ scalar Time
type TagDefinition {
color: String!
key: String!
type: TagDefinitionType!
user: User!
usages: Int!
}

enum TagDefinitionType {
novalue
singlevalue
}

type User {
admin: Boolean!
id: Int!
Expand All @@ -160,6 +154,7 @@ type TimeSpan {
end: Time
oldStart: Time
tags: [TimeSpanTag!]
# TODO not nullable ^
}

type PagedTimeSpans {
Expand All @@ -169,12 +164,12 @@ type PagedTimeSpans {

type TimeSpanTag {
key: String!
stringValue: String
value: String!
}

input InputTimeSpanTag {
key: String!
stringValue: String
value: String!
}

input StatInput {
Expand All @@ -190,7 +185,7 @@ input Range {

type StatisticsEntry {
key: String!
stringValue: String
value: String!
timeSpendInSeconds: Float!
}

Expand Down
28 changes: 10 additions & 18 deletions statistics/summary.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,18 +87,18 @@ func fillEmptyTags(statisticsEntries []*gqlmodel.RangedStatisticsEntries) {
lookup := make(map[string]struct{})
for _, entry := range statisticsEntries {
for _, statEntry := range entry.Entries {
lookup[key(statEntry.Key, statEntry.StringValue)] = struct{}{}
lookup[key(statEntry.Key, statEntry.Value)] = struct{}{}
}
}
for _, entry := range statisticsEntries {
existing := make(map[string]struct{}, len(lookup))
for _, statEntry := range entry.Entries {
existing[key(statEntry.Key, statEntry.StringValue)] = struct{}{}
existing[key(statEntry.Key, statEntry.Value)] = struct{}{}
}
for identifier := range lookup {
if _, ok := existing[identifier]; !ok {
key, value := extract(identifier)
entry.Entries = append(entry.Entries, &gqlmodel.StatisticsEntry{Key: key, StringValue: value, TimeSpendInSeconds: 0})
entry.Entries = append(entry.Entries, &gqlmodel.StatisticsEntry{Key: key, Value: value, TimeSpendInSeconds: 0})
}
}
}
Expand Down Expand Up @@ -129,7 +129,7 @@ type statReturn struct {
QueryStart string
QueryEnd string
Key string
StringValue *string
StringValue string
TimeSpendInSeconds float64
}

Expand All @@ -150,7 +150,7 @@ func group(entries []statReturn) ([]*gqlmodel.RangedStatisticsEntries, error) {
}
stats[id].Entries = append(stats[id].Entries, &gqlmodel.StatisticsEntry{
Key: entry.Key,
StringValue: entry.StringValue,
Value: entry.StringValue,
TimeSpendInSeconds: entry.TimeSpendInSeconds,
})
}
Expand All @@ -173,25 +173,17 @@ func build(tags []*gqlmodel.InputTimeSpanTag, noop string) (string, []interface{
var haveParams []interface{}
for _, tag := range tags {
have = append(have, "(tstx.key = ? AND tstx.string_value = ?)")
haveParams = append(haveParams, tag.Key, tag.StringValue)
haveParams = append(haveParams, tag.Key, tag.Value)
}

return strings.Join(have, " OR "), haveParams
}

func key(key string, value *string) string {
if value == nil {
return key
}
return fmt.Sprintf("%s:%s", key, *value)
func key(key string, value string) string {
return fmt.Sprintf("%s:%s", key, value)
}

func extract(id string) (string, *string) {
func extract(id string) (string, string) {
split := strings.Split(id, ":")
if len(split) == 1 {
return split[0], nil
}

value := split[1]
return split[0], &value
return split[0], split[1]
}
12 changes: 6 additions & 6 deletions statistics/summary_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -275,17 +275,17 @@ func (e *testEntry) Ranges(ranges ...*gqlmodel.Range) *testEntry {
func (e *testEntry) Include(includes ...model.TimeSpanTag) *testEntry {
for _, entry := range includes {
e.include = append(e.include, &gqlmodel.InputTimeSpanTag{
Key: entry.Key,
StringValue: entry.StringValue,
Key: entry.Key,
Value: entry.StringValue,
})
}
return e
}
func (e *testEntry) Exclude(excludes ...model.TimeSpanTag) *testEntry {
for _, entry := range excludes {
e.exclude = append(e.exclude, &gqlmodel.InputTimeSpanTag{
Key: entry.Key,
StringValue: entry.StringValue,
Key: entry.Key,
Value: entry.StringValue,
})
}
return e
Expand All @@ -294,7 +294,7 @@ func (e *testEntry) Exclude(excludes ...model.TimeSpanTag) *testEntry {
func tag(key string, value string) model.TimeSpanTag {
return model.TimeSpanTag{
Key: key,
StringValue: &value,
StringValue: value,
}
}

Expand All @@ -316,7 +316,7 @@ func result(start, stop string, entries ...*gqlmodel.StatisticsEntry) *gqlmodel.
func entry(key string, value string, duration time.Duration) *gqlmodel.StatisticsEntry {
return &gqlmodel.StatisticsEntry{
Key: key,
StringValue: &value,
Value: value,
TimeSpendInSeconds: duration.Seconds(),
}
}
3 changes: 1 addition & 2 deletions tag/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,11 @@ import (
)

// CreateTag creates a tag.
func (r *ResolverForTag) CreateTag(ctx context.Context, key string, color string, typeArg gqlmodel.TagDefinitionType) (*gqlmodel.TagDefinition, error) {
func (r *ResolverForTag) CreateTag(ctx context.Context, key string, color string) (*gqlmodel.TagDefinition, error) {
userID := auth.GetUser(ctx).ID
definition := &model.TagDefinition{
Key: strings.ToLower(key),
Color: color,
Type: model.TagDefinitionType(typeArg),
UserID: userID,
}

Expand Down
13 changes: 5 additions & 8 deletions tag/create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,17 @@ func TestGQL_CreateTag_succeeds_addsTag(t *testing.T) {
db.User(5)

resolver := ResolverForTag{DB: db.DB}
tag, err := resolver.CreateTag(fake.User(5), "new tag", "#fff", gqlmodel.TagDefinitionTypeSinglevalue)
tag, err := resolver.CreateTag(fake.User(5), "new tag", "#fff")

require.Nil(t, err)
expected := &gqlmodel.TagDefinition{
Key: "new tag",
Color: "#fff",
Type: gqlmodel.TagDefinitionTypeSinglevalue,
}
require.Equal(t, expected, tag)
assertTagExist(t, db, model.TagDefinition{
Key: "new tag",
Color: "#fff",
Type: model.TypeSingleValue,
UserID: 5,
})
assertTagCount(t, db, 1)
Expand All @@ -39,10 +37,10 @@ func TestGQL_CreateTag_fails_tagAlreadyExists(t *testing.T) {
db := test.InMemoryDB(t)
defer db.Close()
db.User(5)
db.Create(&model.TagDefinition{Key: "existing tag", Color: "#fff", Type: model.TypeSingleValue, UserID: 5})
db.Create(&model.TagDefinition{Key: "existing tag", Color: "#fff", UserID: 5})

resolver := ResolverForTag{DB: db.DB}
_, err := resolver.CreateTag(fake.User(5), "existing tag", "#fff", gqlmodel.TagDefinitionTypeSinglevalue)
_, err := resolver.CreateTag(fake.User(5), "existing tag", "#fff")

require.EqualError(t, err, "tag with key 'existing tag' does already exist")
assertTagCount(t, db, 1)
Expand All @@ -53,17 +51,16 @@ func TestGQL_CreateTag_succeeds_existingTagForOtherUser(t *testing.T) {
defer db.Close()
db.User(4)
db.User(5)
db.Create(&model.TagDefinition{Key: "existing tag", Color: "#fff", Type: model.TypeSingleValue, UserID: 4})
db.Create(&model.TagDefinition{Key: "existing tag", Color: "#fff", UserID: 4})

resolver := ResolverForTag{DB: db.DB}
_, err := resolver.CreateTag(fake.User(5), "existing tag", "#xxx", gqlmodel.TagDefinitionTypeSinglevalue)
_, err := resolver.CreateTag(fake.User(5), "existing tag", "#xxx")

assert.Nil(t, err)
assertTagCount(t, db, 2)
assertTagExist(t, db, model.TagDefinition{
Key: "existing tag",
Color: "#xxx",
Type: model.TypeSingleValue,
UserID: 5,
})
}
4 changes: 2 additions & 2 deletions tag/get_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ func TestGQL_Tags(t *testing.T) {

require.Nil(t, err)
expected := []*gqlmodel.TagDefinition{
{Key: "my tag", Type: gqlmodel.TagDefinitionTypeSinglevalue, Usages: 3},
{Key: "my tag 2", Type: gqlmodel.TagDefinitionTypeSinglevalue, Usages: 2},
{Key: "my tag", Usages: 3},
{Key: "my tag 2", Usages: 2},
}
require.Equal(t, expected, tags)
}
16 changes: 8 additions & 8 deletions tag/suggest_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,17 @@ func TestGQL_SuggestTag_matchesTags(t *testing.T) {
db.User(1)
db.User(2)
resolver := ResolverForTag{DB: db.DB}
db.Create(&model.TagDefinition{Key: "project", Color: "#fff", Type: model.TypeSingleValue, UserID: 1})
db.Create(&model.TagDefinition{Key: "project2", Color: "#fff", Type: model.TypeSingleValue, UserID: 2})
db.Create(&model.TagDefinition{Key: "priority", Color: "#fff", Type: model.TypeSingleValue, UserID: 1})
db.Create(&model.TagDefinition{Key: "wood", Color: "#fff", Type: model.TypeSingleValue, UserID: 1})
db.Create(&model.TagDefinition{Key: "project", Color: "#fff", UserID: 1})
db.Create(&model.TagDefinition{Key: "project2", Color: "#fff", UserID: 2})
db.Create(&model.TagDefinition{Key: "priority", Color: "#fff", UserID: 1})
db.Create(&model.TagDefinition{Key: "wood", Color: "#fff", UserID: 1})

tags, err := resolver.SuggestTag(fake.User(1), "pr")

require.Nil(t, err)
expected := []*gqlmodel.TagDefinition{
{Key: "project", Color: "#fff", Type: gqlmodel.TagDefinitionTypeSinglevalue},
{Key: "priority", Color: "#fff", Type: gqlmodel.TagDefinitionTypeSinglevalue},
{Key: "project", Color: "#fff"},
{Key: "priority", Color: "#fff"},
}
require.Equal(t, expected, tags)
}
Expand All @@ -36,8 +36,8 @@ func TestGQL_SuggestTag_noMatchingTags(t *testing.T) {
defer db.Close()
db.User(1)
resolver := ResolverForTag{DB: db.DB}
db.Create(&model.TagDefinition{Key: "project", Color: "#fff", Type: model.TypeSingleValue, UserID: 1})
db.Create(&model.TagDefinition{Key: "wood", Color: "#fff", Type: model.TypeSingleValue, UserID: 1})
db.Create(&model.TagDefinition{Key: "project", Color: "#fff", UserID: 1})
db.Create(&model.TagDefinition{Key: "wood", Color: "#fff", UserID: 1})

tags, err := resolver.SuggestTag(fake.User(1), "fire")

Expand Down
Loading

0 comments on commit 9f323d0

Please sign in to comment.