Skip to content
This repository was archived by the owner on Jun 1, 2025. It is now read-only.

Commit e68a1c9

Browse files
Ghislain BeaulacGhislain Beaulac
authored andcommitted
refactored GraphQL Service to make it easier
1 parent fc0cc04 commit e68a1c9

File tree

2 files changed

+35
-15
lines changed

2 files changed

+35
-15
lines changed
Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
1+
import { Column } from './column.interface';
12
import { BackendServiceOption } from './backendServiceOption.interface';
23
import { GraphqlFilteringOption } from './graphqlFilteringOption.interface';
34
import { GraphqlSortingOption } from './graphqlSortingOption.interface';
45
import { GraphqlCursorPaginationOption } from './graphqlCursorPaginationOption.interface';
56
import { GraphqlPaginationOption } from './graphqlPaginationOption.interface';
67

78
export interface GraphqlServiceOption extends BackendServiceOption {
9+
columnIds?: string[];
10+
dataFilters?: string[]; // DEPRECATED, use "columnIds" instead
811
datasetName?: string;
12+
columnDefinitions?: Column[];
913
isWithCursor?: boolean;
1014
paginationOptions?: GraphqlPaginationOption | GraphqlCursorPaginationOption;
1115
filteringOptions?: GraphqlFilteringOption[];
1216
sortingOptions?: GraphqlSortingOption[];
13-
dataFilters?: string[];
1417
keepArgumentFieldDoubleQuotes?: boolean;
1518
}

src/app/modules/angular-slickgrid/services/graphql.service.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,20 +26,35 @@ export class GraphqlService implements BackendService {
2626
* Build the GraphQL query, since the service include/exclude cursor, the output query will be different.
2727
* @param serviceOptions GraphqlServiceOption
2828
*/
29-
buildQuery(serviceOptions?: GraphqlServiceOption) {
30-
if (!this.serviceOptions.datasetName || !this.serviceOptions.dataFilters) {
31-
throw new Error('GraphQL Service requires "datasetName" & "dataFilters" properties for it to work');
29+
buildQuery() {
30+
if (!this.serviceOptions || !this.serviceOptions.datasetName || (!this.serviceOptions.columnIds && !this.serviceOptions.dataFilters && !this.serviceOptions.columnDefinitions)) {
31+
throw new Error('GraphQL Service requires "datasetName" & ("dataFilters" or "columnDefinitions") properties for it to work');
3232
}
3333
const queryQb = new QueryBuilder('query');
3434
const datasetQb = new QueryBuilder(this.serviceOptions.datasetName);
3535
const pageInfoQb = new QueryBuilder('pageInfo');
3636
const dataQb = (this.serviceOptions.isWithCursor) ? new QueryBuilder('edges') : new QueryBuilder('nodes');
37-
const filters = this.buildFilterQuery(this.serviceOptions.dataFilters);
37+
38+
// get all the columnds Ids for the filters to work
39+
let columnIds: string[];
40+
if (this.serviceOptions.columnDefinitions) {
41+
columnIds = Array.isArray(this.serviceOptions.columnDefinitions) ? this.serviceOptions.columnDefinitions.map((column) => column.field) : [];
42+
} else {
43+
columnIds = this.serviceOptions.columnIds || this.serviceOptions.dataFilters || [];
44+
}
45+
46+
// Slickgrid also requires the "id" field to be part of DataView
47+
// push it to the GraphQL query if it wasn't already part of the list
48+
if (!columnIds.includes('id')) {
49+
columnIds.push('id');
50+
}
51+
52+
const filters = this.buildFilterQuery(columnIds);
3853

3954
if (this.serviceOptions.isWithCursor) {
4055
// ...pageInfo { hasNextPage, endCursor }, edges { cursor, node { _filters_ } }
4156
pageInfoQb.find('hasNextPage', 'endCursor');
42-
dataQb.find(['cursor', { 'node': filters }]);
57+
dataQb.find(['cursor', { node: filters }]);
4358
} else {
4459
// ...pageInfo { hasNextPage }, nodes { _filters_ }
4560
pageInfoQb.find('hasNextPage');
@@ -49,7 +64,7 @@ export class GraphqlService implements BackendService {
4964
datasetQb.find(['totalCount', pageInfoQb, dataQb]);
5065

5166
// add dataset filters, could be Pagination and SortingFilters and/or FieldFilters
52-
const datasetFilters: GraphqlDatasetFilter = this.serviceOptions.paginationOptions;
67+
const datasetFilters: GraphqlDatasetFilter = this.serviceOptions.paginationOptions as GraphqlDatasetFilter;
5368
if (this.serviceOptions.sortingOptions) {
5469
// orderBy: [{ field:x, direction: 'ASC' }]
5570
datasetFilters.orderBy = this.serviceOptions.sortingOptions;
@@ -64,7 +79,7 @@ export class GraphqlService implements BackendService {
6479
queryQb.find(datasetQb);
6580

6681
const enumSearchProperties = ['direction:', 'field:', 'operator:'];
67-
return this.trimDoubleQuotesOnEnumField(queryQb.toString(), enumSearchProperties, this.serviceOptions.keepArgumentFieldDoubleQuotes);
82+
return this.trimDoubleQuotesOnEnumField(queryQb.toString(), enumSearchProperties, this.serviceOptions.keepArgumentFieldDoubleQuotes || false);
6883
}
6984

7085
/**
@@ -78,15 +93,15 @@ export class GraphqlService implements BackendService {
7893
* firstName, lastName, shipping{address{street, zip}}
7994
* @param inputArray
8095
*/
81-
buildFilterQuery(inputArray) {
96+
buildFilterQuery(inputArray: string[]) {
8297

83-
const set = (o = {}, a) => {
98+
const set = (o: any = {}, a: any) => {
8499
const k = a.shift();
85100
o[k] = a.length ? set(o[k], a) : null;
86101
return o;
87102
};
88103

89-
const output = inputArray.reduce((o, a) => set(o, a.split('.')), {});
104+
const output = inputArray.reduce((o: any, a: string) => set(o, a.split('.')), {});
90105

91106
return JSON.stringify(output)
92107
.replace(/\"|\:|null/g, '')
@@ -113,7 +128,7 @@ export class GraphqlService implements BackendService {
113128
} else {
114129
// first, last, offset
115130
paginationOptions = this.serviceOptions.paginationOptions as GraphqlPaginationOption;
116-
paginationOptions.offset = 0 ;
131+
paginationOptions.offset = 0;
117132
}
118133
this.updateOptions({ paginationOptions });
119134
}
@@ -128,6 +143,10 @@ export class GraphqlService implements BackendService {
128143
onFilterChanged(event: Event, args: FilterChangedArgs): Promise<string> {
129144
const searchByArray: GraphqlFilteringOption[] = [];
130145
const serviceOptions: BackendServiceOption = args.grid.getOptions();
146+
if (serviceOptions.onBackendEventApi === undefined || !serviceOptions.onBackendEventApi.filterTypingDebounce) {
147+
throw new Error('Something went wrong in the GraphqlService, "onBackendEventApi" is not initialized');
148+
}
149+
131150
let debounceTypingDelay = 0;
132151
if (event.type === 'keyup' || event.type === 'keydown') {
133152
debounceTypingDelay = serviceOptions.onBackendEventApi.filterTypingDebounce || 700;
@@ -167,7 +186,6 @@ export class GraphqlService implements BackendService {
167186

168187
// escaping the search value
169188
searchValue = searchValue.replace(`'`, `''`); // escape single quotes by doubling them
170-
171189
if (operator === '*' || lastValueChar === '*') {
172190
operator = (operator === '*') ? 'endsWith' : 'startsWith';
173191
}
@@ -293,11 +311,10 @@ export class GraphqlService implements BackendService {
293311
* @param enumSearchWords array of enum words to filter
294312
* @returns outputStr output string
295313
*/
296-
trimDoubleQuotesOnEnumField(inputStr: string, enumSearchWords: string[], keepArgumentFieldDoubleQuotes) {
314+
trimDoubleQuotesOnEnumField(inputStr: string, enumSearchWords: string[], keepArgumentFieldDoubleQuotes: boolean) {
297315
const patternWordInQuotes = `\s?((field:\s*)?".*?")`;
298316
let patternRegex = enumSearchWords.join(patternWordInQuotes + '|');
299317
patternRegex += patternWordInQuotes; // the last one should also have the pattern but without the pipe "|"
300-
301318
// example with (field: & direction:): /field:s?(".*?")|direction:s?(".*?")/
302319
const reg = new RegExp(patternRegex, 'g');
303320

0 commit comments

Comments
 (0)