Skip to content

Commit 872ee1f

Browse files
committed
explicitly show and / or
1 parent 434134f commit 872ee1f

File tree

4 files changed

+182
-123
lines changed

4 files changed

+182
-123
lines changed

web/locales/en/plugin__netobserv-plugin.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -378,6 +378,8 @@
378378
"Comparator": "Comparator",
379379
"Add filter": "Add filter",
380380
"Peer": "Peer",
381+
"OR": "OR",
382+
"AND": "AND",
381383
"Not": "Not",
382384
"more than": "more than",
383385
"Disable": "Disable",
@@ -389,6 +391,7 @@
389391
"As peer B": "As peer B",
390392
"As destination": "As destination",
391393
"Remove": "Remove",
394+
"Match": "Match",
392395
"Edit filters": "Edit filters",
393396
"Reset defaults": "Reset defaults",
394397
"Clear all": "Clear all",

web/src/components/toolbar/filters-toolbar.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ div#filter-toolbar-search-filters {
6565

6666
.custom-chip-box {
6767
padding: 0.2em 0.5em 0.2em 0.5em;
68-
margin: 0 1em 0 0;
68+
margin: 0;
6969
flex-direction: column;
7070
}
7171

@@ -76,7 +76,7 @@ div#filter-toolbar-search-filters {
7676

7777
.custom-chip-group {
7878
padding: 0.2em 0.5em 0.2em 0.5em;
79-
margin: 0 1em 0 0;
79+
margin: 0;
8080
color: #000;
8181
background-color: #f0f0f0;
8282
}

web/src/components/toolbar/filters/filters-chips.css

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,26 @@
1111

1212
.custom-chip>.pf-v5-c-menu-toggle__controls {
1313
padding: 0.25em;
14+
}
15+
16+
.match-container {
17+
align-self: center;
18+
}
19+
20+
.match-text {
21+
text-align: center;
22+
}
23+
24+
.and-or-text {
25+
align-self: center;
26+
padding: 0 0.5em 0 0.5em;
27+
}
28+
29+
.flex-block {
30+
display: flex;
31+
flex-wrap: wrap;
32+
align-items: center;
33+
align-content: center;
34+
align-self: center;
35+
justify-content: center;
1436
}

web/src/components/toolbar/filters/filters-chips.tsx

Lines changed: 155 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import {
33
Dropdown,
44
DropdownItem,
55
DropdownList,
6+
Flex,
7+
FlexItem,
68
MenuToggle,
79
MenuToggleElement,
810
Text,
@@ -135,6 +137,21 @@ export const FiltersChips: React.FC<FiltersChipsProps> = ({
135137
[filterDefinitions, filters, setFilters]
136138
);
137139

140+
const getAndOrText = React.useCallback(
141+
(index: number) => {
142+
if (index == 0) {
143+
return undefined;
144+
}
145+
146+
return (
147+
<Text className="and-or-text" component="p">
148+
{filters.match === 'any' ? t('OR') : t('AND')}
149+
</Text>
150+
);
151+
},
152+
[filters.match, t]
153+
);
154+
138155
const getFilterDisplay = React.useCallback(
139156
(chipFilter: Filter, cfIndex: number) => {
140157
let fullName = chipFilter.def.name;
@@ -146,130 +163,133 @@ export const FiltersChips: React.FC<FiltersChipsProps> = ({
146163
}
147164
const someEnabled = hasEnabledFilterValues(chipFilter);
148165
return (
149-
<div key={cfIndex} className={`custom-chip-group ${someEnabled ? '' : 'disabled-group'}`}>
150-
<Tooltip content={`${someEnabled ? t('Disable') : t('Enable')} '${fullName}' ${t('group filter')}`}>
151-
<Text
152-
className="pf-v5-c-chip-group__label"
153-
component={TextVariants.p}
154-
onClick={() => {
155-
//switch all values if no remaining
156-
chipFilter.values.forEach(fv => {
157-
fv.disabled = someEnabled;
158-
});
159-
setFilters(_.cloneDeep(filters));
160-
}}
161-
>
162-
{fullName}
163-
</Text>
164-
</Tooltip>
165-
{chipFilter.values.map((chipFilterValue, fvIndex) => {
166-
if (isForced || chipFilterValue.disabled) {
166+
<div className="flex-block">
167+
{getAndOrText(cfIndex)}
168+
<div key={cfIndex} className={`custom-chip-group ${someEnabled ? '' : 'disabled-group'}`}>
169+
<Tooltip content={`${someEnabled ? t('Disable') : t('Enable')} '${fullName}' ${t('group filter')}`}>
170+
<Text
171+
className="pf-v5-c-chip-group__label"
172+
component={TextVariants.p}
173+
onClick={() => {
174+
//switch all values if no remaining
175+
chipFilter.values.forEach(fv => {
176+
fv.disabled = someEnabled;
177+
});
178+
setFilters(_.cloneDeep(filters));
179+
}}
180+
>
181+
{fullName}
182+
</Text>
183+
</Tooltip>
184+
{chipFilter.values.map((chipFilterValue, fvIndex) => {
185+
if (isForced || chipFilterValue.disabled) {
186+
return (
187+
<div key={fvIndex} className={`custom-chip ${chipFilterValue.disabled ? 'disabled-value' : ''}`}>
188+
<Tooltip
189+
content={`${chipFilterValue.disabled ? t('Enable') : t('Disable')} ${fullName} '${
190+
chipFilterValue.display || chipFilterValue.v
191+
}' ${t('filter')}`}
192+
>
193+
<Text
194+
component={TextVariants.p}
195+
onClick={() => {
196+
chipFilterValue.disabled = !chipFilterValue.disabled;
197+
setFilters(_.cloneDeep(filters));
198+
}}
199+
>
200+
{chipFilterValue.display ? chipFilterValue.display : chipFilterValue.v}
201+
</Text>
202+
</Tooltip>
203+
</div>
204+
);
205+
}
206+
207+
const dropdownId = `${chipFilter.def.id}-${fvIndex}`;
167208
return (
168-
<div key={fvIndex} className={`custom-chip ${chipFilterValue.disabled ? 'disabled-value' : ''}`}>
169-
<Tooltip
170-
content={`${chipFilterValue.disabled ? t('Enable') : t('Disable')} ${fullName} '${
171-
chipFilterValue.display || chipFilterValue.v
172-
}' ${t('filter')}`}
173-
>
174-
<Text
175-
component={TextVariants.p}
209+
<Dropdown
210+
key={fvIndex}
211+
isOpen={dropdownId === openedDropdown}
212+
onOpenChange={(isOpen: boolean) => setOpenedDropdown(isOpen ? dropdownId : undefined)}
213+
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
214+
<MenuToggle
215+
ref={toggleRef}
216+
className={`custom-chip ${chipFilterValue.disabled ? 'disabled-value' : ''}`}
217+
isExpanded={dropdownId === openedDropdown}
218+
onClick={() => setOpenedDropdown(openedDropdown === dropdownId ? undefined : dropdownId)}
219+
>
220+
{chipFilterValue.display ? chipFilterValue.display : chipFilterValue.v}
221+
</MenuToggle>
222+
)}
223+
>
224+
<DropdownList>
225+
<DropdownItem
226+
key="disable"
176227
onClick={() => {
177228
chipFilterValue.disabled = !chipFilterValue.disabled;
178229
setFilters(_.cloneDeep(filters));
230+
setOpenedDropdown(undefined);
179231
}}
180232
>
181-
{chipFilterValue.display ? chipFilterValue.display : chipFilterValue.v}
182-
</Text>
183-
</Tooltip>
184-
</div>
185-
);
186-
}
187-
188-
const dropdownId = `${chipFilter.def.id}-${fvIndex}`;
189-
return (
190-
<Dropdown
191-
key={fvIndex}
192-
isOpen={dropdownId === openedDropdown}
193-
onOpenChange={(isOpen: boolean) => setOpenedDropdown(isOpen ? dropdownId : undefined)}
194-
toggle={(toggleRef: React.Ref<MenuToggleElement>) => (
195-
<MenuToggle
196-
ref={toggleRef}
197-
className={`custom-chip ${chipFilterValue.disabled ? 'disabled-value' : ''}`}
198-
isExpanded={dropdownId === openedDropdown}
199-
onClick={() => setOpenedDropdown(openedDropdown === dropdownId ? undefined : dropdownId)}
200-
>
201-
{chipFilterValue.display ? chipFilterValue.display : chipFilterValue.v}
202-
</MenuToggle>
203-
)}
204-
>
205-
<DropdownList>
206-
<DropdownItem
207-
key="disable"
208-
onClick={() => {
209-
chipFilterValue.disabled = !chipFilterValue.disabled;
210-
setFilters(_.cloneDeep(filters));
211-
setOpenedDropdown(undefined);
212-
}}
213-
>
214-
{chipFilterValue.disabled && <CheckIcon />}
215-
{!chipFilterValue.disabled && <BanIcon />}
216-
&nbsp;{chipFilterValue.disabled ? t('Enable') : t('Disable')}
217-
</DropdownItem>
218-
{filters.match !== 'peers' &&
219-
(chipFilter.def.id.startsWith('src_') || chipFilter.def.id.startsWith('dst_')) && (
220-
<DropdownItem
221-
key="bnf"
222-
onClick={() => {
223-
const bnf = bnfFilterValue(
224-
filterDefinitions,
225-
filters!.list,
226-
chipFilter.def.id,
227-
chipFilterValue
228-
);
229-
setFilters({ ...filters!, list: bnf });
230-
setOpenedDropdown(undefined);
231-
}}
232-
>
233-
<ArrowsAltVIcon style={{ transform: 'rotate(90deg)' }} />
234-
&nbsp;{t('Any')}
233+
{chipFilterValue.disabled && <CheckIcon />}
234+
{!chipFilterValue.disabled && <BanIcon />}
235+
&nbsp;{chipFilterValue.disabled ? t('Enable') : t('Disable')}
236+
</DropdownItem>
237+
{filters.match !== 'peers' &&
238+
(chipFilter.def.id.startsWith('src_') || chipFilter.def.id.startsWith('dst_')) && (
239+
<DropdownItem
240+
key="bnf"
241+
onClick={() => {
242+
const bnf = bnfFilterValue(
243+
filterDefinitions,
244+
filters!.list,
245+
chipFilter.def.id,
246+
chipFilterValue
247+
);
248+
setFilters({ ...filters!, list: bnf });
249+
setOpenedDropdown(undefined);
250+
}}
251+
>
252+
<ArrowsAltVIcon style={{ transform: 'rotate(90deg)' }} />
253+
&nbsp;{t('Any')}
254+
</DropdownItem>
255+
)}
256+
{(chipFilter.def.category === 'targeteable' || chipFilter.def.id.startsWith('dst_')) && (
257+
<DropdownItem key="src" onClick={() => swapValue(chipFilter, chipFilterValue, 'src')}>
258+
<ArrowLeftIcon />
259+
&nbsp;{filters.match === 'peers' ? t('As peer A') : t('As source')}
235260
</DropdownItem>
236261
)}
237-
{(chipFilter.def.category === 'targeteable' || chipFilter.def.id.startsWith('dst_')) && (
238-
<DropdownItem key="src" onClick={() => swapValue(chipFilter, chipFilterValue, 'src')}>
239-
<ArrowLeftIcon />
240-
&nbsp;{filters.match === 'peers' ? t('As peer A') : t('As source')}
241-
</DropdownItem>
242-
)}
243-
{(chipFilter.def.category === 'targeteable' || chipFilter.def.id.startsWith('src_')) && (
244-
<DropdownItem key="dst" onClick={() => swapValue(chipFilter, chipFilterValue, 'dst')}>
245-
<ArrowRightIcon />
246-
&nbsp;{filters.match === 'peers' ? t('As peer B') : t('As destination')}
262+
{(chipFilter.def.category === 'targeteable' || chipFilter.def.id.startsWith('src_')) && (
263+
<DropdownItem key="dst" onClick={() => swapValue(chipFilter, chipFilterValue, 'dst')}>
264+
<ArrowRightIcon />
265+
&nbsp;{filters.match === 'peers' ? t('As peer B') : t('As destination')}
266+
</DropdownItem>
267+
)}
268+
<DropdownItem
269+
key="remove"
270+
onClick={() => {
271+
chipFilter.values = chipFilter.values.filter(val => val.v !== chipFilterValue.v);
272+
if (_.isEmpty(chipFilter.values)) {
273+
setFiltersList(removeFromFilters(filters.list, chipFilter));
274+
} else {
275+
setFilters(_.cloneDeep(filters));
276+
}
277+
setOpenedDropdown(undefined);
278+
}}
279+
>
280+
<TimesIcon />
281+
&nbsp;{t('Remove')}
247282
</DropdownItem>
248-
)}
249-
<DropdownItem
250-
key="remove"
251-
onClick={() => {
252-
chipFilter.values = chipFilter.values.filter(val => val.v !== chipFilterValue.v);
253-
if (_.isEmpty(chipFilter.values)) {
254-
setFiltersList(removeFromFilters(filters.list, chipFilter));
255-
} else {
256-
setFilters(_.cloneDeep(filters));
257-
}
258-
setOpenedDropdown(undefined);
259-
}}
260-
>
261-
<TimesIcon />
262-
&nbsp;{t('Remove')}
263-
</DropdownItem>
264-
</DropdownList>
265-
</Dropdown>
266-
);
267-
})}
268-
{!isForced && (
269-
<Button variant="plain" onClick={() => setFiltersList(removeFromFilters(filters.list, chipFilter))}>
270-
<TimesCircleIcon />
271-
</Button>
272-
)}
283+
</DropdownList>
284+
</Dropdown>
285+
);
286+
})}
287+
{!isForced && (
288+
<Button variant="plain" onClick={() => setFiltersList(removeFromFilters(filters.list, chipFilter))}>
289+
<TimesCircleIcon />
290+
</Button>
291+
)}
292+
</div>
273293
</div>
274294
);
275295
},
@@ -301,16 +321,30 @@ export const FiltersChips: React.FC<FiltersChipsProps> = ({
301321
id={`${isForced ? 'forced-' : ''}filters`}
302322
variant="filter-group"
303323
>
304-
<MatchDropdown selected={filters.match} setMatch={setMatch} />
324+
{(filters.list.length > 2 || hasSrcOrDstFilters(filters.list)) && (
325+
<ToolbarItem className="flex-start match-container">
326+
<Flex direction={{ default: hasSrcOrDstFilters(filters.list) ? 'column' : 'row' }}>
327+
<FlexItem>
328+
<Text className="match-text">{t('Match')}</Text>
329+
</FlexItem>
330+
<FlexItem>
331+
<MatchDropdown selected={filters.match} setMatch={setMatch} />
332+
</FlexItem>
333+
</Flex>
334+
</ToolbarItem>
335+
)}
305336
<ToolbarItem className="flex-start flex">
306337
{getGroups()
307338
.filter(gp => gp.filters.length)
308-
.map(gp => {
339+
.map((gp, index) => {
309340
return (
310-
<div key={gp.id} className={`custom-chip-box ${gp.id !== 'common' ? 'custom-chip-peer' : ''}`}>
311-
{hasSrcOrDstFilters(filters.list) && <Text>{getGroupName(gp.id)}&nbsp;</Text>}
312-
<div className="flex">{gp.filters.map(getFilterDisplay)}</div>
313-
</div>
341+
<>
342+
{getAndOrText(index)}
343+
<div key={gp.id} className={`custom-chip-box ${gp.id !== 'common' ? 'custom-chip-peer' : ''}`}>
344+
{hasSrcOrDstFilters(filters.list) && <Text>{getGroupName(gp.id)}&nbsp;</Text>}
345+
<div className="flex-block">{gp.filters.map(getFilterDisplay)}</div>
346+
</div>
347+
</>
314348
);
315349
})}
316350
</ToolbarItem>

0 commit comments

Comments
 (0)