Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web/src/components/drawer/record/record-panel.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ export const RecordPanel: React.FC<RecordDrawerProps> = ({
const values = [
{
v: Array.isArray(value) ? value.join(value.length == 2 ? '.' : ':') : valueStr,
display: (await def.getOptions(valueStr)).find(o => o.value === valueStr)?.name
display: (await def.autocomplete(valueStr)).find(o => o.value === valueStr)?.name
}
];
// TODO: is it relevant to show composed columns?
Expand Down
11 changes: 5 additions & 6 deletions web/src/components/toolbar/filters/autocomplete-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ export const AutocompleteFilter: React.FC<AutocompleteFilterProps> = ({
(newValue: string) => {
setCurrentValue(newValue);
filterDefinition
.getOptions(newValue)
.autocomplete(newValue)
.then(setOptions)
.catch(err => {
const errorMessage = getHTTPErrorDetails(err);
Expand Down Expand Up @@ -147,11 +147,10 @@ export const AutocompleteFilter: React.FC<AutocompleteFilterProps> = ({
return;
}

createFilterValue(filterDefinition, validation.val!).then(v => {
if (addFilterParent(v)) {
resetFilterValue();
}
});
const fv = createFilterValue(filterDefinition, validation.val!);
if (addFilterParent(fv)) {
resetFilterValue();
}
}, [
options,
filterDefinition,
Expand Down
9 changes: 4 additions & 5 deletions web/src/components/toolbar/filters/text-filter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,11 +74,10 @@ export const TextFilter: React.FC<TextFilterProps> = ({
return;
}

createFilterValue(filterDefinition, validation.val!).then(v => {
if (addFilter(v)) {
resetFilterValue();
}
});
const fv = createFilterValue(filterDefinition, validation.val!);
if (addFilter(fv)) {
resetFilterValue();
}
}, [currentValue, allowEmpty, filterDefinition, setMessageWithDelay, setIndicator, addFilter, resetFilterValue]);

return (
Expand Down
24 changes: 7 additions & 17 deletions web/src/model/filters.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,8 @@ export interface FilterDefinition {
name: string;
component: FilterComponent;
category?: FilterCategory;
getOptions: (value: string) => Promise<FilterOption[]>;
findOption: (value: string) => FilterOption | undefined;
autocomplete: (value: string) => Promise<FilterOption[]>;
validate: (value: string) => { val?: string; err?: string };
checkCompletion?: (value: string, selected: string) => { completed: boolean; option: FilterOption };
autoCompleteAddsQuotes?: boolean;
Expand Down Expand Up @@ -101,22 +102,11 @@ export interface FilterOption {
value: string;
}

export const createFilterValue = (def: FilterDefinition, value: string): Promise<FilterValue> => {
return (
def
.getOptions(value)
.then(opts => {
const option = opts.find(opt => opt.name === value || opt.value === value);
return option
? { v: option.value, display: option.name }
: { v: value, display: value === undefinedValue ? 'n/a' : undefined };
})
// eslint-disable-next-line @typescript-eslint/no-unused-vars
.catch(_ => {
// In case of error, still create the minimal possible FilterValue
return { v: value };
})
);
export const createFilterValue = (def: FilterDefinition, value: string): FilterValue => {
const option = def.findOption(value);
return option
? { v: option.value, display: option.name }
: { v: value, display: value === undefinedValue ? 'n/a' : undefined };
};

export const hasEnabledFilterValues = (filter: Filter) => {
Expand Down
83 changes: 49 additions & 34 deletions web/src/utils/filter-definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,30 @@ import { joinResource, SplitResource, splitResource, SplitStage } from '../model
import { getPort } from '../utils/port';
import { ColumnConfigDef } from './columns';
import {
autocompleteCluster,
autocompleteDirection,
autocompleteDnsErrorCode,
autocompleteDnsResponseCode,
autocompleteDropCause,
autocompleteDropState,
autocompleteDSCP,
autocompleteEmpty,
autocompleteKind,
autocompleteNamespace,
autocompletePort,
autocompleteProtocol,
autocompleteResource,
autocompleteTCPFlags,
autocompleteUDN,
autocompleteZone,
findDirectionOption,
findDnsErrorCodeOption,
findDnsResponseCodeOption,
findDropCauseOption,
findDropStateOption,
findDSCPOption,
findProtocolOption,
getClusterOptions,
getDirectionOptionsAsync,
getDnsErrorCodeOptions,
getDnsResponseCodeOptions,
getDropCauseOptions,
getDropStateOptions,
getDSCPOptions,
getKindOptions,
getNamespaceOptions,
getPortOptions,
getProtocolOptions,
getResourceOptions,
getTCPFlagsOptions,
getUDNOptions,
getZoneOptions,
noOption
portValueToOption
} from './filter-options';
import { validateIPFilter } from './ip';
import { validateK8SName, validateStrictK8SName } from './label';
Expand Down Expand Up @@ -243,7 +249,7 @@ export const getFilterDefinitions = (
return invalid(t('Value is empty'));
}
//allow 0 / 1 or Ingress / Egress
const found = findDirectionOption(value, t);
const found = findDirectionOption(t, true, value);
if (found) {
return valid(found.name);
}
Expand All @@ -254,29 +260,30 @@ export const getFilterDefinitions = (
const isSrc = d.id.includes('src');
const colConfig = columnsDefs.find(c => c.filter === d.id);

let getOptions: (value: string) => Promise<FilterOption[]> = noOption;
let autocomplete: (value: string) => Promise<FilterOption[]> = autocompleteEmpty;
let findOption: (value: string) => FilterOption | undefined = () => undefined;
let validate: (value: string) => { val?: string; err?: string } = rejectEmptyValue;
let encoder: FiltersEncoder = simpleFiltersEncoder(colConfig?.field as Field);
let checkCompletion:
| ((value: string, selected: string) => { completed: boolean; option: FilterOption })
| undefined = undefined;

if (d.id.includes('namespace')) {
getOptions = getNamespaceOptions;
autocomplete = autocompleteNamespace;
validate = k8sNameValidation;
} else if (d.id.includes('cluster')) {
getOptions = getClusterOptions;
autocomplete = autocompleteCluster;
} else if (d.id.includes('udn')) {
getOptions = getUDNOptions;
autocomplete = autocompleteUDN;
} else if (d.id.includes('zone')) {
getOptions = getZoneOptions;
autocomplete = autocompleteZone;
} else if (d.id.includes('name')) {
validate = k8sNameValidation;
} else if (d.id.includes('kind')) {
getOptions = getKindOptions;
autocomplete = autocompleteKind;
encoder = kindFiltersEncoder(`${isSrc ? 'Src' : 'Dst'}K8S_Type`, `${isSrc ? 'Src' : 'Dst'}K8S_OwnerType`);
} else if (d.id.includes('resource')) {
getOptions = getResourceOptions;
autocomplete = autocompleteResource;
validate = k8sResourceValidation;
checkCompletion = k8sResourceCompletion;
encoder = k8sResourceFiltersEncoder(
Expand All @@ -289,33 +296,41 @@ export const getFilterDefinitions = (
} else if (d.id.includes('address')) {
validate = addressValidation;
} else if (d.id.includes('port')) {
getOptions = getPortOptions;
autocomplete = autocompletePort;
findOption = portValueToOption;
validate = portValidation;
} else if (d.id.includes('mac')) {
validate = macValidation;
} else if (d.id.includes('proto')) {
getOptions = getProtocolOptions;
autocomplete = autocompleteProtocol;
findOption = findProtocolOption;
validate = protoValidation;
} else if (d.id.includes('direction')) {
getOptions = v => getDirectionOptionsAsync(v, t, d.id === 'nodedirection');
autocomplete = v => autocompleteDirection(t, d.id === 'nodedirection', v);
findOption = v => findDirectionOption(t, d.id === 'nodedirection', v);
validate = dirValidation;
} else if (d.id.includes('drop_state')) {
getOptions = getDropStateOptions;
autocomplete = autocompleteDropState;
findOption = findDropStateOption;
encoder = simpleFiltersEncoder('PktDropLatestState');
} else if (d.id.includes('drop_cause')) {
getOptions = getDropCauseOptions;
autocomplete = autocompleteDropCause;
findOption = findDropCauseOption;
encoder = simpleFiltersEncoder('PktDropLatestDropCause');
} else if (d.id.includes('dns_flag_response_code')) {
getOptions = getDnsResponseCodeOptions;
autocomplete = autocompleteDnsResponseCode;
findOption = findDnsResponseCodeOption;
} else if (d.id.includes('dns_errno')) {
getOptions = getDnsErrorCodeOptions;
autocomplete = autocompleteDnsErrorCode;
findOption = findDnsErrorCodeOption;
} else if (d.id.includes('dscp')) {
getOptions = getDSCPOptions;
autocomplete = autocompleteDSCP;
findOption = findDSCPOption;
} else if (d.id.includes('flags')) {
getOptions = getTCPFlagsOptions;
autocomplete = autocompleteTCPFlags;
}

return { getOptions, validate, encoder, checkCompletion };
return { autocomplete, findOption, validate, encoder, checkCompletion };
};

return filterDefs.map(d => {
Expand Down
Loading