Skip to content

Commit 3c465b8

Browse files
committed
Add saved filters to FoundTableRowsDs and handle them in GetTableRowsUseCase, improving filter management functionality
1 parent 72093ce commit 3c465b8

3 files changed

Lines changed: 116 additions & 0 deletions

File tree

backend/src/entities/table/application/data-structures/found-table-rows.ds.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,9 @@ export class FoundTableRowsDs {
5959

6060
@ApiProperty()
6161
allow_csv_import: boolean;
62+
63+
@ApiProperty({ type: Object })
64+
saved_filters: Record<string, any>;
6265
}
6366

6467
export class TableStructureDs {

backend/src/entities/table/use-cases/get-table-rows.use.case.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ export class GetTableRowsUseCase extends AbstractUseCase<GetTableRowsDs, FoundTa
9393
tableCustomFields,
9494
userTablePermissions,
9595
customActionEvents,
96+
savedTableFilters,
9697
/* eslint-enable */
9798
] = await Promise.all([
9899
this._dbContext.tableSettingsRepository.findTableSettingsPure(connectionId, tableName),
@@ -103,11 +104,17 @@ export class GetTableRowsUseCase extends AbstractUseCase<GetTableRowsDs, FoundTa
103104
this._dbContext.customFieldsRepository.getCustomFields(connectionId, tableName),
104105
this._dbContext.userAccessRepository.getUserTablePermissions(userId, connectionId, tableName, masterPwd),
105106
this._dbContext.actionEventsRepository.findCustomEventsForTable(connectionId, tableName),
107+
this._dbContext.tableFiltersRepository.findTableFiltersForTableInConnection(tableName, connectionId),
106108
]);
107109
const filteringFields: Array<FilteringFieldsDs> = isObjectEmpty(filters)
108110
? findFilteringFieldsUtil(query, tableStructure)
109111
: parseFilteringFieldsFromBodyData(filters, tableStructure);
110112

113+
if (!filteringFields.length && savedTableFilters) {
114+
const parsedSavedTableFilters = parseFilteringFieldsFromBodyData(savedTableFilters.filters, tableStructure);
115+
filteringFields.push(...parsedSavedTableFilters);
116+
}
117+
111118
const orderingField = findOrderingFieldUtil(query, tableStructure, tableSettings);
112119

113120
const configured = !!tableSettings;
@@ -232,6 +239,7 @@ export class GetTableRowsUseCase extends AbstractUseCase<GetTableRowsDs, FoundTa
232239
large_dataset: largeDataset,
233240
allow_csv_export: allowCsvExport,
234241
allow_csv_import: allowCsvImport,
242+
saved_filters: savedTableFilters.filters,
235243
};
236244

237245
const identitiesMap = new Map<string, any[]>();

backend/test/ava-tests/saas-tests/table-filters-e2e-test.ts

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ test.serial(`${currentTest} should return table filters`, async (t) => {
188188
});
189189

190190
currentTest = `DELETE /table-filters/:slug`;
191+
191192
test.serial(`${currentTest} should delete table filters`, async (t) => {
192193
try {
193194
const connectionToTestDB = getTestData(mockFactory).connectionToPostgres;
@@ -254,3 +255,107 @@ test.serial(`${currentTest} should delete table filters`, async (t) => {
254255
t.fail();
255256
}
256257
});
258+
259+
currentTest = 'GET /table/rows/:slug';
260+
test.serial(
261+
`${currentTest} should return rows with search, with pagination, with sorting and with filters applied from created table filters
262+
with search and DESC sorting`,
263+
async (t) => {
264+
try {
265+
const connectionToTestDB = getTestData(mockFactory).connectionToPostgres;
266+
const firstUserToken = (await registerUserAndReturnUserInfo(app)).token;
267+
const { testTableName, testTableColumnName } = await createTestTable(connectionToTestDB);
268+
269+
testTables.push(testTableName);
270+
271+
const createConnectionResponse = await request(app.getHttpServer())
272+
.post('/connection')
273+
.send(connectionToTestDB)
274+
.set('Cookie', firstUserToken)
275+
.set('Content-Type', 'application/json')
276+
.set('Accept', 'application/json');
277+
const createConnectionRO = JSON.parse(createConnectionResponse.text);
278+
t.is(createConnectionResponse.status, 201);
279+
280+
const createTableSettingsDTO = mockFactory.generateTableSettings(
281+
createConnectionRO.id,
282+
testTableName,
283+
[testTableColumnName],
284+
undefined,
285+
undefined,
286+
3,
287+
QueryOrderingEnum.DESC,
288+
'id',
289+
undefined,
290+
undefined,
291+
undefined,
292+
undefined,
293+
undefined,
294+
);
295+
296+
const createTableSettingsResponse = await request(app.getHttpServer())
297+
.post(`/settings?connectionId=${createConnectionRO.id}&tableName=${testTableName}`)
298+
.send(createTableSettingsDTO)
299+
.set('Cookie', firstUserToken)
300+
.set('Content-Type', 'application/json')
301+
.set('Accept', 'application/json');
302+
t.is(createTableSettingsResponse.status, 201);
303+
304+
const fieldname = 'id';
305+
const fieldvalue = '2';
306+
307+
const filters = {
308+
[fieldname]: { gt: fieldvalue },
309+
};
310+
311+
const createTableFiltersResponse = await request(app.getHttpServer())
312+
.post(`/table-filters/${createConnectionRO.id}/?tableName=${testTableName}`)
313+
.send({ filters })
314+
.set('Cookie', firstUserToken)
315+
.set('Content-Type', 'application/json')
316+
.set('Accept', 'application/json');
317+
318+
const createTableFiltersRO = JSON.parse(createTableFiltersResponse.text);
319+
t.is(createTableFiltersResponse.status, 201);
320+
t.is(createTableFiltersRO.hasOwnProperty('id'), true);
321+
t.is(createTableFiltersRO.hasOwnProperty('tableName'), true);
322+
t.is(createTableFiltersRO.hasOwnProperty('connectionId'), true);
323+
t.is(createTableFiltersRO.hasOwnProperty('filters'), true);
324+
t.deepEqual(createTableFiltersRO.filters, filters);
325+
326+
const getTableRowsResponse = await request(app.getHttpServer())
327+
.get(
328+
`/table/rows/${createConnectionRO.id}?tableName=${testTableName}&search=${testSearchedUserName}&page=1&perPage=200`,
329+
)
330+
.set('Cookie', firstUserToken)
331+
.set('Content-Type', 'application/json')
332+
.set('Accept', 'application/json');
333+
t.is(getTableRowsResponse.status, 200);
334+
335+
const getTableRowsRO = JSON.parse(getTableRowsResponse.text);
336+
console.log('🚀 ~ withsearch,pagination:page=1,perPage=2andDESCsorting`, ~ getTableRowsRO:', getTableRowsRO);
337+
338+
t.is(typeof getTableRowsRO, 'object');
339+
t.is(getTableRowsRO.hasOwnProperty('rows'), true);
340+
t.is(getTableRowsRO.hasOwnProperty('primaryColumns'), true);
341+
t.is(getTableRowsRO.hasOwnProperty('pagination'), true);
342+
t.is(getTableRowsRO.rows.length, 2);
343+
t.is(Object.keys(getTableRowsRO.rows[1]).length, 5);
344+
345+
t.is(getTableRowsRO.rows[0][testTableColumnName], testSearchedUserName);
346+
t.is(getTableRowsRO.rows[0].id, 38);
347+
t.is(getTableRowsRO.rows[1][testTableColumnName], testSearchedUserName);
348+
t.is(getTableRowsRO.rows[1].id, 22);
349+
350+
t.is(getTableRowsRO.pagination.currentPage, 1);
351+
t.is(getTableRowsRO.pagination.perPage, 200);
352+
353+
t.is(typeof getTableRowsRO.primaryColumns, 'object');
354+
t.is(getTableRowsRO.primaryColumns[0].hasOwnProperty('column_name'), true);
355+
t.is(getTableRowsRO.primaryColumns[0].hasOwnProperty('data_type'), true);
356+
} catch (error) {
357+
console.error(error);
358+
t.fail();
359+
}
360+
},
361+
);

0 commit comments

Comments
 (0)