Skip to content

Commit 713e714

Browse files
committed
Refactor the FilterBox component to enhance TypeScript type safety with explicit props, states, and refined filter handling logic.
1 parent e7b72e7 commit 713e714

File tree

1 file changed

+106
-55
lines changed
  • benchexec/tablegenerator/react-table/src/components/FilterBox

1 file changed

+106
-55
lines changed

benchexec/tablegenerator/react-table/src/components/FilterBox/FilterBox.tsx

Lines changed: 106 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -12,33 +12,73 @@ import { faClose, faTrash } from "@fortawesome/free-solid-svg-icons";
1212
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
1313
import equals from "deep-equal";
1414
import { decodeFilter, isNil } from "../../utils/utils";
15+
1516
const classNames = require("classnames");
1617

17-
export default class FilterBox extends React.PureComponent {
18-
listeners: any;
19-
resetFilterHook: any;
20-
constructor(props: any) {
18+
type IdFilter = {
19+
id: "id";
20+
values: any[];
21+
};
22+
23+
type ValueFilter = {
24+
id: string;
25+
value: any;
26+
};
27+
28+
type ReactTableFilter = IdFilter | ValueFilter;
29+
30+
type ColumnFilter = {
31+
title: string;
32+
values: any[];
33+
};
34+
35+
type ToolFilters = Array<ColumnFilter | undefined>;
36+
37+
interface FilterableTool {
38+
name: string;
39+
columns: any[];
40+
}
41+
42+
interface FilterBoxProps {
43+
filtered?: ReactTableFilter[];
44+
ids: Record<string, unknown>;
45+
addTypeToFilter: (filters: ReactTableFilter[]) => void;
46+
setFilter: (filters: ReactTableFilter[], replace: boolean) => void;
47+
hiddenCols?: any[][];
48+
visible: boolean;
49+
hide: () => void;
50+
headerComponent?: React.ReactNode;
51+
filterable: FilterableTool[];
52+
}
53+
54+
interface FilterBoxState {
55+
filters: ToolFilters[];
56+
idFilters?: any[] | null;
57+
}
58+
59+
export default class FilterBox extends React.PureComponent<FilterBoxProps, FilterBoxState> {
60+
listeners: Array<() => void>;
61+
resetFilterHook: (fun: () => void) => void;
62+
63+
constructor(props: FilterBoxProps) {
2164
super(props);
2265

2366
const { filtered } = props;
2467

2568
this.listeners = [];
2669

27-
this.resetFilterHook = (fun: any) => this.listeners.push(fun);
70+
this.resetFilterHook = (fun: () => void) => this.listeners.push(fun);
2871

2972
this.state = {
3073
filters: this.createFiltersFromReactTableStructure(filtered),
3174
idFilters: this.retrieveIdFilters(filtered),
3275
};
3376
}
3477

35-
componentDidUpdate(prevProps: any) {
36-
// @ts-expect-error TS(2339): Property 'filtered' does not exist on type 'Readon... Remove this comment to see the full error message
78+
componentDidUpdate(prevProps: FilterBoxProps) {
3779
if (!equals(prevProps.filtered, this.props.filtered)) {
3880
this.setState({
39-
// @ts-expect-error TS(2339): Property 'filtered' does not exist on type 'Readon... Remove this comment to see the full error message
4081
filters: this.createFiltersFromReactTableStructure(this.props.filtered),
41-
// @ts-expect-error TS(2339): Property 'filtered' does not exist on type 'Readon... Remove this comment to see the full error message
4282
idFilters: this.retrieveIdFilters(this.props.filtered),
4383
});
4484
}
@@ -50,121 +90,138 @@ export default class FilterBox extends React.PureComponent {
5090
}
5191

5292
resetIdFilters() {
53-
const empty = null; //Object.keys(this.props.ids).map(() => null);
93+
const empty: any[] | null = null; //Object.keys(this.props.ids).map(() => null);
5494
this.setState({ idFilters: empty });
55-
// @ts-expect-error TS(2339): Property 'filters' does not exist on type 'Readonl... Remove this comment to see the full error message
5695
this.sendFilters({ filter: this.state.filters, idFilter: empty });
5796
}
5897

5998
resetAllContainers() {
60-
this.listeners.forEach((fun: any) => fun());
99+
this.listeners.forEach((fun) => fun());
61100
}
62101

63-
retrieveIdFilters(filters: any) {
64-
const possibleIdFilter = filters.find((filter: any) => filter.id === "id");
102+
retrieveIdFilters(filters: ReactTableFilter[] | undefined): any[] | undefined {
103+
if (!filters || !filters.length) {
104+
return [];
105+
}
106+
107+
const possibleIdFilter = filters.find(
108+
(filter): filter is IdFilter =>
109+
filter.id === "id" && (filter as IdFilter).values !== undefined,
110+
);
65111
return possibleIdFilter ? possibleIdFilter.values : [];
66112
}
67113

68-
createFiltersFromReactTableStructure(filters: any) {
114+
createFiltersFromReactTableStructure(filters: ReactTableFilter[] | undefined): ToolFilters[] {
69115
if (!filters || !filters.length) {
70116
return [];
71117
}
72118

73-
const out: any = [];
119+
const outByTool: Record<string, ToolFilters> = {};
74120

75-
for (const { id, value } of filters.flat()) {
76-
if (id === "id") {
121+
const flattened: ReactTableFilter[] = Array.isArray((filters as any)[0])
122+
? (filters as any).flat()
123+
: filters;
124+
125+
for (const f of flattened) {
126+
if (f.id === "id") {
77127
continue;
78128
}
79-
const { tool, name: title, column } = decodeFilter(id);
80-
const toolArr = out[tool] || [];
81-
if (!toolArr[column]) {
82-
toolArr[column] = { title, values: [value] };
129+
130+
const { id, value } = f as ValueFilter;
131+
const { tool, name, column } = decodeFilter(id) as {
132+
tool: string | number;
133+
name: string;
134+
column: string | number;
135+
};
136+
const title = name;
137+
138+
const columnIndex = Number(column);
139+
if (!Number.isFinite(columnIndex)) {
140+
continue;
141+
}
142+
143+
const toolId = String(tool);
144+
const toolArr: ToolFilters = outByTool[toolId] || [];
145+
146+
if (!toolArr[columnIndex]) {
147+
toolArr[columnIndex] = { title, values: [value] };
83148
} else {
84-
toolArr[column].values.push(value);
149+
toolArr[columnIndex]!.values.push(value);
85150
}
86-
out[tool] = toolArr;
151+
outByTool[toolId] = toolArr;
87152
}
88-
return out;
153+
return Object.values(outByTool);
89154
}
90155

91156
flattenFilterStructure() {
92-
// @ts-expect-error TS(2339): Property 'filters' does not exist on type 'Readonl... Remove this comment to see the full error message
93-
return Object.values(Object.values(this.state.filters));
157+
return Object.values(this.state.filters).flat();
94158
}
95159

96-
sendFilters({ filter, idFilter }: any) {
97-
const newFilter = [
160+
sendFilters({ filter, idFilter }: { filter: ToolFilters[]; idFilter?: any[] | null }) {
161+
const newFilter: ReactTableFilter[] = [
98162
...filter
99-
.map((tool: any, toolIdx: any) => {
100-
if (tool === null || tool === undefined) {
163+
.map((tool, toolIdx) => {
164+
if (!tool) {
101165
return null;
102166
}
103-
return tool.map((col: any, colIdx: any) => {
104-
return col.values.map((val: any) => ({
167+
return tool.map((col, colIdx) => {
168+
if (!col) {
169+
return null;
170+
}
171+
return col.values.map((val) => ({
105172
id: `${toolIdx}_${col.title}_${colIdx}`,
106173
value: val,
107174
}));
108175
});
109176
})
110177
.flat(3)
111-
.filter((i: any) => i !== null && i !== undefined),
178+
.filter((i): i is ValueFilter => i !== null && i !== undefined),
112179
];
180+
113181
if (idFilter && idFilter.length > 0) {
114182
newFilter.push({ id: "id", values: idFilter });
115183
}
116184

117-
// @ts-expect-error TS(2339): Property 'addTypeToFilter' does not exist on type ... Remove this comment to see the full error message
118185
this.props.addTypeToFilter(newFilter);
119-
// @ts-expect-error TS(2339): Property 'setFilter' does not exist on type 'Reado... Remove this comment to see the full error message
120186
this.props.setFilter(newFilter, true);
121187
}
122188

123-
updateFilters(toolIdx: any, columnIdx: any, data: any) {
189+
updateFilters(toolIdx: number, columnIdx: number, data: ColumnFilter) {
124190
//this.props.setFilter(newFilter);
125-
// @ts-expect-error TS(2339): Property 'filters' does not exist on type 'Readonl... Remove this comment to see the full error message
126191
const newFilters = [...this.state.filters];
127-
// @ts-expect-error TS(2339): Property 'idFilters' does not exist on type 'Reado... Remove this comment to see the full error message
128192
const idFilter = this.state.idFilters;
129193
newFilters[toolIdx] = newFilters[toolIdx] || [];
130-
newFilters[toolIdx][columnIdx] = data;
194+
newFilters[toolIdx]![columnIdx] = data;
131195
this.setState({ filters: newFilters });
132196
this.sendFilters({ filter: newFilters, idFilter });
133197
}
134198

135199
updateIdFilters(data: any) {
136-
// @ts-expect-error TS(2339): Property 'ids' does not exist on type 'Readonly<{}... Remove this comment to see the full error message
137-
const mapped = Object.keys(this.props.ids).map((i) => data[i]);
200+
const ids = this.props.ids || {};
201+
const mapped = Object.keys(ids).map((i) => (data as any)[i]);
138202

139203
const newFilter = mapped.some((item) => item !== "" && !isNil(item))
140204
? mapped
141205
: undefined;
142206

143207
this.setState({ idFilters: newFilter });
144-
145-
// @ts-expect-error TS(2339): Property 'filters' does not exist on type 'Readonl... Remove this comment to see the full error message
146208
this.sendFilters({ filter: this.state.filters, idFilter: newFilter });
147209
}
148210

149211
render() {
150-
// @ts-expect-error TS(2339): Property 'hiddenCols' does not exist on type 'Read... Remove this comment to see the full error message
151212
const hiddenCols = this.props.hiddenCols || [];
152213
return (
153214
<div
154215
className={classNames("filterBox", {
155-
// @ts-expect-error TS(2339): Property 'visible' does not exist on type 'Readonl... Remove this comment to see the full error message
156216
"filterBox--hidden": !this.props.visible,
157217
})}
158218
>
159219
<div className="filterBox--header">
160220
<FontAwesomeIcon
161221
icon={faClose}
162222
className="filterBox--header--icon"
163-
// @ts-expect-error TS(2339): Property 'hide' does not exist on type 'Readonly<{... Remove this comment to see the full error message
164223
onClick={this.props.hide}
165224
/>
166-
// @ts-expect-error TS(2339): Property 'headerComponent' does not
167-
exist on type ... Remove this comment to see the full error message
168225
{this.props.headerComponent}
169226
<FontAwesomeIcon
170227
icon={faTrash}
@@ -175,24 +232,18 @@ export default class FilterBox extends React.PureComponent {
175232

176233
<div className="filter-card--container">
177234
<TaskFilterCard
178-
// @ts-expect-error TS(2322): Type '{ ids: any; updateFilters: (data: any) => vo... Remove this comment to see the full error message
179235
ids={this.props.ids}
180236
updateFilters={(data: any) => this.updateIdFilters(data)}
181237
resetFilterHook={this.resetFilterHook}
182-
// @ts-expect-error TS(2339): Property 'idFilters' does not exist on type 'Reado... Remove this comment to see the full error message
183238
filters={this.state.idFilters}
184239
/>
185-
// @ts-expect-error TS(2339): Property 'filterable' does not exist on
186-
type 'Read... Remove this comment to see the full error message
187240
{this.props.filterable.map((tool: any, idx: any) => {
188241
return (
189242
<FilterContainer
190-
// @ts-expect-error TS(2322): Type '{ resetFilterHook: any; updateFilters: (data... Remove this comment to see the full error message
191243
resetFilterHook={this.resetFilterHook}
192244
updateFilters={(data: any, columnIndex: any) =>
193245
this.updateFilters(idx, columnIndex, data)
194246
}
195-
// @ts-expect-error TS(2339): Property 'filters' does not exist on type 'Readonl... Remove this comment to see the full error message
196247
currentFilters={this.state.filters[idx] || []}
197248
toolName={tool.name}
198249
filters={tool.columns}

0 commit comments

Comments
 (0)