-
Notifications
You must be signed in to change notification settings - Fork 186
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Added Tags for Organizational Management #369
Added Tags for Organizational Management #369
Conversation
Codecov Report
@@ Coverage Diff @@
## master #369 +/- ##
==========================================
+ Coverage 81.38% 83.26% +1.88%
==========================================
Files 27 27
Lines 1606 1733 +127
==========================================
+ Hits 1307 1443 +136
+ Misses 222 210 -12
- Partials 77 80 +3
Continue to review full report at Codecov.
|
); | ||
} | ||
return this.flags; | ||
} | ||
}, | ||
methods: { | ||
tagFormatter(row, col, val) { | ||
return val.map(tag => tag.value).join(', '); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we'll work on getting this working 👍
v-model="newTag.value" | ||
ref="saveTagInput" | ||
size="mini" | ||
:trigger-on-focus="false" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think if we set trigger-on-focus to true, it helps to standardize tags creation and reduce typos
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhouzhuojie this was set to false because focus was triggering a save operation which we didn't want, requiring the saveTagInput method have to handle or ignore values that are empty but would still cancel your operation when tabbed away. This conflicts with entry process we're using with the save on enter and cancel.
}, | ||
loadAllTags() { | ||
Axios.get( | ||
`${API_URL}/tags` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I noticed that even when we delete the tag from across flags, it still shows up in the autocomplete.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is actually intended for the Flags delete, because it simply removes the reference to the Tag from the Flag and not the actual Tag itself because it could be referenced by another Flag. Let us know if there's another way you'd like to handle this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhouzhuojie, I was talking to @bradphilips and a couple of our other Flagr users, and we wondered if this would be a preferred way to handle this anyway. It would keep us from creating and deleting the same tag over and over if it goes in and out of use.
Brad also mentioned an option to search for any flags with the removed tag and fully delete the tag if there aren't any. I can see an argument for doing that to prevent unused tags from sticking around.
Personally, I like leaving them the way it's currently set up, but I don't think we'd argue if you want to fully delete the tags.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, lgtm
pkg/handler/eval_cache.go
Outdated
|
||
results := []*entity.Flag{} | ||
for _, t := range tags { | ||
s := util.SafeString(t) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
t is already a string type, so no need to cast to string here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perfect, we'll remove this 👍
pkg/handler/eval_cache.go
Outdated
} | ||
} | ||
|
||
return FlattenFlags(results) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can see that you are doing dedup here. Since flag id order doesn't matter, how about we define
tagCache: map[string]map[uint]*entity.Flag // i.e. tag => map[flagID]*entity.Flag
And when loop through the tags, we just need to get a union of the maps, and then return the values of that union map as a slice
pkg/handler/eval.go
Outdated
@@ -39,7 +39,8 @@ func (e *eval) PostEvaluation(params evaluation.PostEvaluationParams) middleware | |||
ErrorMessage("empty body")) | |||
} | |||
|
|||
evalResult := EvalFlag(*evalContext) | |||
flag := LookupFlag(*evalContext) | |||
evalResult := EvalFlagWithContext(flag, *evalContext) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
since the function EvalFlag is still there and flag
variable is not used below the line, I think you can keep evalResult := EvalFlag(*evalContext)
type Tag struct { | ||
gorm.Model | ||
|
||
Value string `sql:"type:varchar(64);unique_index:idx_tag_value"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thinking about the validation of Value
field, I think it's probably safer to start with stricter regex pattern, as the tag may grow with inconsistent naming pattern. e.g. eng_team_abc
vs Eng Team EFG
. A good starting point is util.IsSafeKey
.
In the future, we can decouple the validation of tags with loose restrictions if needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zhouzhuojie Makes perfect sense, could util.IsSafeKey
be re-used here or should we develop an alternate method with our own requirements?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Added validation for this in the last commit. I copied and modified the regex from the IsSafeKey
slightly to allow for spaces. Let me know if this is to your liking. Thanks!
…gic and removed SafeString
@zhouzhuojie Made some changes for items 1,4,5 and 6. Let us know what you'd like to do on the others. Thanks! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Left a few comments, and awesome work! Thanks for the contribution. I will take a look again soon.
}, | ||
loadAllTags() { | ||
Axios.get( | ||
`${API_URL}/tags` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks, lgtm
operationId: findAllTags | ||
parameters: | ||
- in: query | ||
name: limit |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, we may also want to add offset
to enable pagination
|
||
if err := getDB().Find(s).Association("Tags").Delete(t).Error; err != nil { | ||
return tag.NewDeleteTagDefault(500).WithPayload(ErrorMessage("%s", err)) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may also need entity.SaveFlagSnapshot()
to capture tag deletion in flag history.
}, | ||
}) | ||
|
||
// step 0. it should return 0 tags before creaetion |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you also add some tests for limit
and tags like
parameter?
pkg/handler/eval_cache.go
Outdated
return values(results) | ||
} | ||
|
||
func values(m map[uint]*entity.Flag) []*entity.Flag { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the function names values
and merge
are too generic inside the handler package, and these two functions are simple enough and I think it's better to just inline into the GetByTags function.
… values and merge methods.
Awesome, thank you @zhouzhuojie -- Fixed all the additional comments as well. Let us know if there's anything additional. |
@zhouzhuojie thanks so much for the merge. Do you have an idea of when this will get into a release? We're eager to deploy this in our infrastructure! Thanks! |
I see that it was just done. Thank you! :) |
Added Tags for Organizational Management
Developed in collaboration with @bradphilips and @nambup.
Description
Motivation and Context
Please see Issue #362
How Has This Been Tested?
Types of changes
Checklist: