-
Notifications
You must be signed in to change notification settings - Fork 8.5k
Close timepicker when a filter/interval is selected #9618
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
Close timepicker when a filter/interval is selected #9618
Conversation
cjcenizal
left a comment
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.
Just a couple suggestions from looking at the code. I haven't tested the functionality yet.
| template: toggleHtml, | ||
| replace: true, | ||
| link: ($scope) => { | ||
| require: '^kbnTopNav', |
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.
Do we need to require this? Can we add onFilterSelect and onIntervalSelect callbacks, and follow the same pattern as timerpicker.js? This would be a little more explicit, and less brittle.
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.
If you took at the corresponding HTML template, you'll see kbnTopNav written all over it. I agree that the way these all tie in together is brittle, but I think it's outside of the scope of this PR to disentangle this. At very least, this require call makes it more explicit that the directive relies on being nested inside the kbnTopNav directive.
| interval: '=', | ||
| activeTab: '=' | ||
| activeTab: '=', | ||
| onFilterSelect: '=', |
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.
The "Angular way" of doing this would be to refer to the callbacks as onFilterSelect: '&' and then in the markup pass in the callback like this: on-filter-select="updateFilter()".
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.
@cjcenizal I thought about this too, but then I couldn't actually think of any real disadvantages of the way Lukas is doing it here which is much simpler to understand. Do you know what gotchas there might be with the current implementation?
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.
It would not be possible to pass arguments like from and to if we used onFilterSelect: '&'. This looks good to React-trained eyes. 😉
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.
@weltenwort It doesn't look like the from and to arguments are being passed anyway? But to pass them, Angular wants you to do in this super intuitive way (sarcasm :)
on-filter=select="updateFilter(from, to)"onFilterSelect({ from, to });@Bargs I couldn't think of any disadvantages either because it was always just "the way to do things". So I did some digging and the only thing I could find are some vague references on StackOverflow about how the expression interpreted by & is executed in the parent scope, but when interpreted by = it's executed in the call site's scope. The actual Angular docs don't really make this clear.
So I make this pen as a test. Two directives, each one representing each approach. They each receive a callback and call it immediately, which logs out this. If you open up console you can see that this evaluates to the object in which the callback is defined when using & and the directive that calls the callback when using =.
So I think the only real advantage is that & will bind the callback to the right scope.
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.
Ah interesting, thanks for the details. All the more reason to avoid this!
|
|
|
When I looked at this before I didn't realize quite how twisted up the scopes are. The fact that What if we just updated |
|
@Bargs apologies in advance if my reply is borderline-nonsensical -- I'm technically on holiday right now so I can't dig into the code and give a well-informed suggestion. :) I think using an event here would side-step the complexity of the way all of these top nav directives are interacting, but it seems like a band-aid, since it doesn't actually reduce the complexity. On a tactical level, I think passing callbacks to directives is more explicit and clearer than using events, so I would reach for that by default. And then from there, maybe we could try to disentangle the top nav? This is somewhat touched upon in #9050 (comment). Again, sorry if this is not actually a helpful comment! |
|
Honestly I don't feel that strongly about it being an event or a callback. The point that I should have made more clearly is that I think we should avoid changing the way Instead of an event we could just pass |
Bargs
left a comment
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.
@lukasolson and I chatted over zoom about my previous comment. He pointed out that there was an issue with a race condition when trying to rely on the two way binding to update the from/to properties on timefilter. If I understand correctly, the auto close would destroy the timepicker directive before the two-way binding would have a chance to update the property on the parent scope.
So with that said, I'm good with the current implementation. I left one minor inline comment. Otherwise this looks good.
| $scope.applyAbsolute = function () { | ||
| $scope.from = moment($scope.absolute.from); | ||
| $scope.to = moment($scope.absolute.to); | ||
| $scope.onFilterSelect($scope.absolute.from, $scope.absolute.to); |
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.
It looks like the old code was cloning the absolute dates before setting them on from/to. I wonder if we should continue to clone them before passing to onFilterSelect? I checked the git logs but there's no hint why cloning my have been necessary. The current implementation seems to work fine, but I'd worry about introducing some subtle bug if we don't make this equivalent to the old code.
|
I'm on vacation until Monday, so I won't be able to review this again until then. If I'm blocking the merge, feel free to move forward without me. 😄 |
weltenwort
left a comment
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 I agree that untangling the kbnTopNav would inflate this PR too much, this LGTM.
cjcenizal
left a comment
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.
Functionality and code LGTM!
|
Changes look good but there appear to be a couple test failures |
|
@lukasolson Nice! Let's backport to 5.3? |
* Close timepicker when a filter/interval is selected * Copy absolute variables before sending * Use & instead of = for directive binding * Fix timepicker tests * Fix timepicker tests and remove tests that no longer apply
|
Backported to 5.x in 1baeae8. |
Replaces #9218.
Closes #9188.
Closes #5682.
This PR changes the behavior of the timepicker such that when you select a time filter or auto-refresh interval, the timepicker is automatically closed.