Skip to content

Commit

Permalink
Add capability to collapse all grouping in topology view
Browse files Browse the repository at this point in the history
  • Loading branch information
jeff-phillips-18 committed Jul 16, 2020
1 parent d7a782d commit f724dc6
Show file tree
Hide file tree
Showing 21 changed files with 318 additions and 69 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ import {
TOPOLOGY_SEARCH_FILTER_KEY,
useDisplayFilters,
useAppliedDisplayFilters,
useExpandGroups,
} from './filters';
import TopologyHelmReleasePanel from './helm/TopologyHelmReleasePanel';
import { TYPE_HELM_RELEASE, TYPE_HELM_WORKLOAD } from './helm/components/const';
Expand Down Expand Up @@ -122,6 +123,7 @@ const Topology: React.FC<ComponentProps> = ({
const createResourceAccess: string[] = useAddToProjectAccess(namespace);
const [dragHint, setDragHint] = React.useState<string>('');
const filters = useDisplayFilters();
const expandGroups = useExpandGroups();
const appliedFilters = useAppliedDisplayFilters();
const [displayFilterers, setDisplayFilterers] = React.useState<TopologyApplyDisplayOptions[]>(
null,
Expand Down Expand Up @@ -263,6 +265,7 @@ const Topology: React.FC<ComponentProps> = ({
const newModel = updateModelFromFilters(
model,
filters,
expandGroups,
application,
displayFilterers,
onSupportedFiltersChange,
Expand All @@ -283,7 +286,7 @@ const Topology: React.FC<ComponentProps> = ({
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [model, visualization, filters, application, displayFilterers, filtersLoaded]);
}, [model, visualization, filters, expandGroups, application, displayFilterers, filtersLoaded]);

React.useEffect(() => {
if (!applicationRef.current) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ describe('topology model ', () => {
const newModel = updateModelFromFilters(
topologyDataModel,
filters,
true,
ALL_APPLICATIONS_KEY,
filterers,
);
Expand All @@ -54,6 +55,7 @@ describe('topology model ', () => {
const newModel = updateModelFromFilters(
topologyTransformedData,
filters,
true,
'application-1',
filterers,
);
Expand All @@ -69,6 +71,21 @@ describe('topology model ', () => {
const newModel = updateModelFromFilters(
topologyTransformedData,
filters,
true,
ALL_APPLICATIONS_KEY,
filterers,
);
expect(newModel.nodes.filter((n) => n.group).length).toBe(2);
expect(newModel.nodes.filter((n) => n.group && n.collapsed).length).toBe(2);
});

it('should flag application groups as collapsed when expand groups is false', () => {
const topologyTransformedData = getTransformedTopologyData();
getFilterById(EXPAND_APPLICATION_GROUPS_FILTER_ID, filters).value = true;
const newModel = updateModelFromFilters(
topologyTransformedData,
filters,
false,
ALL_APPLICATIONS_KEY,
filterers,
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const getApplicationGroupForNode = (node: NodeModel, groups: NodeModel[]): NodeM
export const updateModelFromFilters = (
model: Model,
filters: DisplayFilters,
expandGroups: boolean,
application: string = ALL_APPLICATIONS_KEY,
displayFilterers?: TopologyApplyDisplayOptions[],
onSupportedFiltersChange?: (supportedFilterIds: string[]) => void,
Expand All @@ -34,13 +35,14 @@ export const updateModelFromFilters = (
edges: [...model.edges],
};
const supportedFilters = [...DEFAULT_SUPPORTED_FILTER_IDS];
const expandGroups = getFilterById(EXPAND_APPLICATION_GROUPS_FILTER_ID, filters)?.value ?? true;
const expandApplicationGroups =
expandGroups && (getFilterById(EXPAND_APPLICATION_GROUPS_FILTER_ID, filters)?.value ?? true);
let appGroupFound = false;
dataModel.nodes.forEach((d) => {
d.visible = true;
if (displayFilterers) {
displayFilterers.forEach((displayFilterer) => {
const appliedFilters = displayFilterer(model, filters);
const appliedFilters = displayFilterer(model, filters, expandGroups);
supportedFilters.push(...appliedFilters.filter((f) => !supportedFilters.includes(f)));
});
}
Expand All @@ -49,7 +51,7 @@ export const updateModelFromFilters = (
appGroupFound = true;
supportedFilters.push(EXPAND_APPLICATION_GROUPS_FILTER_ID);
}
d.collapsed = !expandGroups;
d.collapsed = !expandApplicationGroups;
}
});

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
@import '../../../../../../public/style/vars';

.odc-topology-filter-dropdown {
&__expand-groups-switcher {
display: flex;
align-items: center;

.pf-c-select__menu-group-title {
flex: 1;
}

.pf-c-switch {
margin-right: var(--pf-global--spacer--sm);
}

.pf-m-disabled {
color: var(--pf-c-check__label--disabled--Color);
}
}

&__group {
&:not(:first-of-type) {
margin-top: var(--pf-global--spacer--sm);
border-top: 1px solid var(--pf-global--BorderColor--300);
}
}

&__expand-groups-label .pf-c-select__menu-group-title {
padding-top: 0;
padding-bottom: 0;
}
}
Original file line number Diff line number Diff line change
@@ -1,76 +1,101 @@
import * as React from 'react';
import { Select, SelectGroup, SelectOption, SelectVariant } from '@patternfly/react-core';
import { Select, SelectGroup, SelectOption, SelectVariant, Switch } from '@patternfly/react-core';
import { TopologyDisplayFilterType, DisplayFilters } from '../topology-types';

import './FilterDropdown.scss';

type FilterDropdownProps = {
filters: DisplayFilters;
supportedFilters: string[];
onChange: (filter: DisplayFilters) => void;
groupsExpanded: boolean;
onGroupsExpandedChange: (collapsed: boolean) => void;
opened?: boolean; // Use only for testing
};

const FilterDropdown: React.FC<FilterDropdownProps> = ({ filters, supportedFilters, onChange }) => {
const [isOpen, setIsOpen] = React.useState(false);
const selected = filters.filter((f) => f.value).map((f) => f.id);
const FilterDropdown: React.FC<FilterDropdownProps> = ({
filters,
supportedFilters,
onChange,
groupsExpanded,
onGroupsExpandedChange,
opened = false,
}) => {
const [isOpen, setIsOpen] = React.useState(opened);

const onToggle = (open: boolean): void => setIsOpen(open);
const onSelect = (e: React.MouseEvent, key: string) => {
const index = filters.findIndex((f) => f.id === key);
if (index === -1) {
return;
}
const filter = { ...filters[index], value: (e.target as HTMLInputElement).checked };
onChange([...filters.slice(0, index), filter, ...filters.slice(index + 1)]);
};

const ShowFiltersKeyValue = filters
.filter((f) => f.type === TopologyDisplayFilterType.show && supportedFilters.includes(f.id))
.sort((a, b) => a.priority - b.priority)
.reduce((acc, f) => {
acc[f.id] = f.label;
return acc;
}, {});
const ExpandFiltersKeyValue = filters
const expandFilters = filters
.filter((f) => f.type === TopologyDisplayFilterType.expand && supportedFilters.includes(f.id))
.sort((a, b) => a.priority - b.priority)
.reduce((acc, f) => {
acc[f.id] = f.label;
return acc;
}, {});
const options = [];
if (Object.keys(ShowFiltersKeyValue).length) {
options.push(
<SelectGroup key="show" label="Show">
{Object.keys(ShowFiltersKeyValue).map((key) => (
<SelectOption key={key} value={key}>
{ShowFiltersKeyValue[key]}
</SelectOption>
))}
</SelectGroup>,
);
}
if (Object.keys(ExpandFiltersKeyValue).length) {
options.push(
<SelectGroup key="expand" label="Expand">
{Object.keys(ExpandFiltersKeyValue).map((key) => (
<SelectOption key={key} value={key}>
{ExpandFiltersKeyValue[key]}
</SelectOption>
))}
</SelectGroup>,
);
}
.sort((a, b) => a.priority - b.priority);

const showFilters = filters
.filter((f) => f.type === TopologyDisplayFilterType.show && supportedFilters.includes(f.id))
.sort((a, b) => a.priority - b.priority);

const selectContent = (
<div className="odc-topology-filter-dropdown">
{expandFilters.length && (
<div className="odc-topology-filter-dropdown__group">
<span
key="expand-groups-switch"
className="odc-topology-filter-dropdown__expand-groups-switcher"
>
<span className="pf-c-select__menu-group-title">Expand</span>
<Switch
id="groups-collapse-switch"
isChecked={groupsExpanded}
onChange={onGroupsExpandedChange}
/>
</span>
<SelectGroup key="expand" className="odc-topology-filter-dropdown__expand-groups-label">
{expandFilters.map((filter) => (
<SelectOption
key={filter.id}
value={filter.id}
isDisabled={!groupsExpanded}
isChecked={filter.value}
>
{filter.label}
</SelectOption>
))}
</SelectGroup>
</div>
)}
{showFilters.length && (
<div className="odc-topology-filter-dropdown__group">
<SelectGroup key="show" label="Show">
{showFilters.map((filter) => (
<SelectOption key={filter.id} value={filter.id} isChecked={filter.value}>
{filter.label}
</SelectOption>
))}
</SelectGroup>
</div>
)}
</div>
);

return (
<Select
className="odc-filter-dropdown__select"
className="odc-topology-filter-dropdown__select"
variant={SelectVariant.checkbox}
customContent={selectContent}
onToggle={onToggle}
selections={selected}
isOpen={isOpen}
onSelect={onSelect}
placeholderText="Display Options"
isGrouped
isCheckboxSelectionBadgeHidden
>
{...options}
</Select>
/>
);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,12 @@ import { RootState } from '@console/internal/redux';
import { TextFilter } from '@console/internal/components/factory';
import { InfoCircleIcon } from '@patternfly/react-icons';
import { Visualization } from '@patternfly/react-topology';
import { setTopologyFilters } from '../redux/action';
import { setTopologyFilters, setGroupsExpanded } from '../redux/action';
import { DisplayFilters } from '../topology-types';
import {
getSupportedTopologyFilters,
getTopologyFilters,
getTopologyGroupsExpanded,
getTopologySearchQuery,
} from './filter-utils';

Expand All @@ -20,10 +21,12 @@ import './TopologyFilterBar.scss';
type StateProps = {
filters: DisplayFilters;
supportedFilters: string[];
groupsExpanded: boolean;
};

type DispatchProps = {
onFiltersChange: (filters: DisplayFilters) => void;
onGroupsExpandedChange: (expanded: boolean) => void;
};

type OwnProps = {
Expand All @@ -33,6 +36,7 @@ type OwnProps = {

type MergeProps = {
onDisplayFiltersChange: (display: DisplayFilters) => void;
onGroupsExpandedChange: (expanded: boolean) => void;
} & StateProps &
OwnProps;

Expand All @@ -41,7 +45,9 @@ type TopologyFilterBarProps = MergeProps;
const TopologyFilterBar: React.FC<TopologyFilterBarProps> = ({
filters,
supportedFilters,
groupsExpanded,
onDisplayFiltersChange,
onGroupsExpandedChange,
onSearchChange,
visualization,
}) => {
Expand All @@ -68,6 +74,8 @@ const TopologyFilterBar: React.FC<TopologyFilterBarProps> = ({
filters={filters}
supportedFilters={supportedFilters}
onChange={onDisplayFiltersChange}
groupsExpanded={groupsExpanded}
onGroupsExpandedChange={onGroupsExpandedChange}
/>
</ToolbarGroup>
<ToolbarGroup className="odc-topology-filter-bar__search">
Expand Down Expand Up @@ -102,24 +110,32 @@ const TopologyFilterBar: React.FC<TopologyFilterBarProps> = ({
const mapStateToProps = (state: RootState): StateProps => ({
filters: getTopologyFilters(state),
supportedFilters: getSupportedTopologyFilters(state),
groupsExpanded: getTopologyGroupsExpanded(state),
});

const dispatchToProps = (dispatch: Dispatch): DispatchProps => ({
onFiltersChange: (filters: DisplayFilters) => {
dispatch(setTopologyFilters(filters));
},
onGroupsExpandedChange: (expanded: boolean) => {
dispatch(setGroupsExpanded(expanded));
},
});

const mergeProps = (
{ filters, supportedFilters }: StateProps,
{ onFiltersChange }: DispatchProps,
{ filters, supportedFilters, groupsExpanded }: StateProps,
{ onFiltersChange, onGroupsExpandedChange }: DispatchProps,
{ visualization, onSearchChange }: OwnProps,
): MergeProps => ({
filters,
supportedFilters,
groupsExpanded,
onDisplayFiltersChange: (changedFilters: DisplayFilters) => {
onFiltersChange(changedFilters);
},
onGroupsExpandedChange: (collapsed: boolean) => {
onGroupsExpandedChange(collapsed);
},
onSearchChange,
visualization,
});
Expand Down

0 comments on commit f724dc6

Please sign in to comment.