Skip to content

Commit

Permalink
Merge pull request #5416 from rohitkrai03/topology-filter-fix
Browse files Browse the repository at this point in the history
Bug 1834956: Remove topology text filter from redux and rely on URL search params
  • Loading branch information
openshift-merge-robot committed May 14, 2020
2 parents a769da4 + f5e42ab commit 85a03f2
Show file tree
Hide file tree
Showing 12 changed files with 80 additions and 118 deletions.
27 changes: 25 additions & 2 deletions frontend/packages/dev-console/src/components/topology/Topology.tsx
Expand Up @@ -51,7 +51,13 @@ import { topologyModelFromDataModel } from './data-transforms/topology-model';
import { layoutFactory, COLA_LAYOUT, COLA_FORCE_LAYOUT } from './layouts/layoutFactory';
import { TYPE_APPLICATION_GROUP, ComponentFactory } from './components';
import TopologyFilterBar from './filters/TopologyFilterBar';
import { getTopologyFilters, TopologyFilters } from './filters/filter-utils';
import {
getTopologyFilters,
getTopologySearchQuery,
TopologyFilters,
TOPOLOGY_SEARCH_FILTER_KEY,
FILTER_ACTIVE_CLASS,
} from './filters/filter-utils';
import TopologyHelmReleasePanel from './helm/TopologyHelmReleasePanel';
import { TYPE_HELM_RELEASE } from './helm/components/const';
import { HelmComponentFactory } from './helm/components/helmComponentFactory';
Expand Down Expand Up @@ -227,6 +233,21 @@ const Topology: React.FC<ComponentProps> = ({
})();
}, [layout]);

const onSearchChange = (searchQuery) => {
if (searchQuery.length > 0) {
setQueryArgument(TOPOLOGY_SEARCH_FILTER_KEY, searchQuery);
document.body.classList.add(FILTER_ACTIVE_CLASS);
} else {
removeQueryArgument(TOPOLOGY_SEARCH_FILTER_KEY);
document.body.classList.remove(FILTER_ACTIVE_CLASS);
}
};

React.useEffect(() => {
const searchQuery = getTopologySearchQuery();
searchQuery && onSearchChange(searchQuery);
}, []);

const onSidebarClose = () => {
setSelectedIds([]);
removeQueryArgument('selectId');
Expand Down Expand Up @@ -346,7 +367,9 @@ const Topology: React.FC<ComponentProps> = ({

return (
<TopologyView
viewToolbar={<TopologyFilterBar visualization={visRef.current} />}
viewToolbar={
<TopologyFilterBar visualization={visRef.current} onSearchChange={onSearchChange} />
}
controlBar={renderControlBar()}
sideBar={sideBar}
sideBarOpen={!!sideBar}
Expand Down
Expand Up @@ -11,13 +11,6 @@ import {
removeQueryArgument,
} from '@console/internal/components/utils';

// FIXME upgrading redux types is causing many errors at this time
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
import { useSelector, useDispatch } from 'react-redux';
import { RootState } from '@console/internal/redux';
import { getTopologyFilters } from './filters/filter-utils';

import EmptyState from '../EmptyState';
import NamespacedPage, { NamespacedPageVariants } from '../NamespacedPage';
import ProjectsExistWrapper from '../ProjectsExistWrapper';
Expand All @@ -28,8 +21,7 @@ import TopologyShortcuts from './TopologyShortcuts';
import { LAST_TOPOLOGY_VIEW_LOCAL_STORAGE_KEY } from './components/const';

import './TopologyPage.scss';
import { TOPOLOGY_SEARCH_FILTER_KEY } from './redux/const';
import { setTopologyFilters } from './redux/action';
import { TOPOLOGY_SEARCH_FILTER_KEY } from './filters';

export interface TopologyPageProps {
match: RMatch<{
Expand Down Expand Up @@ -86,13 +78,9 @@ export const TopologyPage: React.FC<TopologyPageProps> = ({ match }) => {
exact: true,
});

const dispatch = useDispatch();
const displayFilters = useSelector((state: RootState) => getTopologyFilters(state).display);

const handleNamespaceChange = (ns: string) => {
if (ns !== namespace) {
removeQueryArgument(TOPOLOGY_SEARCH_FILTER_KEY);
dispatch(setTopologyFilters({ display: displayFilters, searchQuery: '' }));
}
};

Expand Down
@@ -1,30 +1,24 @@
import * as React from 'react';
import * as classNames from 'classnames';
import { connect } from 'react-redux';
import { RootState } from '@console/internal/redux';
import { GraphComponent as BaseGraphComponent, WithContextMenuProps } from '@console/topology';
import { TopologyFilters, getTopologyFilters } from '../filters/filter-utils';

type GraphComponentProps = React.ComponentProps<typeof BaseGraphComponent> & {
dragEditInProgress?: boolean;
hasDropTarget?: boolean;
dragCreate?: boolean;
filters: TopologyFilters;
} & WithContextMenuProps;

const DRAG_ACTIVE_CLASS = 'odc-m-drag-active';
const FILTER_ACTIVE_CLASS = 'odc-m-filter-active';
const VALID_DROP_CLASS = 'odc-m-valid-drop-target';

const GraphComponent: React.FC<GraphComponentProps> = (props) => {
const { dragEditInProgress, hasDropTarget, dragCreate, filters } = props;
const { dragEditInProgress, hasDropTarget, dragCreate } = props;
const graphClasses = classNames('odc-graph', { 'odc-m-drag-create': dragCreate });

React.useEffect(() => {
const addClassList = [];
const removeClassList = [];
filters.searchQuery.trim() !== ''
? addClassList.push(FILTER_ACTIVE_CLASS)
: removeClassList.push(FILTER_ACTIVE_CLASS);

dragEditInProgress
? addClassList.push(DRAG_ACTIVE_CLASS)
: removeClassList.push(DRAG_ACTIVE_CLASS);
Expand All @@ -36,16 +30,12 @@ const GraphComponent: React.FC<GraphComponentProps> = (props) => {
if (removeClassList.length) {
removeClassList.forEach((className) => document.body.classList.remove(className));
}
}, [dragEditInProgress, filters.searchQuery, hasDropTarget]);
}, [dragEditInProgress, hasDropTarget]);
return (
<g className={graphClasses}>
<BaseGraphComponent {...props} />
</g>
);
};

const GraphComponentState = (state: RootState) => {
const filters = getTopologyFilters(state);
return { filters };
};
export default connect(GraphComponentState)(GraphComponent);
export default GraphComponent;
Expand Up @@ -10,24 +10,13 @@ import { topologyModelFromDataModel } from '../topology-model';
import { transformTopologyData } from '../data-transformer';
import { TopologyFilters } from '../../filters/filter-utils';
import { allowedResources } from '../../topology-utils';
import { DEFAULT_TOPOLOGY_FILTERS } from '../../redux/const';

describe('topology model ', () => {
let filters: TopologyFilters;

beforeEach(() => {
filters = {
display: {
podCount: true,
eventSources: true,
virtualMachines: true,
showLabels: true,
knativeServices: true,
appGrouping: true,
operatorGrouping: true,
helmGrouping: true,
},
searchQuery: '',
};
filters = _.cloneDeep(DEFAULT_TOPOLOGY_FILTERS);
});

it('should return topology model data', () => {
Expand Down
Expand Up @@ -6,10 +6,14 @@ import { RootState } from '@console/internal/redux';
import { TextFilter } from '@console/internal/components/factory';
import { InfoCircleIcon } from '@patternfly/react-icons';
import { Visualization } from '@console/topology';
import { setQueryArgument, removeQueryArgument } from '@console/internal/components/utils';
import { setTopologyFilters } from '../redux/action';
import { TOPOLOGY_SEARCH_FILTER_KEY } from '../redux/const';
import { TopologyFilters, DisplayFilters, getTopologyFilters } from './filter-utils';
import {
TopologyFilters,
DisplayFilters,
getTopologyFilters,
getTopologySearchQuery,
} from './filter-utils';

import FilterDropdown from './FilterDropdown';
import './TopologyFilterBar.scss';

Expand All @@ -23,22 +27,38 @@ type DispatchProps = {

type OwnProps = {
visualization: Visualization;
onSearchChange: (searchQuery: string) => void;
};

type MergeProps = {
onDisplayFiltersChange: (display: DisplayFilters) => void;
onSearchQueryChange: (searchQuery: string) => void;
} & StateProps &
OwnProps;

type TopologyFilterBarProps = MergeProps;

const TopologyFilterBar: React.FC<TopologyFilterBarProps> = ({
filters: { display, searchQuery },
filters: { display },
onDisplayFiltersChange,
onSearchQueryChange,
onSearchChange,
visualization,
}) => {
const [searchQuery, setSearchQuery] = React.useState<string>('');

React.useEffect(() => {
const query = getTopologySearchQuery();
setSearchQuery(query);
}, []);

const onTextFilterChange = React.useCallback(
(text) => {
const query = text?.trim();
setSearchQuery(query);
onSearchChange(query);
},
[onSearchChange],
);

return (
<Toolbar className="co-namespace-bar odc-topology-filter-bar">
<ToolbarGroup>
Expand All @@ -52,7 +72,7 @@ const TopologyFilterBar: React.FC<TopologyFilterBarProps> = ({
placeholder="Find by name..."
value={searchQuery}
autoFocus
onChange={onSearchQueryChange}
onChange={onTextFilterChange}
/>
</ToolbarItem>
<ToolbarItem>
Expand Down Expand Up @@ -92,20 +112,13 @@ const dispatchToProps = (dispatch: Dispatch): DispatchProps => ({
const mergeProps = (
{ filters }: StateProps,
{ onFiltersChange }: DispatchProps,
{ visualization }: OwnProps,
{ visualization, onSearchChange }: OwnProps,
): MergeProps => ({
filters,
onDisplayFiltersChange: (display: DisplayFilters) => {
onFiltersChange({ ...filters, display });
},
onSearchQueryChange: (searchQuery) => {
onFiltersChange({ ...filters, searchQuery });
if (searchQuery.length > 0) {
setQueryArgument(TOPOLOGY_SEARCH_FILTER_KEY, searchQuery);
} else {
removeQueryArgument(TOPOLOGY_SEARCH_FILTER_KEY);
}
},
onSearchChange,
visualization,
});

Expand Down
@@ -1,26 +1,17 @@
// FIXME upgrading redux types is causing many errors at this time
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
import { useSelector } from 'react-redux';
import { RootState } from '@console/internal/redux';
import { testHook } from '../../../../test/test-utils';
import { useSearchFilter } from '../useSearchFilter';
import { getTopologySearchQuery } from '../filter-utils';

jest.mock('react-redux', () => ({
useSelector: jest.fn(),
jest.mock('../filter-utils', () => ({
getTopologySearchQuery: jest.fn(),
}));

const testUseSearchFilter = (
text: string | null | undefined,
searchQuery: string | undefined,
): ReturnType<typeof useSearchFilter> => {
(useSelector as jest.Mock).mockImplementation((fn: (state: Partial<RootState>) => any) => {
return fn({
plugins: {
devconsole: { topology: new Map(Object.entries({ filters: { searchQuery } })) },
},
});
});
(getTopologySearchQuery as jest.Mock).mockImplementation(() => searchQuery);

// eslint-disable-next-line react-hooks/rules-of-hooks
return useSearchFilter(text);
};
Expand Down
@@ -1,4 +1,8 @@
import { RootState } from '@console/internal/redux';
import { getQueryArgument } from '@console/internal/components/utils';

export const TOPOLOGY_SEARCH_FILTER_KEY = 'searchQuery';
export const FILTER_ACTIVE_CLASS = 'odc-m-filter-active';

export enum ShowFiltersKeyValue {
podCount = 'Pod Count',
Expand All @@ -20,13 +24,12 @@ export const getTopologyFilters = ({
},
}: RootState): TopologyFilters => topology.get('filters');

export const getTopologySearchQuery = () => getQueryArgument(TOPOLOGY_SEARCH_FILTER_KEY) ?? '';

export type TopologyFilters = {
display: DisplayFilters;
searchQuery: SearchQuery;
};

export type SearchQuery = string;

export type DisplayFilters = {
podCount: boolean;
eventSources: boolean;
Expand Down
@@ -1,17 +1,12 @@
import * as React from 'react';
import * as fuzzy from 'fuzzysearch';
import { toLower } from 'lodash';
// FIXME upgrading redux types is causing many errors at this time
// eslint-disable-next-line @typescript-eslint/ban-ts-ignore
// @ts-ignore
import { useSelector } from 'react-redux';
import { RootState } from '@console/internal/redux';
import { getTopologyFilters } from './filter-utils';
import { getTopologySearchQuery } from './filter-utils';

const fuzzyCaseInsensitive = (a: string, b: string): boolean => fuzzy(toLower(a), toLower(b));

const useSearchFilter = (text: string): [boolean, string] => {
const searchQuery = useSelector((state: RootState) => getTopologyFilters(state).searchQuery);
const searchQuery = getTopologySearchQuery();
const filtered = React.useMemo(() => fuzzyCaseInsensitive(searchQuery, text), [
searchQuery,
text,
Expand Down
@@ -1,5 +1,4 @@
export const TOPOLOGY_DISPLAY_FILTERS_LOCAL_STORAGE_KEY = `bridge/topology-display-filters`;
export const TOPOLOGY_SEARCH_FILTER_KEY = 'searchQuery';
export const DEFAULT_TOPOLOGY_FILTERS = {
display: {
podCount: false,
Expand All @@ -11,5 +10,4 @@ export const DEFAULT_TOPOLOGY_FILTERS = {
operatorGrouping: true,
helmGrouping: true,
},
searchQuery: '',
};
@@ -1,17 +1,12 @@
import { Map } from 'immutable';
import { merge } from 'lodash';
import { TopologyAction, Actions } from './action';
import {
TOPOLOGY_DISPLAY_FILTERS_LOCAL_STORAGE_KEY,
DEFAULT_TOPOLOGY_FILTERS,
TOPOLOGY_SEARCH_FILTER_KEY,
} from './const';
import { TOPOLOGY_DISPLAY_FILTERS_LOCAL_STORAGE_KEY, DEFAULT_TOPOLOGY_FILTERS } from './const';

export type State = Map<string, any>;

export const getDefaultTopologyFilters = () => {
const displayFilters = localStorage.getItem(TOPOLOGY_DISPLAY_FILTERS_LOCAL_STORAGE_KEY);
const searchQuery = new URLSearchParams(window.location.search).get(TOPOLOGY_SEARCH_FILTER_KEY);

if (!displayFilters) {
localStorage.setItem(
Expand All @@ -22,7 +17,6 @@ export const getDefaultTopologyFilters = () => {

const filters = merge({}, DEFAULT_TOPOLOGY_FILTERS, {
display: JSON.parse(displayFilters) ?? {},
searchQuery: searchQuery ?? '',
});

return filters;
Expand Down

0 comments on commit 85a03f2

Please sign in to comment.