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
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,11 @@ function ViolationsTablePage(): ReactElement {
setSearchFilter(updateSearchFilter(searchFilter, payload));
};

useEffectAfterFirstRender(() => {
setSearchFilter({});
setPage(1);
}, [filteredWorkflowView, setSearchFilter, setPage]);

useEffectAfterFirstRender(() => {
if (hasExecutableFilter && !isViewFiltered) {
// If the user applies a filter to a previously unfiltered table, return to page 1
Expand Down Expand Up @@ -351,6 +356,7 @@ function ViolationsTablePage(): ReactElement {
onFilterChange={setSearchFilter}
onSearch={onSearch}
additionalContextFilter={additionalContextFilter}
filteredWorkflowView={filteredWorkflowView}
hasActiveViolations={selectedViolationStateTab === 'ACTIVE'}
isTableDataUpdating={isTableDataUpdating}
/>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import type { ListAlert } from 'types/alert.proto';
import { getAxiosErrorMessage } from 'utils/responseErrorUtils';
import type { SearchFilter } from 'types/search';
import type { OnSearchCallback } from 'Components/CompoundSearchFilter/types';
import type { FilteredWorkflowView } from 'Components/FilteredWorkflowViewSelector/types';
import ResolveConfirmation from './Modals/ResolveConfirmation';
import ExcludeConfirmation from './Modals/ExcludeConfirmation';
import ViolationsTableSearchFilter from './ViolationsTableSearchFilter';
Expand Down Expand Up @@ -81,6 +82,7 @@ type ViolationsTablePanelProps = {
onFilterChange: (newFilter: SearchFilter) => void;
onSearch: OnSearchCallback;
additionalContextFilter: SearchFilter;
filteredWorkflowView: FilteredWorkflowView;
hasActiveViolations: boolean;
isTableDataUpdating: boolean;
};
Expand All @@ -100,6 +102,7 @@ function ViolationsTablePanel({
onFilterChange,
onSearch,
additionalContextFilter,
filteredWorkflowView,
hasActiveViolations,
isTableDataUpdating,
}: ViolationsTablePanelProps): ReactElement {
Expand Down Expand Up @@ -240,6 +243,7 @@ function ViolationsTablePanel({
onFilterChange={onFilterChange}
onSearch={onSearch}
additionalContextFilter={additionalContextFilter}
filteredWorkflowView={filteredWorkflowView}
/>
<Divider component="div" />
<Toolbar>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,107 +3,33 @@ import { Toolbar, ToolbarContent, ToolbarGroup, ToolbarItem } from '@patternfly/
import type { SearchFilter } from 'types/search';
import useAnalytics from 'hooks/useAnalytics';
import { createFilterTracker } from 'utils/analyticsEventTracking';
import type {
CompoundSearchFilterConfig,
OnSearchCallback,
} from 'Components/CompoundSearchFilter/types';
import type { OnSearchCallback } from 'Components/CompoundSearchFilter/types';
import CompoundSearchFilter from 'Components/CompoundSearchFilter/components/CompoundSearchFilter';
import CompoundSearchFilterLabels from 'Components/CompoundSearchFilter/components/CompoundSearchFilterLabels';
import {
Category as PolicyCategory,
LifecycleStage as PolicyLifecycleStage,
Name as PolicyName,
Severity as PolicySeverity,
} from 'Components/CompoundSearchFilter/attributes/policy';
import {
EntityType as AlertEntityType,
ViolationTime as AlertViolationTime,
} from 'Components/CompoundSearchFilter/attributes/alert';
import {
clusterIdAttribute,
clusterLabelAttribute,
clusterNameAttribute,
} from 'Components/CompoundSearchFilter/attributes/cluster';
import {
Annotation as NamespaceAnnotation,
ID as NamespaceID,
Label as NamespaceLabel,
Name as NamespaceName,
} from 'Components/CompoundSearchFilter/attributes/namespace';
import {
Annotation as DeploymentAnnotation,
ID as DeploymentID,
Inactive as DeploymentInactive,
Label as DeploymentLabel,
Name as DeploymentName,
} from 'Components/CompoundSearchFilter/attributes/deployment';
import { Name as ResourceName } from 'Components/CompoundSearchFilter/attributes/resource';
import {
Annotation as NodeAnnotation,
Label as NodeLabel,
Name as NodeName,
} from 'Components/CompoundSearchFilter/attributes/node';
import type { FilteredWorkflowView } from 'Components/FilteredWorkflowViewSelector/types';

const searchFilterConfig: CompoundSearchFilterConfig = [
{
displayName: 'Cluster',
searchCategory: 'ALERTS',
attributes: [clusterIdAttribute, clusterLabelAttribute, clusterNameAttribute],
},
{
displayName: 'Deployment',
searchCategory: 'ALERTS',
attributes: [
DeploymentAnnotation,
DeploymentID,
DeploymentLabel,
DeploymentName,
DeploymentInactive, // Status
],
},
{
displayName: 'Namespace',
searchCategory: 'ALERTS',
attributes: [NamespaceAnnotation, NamespaceID, NamespaceLabel, NamespaceName],
},
{
displayName: 'Policy',
searchCategory: 'ALERTS',
attributes: [PolicyCategory, PolicyLifecycleStage, PolicyName, PolicySeverity],
},
{
displayName: 'Policy violation',
searchCategory: 'ALERTS',
attributes: [AlertViolationTime, AlertEntityType], // non-alphabetical because no Name
},
{
displayName: 'Node',
searchCategory: 'ALERTS',
attributes: [NodeAnnotation, NodeLabel, NodeName],
},
{
displayName: 'Resource',
searchCategory: 'ALERTS',
attributes: [ResourceName],
},
];
import { getSearchFilterConfig } from './ViolationsTableSearchFilter.utils';

export type ViolationsTableSearchFilterProps = {
searchFilter: SearchFilter;
onFilterChange: (newFilter: SearchFilter) => void;
onSearch: OnSearchCallback;
additionalContextFilter: SearchFilter;
filteredWorkflowView: FilteredWorkflowView;
};

function ViolationsTableSearchFilter({
searchFilter,
onFilterChange,
onSearch,
additionalContextFilter,
filteredWorkflowView,
}: ViolationsTableSearchFilterProps) {
const { analyticsTrack } = useAnalytics();
const trackAppliedFilter = createFilterTracker(analyticsTrack);

const searchFilterConfig = getSearchFilterConfig(filteredWorkflowView);

const onSearchHandler: OnSearchCallback = (payload) => {
onSearch(payload);
trackAppliedFilter('Policy Violations Filter Applied', payload);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import { getSearchFilterConfig } from './ViolationsTableSearchFilter.utils';

describe('getSearchFilterConfig', () => {
it('should return exactly the expected entities for "Applications view"', () => {
const config = getSearchFilterConfig('Applications view');
const names = config.map((e) => e.displayName).sort();

expect(names).toEqual(
['Cluster', 'Deployment', 'Namespace', 'Policy', 'Policy violation'].sort()
);
});

it('should return exactly the expected entities for "Platform view"', () => {
const config = getSearchFilterConfig('Platform view');
const names = config.map((e) => e.displayName).sort();

expect(names).toEqual(
['Cluster', 'Deployment', 'Namespace', 'Policy', 'Policy violation'].sort()
);
});

it('should return exactly the expected entities for "Node view"', () => {
const config = getSearchFilterConfig('Node view');
const names = config.map((e) => e.displayName).sort();

expect(names).toEqual(['Cluster', 'Node', 'Policy', 'Policy violation'].sort());
});

it('should return all entities for "Full view"', () => {
const config = getSearchFilterConfig('Full view');
const names = config.map((e) => e.displayName).sort();

expect(names).toEqual(
[
'Cluster',
'Deployment',
'Namespace',
'Node',
'Policy',
'Policy violation',
'Resource',
].sort()
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import type { CompoundSearchFilterConfig } from 'Components/CompoundSearchFilter/types';
import {
Category as PolicyCategory,
LifecycleStage as PolicyLifecycleStage,
Name as PolicyName,
Severity as PolicySeverity,
} from 'Components/CompoundSearchFilter/attributes/policy';
import {
EntityType as AlertEntityType,
ViolationTime as AlertViolationTime,
} from 'Components/CompoundSearchFilter/attributes/alert';
import {
clusterIdAttribute,
clusterLabelAttribute,
clusterNameAttribute,
} from 'Components/CompoundSearchFilter/attributes/cluster';
import {
Annotation as NamespaceAnnotation,
ID as NamespaceID,
Label as NamespaceLabel,
Name as NamespaceName,
} from 'Components/CompoundSearchFilter/attributes/namespace';
import {
Annotation as DeploymentAnnotation,
ID as DeploymentID,
Inactive as DeploymentInactive,
Label as DeploymentLabel,
Name as DeploymentName,
} from 'Components/CompoundSearchFilter/attributes/deployment';
import { Name as ResourceName } from 'Components/CompoundSearchFilter/attributes/resource';
import {
Annotation as NodeAnnotation,
Label as NodeLabel,
Name as NodeName,
} from 'Components/CompoundSearchFilter/attributes/node';
import type { FilteredWorkflowView } from 'Components/FilteredWorkflowViewSelector/types';

type ViolationSearchEntityName =
| 'Cluster'
| 'Deployment'
| 'Namespace'
| 'Node'
| 'Policy'
| 'Policy violation'
| 'Resource';

const allSearchFilterEntities: CompoundSearchFilterConfig = [
{
displayName: 'Cluster',
searchCategory: 'ALERTS',
attributes: [clusterIdAttribute, clusterLabelAttribute, clusterNameAttribute],
},
{
displayName: 'Deployment',
searchCategory: 'ALERTS',
attributes: [
DeploymentAnnotation,
DeploymentID,
DeploymentLabel,
DeploymentName,
DeploymentInactive, // Status
],
},
{
displayName: 'Namespace',
searchCategory: 'ALERTS',
attributes: [NamespaceAnnotation, NamespaceID, NamespaceLabel, NamespaceName],
},
{
displayName: 'Node',
searchCategory: 'ALERTS',
attributes: [NodeAnnotation, NodeLabel, NodeName],
},
{
displayName: 'Policy',
searchCategory: 'ALERTS',
attributes: [PolicyCategory, PolicyLifecycleStage, PolicyName, PolicySeverity],
},
{
displayName: 'Policy violation',
searchCategory: 'ALERTS',
attributes: [AlertViolationTime, AlertEntityType], // non-alphabetical because no Name
},
{
displayName: 'Resource',
searchCategory: 'ALERTS',
attributes: [ResourceName],
},
];

const allowedEntitiesByView: Record<FilteredWorkflowView, ViolationSearchEntityName[]> = {
'Applications view': ['Cluster', 'Deployment', 'Namespace', 'Policy', 'Policy violation'],
'Platform view': ['Cluster', 'Deployment', 'Namespace', 'Policy', 'Policy violation'],
'Node view': ['Cluster', 'Policy', 'Policy violation', 'Node'],
'Full view': [],
};

export function getSearchFilterConfig(
filteredWorkflowView: FilteredWorkflowView
): CompoundSearchFilterConfig {
const allowed = allowedEntitiesByView[filteredWorkflowView];
if (allowed.length === 0) {
return allSearchFilterEntities;
}
return allSearchFilterEntities.filter((entity) =>
(allowed as readonly string[]).includes(entity.displayName)
);
}
Loading