Skip to content

Commit 2ebffac

Browse files
authored
Sourabh/fixing description filter for named version (#191)
* Removing description filter as it is not supported from the server side * Adding virtualization for table
1 parent 558a7ff commit 2ebffac

9 files changed

Lines changed: 195 additions & 87 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"changes": [
3+
{
4+
"packageName": "@itwin/manage-versions-react",
5+
"comment": "Fix filter state persistence across tabs and remove description filter",
6+
"type": "patch"
7+
}
8+
],
9+
"packageName": "@itwin/manage-versions-react"
10+
}

packages/modules/manage-versions/jest.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ module.exports = {
1212
"^.+\\.module\\.(css|sass|scss)$",
1313
],
1414
testEnvironment: "jsdom",
15+
setupFilesAfterEnv: ["<rootDir>/src/tests/setupTests.ts"],
1516
moduleNameMapper: {
1617
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga|svg?.+)$":
1718
"<rootDir>/src/tests/mocks/fileMock.js",

packages/modules/manage-versions/src/components/ManageVersions/ChangesTab/ChangesTab.test.tsx

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ import { defaultStrings } from "../ManageVersions";
2424
import { RequestStatus } from "../types";
2525
import ChangesTab, { ChangesTabProps } from "./ChangesTab";
2626

27+
const TEST_CONTAINER_HEIGHT = 400;
28+
2729
const renderComponent = (initialProps?: Partial<ChangesTabProps>) => {
2830
const props: ChangesTabProps = {
2931
changesets: MockedChangesetList(),
@@ -35,9 +37,11 @@ const renderComponent = (initialProps?: Partial<ChangesTabProps>) => {
3537
...initialProps,
3638
};
3739
return render(
38-
<ConfigProvider {...MOCKED_CONFIG_PROPS}>
39-
<ChangesTab {...props} />
40-
</ConfigProvider>
40+
<div style={{ height: TEST_CONTAINER_HEIGHT }}>
41+
<ConfigProvider {...MOCKED_CONFIG_PROPS}>
42+
<ChangesTab {...props} />
43+
</ConfigProvider>
44+
</div>
4145
);
4246
};
4347

@@ -47,7 +51,8 @@ describe("ChangesTab", () => {
4751
const rows = container.querySelectorAll(
4852
".iac-changes-table-body [role='row']"
4953
);
50-
expect(rows.length).toBe(3);
54+
// Virtualization renders only visible rows
55+
expect(rows.length).toBeGreaterThanOrEqual(1);
5156

5257
rows.forEach((row, index) => {
5358
const cells = row.querySelectorAll("div[role='cell']");
@@ -107,7 +112,7 @@ describe("ChangesTab", () => {
107112
const rows = container.querySelectorAll(
108113
".iac-changes-table-body [role='row']"
109114
);
110-
expect(rows.length).toBe(1);
115+
expect(rows.length).toBeGreaterThanOrEqual(1);
111116

112117
const createVersionIcon = container.querySelector(
113118
".iac-create-version-icon-hidden"
@@ -124,7 +129,8 @@ describe("ChangesTab", () => {
124129
);
125130
const infoIcons = screen.queryAllByText("Information Panel");
126131
//should open information panel
127-
expect(infoIcons.length).toBe(rows.length);
132+
expect(infoIcons.length).toBeGreaterThanOrEqual(1);
133+
expect(rows.length).toBeGreaterThanOrEqual(1);
128134
await act(() => fireEvent.click(infoIcons[0]));
129135
const panel = container.querySelector(".iac-info-panel");
130136
expect(panel).toBeTruthy();

packages/modules/manage-versions/src/components/ManageVersions/ChangesTab/ChangesTab.tsx

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ export type ChangesTabProps = {
2929
onVersionCreated: () => void;
3030
latestVersion: NamedVersion | undefined;
3131
onFilterChange: (filters: { id: string; value: any }[]) => void;
32+
afterIndex?: number;
33+
lastIndex?: number;
3234
};
3335

3436
const ChangesTab = (props: ChangesTabProps) => {
@@ -39,6 +41,8 @@ const ChangesTab = (props: ChangesTabProps) => {
3941
onVersionCreated,
4042
latestVersion,
4143
onFilterChange,
44+
afterIndex,
45+
lastIndex,
4246
} = props;
4347

4448
const { stringsOverrides } = useConfig();
@@ -176,11 +180,21 @@ const ChangesTab = (props: ChangesTabProps) => {
176180
stringsOverrides.messageNoChanges,
177181
]);
178182

183+
const initialFilters = React.useMemo(() => {
184+
const filterArray = [];
185+
if (afterIndex !== undefined || lastIndex !== undefined) {
186+
const fromValue = afterIndex !== undefined ? afterIndex + 1 : undefined;
187+
filterArray.push({ id: "index", value: [fromValue, lastIndex] });
188+
}
189+
return filterArray;
190+
}, [afterIndex, lastIndex]);
191+
179192
return (
180193
<>
181194
<Table<Changeset>
182195
columns={columns}
183196
data={changesets}
197+
enableVirtualization={true}
184198
manualFilters={true}
185199
onFilter={onFilterChange}
186200
bodyProps={{
@@ -194,6 +208,7 @@ const ChangesTab = (props: ChangesTabProps) => {
194208
emptyFilteredTableContent={stringsOverrides.messageNoFilterResults}
195209
onBottomReached={loadMoreChanges}
196210
className="iac-changes-table"
211+
initialState={{ filters: initialFilters }}
197212
/>
198213
{isCreateVersionModalOpen && (
199214
<CreateVersionModal

packages/modules/manage-versions/src/components/ManageVersions/ManageVersions.test.tsx

Lines changed: 49 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,20 @@ import {
3131
ManageVersionsTabs,
3232
} from "./ManageVersions";
3333

34+
const TEST_CONTAINER_HEIGHT = 600;
35+
3436
const renderComponent = (initialProps?: Partial<ManageVersionsProps>) => {
3537
const props: ManageVersionsProps = {
3638
accessToken: "test_token",
3739
imodelId: MOCKED_IMODEL_ID,
3840
enableHideVersions: false,
3941
...initialProps,
4042
};
41-
return render(<ManageVersions {...props} />);
43+
return render(
44+
<div style={{ height: TEST_CONTAINER_HEIGHT }}>
45+
<ManageVersions {...props} />
46+
</div>
47+
);
4248
};
4349

4450
describe("ManageVersions", () => {
@@ -71,23 +77,31 @@ describe("ManageVersions", () => {
7177
const versionRows = container.querySelectorAll(
7278
".iac-versions-table-body [role='row']"
7379
);
74-
expect(versionRows.length).toBe(3);
75-
76-
versionRows.forEach(async (row, index) => {
77-
const cells = row.querySelectorAll("div[role='cell']");
78-
expect(cells.length).toBe(5);
79-
const mockedVersion = MockedVersion(versionRows.length - 1 - index);
80-
expect(cells[0].textContent).toContain(mockedVersion.name);
81-
expect(cells[1].textContent).toContain(mockedVersion.description);
82-
await waitFor(
83-
() => expect(cells[2].textContent).toContain(mockedVersion.createdBy),
84-
{ timeout: 10000 }
85-
);
86-
expect(cells[3].textContent).toContain(mockedVersion.createdDateTime);
87-
const actionsCell = cells[4] as HTMLElement;
88-
const button = within(actionsCell as HTMLElement).getByText("More");
89-
expect(button).toBeTruthy();
80+
// Virtualization renders only visible rows
81+
expect(versionRows.length).toBeGreaterThanOrEqual(1);
82+
83+
// Check that at least the first visible row has the expected structure
84+
const firstRow = versionRows[0];
85+
const cells = firstRow.querySelectorAll("div[role='cell']");
86+
expect(cells.length).toBe(5);
87+
88+
// Check that at least one of the mocked versions is visible
89+
const allVersionNames = Array.from(versionRows).map((row) => {
90+
const nameCell = row.querySelectorAll("div[role='cell']")[0];
91+
return nameCell.textContent;
9092
});
93+
94+
// At least one version name should match
95+
const hasMatchingVersion = [0, 1, 2].some((i) =>
96+
allVersionNames.some((name) => name?.includes(MockedVersion(i).name))
97+
);
98+
expect(hasMatchingVersion).toBe(true);
99+
100+
// Check that More button exists in action column
101+
const actionsCell = cells[4] as HTMLElement;
102+
const button = within(actionsCell as HTMLElement).getByText("More");
103+
expect(button).toBeTruthy();
104+
91105
expect(mockGetVersions).toHaveBeenCalledWith(MOCKED_IMODEL_ID, {
92106
top: 100,
93107
skip: undefined,
@@ -108,7 +122,8 @@ describe("ManageVersions", () => {
108122
const changesetRows = container.querySelectorAll(
109123
".iac-changes-table-body [role='row']"
110124
);
111-
expect(changesetRows.length).toBe(3);
125+
// Virtualization renders only visible rows
126+
expect(changesetRows.length).toBeGreaterThanOrEqual(1);
112127

113128
changesetRows.forEach((row, index) => {
114129
const cells = row.querySelectorAll("div[role='cell']");
@@ -210,7 +225,7 @@ describe("ManageVersions", () => {
210225
const createVersionButtons = screen.getAllByText(
211226
defaultStrings.createNamedVersion
212227
);
213-
expect(createVersionButtons.length).toBe(3);
228+
expect(createVersionButtons.length).toBeGreaterThanOrEqual(1);
214229
createVersionButtons[0].click();
215230

216231
await waitForSelectorToExist(".iac-additional-info");
@@ -328,7 +343,8 @@ describe("ManageVersions", () => {
328343
const initialVersionRows = container.querySelectorAll(
329344
".iac-versions-table-body [role='row']"
330345
);
331-
expect(initialVersionRows.length).toBe(2);
346+
// Virtualization renders only visible rows
347+
expect(initialVersionRows.length).toBeGreaterThanOrEqual(1);
332348

333349
expect(screen.queryByText(MockedVersion(4).name)).not.toBeInTheDocument();
334350
expect(screen.queryByText(MockedVersion(3).name)).not.toBeInTheDocument();
@@ -341,7 +357,8 @@ describe("ManageVersions", () => {
341357
const allVersionRows = container.querySelectorAll(
342358
".iac-versions-table-body [role='row']"
343359
);
344-
expect(allVersionRows.length).toBe(4);
360+
// Virtualization renders only visible rows - with toggle more should be visible
361+
expect(allVersionRows.length).toBeGreaterThanOrEqual(2);
345362

346363
const hiddenIcons = container.querySelectorAll(
347364
"svg[data-testid='hidden-version-icon']"
@@ -359,11 +376,17 @@ describe("ManageVersions", () => {
359376
mockUpdateVersion.mockResolvedValue(MockedVersion(2, { state: "hidden" }));
360377
const { container } = renderComponent({ enableHideVersions: true });
361378

362-
await waitFor(() => container.querySelector(".iac-versions-table-body"));
379+
// Wait for at least one row to render with virtualization
380+
await waitFor(() => {
381+
const rows = container.querySelectorAll(
382+
".iac-versions-table-body [role='row']"
383+
);
384+
expect(rows.length).toBeGreaterThanOrEqual(1);
385+
});
386+
363387
const initialVersionRows = container.querySelectorAll(
364388
".iac-versions-table-body [role='row']"
365389
);
366-
expect(initialVersionRows.length).toBe(3);
367390

368391
const firstRowCells =
369392
initialVersionRows[0].querySelectorAll("div[role='cell']");
@@ -386,7 +409,7 @@ describe("ManageVersions", () => {
386409
const updatedVersionRows = container.querySelectorAll(
387410
".iac-versions-table-body [role='row']"
388411
);
389-
expect(updatedVersionRows.length).toBe(2);
412+
expect(updatedVersionRows.length).toBeGreaterThanOrEqual(2);
390413
const hiddenIcons = container.querySelectorAll(
391414
"svg[data-testid='hidden-version-icon']"
392415
);
@@ -415,7 +438,8 @@ it("should render with changesets tab opened", async () => {
415438
const changesetRows = container.querySelectorAll(
416439
".iac-changes-table-body [role='row']"
417440
);
418-
expect(changesetRows.length).toBe(3);
441+
// Virtualization renders only visible rows
442+
expect(changesetRows.length).toBeGreaterThanOrEqual(1);
419443

420444
changesetRows.forEach(async (row, index) => {
421445
const cells = row.querySelectorAll("div[role='cell']");

packages/modules/manage-versions/src/components/ManageVersions/ManageVersions.tsx

Lines changed: 10 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -254,8 +254,6 @@ const ManageVersionsComponent = (props: ManageVersionsProps) => {
254254
RequestStatus.NotStarted
255255
);
256256
const [versionNameFilter, setVersionNameFilter] = React.useState("");
257-
const [versionDescriptionFilter, setVersionDescriptionFilter] =
258-
React.useState("");
259257

260258
const [changesets, setChangesets] = React.useState<Changeset[]>();
261259
const [changesetStatus, setChangesetStatus] = React.useState(
@@ -277,12 +275,7 @@ const ManageVersionsComponent = (props: ManageVersionsProps) => {
277275
);
278276

279277
const getVersions = React.useCallback(
280-
(
281-
skip?: number,
282-
reloadSubrows?: boolean,
283-
nameFilter?: string,
284-
descriptionFilter?: string
285-
) => {
278+
(skip?: number, reloadSubrows?: boolean, nameFilter?: string) => {
286279
setVersionStatus(RequestStatus.InProgress);
287280
const requestOptions: any = {
288281
top: NAMED_VERSION_TOP,
@@ -293,10 +286,6 @@ const ManageVersionsComponent = (props: ManageVersionsProps) => {
293286
requestOptions.name = nameFilter;
294287
}
295288

296-
if (descriptionFilter) {
297-
requestOptions.$search = descriptionFilter;
298-
}
299-
300289
versionClient
301290
.get(imodelId, requestOptions)
302291
.then((newVersions) => {
@@ -328,18 +317,8 @@ const ManageVersionsComponent = (props: ManageVersionsProps) => {
328317
return;
329318
}
330319

331-
getVersions(
332-
versionsTableData?.length,
333-
false,
334-
versionNameFilter,
335-
versionDescriptionFilter
336-
);
337-
}, [
338-
getVersions,
339-
versionsTableData,
340-
versionNameFilter,
341-
versionDescriptionFilter,
342-
]);
320+
getVersions(versionsTableData?.length, false, versionNameFilter);
321+
}, [getVersions, versionsTableData, versionNameFilter]);
343322

344323
const getChangesets = React.useCallback(
345324
(afterIndex?: number, lastIndex?: number) => {
@@ -379,28 +358,21 @@ const ManageVersionsComponent = (props: ManageVersionsProps) => {
379358
const refreshVersions = React.useCallback(
380359
(reloadSubrows?: boolean) => {
381360
setVersionsTableData([]);
382-
getVersions(
383-
undefined,
384-
reloadSubrows,
385-
versionNameFilter,
386-
versionDescriptionFilter
387-
);
361+
getVersions(undefined, reloadSubrows, versionNameFilter);
388362
},
389-
[getVersions, versionNameFilter, versionDescriptionFilter]
363+
[getVersions, versionNameFilter]
390364
);
391365

392366
const handleVersionFilterChange = React.useCallback(
393367
(filters: { id: string; value: any }[]) => {
394368
const nameFilter = filters.find((f) => f.id === "name");
395-
const descriptionFilter = filters.find((f) => f.id === "description");
396369

397370
const nameText = nameFilter?.value || "";
398-
const descriptionText = descriptionFilter?.value || "";
399371

400372
setVersionNameFilter(nameText);
401-
setVersionDescriptionFilter(descriptionText);
373+
setVersionsTableData([]);
402374

403-
getVersions(undefined, false, nameText, descriptionText);
375+
getVersions(undefined, false, nameText);
404376
},
405377
[getVersions]
406378
);
@@ -671,6 +643,7 @@ const ManageVersionsComponent = (props: ManageVersionsProps) => {
671643
handleHideVersion={handleToggleVersionState}
672644
showHiddenVersions={showHiddenVersions}
673645
onFilterChange={handleVersionFilterChange}
646+
nameFilter={versionNameFilter}
674647
/>
675648
)}
676649
{_currentTab === ManageVersionsTabs.Changes && (
@@ -683,6 +656,8 @@ const ManageVersionsComponent = (props: ManageVersionsProps) => {
683656
onVersionCreated={onVersionCreated}
684657
latestVersion={latestVersion?.version}
685658
onFilterChange={handleChangesetFilterChange}
659+
afterIndex={changesetAfterIndex}
660+
lastIndex={changesetLastIndex}
686661
/>
687662
)}
688663
</div>

0 commit comments

Comments
 (0)