-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
UI Support for Store filtering #3166
Conversation
@bwplotka @prmsrswt Could you review this? |
Awesome work! I haven't had the time to review it fully yet, just a few nits the came to my mind
Thanks for the PR! |
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.
Overall amazing work! There are just a few nits from my side.
Also, it would be nice if you can add a few tests here and there so that we don't break this in the future.
One more thing; we can also add the storeMatches
parameter to the URI on the client-side as well. This way it'd be also persisted if we refresh the page etc. @squat @GiedriusS WDYT? @aribalam If you want to dabble into this, take a look at parseOption
and toQueryString
functions in src/uitls/index.ts
.
@@ -91,6 +96,7 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> { | |||
maxSourceResolution, | |||
useDeduplication, | |||
usePartialResponse, | |||
// TODO: Add support for Store Matches |
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'd nice to see this get done in this PR, but it's not a blocker :)
@prmsrswt Thanks for the review! will change all the mentioned points as soon as possible! :) |
@prmsrswt Using multi-select is the best way to go. However, reactstrap does not have any similar implementation of it. We could use any third party library for this, but the look-and-feel would be different from the general theme of the application. We could try to implement on our own using dropdowns, but that would be pretty much complex. |
Writing our own implementation for multiselect would be a waste of effort IMO. There are some pretty good libraries out there, just pick one that fits best for our use case and has a reasonably low footprint. |
@prmsrswt This is the UI that I have proposed to add. Please have a look. I am using a third-party library named |
This looks great, please go ahead. Thanks for your work. |
c252451
to
0f18fcf
Compare
@prmsrswt I have successfully integrated the store filter using the new UI.
I have also taken care of the above. However, I am not able to build the latest version of this using Could you take a look at this? |
You can try to build manually, try running The React tests are failing because you haven't updated the tests to expect the new query parameter you added ( |
a1d1a22
to
699171e
Compare
@prmsrswt The test cases are passing finally!. :) |
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.
Good work! Just a small nit, not a blocker though, can be done in a separate PR.
Edit: Found a bug that was crashing things, should be simple enough to fix.
}, | ||
}, | ||
]; | ||
const query = | ||
'?g0.expr=rate(node_cpu_seconds_total%7Bmode%3D%22system%22%7D%5B1m%5D)&g0.tab=0&g0.stacked=0&g0.range_input=1h&g0.max_source_resolution=raw&g0.deduplicate=1&g0.partial_response=0&g0.end_input=2019-10-25%2023%3A37%3A00&g0.moment_input=2019-10-25%2023%3A37%3A00&g1.expr=node_filesystem_avail_bytes&g1.tab=1&g1.stacked=0&g1.range_input=1h&g1.max_source_resolution=auto&g1.deduplicate=0&g1.partial_response=1'; | ||
'?g0.expr=rate(node_cpu_seconds_total%7Bmode%3D%22system%22%7D%5B1m%5D)&g0.tab=0&g0.stacked=0&g0.range_input=1h&g0.max_source_resolution=raw&g0.deduplicate=1&g0.partial_response=0&g0.store_matches=%5B%5D&g0.end_input=2019-10-25%2023%3A37%3A00&g0.moment_input=2019-10-25%2023%3A37%3A00&g1.expr=node_filesystem_avail_bytes&g1.tab=1&g1.stacked=0&g1.range_input=1h&g1.max_source_resolution=auto&g1.deduplicate=0&g1.partial_response=1&g1.store_matches=%5B%7B%22name%22%3A%22thanos_sidecar_one%3A10901%22%2C%22lastCheck%22%3A%222020-09-20T11%3A35%3A18.250713478Z%22%2C%22lastError%22%3Anull%2C%22labelSets%22%3A%5B%7B%22labels%22%3A%5B%7B%22name%22%3A%22monitor%22%2C%22value%22%3A%22prometheus_one%22%7D%5D%7D%5D%2C%22minTime%22%3A1600598100000%2C%22maxTime%22%3A9223372036854776000%7D%5D'; |
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 we should only store the name
of the store in the URI as the name is sufficient to identify a store uniquely.
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 too thought of passing only the store name, but the Select component that is being used takes in only objects as options. So passing a string array was not an option. I can create an interface with only store name as the key though. Would like your opinion on this.
@@ -255,8 +268,12 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> { | |||
this.setOptions({ usePartialResponse: event.target.checked }); | |||
}; | |||
|
|||
handleStoreMatchChange = (selectedStores: any): void => { | |||
this.setOptions({ storeMatches: selectedStores }); |
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.
Oh, I found a non-obvious bug here. If you add some stores to the filter and then remove all of them selectedStores
becomes null
instead of []
.
Modify this line to this.setOptions({ storeMatches: selectedStores || [] });
Also, just to be on the safer side, change line 152 to expect storeMatchers
as null
. Can be done easily using optional chaining; this.props.options.storeMatches?.forEach((store: Store) =>
(notice the ?
after storeMatches
).
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.
Fixed! That one line check using ?
was really cool! :)
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 forget to run make assets
though 😅 so the production build is still buggy.
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 for this. We definitely need something like this, just before we merge, wonder if we should make it less visible 🤔
Is there a quick way we can hide this option totally under some debug
button? It takes quite space and should be used very very rarely -> only for rare debug use cases.
@@ -138,6 +146,11 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> { | |||
partial_response: this.props.options.usePartialResponse.toString(), | |||
}); | |||
|
|||
// add storeMatches to query params |
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.
Comments should be full sentence? (: (capital letter, trailing period)
|
||
useEffect(() => { | ||
// convert stores data to a unified stores array |
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.
ditto
Thanks for helping BTW ❤️ |
@bwplotka I have added a debug checkbox beside the |
I guess this checkbox will do. Maybe name the checkbox |
This is perfect! Thanks 👍 Let's rebase and add @prmsrswt suggestion and LGTM ❤️ |
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
8eae99b
to
ba86337
Compare
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 guess the bindata.go
wasn't able to survive a rebase XD. I have a small nit, just implement it and run make assets
again, the CI should pass after this. Oh there are some lint errors too, can you also fix them?
@@ -296,6 +313,23 @@ class Panel extends Component<PanelProps & PathPrefixProps, PanelState> { | |||
</Checkbox> | |||
</Col> | |||
</Row> | |||
{stores.length > 0 ? (<Row> |
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.
Cases like this are called conditional rendering in React and it's better to use &&
instead of the ternary operator.
So instead of {condition ? <Component /> : ""}
we can just do {condition && <Component />}
Also, if stores
is null or undefined here, it'll cause and error too, you can do {stores?.length > 0 ....
to prevent this.
Signed-off-by: aribalam <[email protected]>
8a74f4d
to
2ed2f47
Compare
Signed-off-by: aribalam <[email protected]>
Signed-off-by: aribalam <[email protected]>
2ed2f47
to
02534b9
Compare
@prmsrswt All fixed. :) |
Great work! Thanks 🎉 |
🎉 |
Changes
Fixes #3096
Added support for Store filtering / Matching through the new React UI Interface.
The PR makes changes in the two files
PanelList.tsx
andPanel.tsx
. ThePanelList
component retrieves a list of stores from the API and passes it to thePanels
as props.The Panels creates checkboxes for each store that determines whether the store should be selected for querying. The query, on execution, creates appropriate URL Params for store selection (using the
storeMatch[]
parameter) and displays the result.Verification
Below is the screenshots of the new feature.
The query result when there is no store filtering
The query result when only the first store is selected
The query result multiple stores are selected
The query result when the third store is selected