From 6ff81d4a3d5f7011979917997b8409d7910f2d25 Mon Sep 17 00:00:00 2001 From: Ronald Van Ryswyk Date: Fri, 6 Oct 2023 11:21:34 +1030 Subject: [PATCH 1/3] Pass in undefined (instead of null) so TypeScript uses the default value in the parameter signature --- .../src/services/__tests__/graphql.service.spec.ts | 9 +++++++++ packages/graphql/src/services/graphql.service.ts | 2 +- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/packages/graphql/src/services/__tests__/graphql.service.spec.ts b/packages/graphql/src/services/__tests__/graphql.service.spec.ts index cc1910663..594861c8f 100644 --- a/packages/graphql/src/services/__tests__/graphql.service.spec.ts +++ b/packages/graphql/src/services/__tests__/graphql.service.spec.ts @@ -416,6 +416,15 @@ describe('GraphqlService', () => { expect(removeSpaces(query)).toBe(removeSpaces(expectation)); }); + + it('should return a query string including a direct reference to a complex object', () => { + const expectation = `firstName, lastName, billing{address{street, zip}}`; + const columns = ['firstName', 'lastName', 'billing', 'billing.address.street', 'billing.address.zip']; + + const query = service.buildFilterQuery(columns); + + expect(removeSpaces(query)).toBe(removeSpaces(expectation)); + }); }); describe('clearFilters method', () => { diff --git a/packages/graphql/src/services/graphql.service.ts b/packages/graphql/src/services/graphql.service.ts index 003454cd1..c633d8393 100644 --- a/packages/graphql/src/services/graphql.service.ts +++ b/packages/graphql/src/services/graphql.service.ts @@ -195,7 +195,7 @@ export class GraphqlService implements BackendService { const set = (o: any = {}, a: any) => { const k = a.shift(); - o[k] = a.length ? set(o[k], a) : null; + o[k] = a.length ? set(o[k] ?? undefined, a) : null; return o; }; From 4ec4c4eabae4cff3b97e94776b26dc8c6fa3af88 Mon Sep 17 00:00:00 2001 From: Ronald Van Ryswyk Date: Fri, 24 Nov 2023 16:51:41 +1030 Subject: [PATCH 2/3] Implement excludeFieldFromQuery flag --- packages/common/src/interfaces/column.interface.ts | 3 +++ .../src/services/__tests__/graphql.service.spec.ts | 14 ++++++++++++++ packages/graphql/src/services/graphql.service.ts | 4 +++- .../services/__tests__/grid-odata.service.spec.ts | 6 +++++- 4 files changed, 25 insertions(+), 2 deletions(-) diff --git a/packages/common/src/interfaces/column.interface.ts b/packages/common/src/interfaces/column.interface.ts index 79b651c17..1f1fe595f 100644 --- a/packages/common/src/interfaces/column.interface.ts +++ b/packages/common/src/interfaces/column.interface.ts @@ -108,6 +108,9 @@ export interface Column { /** Default to false, which leads to exclude the column title from the Grid Menu. */ excludeFromGridMenu?: boolean; + /** Defaults to false, which leads to exclude the field property, but including the fields property, from the query (typically a backend service query) */ + excludeFieldFromQuery?: boolean; + /** Defaults to false, which leads to exclude the field from the query (typically a backend service query) */ excludeFromQuery?: boolean; diff --git a/packages/graphql/src/services/__tests__/graphql.service.spec.ts b/packages/graphql/src/services/__tests__/graphql.service.spec.ts index b3589baaa..3b87bb7d7 100644 --- a/packages/graphql/src/services/__tests__/graphql.service.spec.ts +++ b/packages/graphql/src/services/__tests__/graphql.service.spec.ts @@ -187,6 +187,20 @@ describe('GraphqlService', () => { expect(removeSpaces(query)).toBe(removeSpaces(expectation)); }); + it('should exclude a column field, and expect a query string without it, but still include any fields specified', () => { + const expectation = `query{ users(first:10, offset:0){ totalCount, nodes{ id, field1, field3, field4, field5 }}}`; + const columns = [ + { id: 'field1', field: 'field1', width: 100 }, + { id: 'field2', field: 'field2', fields: ['field3', 'field4', 'field5'], width: 100, excludeFieldFromQuery: true } + ]; + jest.spyOn(gridStub, 'getColumns').mockReturnValue(columns); + + service.init({ datasetName: 'users' }, paginationOptions, gridStub); + const query = service.buildQuery(); + + expect(removeSpaces(query)).toBe(removeSpaces(expectation)); + }); + it('should use default pagination "first" option when "paginationOptions" is not provided', () => { const expectation = `query{ users(first:${DEFAULT_ITEMS_PER_PAGE}, offset:0){ totalCount, nodes{ id, field1 }}}`; const columns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100, excludeFromQuery: true }]; diff --git a/packages/graphql/src/services/graphql.service.ts b/packages/graphql/src/services/graphql.service.ts index eda7f9be7..b03da89a1 100644 --- a/packages/graphql/src/services/graphql.service.ts +++ b/packages/graphql/src/services/graphql.service.ts @@ -98,7 +98,9 @@ export class GraphqlService implements BackendService { const columnIds: string[] = []; if (columnDefinitions && Array.isArray(columnDefinitions)) { for (const column of columnDefinitions) { - columnIds.push(column.field); + if (!column.excludeFieldFromQuery) { + columnIds.push(column.field); + } // if extra "fields" are passed, also push them to columnIds if (column.fields) { diff --git a/packages/odata/src/services/__tests__/grid-odata.service.spec.ts b/packages/odata/src/services/__tests__/grid-odata.service.spec.ts index b0117bb24..bfaee961a 100644 --- a/packages/odata/src/services/__tests__/grid-odata.service.spec.ts +++ b/packages/odata/src/services/__tests__/grid-odata.service.spec.ts @@ -111,7 +111,11 @@ describe('GridOdataService', () => { it('should use default pagination "$top" option when "paginationOptions" is not provided', () => { const expectation = `$top=${DEFAULT_ITEMS_PER_PAGE}`; - const columns = [{ id: 'field1', field: 'field1', width: 100 }, { id: 'field2', field: 'field2', width: 100, excludeFromQuery: true }]; + const columns = [ + { id: 'field1', field: 'field1', width: 100 }, + { id: 'field2', field: 'field2', width: 100, excludeFromQuery: true }, + { id: 'field3', field: 'field3', fields: ['field4', 'field5', 'field6'], width: 100, excludeFieldFromQuery: true } + ]; jest.spyOn(gridStub, 'getColumns').mockReturnValue(columns); service.init(null as any, undefined, gridStub); From f923994ee886b4925e9ea77bae35a244f725a7ac Mon Sep 17 00:00:00 2001 From: Ronald Van Ryswyk Date: Sun, 26 Nov 2023 07:52:20 +1030 Subject: [PATCH 3/3] Use backticks for properties in JsDoc --- packages/common/src/interfaces/column.interface.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/common/src/interfaces/column.interface.ts b/packages/common/src/interfaces/column.interface.ts index 1f1fe595f..d45bb4e99 100644 --- a/packages/common/src/interfaces/column.interface.ts +++ b/packages/common/src/interfaces/column.interface.ts @@ -108,10 +108,10 @@ export interface Column { /** Default to false, which leads to exclude the column title from the Grid Menu. */ excludeFromGridMenu?: boolean; - /** Defaults to false, which leads to exclude the field property, but including the fields property, from the query (typically a backend service query) */ + /** Defaults to false, which leads to exclude the `field` property, but still includes the `fields` property, from the query (typically a backend service query) */ excludeFieldFromQuery?: boolean; - /** Defaults to false, which leads to exclude the field from the query (typically a backend service query) */ + /** Defaults to false, which leads to exclude the `field` (and `fields`) from the query (typically a backend service query) */ excludeFromQuery?: boolean; /** Defaults to false, which leads to exclude the column from getting a header menu. For example, the checkbox row selection should not have a header menu. */