Skip to content
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

Persist selected filters in checks results inside Redux #1445

Merged
merged 1 commit into from
May 29, 2023

Conversation

dottorblaster
Copy link
Contributor

@dottorblaster dottorblaster commented May 23, 2023

Saving applied filters into a redux slice so when the user comes back we just restore previously applied state

How was this tested?

Jest test added

@dottorblaster dottorblaster added the enhancement New feature or request label May 23, 2023
@dottorblaster dottorblaster self-assigned this May 23, 2023
@dottorblaster dottorblaster force-pushed the persist-checks-results-filters-redux branch from fe9e421 to ddde3a1 Compare May 24, 2023 10:28
@dottorblaster dottorblaster marked this pull request as ready for review May 24, 2023 13:19
Copy link
Member

@nelsonkopliku nelsonkopliku left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great job!

Just a couple of suggestions if they help.

Additionally, as we discussed, just noting that the filter in the query string gets wiped out when navigating among the pages.
However this does not impact the feature which works just fine. I am ok with the tradeoff if it's too much of a hassle re-applying the qs when we have saved filters and we navigate back to the executions results.

@@ -4,14 +4,25 @@ import Filter from '@components/Table/Filter';

export const RESULT_FILTER_FIELD = 'result';

function ChecksResultFilters({ onChange }) {
const getFilters = (savedFilters, searchParams) =>
savedFilters &&
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I am getting it right in the worst case savedFilters comes as an empty array, so this initial check might be not necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could come as undefined, updated it to have a default prop 👍

const getFilters = (savedFilters, searchParams) =>
savedFilters &&
savedFilters.length >= 0 &&
searchParams.getAll('health').length === 0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could extract this searchParams.getAll('health') outside of getFilters function.
I am aware it wouldn't change much 😅, so not a biggie. However if you want to give it a go here's the changes it would require.

function ChecksResultFilters() {
  //...
  const qsFilters = searchParams.getAll('health');

  useEffect(() => {
    const selectedFilters = getFilters(savedFilters, qsFilters);
    
    setFiltersForField({
        //...
    });
  }, [searchParams, savedFilters]);

  //...
  return (
    <div className="flex">
      <Filter
        //...
        value={getFilters(savedFilters, qsFilters)}
      />
    </div>
  );
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried and the component exploded in my face 😅

/>
);

expect(screen.getAllByText('test-cluster')).toHaveLength(2);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about squashing this test and the previous one in a it.each version with two scenarios?
One scenario that does not pass a savedFilters (or an empty one) but it provides the route with querystring, another scenario that does provide the savedFilters without querystring.

At the end the expectations are the same for the two tests 🤔

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it calls for too much refactor that you don't feel like addressing, keep it as it is.

Copy link
Contributor

@arbulu89 arbulu89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dottorblaster The code looks good.
I only commented the naming part (our beloved naming).
I think we could generalize this. We will have sooner than later checks that are not only cluster based, so what about making the state already generic?
The usage would be exactly the same, we just need to build the payload correctly, that's all.

@@ -0,0 +1,17 @@
import { createSlice } from '@reduxjs/toolkit';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would rename this file to checksResultsFilters. Surely we will want to use this for future visualizations, where we have hosts based results, but I expect the execution results view being the same, as data will be coming from wanda in the same way.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, you're right

name: 'clusterChecksResultsFilters',
initialState,
reducers: {
setClusterFilters: (state, { payload: { clusterID, filters } }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about making this generic setChecksResultsFilters.
Getting the { id: filters } payload. I'm just thinking for future uses where we don't only have checks for clusters.
All of our resouces (clusters, hosts, sap systesms) are identified by uuid, so there wouldn't be any collision.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right again :D

name: 'clusterChecksResultsFilters',
initialState,
reducers: {
setClusterFilters: (state, { payload: { clusterID, filters } }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know, the code is ultra simple, but what about adding a test?

@@ -101,9 +101,11 @@ function ExecutionResults({
executionData,
executionError,
clusterSelectedChecks = [],
savedFilters,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we maybe add an empty list as default?
To make things a bit more secure, and in fact it would even help to story book

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me check if nothing explodes, sure

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I managed to assign a default prop but I had to declare it outside the inline scope. Left a comment about that, hope it's ok

@dottorblaster dottorblaster force-pushed the persist-checks-results-filters-redux branch from 7c62a09 to 585ca15 Compare May 25, 2023 14:06
Copy link
Member

@EMaksy EMaksy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice, well done :D

Besides @nelsonkopliku suggestions nothing to add.

LGTM.

EMaksy

This comment was marked as duplicate.

@dottorblaster dottorblaster force-pushed the persist-checks-results-filters-redux branch 3 times, most recently from 528b971 to 8cc32fa Compare May 29, 2023 08:15
Copy link
Contributor

@arbulu89 arbulu89 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@dottorblaster It looks great!
I would simply change clusterID by resourceID/groupID to finish making it generic now that we changed the files/state names.
(Maybe run find all thing in the changes hehe, as clusterID is everywhere, specially on the tests)

@@ -0,0 +1,4 @@
export const getSelectedFilters =
(clusterID) =>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would change clusterID by groupID/resourceID once we started making it generic

name: 'checksResultsFilters',
initialState,
reducers: {
setSelectedFilters: (state, { payload: { clusterID, filters } }) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

clusterID by resourceID maybe?

onStartExecution={(clusterId, hosts, selectedChecks, navigate) =>
dispatch(executionRequested(clusterId, hosts, selectedChecks, navigate))
}
onSaveFilters={(filters) =>
dispatch(setSelectedFilters({ clusterID, filters }))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`setSelectedFilters({ resourceID: clusterID, filters })

@dottorblaster dottorblaster force-pushed the persist-checks-results-filters-redux branch from 1d09f71 to 9190c5f Compare May 29, 2023 13:58
Save filters in redux when filtering checks results
@dottorblaster dottorblaster force-pushed the persist-checks-results-filters-redux branch from 9190c5f to a43a4ff Compare May 29, 2023 14:28
@dottorblaster dottorblaster merged commit e9c5856 into main May 29, 2023
@dottorblaster dottorblaster deleted the persist-checks-results-filters-redux branch May 29, 2023 14:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Development

Successfully merging this pull request may close these issues.

4 participants