Skip to content

Commit 4748623

Browse files
authored
Merge pull request #182 from VibhavSetlur/staging
Staging sync: shared toolbar filtering across data grids
2 parents fe91a4e + a0f3b94 commit 4748623

12 files changed

Lines changed: 418 additions & 18 deletions

File tree

app/(reference-data)/genomes/Annotations/page.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Link from 'next/link';
88
import { parseWorkspaceGetObject, workspaceGet } from '@/lib/api/workspace';
99
import { USE_NEW_PROXY } from '@/lib/api/config';
1010
import DataControlHeader from '@/components/layout/DataControlHeader';
11+
import { useToolbarGridFiltering } from '@/lib/hooks/useToolbarGridFiltering';
1112

1213
interface SubsystemItem {
1314
id: string; // role
@@ -184,24 +185,38 @@ export default function SubsystemsPage() {
184185
[],
185186
);
186187

188+
const {
189+
filteredRows,
190+
handleFilterModelChange,
191+
handleToolbarApplyFilterModel,
192+
} = useToolbarGridFiltering<SubsystemItem>({
193+
rows,
194+
onFilterApplied: () => setPaginationModel((prev) => ({ ...prev, page: 0 })),
195+
});
196+
187197
return (
188198
<>
189199
<Typography variant="h5" fontWeight={600} gutterBottom>
190200
Subsystems
191201
</Typography>
192202
<DataGrid<SubsystemItem>
193-
rows={rows}
203+
rows={filteredRows}
194204
columns={columns}
195205
loading={isLoading}
196206
pageSizeOptions={[10, 25, 50, 100]}
197207
paginationModel={paginationModel}
198208
onPaginationModelChange={setPaginationModel}
199209
sortModel={sortModel}
200210
onSortModelChange={setSortModel}
211+
filterMode="server"
212+
onFilterModelChange={handleFilterModelChange}
201213
showToolbar
202214
slots={{ toolbar: DataControlHeader }}
203215
slotProps={{
204-
toolbar: { showQuickFilter: true },
216+
toolbar: {
217+
showQuickFilter: true,
218+
onApplyFilterModel: handleToolbarApplyFilterModel,
219+
},
205220
}}
206221
hideFooter
207222
disableColumnMenu

app/(reference-data)/genomes/page.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Alert from '@mui/material/Alert';
88
import { workspaceLs } from '@/lib/api/workspace';
99
import { USE_NEW_PROXY } from '@/lib/api/config';
1010
import DataControlHeader from '@/components/layout/DataControlHeader';
11+
import { useToolbarGridFiltering } from '@/lib/hooks/useToolbarGridFiltering';
1112

1213
interface PlantModelItem {
1314
id: string;
@@ -102,6 +103,15 @@ export default function PlantsPage() {
102103
staleTime: 5 * 60 * 1000,
103104
});
104105

106+
const {
107+
filteredRows,
108+
handleFilterModelChange,
109+
handleToolbarApplyFilterModel,
110+
} = useToolbarGridFiltering<PlantModelItem>({
111+
rows,
112+
onFilterApplied: () => setPaginationModel((prev) => ({ ...prev, page: 0 })),
113+
});
114+
105115
return (
106116
<>
107117
<Typography variant="h5" fontWeight={600} gutterBottom>
@@ -111,18 +121,23 @@ export default function PlantsPage() {
111121
PlantSEED v2.0<br />Update In Progress: Annotation and reconstruction services are temporarily offline for updates and will be restored shortly.
112122
</Alert>
113123
<DataGrid<PlantModelItem>
114-
rows={rows}
124+
rows={filteredRows}
115125
columns={columns}
116126
loading={isLoading}
117127
pageSizeOptions={[10, 25, 50, 100]}
118128
paginationModel={paginationModel}
119129
onPaginationModelChange={setPaginationModel}
120130
sortModel={sortModel}
121131
onSortModelChange={setSortModel}
132+
filterMode="server"
133+
onFilterModelChange={handleFilterModelChange}
122134
showToolbar
123135
slots={{ toolbar: DataControlHeader }}
124136
slotProps={{
125-
toolbar: { showQuickFilter: true },
137+
toolbar: {
138+
showQuickFilter: true,
139+
onApplyFilterModel: handleToolbarApplyFilterModel,
140+
},
126141
}}
127142
hideFooter
128143
disableColumnMenu

app/(reference-data)/list-media/page.tsx

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { workspaceLs } from '@/lib/api/workspace';
1010
import { listPublicMediaFromApi } from '@/lib/api/modelseed';
1111
import { USE_MODELSEED_API, USE_NEW_PROXY } from '@/lib/api/config';
1212
import DataControlHeader from '@/components/layout/DataControlHeader';
13+
import { useToolbarGridFiltering } from '@/lib/hooks/useToolbarGridFiltering';
1314

1415
interface MediaItem {
1516
id: string;
@@ -95,24 +96,38 @@ export default function MediaPage() {
9596
{ field: 'type', headerName: 'Type', width: 180 },
9697
], []);
9798

99+
const {
100+
filteredRows,
101+
handleFilterModelChange,
102+
handleToolbarApplyFilterModel,
103+
} = useToolbarGridFiltering<MediaItem>({
104+
rows,
105+
onFilterApplied: () => setPaginationModel((prev) => ({ ...prev, page: 0 })),
106+
});
107+
98108
return (
99109
<>
100110
<Typography variant="h5" fontWeight={600} gutterBottom>
101111
Media Formulations
102112
</Typography>
103113
<DataGrid<MediaItem>
104-
rows={rows}
114+
rows={filteredRows}
105115
columns={columns}
106116
loading={isLoading}
107117
pageSizeOptions={[10, 25, 50, 100]}
108118
paginationModel={paginationModel}
109119
onPaginationModelChange={setPaginationModel}
110120
sortModel={sortModel}
111121
onSortModelChange={setSortModel}
122+
filterMode="server"
123+
onFilterModelChange={handleFilterModelChange}
112124
showToolbar
113125
slots={{ toolbar: DataControlHeader }}
114126
slotProps={{
115-
toolbar: { showQuickFilter: true },
127+
toolbar: {
128+
showQuickFilter: true,
129+
onApplyFilterModel: handleToolbarApplyFilterModel,
130+
},
116131
}}
117132
hideFooter
118133
disableColumnMenu

app/(user-data)/my-jobs/page.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { USE_MODELSEED_API } from '@/lib/api/config';
2626
import AuthGuard from '@/components/auth/AuthGuard';
2727
import DataControlHeader from '@/components/layout/DataControlHeader';
2828
import ExportModal from '@/components/ui/ExportModal';
29+
import { useToolbarGridFiltering } from '@/lib/hooks/useToolbarGridFiltering';
2930

3031
/* ---------- types ---------- */
3132

@@ -322,6 +323,19 @@ function MyJobsContent() {
322323
},
323324
], [handleRefreshJob]);
324325

326+
const handleFiltersApplied = useCallback(() => {
327+
setPagination((prev) => ({ ...prev, page: 0 }));
328+
}, []);
329+
330+
const {
331+
filteredRows,
332+
handleFilterModelChange,
333+
handleToolbarApplyFilterModel,
334+
} = useToolbarGridFiltering<JobRow>({
335+
rows: jobRows,
336+
onFilterApplied: handleFiltersApplied,
337+
});
338+
325339
const exportColumns = useMemo(() => [
326340
{ field: 'id', headerName: 'Job ID', defaultSelected: true },
327341
{ field: 'task', headerName: 'Task', defaultSelected: true },
@@ -394,7 +408,7 @@ function MyJobsContent() {
394408
)}
395409

396410
<DataGrid<JobRow>
397-
rows={jobRows}
411+
rows={filteredRows}
398412
columns={columns}
399413
pageSizeOptions={[10, 25, 50, 100]}
400414
paginationModel={pagination}
@@ -406,9 +420,16 @@ function MyJobsContent() {
406420
sortModel: [{ field: 'submitted', sort: 'desc' }],
407421
},
408422
}}
423+
filterMode="server"
424+
onFilterModelChange={handleFilterModelChange}
409425
showToolbar
410426
slots={{ toolbar: DataControlHeader }}
411-
slotProps={{ toolbar: { showQuickFilter: true } }}
427+
slotProps={{
428+
toolbar: {
429+
showQuickFilter: true,
430+
onApplyFilterModel: handleToolbarApplyFilterModel,
431+
},
432+
}}
412433
hideFooter
413434
disableRowSelectionOnClick
414435
getRowId={(row) => row.id}

app/(user-data)/my-models/page.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ import DownloadModelMenu from '@/components/ui/DownloadModelMenu';
3939
import DeleteModelModal from '@/components/ui/DeleteModelModal';
4040
import CopyModelModal from '@/components/ui/CopyModelModal';
4141
import DataControlHeader from '@/components/layout/DataControlHeader';
42+
import { useToolbarGridFiltering } from '@/lib/hooks/useToolbarGridFiltering';
4243
import {
4344
isActiveJobStatus,
4445
isTerminalJobStatus,
@@ -557,6 +558,20 @@ export default function MyModelsPage() {
557558
},
558559
], [handleModelDeleted, recentJobByRow]);
559560

561+
const handleFiltersApplied = useCallback(() => {
562+
setPaginationModel((prev) => ({ ...prev, page: 0 }));
563+
}, []);
564+
565+
const {
566+
filterModel,
567+
filteredRows,
568+
handleFilterModelChange,
569+
handleToolbarApplyFilterModel,
570+
} = useToolbarGridFiltering<MyModelItem>({
571+
rows,
572+
onFilterApplied: handleFiltersApplied,
573+
});
574+
560575
return (
561576
<AuthGuard>
562577
<Box sx={{ maxWidth: '1400px', mx: 'auto', display: 'flex', flexDirection: 'column', gap: 2 }}>
@@ -710,7 +725,7 @@ export default function MyModelsPage() {
710725
</Typography>
711726
) : (
712727
<DataGrid<MyModelItem>
713-
rows={rows}
728+
rows={filteredRows}
714729
columns={columns}
715730
loading={isLoading}
716731
pageSizeOptions={[10, 25, 50, 100]}
@@ -723,10 +738,16 @@ export default function MyModelsPage() {
723738
sortModel: [{ field: 'modDate', sort: 'desc' }],
724739
},
725740
}}
741+
filterModel={filterModel}
742+
filterMode="server"
743+
onFilterModelChange={handleFilterModelChange}
726744
showToolbar
727745
slots={{ toolbar: DataControlHeader }}
728746
slotProps={{
729-
toolbar: { showQuickFilter: true },
747+
toolbar: {
748+
showQuickFilter: true,
749+
onApplyFilterModel: handleToolbarApplyFilterModel,
750+
},
730751
}}
731752
hideFooter
732753
disableColumnMenu

app/(user-data)/myMedia/page.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { useAuth } from '@/components/auth/AuthProvider';
2121
import DataControlHeader from '@/components/layout/DataControlHeader';
2222
import ExportModal from '@/components/ui/ExportModal';
2323
import { parseWorkspaceDate } from '@/lib/utils/date';
24+
import { useToolbarGridFiltering } from '@/lib/hooks/useToolbarGridFiltering';
2425

2526
interface MyMediaItem {
2627
id: string;
@@ -197,6 +198,20 @@ export default function MyMediaPage() {
197198
},
198199
], [exportingMediaId, isDeletingMedia, goToMediaPath]);
199200

201+
const handleFiltersApplied = useCallback(() => {
202+
setPaginationModel((prev) => ({ ...prev, page: 0 }));
203+
}, []);
204+
205+
const {
206+
filterModel,
207+
filteredRows,
208+
handleFilterModelChange,
209+
handleToolbarApplyFilterModel,
210+
} = useToolbarGridFiltering<MyMediaItem>({
211+
rows,
212+
onFilterApplied: handleFiltersApplied,
213+
});
214+
200215
const exportColumns = useMemo(() => [
201216
{ field: 'id', headerName: 'Media ID', defaultSelected: true },
202217
{ field: 'name', headerName: 'Name', defaultSelected: true },
@@ -252,18 +267,24 @@ export default function MyMediaPage() {
252267
</Typography>
253268
) : (
254269
<DataGrid<MyMediaItem>
255-
rows={rows}
270+
rows={filteredRows}
256271
columns={columns}
257272
loading={isLoading}
258273
pageSizeOptions={[10, 25, 50, 100]}
259274
paginationModel={paginationModel}
260275
onPaginationModelChange={setPaginationModel}
261276
sortModel={sortModel}
262277
onSortModelChange={setSortModel}
278+
filterModel={filterModel}
279+
filterMode="server"
280+
onFilterModelChange={handleFilterModelChange}
263281
showToolbar
264282
slots={{ toolbar: DataControlHeader }}
265283
slotProps={{
266-
toolbar: { showQuickFilter: true },
284+
toolbar: {
285+
showQuickFilter: true,
286+
onApplyFilterModel: handleToolbarApplyFilterModel,
287+
},
267288
}}
268289
hideFooter
269290
disableColumnMenu

components/build-model/PatricGenomesTable.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,8 @@ export default function PatricGenomesTable({ onSelectGenome, disabled = false }:
8181
const filtered = filterDocsByGridModel(
8282
raw.rows as unknown as Record<string, unknown>[],
8383
filterModel.items ?? [],
84+
undefined,
85+
String(filterModel.logicOperator ?? '').toLowerCase() === 'or' ? 'or' : 'and',
8486
) as unknown as PatricGenome[];
8587
const sm = sortModel[0];
8688
const sorted = sm?.field

components/build-model/RastGenomesTable.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import Button from '@mui/material/Button';
88
import Typography from '@mui/material/Typography';
99
import DataControlHeader from '@/components/layout/DataControlHeader';
1010
import { listRastGenomes, RastGenomeJob } from '@/lib/api/modelseed';
11+
import { useToolbarGridFiltering } from '@/lib/hooks/useToolbarGridFiltering';
1112

1213
interface RastGenomesTableProps {
1314
onSelectGenome: (job: RastGenomeJob) => void;
@@ -60,6 +61,15 @@ export default function RastGenomesTable({ onSelectGenome, disabled = false }: R
6061
[disabled, onSelectGenome],
6162
);
6263

64+
const {
65+
filteredRows,
66+
handleFilterModelChange,
67+
handleToolbarApplyFilterModel,
68+
} = useToolbarGridFiltering<RastGenomeJob>({
69+
rows,
70+
onFilterApplied: () => setPaginationModel((prev) => ({ ...prev, page: 0 })),
71+
});
72+
6373
return (
6474
<Box>
6575
{error && (
@@ -69,7 +79,7 @@ export default function RastGenomesTable({ onSelectGenome, disabled = false }: R
6979
)}
7080
<DataGrid<RastGenomeJob>
7181
autoHeight
72-
rows={rows}
82+
rows={filteredRows}
7383
columns={columns}
7484
loading={isLoading}
7585
getRowId={(row) => row.id || row.genome_id}
@@ -78,8 +88,11 @@ export default function RastGenomesTable({ onSelectGenome, disabled = false }: R
7888
onPaginationModelChange={setPaginationModel}
7989
sortModel={sortModel}
8090
onSortModelChange={setSortModel}
91+
filterMode="server"
92+
onFilterModelChange={handleFilterModelChange}
8193
showToolbar
8294
slots={{ toolbar: DataControlHeader }}
95+
slotProps={{ toolbar: { onApplyFilterModel: handleToolbarApplyFilterModel } }}
8396
hideFooter
8497
disableRowSelectionOnClick
8598
disableColumnMenu

components/layout/DataControlHeader.tsx

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,22 @@ function ToolbarSearchField({ onApplyFilterModel }: { onApplyFilterModel?: (mode
211211
// For server-side pages: call the page's handler directly so the server
212212
// re-fetches with both column filters and the new quick search.
213213
if (typeof onApplyFilterModel === 'function') {
214-
onApplyFilterModel(newModel, {});
214+
onApplyFilterModel(newModel, { source: 'toolbar' });
215+
// Update the grid's internal model so the input retains the committed value.
216+
apiRef.current.setFilterModel({
217+
items: items.slice(0, 1),
218+
logicOperator,
219+
quickFilterValues: newModel.quickFilterValues,
220+
quickFilterLogicOperator: newModel.quickFilterLogicOperator,
221+
});
215222
} else {
216-
// Client-side: use setFilterModel normally (grid handles filtering in-memory).
217-
apiRef.current.setFilterModel(newModel);
223+
// Client-side: use setFilterModel normally, but truncate to 1 item to avoid CE limits.
224+
apiRef.current.setFilterModel({
225+
items: items.slice(0, 1),
226+
logicOperator,
227+
quickFilterValues: newModel.quickFilterValues,
228+
quickFilterLogicOperator: newModel.quickFilterLogicOperator,
229+
});
218230
}
219231
},
220232
[apiRef, onApplyFilterModel],

0 commit comments

Comments
 (0)