Skip to content

Commit

Permalink
fix: location.query
Browse files Browse the repository at this point in the history
  • Loading branch information
daniele-mng committed Sep 13, 2024
1 parent ec0f668 commit f13c241
Show file tree
Hide file tree
Showing 10 changed files with 187 additions and 172 deletions.
15 changes: 8 additions & 7 deletions src/web/entities/container.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -320,17 +320,18 @@ class EntitiesContainer extends React.Component {
this.changeFilter(RESET_FILTER);
}

handleFilterReset() {
const {navigate, location} = this.props;
const query = {...location.query};
handleFilterReset = () => {
const {navigate, location, searchParams} = this.props;

// remove filter param from url
delete query.filter;
searchParams.delete('filter');

navigate({pathname: location.pathname, query});
navigate({
pathname: location.pathname,
search: searchParams.toString(),
});

this.changeFilter();
}
};

openTagDialog() {
this.setState({tagDialogVisible: true});
Expand Down
175 changes: 87 additions & 88 deletions src/web/entities/withEntitiesContainer.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import React from 'react';

import {useLocation} from 'react-router-dom';
import {useSearchParams} from 'react-router-dom';

import {connect} from 'react-redux';

Expand All @@ -27,99 +27,98 @@ import EntitiesContainer from './container';

const noop = () => {};

const withEntitiesContainer = (
gmpname,
{
entitiesSelector,
loadEntities: loadEntitiesFunc,
reloadInterval = noop,
fallbackFilter,
},
) => Component => {
let EntitiesContainerWrapper = ({
children,
filter,
loadEntities,
notify,
...props
}) => (
<Reload
reloadInterval={() => reloadInterval(props)}
reload={(newFilter = filter) => loadEntities(newFilter)}
name={gmpname}
>
{({reload}) => (
<EntitiesContainer
{...props}
filter={filter}
notify={notify}
gmpname={gmpname}
reload={reload}
>
{pageProps => <Component {...pageProps} />}
</EntitiesContainer>
)}
</Reload>
);

EntitiesContainerWrapper.propTypes = {
filter: PropTypes.filter,
loadEntities: PropTypes.func.isRequired,
notify: PropTypes.func.isRequired,
};

const mapStateToProps = (state, {filter}) => {
const eSelector = entitiesSelector(state);
const entities = eSelector.getEntities(filter);
return {
entities,
entitiesCounts: eSelector.getEntitiesCounts(filter),
entitiesError: eSelector.getEntitiesError(filter),
const withEntitiesContainer =
(
gmpname,
{
entitiesSelector,
loadEntities: loadEntitiesFunc,
reloadInterval = noop,
fallbackFilter,
},
) =>
Component => {
let EntitiesContainerWrapper = ({
children,
filter,
isLoading: eSelector.isLoadingEntities(filter),
loadedFilter: eSelector.getLoadedFilter(filter),
};
};

const mapDispatchToProps = (dispatch, {gmp}) => ({
loadEntities: filter => dispatch(loadEntitiesFunc(gmp)(filter)),
updateFilter: filter => dispatch(pageFilter(gmpname, filter)),
onInteraction: () => dispatch(renewSessionTimeout(gmp)()),
});

EntitiesContainerWrapper = compose(
withDialogNotification,
withDownload,
withGmp,
connect(
mapStateToProps,
mapDispatchToProps,
),
)(EntitiesContainerWrapper);

return props => {
const location = useLocation();
return (
<SubscriptionProvider>
{({notify}) => (
<FilterProvider
fallbackFilter={fallbackFilter}
loadEntities,
notify,
...props
}) => (
<Reload
reloadInterval={() => reloadInterval(props)}
reload={(newFilter = filter) => loadEntities(newFilter)}
name={gmpname}
>
{({reload}) => (
<EntitiesContainer
{...props}
filter={filter}
notify={notify}
gmpname={gmpname}
locationQuery={location.query}
reload={reload}
>
{({filter}) => (
<EntitiesContainerWrapper
{...props}
filter={filter}
notify={notify}
/>
)}
</FilterProvider>
{pageProps => <Component {...pageProps} />}
</EntitiesContainer>
)}
</SubscriptionProvider>
</Reload>
);

EntitiesContainerWrapper.propTypes = {
filter: PropTypes.filter,
loadEntities: PropTypes.func.isRequired,
notify: PropTypes.func.isRequired,
};

const mapStateToProps = (state, {filter}) => {
const eSelector = entitiesSelector(state);
const entities = eSelector.getEntities(filter);
return {
entities,
entitiesCounts: eSelector.getEntitiesCounts(filter),
entitiesError: eSelector.getEntitiesError(filter),
filter,
isLoading: eSelector.isLoadingEntities(filter),
loadedFilter: eSelector.getLoadedFilter(filter),
};
};

const mapDispatchToProps = (dispatch, {gmp}) => ({
loadEntities: filter => dispatch(loadEntitiesFunc(gmp)(filter)),
updateFilter: filter => dispatch(pageFilter(gmpname, filter)),
onInteraction: () => dispatch(renewSessionTimeout(gmp)()),
});

EntitiesContainerWrapper = compose(
withDialogNotification,
withDownload,
withGmp,
connect(mapStateToProps, mapDispatchToProps),
)(EntitiesContainerWrapper);

return props => {
const [searchParams] = useSearchParams();
return (
<SubscriptionProvider>
{({notify}) => (
<FilterProvider
fallbackFilter={fallbackFilter}
gmpname={gmpname}
locationQuery={searchParams.toString()}
>
{({filter}) => (
<EntitiesContainerWrapper
{...props}
filter={filter}
notify={notify}
/>
)}
</FilterProvider>
)}
</SubscriptionProvider>
);
};
};
};

export default withEntitiesContainer;

Expand Down
19 changes: 9 additions & 10 deletions src/web/hooks/usePageFilter.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import {useCallback, useEffect, useState} from 'react';

import {useLocation, useNavigate} from 'react-router-dom';
import {useSearchParams, useNavigate} from 'react-router-dom';

import {useDispatch} from 'react-redux';

Expand Down Expand Up @@ -52,6 +52,7 @@ const useDefaultFilter = pageName =>
* still loading, function to change the filter, function to remove the
* filter and function to reset the filter
*/

const usePageFilter = (
pageName,
gmpName,
Expand All @@ -62,7 +63,7 @@ const usePageFilter = (
) => {
const gmp = useGmp();
const dispatch = useDispatch();
const location = useLocation();
const [searchParams, setSearchParams] = useSearchParams();

Check failure on line 66 in src/web/hooks/usePageFilter.js

View workflow job for this annotation

GitHub Actions / Run tests (20)

src/web/hooks/__tests__/usePageFilter.jsx > usePageFilter tests > should prefer pageFilter over defaultSettingFilter

Error: useLocation() may be used only in the context of a <Router> component. ❯ Object.invariant [as UNSAFE_invariant] node_modules/@remix-run/router/history.ts:494:11 ❯ Object.useLocation node_modules/react-router/lib/hooks.tsx:105:3 ❯ Proxy.useSearchParams node_modules/react-router-dom/index.tsx:1481:18 ❯ Module.usePageFilter [as default] src/web/hooks/usePageFilter.js:66:43 ❯ src/web/hooks/__tests__/usePageFilter.jsx:85:39 ❯ TestComponent node_modules/@testing-library/react/dist/pure.js:309:27 ❯ renderWithHooks node_modules/react-dom/cjs/react-dom.development.js:15486:18 ❯ mountIndeterminateComponent node_modules/react-dom/cjs/react-dom.development.js:20103:13 ❯ beginWork node_modules/react-dom/cjs/react-dom.development.js:21626:16 ❯ beginWork$1 node_modules/react-dom/cjs/react-dom.development.js:27465:14
const navigate = useNavigate();
const [defaultSettingFilter, defaultSettingsFilterError] =
useDefaultFilter(gmpName);
Expand All @@ -80,9 +81,9 @@ const usePageFilter = (

// use null as value for not set at all
let returnedFilter;
// only use location directly if locationQueryFilterString is undefined
// only use searchParams directly if locationQueryFilterString is undefined
const locationQueryFilterString =
initialLocationQueryFilterString || location?.query?.filter;
initialLocationQueryFilterString || searchParams.get('filter');

const [locationQueryFilter, setLocationQueryFilter] = useState(
hasValue(locationQueryFilterString)
Expand Down Expand Up @@ -163,15 +164,13 @@ const usePageFilter = (
}, [changeFilter]);

const resetFilter = useCallback(() => {
const query = {...location.query};

// remove filter param from url
delete query.filter;
const query = new URLSearchParams(searchParams);
query.delete('filter');

navigate({pathname: location.pathname, query});
setSearchParams(query);

changeFilter();
}, [changeFilter, navigate, location]);
}, [changeFilter, setSearchParams, searchParams]);

return [
returnedFilter,
Expand Down
30 changes: 22 additions & 8 deletions src/web/pages/extras/__tests__/cvsscalculatorpage.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/


import {describe, test, expect, testing} from '@gsa/testing';
import {describe, test, expect, testing, beforeEach} from '@gsa/testing';

import {fireEvent, rendererWith, waitFor, wait} from 'web/utils/testing';

Expand Down Expand Up @@ -37,10 +36,14 @@ const location = {
};

describe('CvssCalculator page tests', () => {
beforeEach(() => {
window.history.pushState({}, 'Test Title', '/');
});
test('Should render with default values', () => {
const {render} = rendererWith({
gmp,
store: true,
router: true,
});

const {element, getAllByTestId} = render(<CvssCalculator />);
Expand Down Expand Up @@ -75,14 +78,19 @@ describe('CvssCalculator page tests', () => {
});

test('Should render userVector from url', async () => {
window.history.pushState(
{},
'Test Title',
`?cvssVector=AV:N/AC:L/Au:N/C:P/I:P/A:P`,
);

const {render} = rendererWith({
gmp,
store: true,
router: true,
});

const {element, getAllByTestId} = render(
<CvssCalculator location={location} />,
);
const {element, getAllByTestId} = render(<CvssCalculator />);

await wait();

Expand Down Expand Up @@ -117,6 +125,7 @@ describe('CvssCalculator page tests', () => {
const {render} = rendererWith({
gmp,
store: true,
router: true,
});

const {element, getAllByTestId} = render(
Expand Down Expand Up @@ -164,14 +173,19 @@ describe('CvssCalculator page tests', () => {
});

test('Changing displayed select values should change userVector', async () => {
window.history.pushState(
{},
'Test Title',
`?cvssVector=AV:N/AC:L/Au:N/C:P/I:P/A:P`,
);

const {render} = rendererWith({
gmp,
store: true,
router: true,
});

const {element, getAllByTestId} = render(
<CvssCalculator location={location} />,
);
const {element, getAllByTestId} = render(<CvssCalculator />);

await wait();

Expand Down
12 changes: 8 additions & 4 deletions src/web/pages/extras/cvssV4/CvssV4Calculator.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,17 @@ import SeverityBar from 'web/components/bar/severitybar';
import styled from 'styled-components';
import TextField from 'web/components/form/textfield';
import MetricsGroups from 'web/pages/extras/cvssV4/MetricsGroups';
import {useSearchParams} from 'react-router-dom';

const StyledTextField = styled(TextField)`
width: 180px;
`;

const cvssV4Prefix = 'CVSS:4.0/';

const CvssV4Calculator = ({location}) => {
const CvssV4Calculator = () => {
const [searchParams] = useSearchParams();

const initialState = useMemo(() => {
return expectedMetricOptionsOrdered.reduce((obj, item) => {
obj[item[0]] = item[1];
Expand All @@ -50,13 +53,14 @@ const CvssV4Calculator = ({location}) => {
const cvssVector = `${cvssV4Prefix}${removeUnusedMetrics(selectedOptions)}`;

useEffect(() => {
if (location?.query?.cvssVector?.includes(cvssV4Prefix)) {
const newOptions = processVector(location.query.cvssVector);
const cvssVectorParam = searchParams.get('cvssVector');
if (cvssVectorParam?.includes(cvssV4Prefix)) {
const newOptions = processVector(cvssVectorParam);
setSelectedOptions({...initialState, ...newOptions});
}

// eslint-disable-next-line react-hooks/exhaustive-deps
}, [location]);
}, [searchParams]);

const handleInputCVSSVectorChange = value => {
setInputCVSSVector(value);
Expand Down
Loading

0 comments on commit f13c241

Please sign in to comment.