Skip to content

Commit

Permalink
feat: full path filter
Browse files Browse the repository at this point in the history
Splits path filter between boots and tests; Adds filtering to hardwareDetails; Syncs filter listing and input field; Fixes boot commit history graph not using the path filter. Closes #578 and Closes #582
  • Loading branch information
MarceloRobert committed Nov 27, 2024
1 parent f3d8e13 commit d428e9c
Show file tree
Hide file tree
Showing 15 changed files with 84 additions and 29 deletions.
2 changes: 1 addition & 1 deletion backend/kernelCI_app/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ class FilterParams:
"like": ["like", "LIKE"],
}

string_like_filters = ["test.path"]
string_like_filters = ["boot.path", "test.path"]

def __init__(self, request):
self.filters = []
Expand Down
8 changes: 7 additions & 1 deletion backend/kernelCI_app/views/hardwareDetailsView.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,13 @@ def pass_in_filters(self, data, filters):
field = currentFilter.get("field")
value = currentFilter.get("value")

if data[field] not in value:
if (
field == "path"
and value[0] not in data[field]
):
return False

if (data[field] not in value):
return False

return True
Expand Down
19 changes: 15 additions & 4 deletions backend/kernelCI_app/views/treeDetailsSlowView.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def __init__(self):
self.filterTreeDetailsCompiler = set()
self.filterArchitecture = set()
self.filterHardware = set()
self.filterPath = ""
self.filterTestPath = ""
self.filterBootPath = ""
self.filter_handlers = {
"boot.status": self.__handle_boot_status,
"boot.duration": self.__handle_boot_duration,
Expand All @@ -38,6 +39,7 @@ def __init__(self):
"architecture": self.__handle_architecture,
"test.hardware": self.__handle_hardware,
"test.path": self.__handle_path,
"boot.path": self.__handle_path,
}

self.testHistory = []
Expand Down Expand Up @@ -98,7 +100,10 @@ def __handle_hardware(self, current_filter):
self.filterHardware.add(current_filter["value"])

def __handle_path(self, current_filter):
self.filterPath = current_filter["value"]
if current_filter["field"] == "boot.path":
self.filterBootPath = current_filter["value"]
else:
self.filterTestPath = current_filter["value"]

def __processFilters(self, request):
try:
Expand Down Expand Up @@ -478,8 +483,14 @@ def get(self, request, commit_hash: str | None):

if (
(
self.filterPath != ""
and (self.filterPath not in path)
path.startswith("boot")
and self.filterBootPath != ""
and (self.filterBootPath not in path)
)
or (
not path.startswith("boot")
and self.filterTestPath != ""
and (self.filterTestPath not in path)
)
or (
len(self.filterHardware) > 0
Expand Down
18 changes: 11 additions & 7 deletions dashboard/src/components/BootsTable/BootsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,8 @@ interface IBootsTable {
filter: TestsTableFilter;
getRowLink: (testId: TestHistory['id']) => LinkProps;
onClickFilter: (newFilter: TestsTableFilter) => void;
updatePathFilter: (pathFilter: string) => void;
updatePathFilter?: (pathFilter: string) => void;
currentPathFilter?: string;
}

const TableCellComponent = ({
Expand Down Expand Up @@ -192,12 +193,14 @@ const TableRowComponent = ({
const TableCellMemoized = memo(TableCellComponent);
const TableRowMemoized = memo(TableRowComponent);

// TODO: would be useful if the navigation happened within the table, so the parent component would only be required to pass the navigation url instead of the whole function for the update and the currentPath diffFilter (boots/tests Table)
export function BootsTable({
testHistory,
filter,
getRowLink,
onClickFilter,
updatePathFilter,
currentPathFilter,
}: IBootsTable): JSX.Element {
const [sorting, setSorting] = useState<SortingState>([]);
const [pagination, setPagination] = useState<PaginationState>({
Expand Down Expand Up @@ -313,14 +316,14 @@ export function BootsTable({
?.setFilterValue(filter !== 'all' ? filter : undefined);
}, [filter, table]);

// TODO: there should be a filtering for the frontend before the backend AND that filtering should consider the individual tests inside each test "batch" (the data from individualTestsTables), not only the rows of the external table
const onSearchChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value !== undefined) {
if (e.target.value !== undefined && updatePathFilter) {
updatePathFilter(e.target.value);
}
// TODO: only use the frontend filtering when the backend filter function is undefined (like in BuildDetails page)
table.setGlobalFilter(String(e.target.value));
if (updatePathFilter === undefined) {
table.setGlobalFilter(String(e.target.value));
}
},
[table, updatePathFilter],
);
Expand All @@ -342,9 +345,10 @@ export function BootsTable({
{header.id === 'path' ? (
<div className="flex items-center">
{headerComponent}
{/* TODO: add startingValue with the currentPathFilter from the diffFilter param, same for TestsTable */}
<DebounceInput
key={currentPathFilter}
debouncedSideEffect={onSearchChange}
startingValue={currentPathFilter}
className="w-50 font-normal"
type="text"
placeholder={intl.formatMessage({ id: 'global.search' })}
Expand All @@ -356,7 +360,7 @@ export function BootsTable({
</TableHead>
);
});
}, [groupHeaders, intl, onSearchChange, sorting]);
}, [currentPathFilter, groupHeaders, intl, onSearchChange, sorting]);

const modelRows = table.getRowModel().rows;

Expand Down
13 changes: 9 additions & 4 deletions dashboard/src/components/TestsTable/TestsTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,10 @@ export interface ITestsTable {
innerColumns?: ColumnDef<TIndividualTest>[];
getRowLink: (testId: TestHistory['id']) => LinkProps;
updatePathFilter?: (pathFilter: string) => void;
currentPathFilter?: string;
}

// TODO: would be useful if the navigation happened within the table, so the parent component would only be required to pass the navigation url instead of the whole function for the update and the currentPath diffFilter (boots/tests Table)
export function TestsTable({
testHistory,
onClickFilter,
Expand All @@ -58,6 +60,7 @@ export function TestsTable({
innerColumns = defaultInnerColumns,
getRowLink,
updatePathFilter,
currentPathFilter,
}: ITestsTable): JSX.Element {
const [sorting, setSorting] = useState<SortingState>([]);
const [expanded, setExpanded] = useState<ExpandedState>({});
Expand Down Expand Up @@ -255,14 +258,14 @@ export function TestsTable({
[filterCount, intl, filter],
);

// TODO: there should be a filtering for the frontend before the backend AND that filtering should consider the individual tests inside each test "batch" (the data from individualTestsTables), not only the rows of the external table
const onSearchChange = useCallback(
(e: React.ChangeEvent<HTMLInputElement>) => {
if (e.target.value !== undefined && updatePathFilter) {
updatePathFilter(e.target.value);
}
// TODO: remove this frontend filter when the hardwareDetails backend filtering gets in place
table.setGlobalFilter(String(e.target.value));
if (updatePathFilter === undefined) {
table.setGlobalFilter(String(e.target.value));
}
},
[table, updatePathFilter],
);
Expand All @@ -285,7 +288,9 @@ export function TestsTable({
<div className="flex items-center">
{headerComponent}
<DebounceInput
key={currentPathFilter}
debouncedSideEffect={onSearchChange}
startingValue={currentPathFilter}
className="w-50 font-normal"
type="text"
placeholder={intl.formatMessage({ id: 'global.search' })}
Expand All @@ -297,7 +302,7 @@ export function TestsTable({
</TableHead>
);
});
}, [groupHeaders, intl, onSearchChange, sorting]);
}, [currentPathFilter, groupHeaders, intl, onSearchChange, sorting]);

const modelRows = table.getRowModel().rows;
const tableRows = useMemo((): JSX.Element[] | JSX.Element => {
Expand Down
8 changes: 6 additions & 2 deletions dashboard/src/pages/TreeDetails/Tabs/Boots/BootsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ const BootsTab = ({ reqFilter }: BootsTabProps): JSX.Element => {
const { treeId } = useParams({
from: '/tree/$treeId/',
});
const { tableFilter } = useSearch({
const { tableFilter, diffFilter } = useSearch({
from: '/tree/$treeId/',
});
const currentPathFilter = diffFilter.bootPath
? Object.keys(diffFilter.bootPath)[0]
: undefined;

const navigate = useNavigate({ from: '/tree/$treeId/' });

Expand All @@ -45,7 +48,7 @@ const BootsTab = ({ reqFilter }: BootsTabProps): JSX.Element => {
...previousSearch,
diffFilter: {
...previousSearch.diffFilter,
path: pathFilter === '' ? undefined : { [pathFilter]: true },
bootPath: pathFilter === '' ? undefined : { [pathFilter]: true },
},
}),
});
Expand Down Expand Up @@ -181,6 +184,7 @@ const BootsTab = ({ reqFilter }: BootsTabProps): JSX.Element => {
testHistory={data.bootHistory}
getRowLink={getRowLink}
updatePathFilter={updatePathFilter}
currentPathFilter={currentPathFilter}
/>
</div>
);
Expand Down
8 changes: 6 additions & 2 deletions dashboard/src/pages/TreeDetails/Tabs/Tests/TestsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,12 @@ const TestsTab = ({ reqFilter }: TestsTabProps): JSX.Element => {
filter: reqFilter,
});

const { tableFilter } = useSearch({
const { tableFilter, diffFilter } = useSearch({
from: '/tree/$treeId/',
});
const currentPathFilter = diffFilter.testPath
? Object.keys(diffFilter.testPath)[0]
: undefined;

const navigate = useNavigate({ from: '/tree/$treeId' });

Expand All @@ -51,7 +54,7 @@ const TestsTab = ({ reqFilter }: TestsTabProps): JSX.Element => {
...previousSearch,
diffFilter: {
...previousSearch.diffFilter,
path: pathFilter === '' ? undefined : { [pathFilter]: true },
testPath: pathFilter === '' ? undefined : { [pathFilter]: true },
},
}),
});
Expand Down Expand Up @@ -186,6 +189,7 @@ const TestsTab = ({ reqFilter }: TestsTabProps): JSX.Element => {
filter={tableFilter.testsTable}
getRowLink={getRowLink}
updatePathFilter={updatePathFilter}
currentPathFilter={currentPathFilter}
/>
</div>
);
Expand Down
3 changes: 2 additions & 1 deletion dashboard/src/pages/TreeDetails/TreeDetailsFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ const filterFieldMap = {
'test.duration_[gte]': 'testDurationMin',
'test.duration_[lte]': 'testDurationMax',
'test.hardware': 'hardware',
'test.path': 'path',
'test.path': 'testPath',
'boot.path': 'bootPath',
} as const satisfies Record<TRequestFiltersValues, TFilterKeys>;

export const mapFilterToReq = (
Expand Down
2 changes: 2 additions & 0 deletions dashboard/src/pages/hardwareDetails/HardwareDetailsFilter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ const filterFieldMap = {
'test.status': 'testStatus',
'test.duration_[gte]': 'testDurationMin',
'test.duration_[lte]': 'testDurationMax',
'test.path': 'testPath',
'boot.path': 'bootPath',
} as const satisfies Record<TRequestFiltersValues, TFilterKeys>;

export const mapFilterToReq = (
Expand Down
8 changes: 6 additions & 2 deletions dashboard/src/pages/hardwareDetails/Tabs/Boots/BootsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -145,9 +145,12 @@ const ErrorsSummary = ({
export const MemoizedErrorsSummary = memo(ErrorsSummary);

const BootsTab = ({ boots, hardwareId }: TBootsTab): JSX.Element => {
const { tableFilter } = useSearch({
const { tableFilter, diffFilter } = useSearch({
from: '/hardware/$hardwareId',
});
const currentPathFilter = diffFilter.bootPath
? Object.keys(diffFilter.bootPath)[0]
: undefined;

const getRowLink = useCallback(
(bootId: string): LinkProps => ({
Expand All @@ -170,7 +173,7 @@ const BootsTab = ({ boots, hardwareId }: TBootsTab): JSX.Element => {
...previousSearch,
diffFilter: {
...previousSearch.diffFilter,
path: pathFilter === '' ? undefined : { [pathFilter]: true },
bootPath: pathFilter === '' ? undefined : { [pathFilter]: true },
},
}),
});
Expand Down Expand Up @@ -245,6 +248,7 @@ const BootsTab = ({ boots, hardwareId }: TBootsTab): JSX.Element => {
testHistory={boots.history}
onClickFilter={onClickFilter}
updatePathFilter={updatePathFilter}
currentPathFilter={currentPathFilter}
/>
</div>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ const HardwareDetailsTestTable = ({
testHistory,
hardwareId,
updatePathFilter,
currentPathFilter,
}: IHardwareDetailsTestTable): JSX.Element => {
const getRowLink = useCallback(
(bootId: string): LinkProps => ({
Expand All @@ -116,6 +117,7 @@ const HardwareDetailsTestTable = ({
innerColumns={innerColumns}
getRowLink={getRowLink}
updatePathFilter={updatePathFilter}
currentPathFilter={currentPathFilter}
/>
);
};
Expand Down
9 changes: 6 additions & 3 deletions dashboard/src/pages/hardwareDetails/Tabs/Tests/TestsTab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,23 @@ interface TTestsTab {
}

const TestsTab = ({ tests, hardwareId }: TTestsTab): JSX.Element => {
const { tableFilter } = useSearch({
const { tableFilter, diffFilter } = useSearch({
from: '/hardware/$hardwareId',
});
const currentPathFilter = diffFilter.testPath
? Object.keys(diffFilter.testPath)[0]
: undefined;

const navigate = useNavigate({ from: '/hardware/$hardwareId' });

// TODO: move inside the same hook for the tables, passing navigate, in order to not repeat the same code in each tab of each monitor
const updatePathFilter = useCallback(
(pathFilter: string) => {
navigate({
search: previousSearch => ({
...previousSearch,
diffFilter: {
...previousSearch.diffFilter,
path: pathFilter === '' ? undefined : { [pathFilter]: true },
testPath: pathFilter === '' ? undefined : { [pathFilter]: true },
},
}),
});
Expand Down Expand Up @@ -116,6 +118,7 @@ const TestsTab = ({ tests, hardwareId }: TTestsTab): JSX.Element => {
hardwareId={hardwareId}
onClickFilter={onClickFilter}
updatePathFilter={updatePathFilter}
currentPathFilter={currentPathFilter}
/>
</div>
);
Expand Down
6 changes: 6 additions & 0 deletions dashboard/src/types/hardware/hardwareDetails.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ export const zFilterObjectsKeys = z.enum([
'testStatus',
'trees',
'path',
'bootPath',
'testPath',
]);
export const zFilterNumberKeys = z.enum([
'buildDurationMin',
Expand Down Expand Up @@ -98,6 +100,8 @@ export const zDiffFilter = z
testDurationMax: zFilterNumberValue,
trees: zFilterBoolValue,
path: zFilterBoolValue,
bootPath: zFilterBoolValue,
testPath: zFilterBoolValue,
} satisfies Record<TFilterKeys, unknown>),
z.record(z.never()),
])
Expand Down Expand Up @@ -132,6 +136,8 @@ const requestFilters = {
'boot.status',
'boot.duration_[gte]',
'boot.duration_[lte]',
'test.path',
'boot.path',
],
} as const;

Expand Down
Loading

0 comments on commit d428e9c

Please sign in to comment.