Skip to content

Commit

Permalink
feat: Infinite Scroll for GraphQL Backend Service
Browse files Browse the repository at this point in the history
- add new Example 27 for GraphQL with Infinite Scroll demo
  • Loading branch information
ghiscoding committed Jul 25, 2024
1 parent 919fe25 commit a057864
Show file tree
Hide file tree
Showing 16 changed files with 727 additions and 52 deletions.
2 changes: 2 additions & 0 deletions examples/vite-demo-vanilla-bundle/src/app-routing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import Example23 from './examples/example23';
import Example24 from './examples/example24';
import Example25 from './examples/example25';
import Example26 from './examples/example26';
import Example27 from './examples/example27';

export class AppRouting {
constructor(private config: RouterConfig) {
Expand Down Expand Up @@ -59,6 +60,7 @@ export class AppRouting {
{ route: 'example24', name: 'example24', view: './examples/example24.html', viewModel: Example24, title: 'Example24', },
{ route: 'example25', name: 'example25', view: './examples/example25.html', viewModel: Example25, title: 'Example25', },
{ route: 'example26', name: 'example26', view: './examples/example26.html', viewModel: Example26, title: 'Example26', },
{ route: 'example27', name: 'example27', view: './examples/example27.html', viewModel: Example27, title: 'Example27', },
{ route: '', redirect: 'example01' },
{ route: '**', redirect: 'example01' }
];
Expand Down
3 changes: 3 additions & 0 deletions examples/vite-demo-vanilla-bundle/src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,9 @@ <h4 class="is-size-4 has-text-white">Slickgrid-Universal</h4>
<a class="navbar-item" onclick.delegate="loadRoute('example26')">
Example26 - OData with Infinite Scroll
</a>
<a class="navbar-item" onclick.delegate="loadRoute('example27')">
Example27 - GraphQL with Infinite Scroll
</a>
</div>
</div>
</div>
Expand Down
7 changes: 5 additions & 2 deletions examples/vite-demo-vanilla-bundle/src/examples/example09.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,10 @@ export default class Example09 {
}
},
{ id: 'company', name: 'Company', field: 'company', filterable: true, sortable: true },
{ id: 'category_name', name: 'Category', field: 'category/name', filterable: true, sortable: true }
{
id: 'category_name', name: 'Category', field: 'category/name', filterable: true, sortable: true,
formatter: (row, cell, val, colDef, dataContext) => dataContext['category']?.['name'] || ''
}
];

this.gridOptions = {
Expand Down Expand Up @@ -190,7 +193,7 @@ export default class Example09 {

getCustomerCallback(data) {
// totalItems property needs to be filled for pagination to work correctly
// however we need to force Aurelia to do a dirty check, doing a clone object will do just that
// however we need to force a dirty check, doing a clone object will do just that
let totalItemCount: number = data['totalRecordCount']; // you can use "totalRecordCount" or any name or "odata.count" when "enableCount" is set
if (this.isCountEnabled) {
totalItemCount = (this.odataVersion === 4) ? data['@odata.count'] : data['d']['__count'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -223,7 +223,7 @@ export default class Example15 {

getCustomerCallback(data) {
// totalItems property needs to be filled for pagination to work correctly
// however we need to force Aurelia to do a dirty check, doing a clone object will do just that
// however we need to force a dirty check, doing a clone object will do just that
let countPropName = 'totalRecordCount'; // you can use "totalRecordCount" or any name or "odata.count" when "enableCount" is set
if (this.isCountEnabled) {
countPropName = (this.odataVersion === 4) ? '@odata.count' : 'odata.count';
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
<div class="demo26">

<h3 class="title is-3">
Example 26 - OData (v4) Backend Service with Infinite Scroll
<div class="subtitle code-link">
Expand Down
23 changes: 13 additions & 10 deletions examples/vite-demo-vanilla-bundle/src/examples/example26.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,10 @@ export default class Example26 {
}
},
{ id: 'company', name: 'Company', field: 'company', filterable: true, sortable: true },
{ id: 'category_name', name: 'Category', field: 'category/name', filterable: true, sortable: true }
{
id: 'category_name', name: 'Category', field: 'category/name', filterable: true, sortable: true,
formatter: (row, cell, val, colDef, dataContext) => dataContext['category']?.['name'] || ''
}
];

this.gridOptions = {
Expand Down Expand Up @@ -169,7 +172,7 @@ export default class Example26 {

getCustomerCallback(data) {
// totalItems property needs to be filled for pagination to work correctly
// however we need to force Aurelia to do a dirty check, doing a clone object will do just that
// however we need to force a dirty check, doing a clone object will do just that
const totalItemCount: number = data['@odata.count'];
this.metricsTotalItemCount = totalItemCount;

Expand Down Expand Up @@ -204,7 +207,7 @@ export default class Example26 {
* This function is only here to mock a WebAPI call (since we are using a JSON file for the demo)
* in your case the getCustomer() should be a WebAPI function returning a Promise
*/
getCustomerDataApiMock(query): Promise<any> {
getCustomerDataApiMock(query: string): Promise<any> {
this.errorStatusClass = 'hidden';

// the mock is returning a Promise, just like a WebAPI typically does
Expand Down Expand Up @@ -238,17 +241,17 @@ export default class Example26 {
const filterBy = param.substring('$filter='.length).replace('%20', ' ');
if (filterBy.includes('matchespattern')) {
const regex = new RegExp(`matchespattern\\(([a-zA-Z]+),\\s'${CARET_HTML_ESCAPED}(.*?)'\\)`, 'i');
const filterMatch = filterBy.match(regex);
const filterMatch = filterBy.match(regex) || [];
const fieldName = filterMatch[1].trim();
columnFilters[fieldName] = { type: 'matchespattern', term: '^' + filterMatch[2].trim() };
}
if (filterBy.includes('contains')) {
const filterMatch = filterBy.match(/contains\(([a-zA-Z/]+),\s?'(.*?)'/);
const filterMatch = filterBy.match(/contains\(([a-zA-Z/]+),\s?'(.*?)'/) || [];
const fieldName = filterMatch[1].trim();
columnFilters[fieldName] = { type: 'substring', term: filterMatch[2].trim() };
}
if (filterBy.includes('substringof')) {
const filterMatch = filterBy.match(/substringof\('(.*?)',\s([a-zA-Z/]+)/);
const filterMatch = filterBy.match(/substringof\('(.*?)',\s([a-zA-Z/]+)/) || [];
const fieldName = filterMatch[2].trim();
columnFilters[fieldName] = { type: 'substring', term: filterMatch[1].trim() };
}
Expand All @@ -263,16 +266,16 @@ export default class Example26 {
}
}
if (filterBy.includes('startswith') && filterBy.includes('endswith')) {
const filterStartMatch = filterBy.match(/startswith\(([a-zA-Z ]*),\s?'(.*?)'/);
const filterEndMatch = filterBy.match(/endswith\(([a-zA-Z ]*),\s?'(.*?)'/);
const filterStartMatch = filterBy.match(/startswith\(([a-zA-Z ]*),\s?'(.*?)'/) || [];
const filterEndMatch = filterBy.match(/endswith\(([a-zA-Z ]*),\s?'(.*?)'/) || [];
const fieldName = filterStartMatch[1].trim();
columnFilters[fieldName] = { type: 'starts+ends', term: [filterStartMatch[2].trim(), filterEndMatch[2].trim()] };
} else if (filterBy.includes('startswith')) {
const filterMatch = filterBy.match(/startswith\(([a-zA-Z ]*),\s?'(.*?)'/);
const filterMatch = filterBy.match(/startswith\(([a-zA-Z ]*),\s?'(.*?)'/) || [];
const fieldName = filterMatch[1].trim();
columnFilters[fieldName] = { type: 'starts', term: filterMatch[2].trim() };
} else if (filterBy.includes('endswith')) {
const filterMatch = filterBy.match(/endswith\(([a-zA-Z ]*),\s?'(.*?)'/);
const filterMatch = filterBy.match(/endswith\(([a-zA-Z ]*),\s?'(.*?)'/) || [];
const fieldName = filterMatch[1].trim();
columnFilters[fieldName] = { type: 'ends', term: filterMatch[2].trim() };
}
Expand Down
69 changes: 69 additions & 0 deletions examples/vite-demo-vanilla-bundle/src/examples/example27.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<div class="demo26">
<h3 class="title is-3">
Example 27 - GraphQL Backend Service with Infinite Scroll
<div class="subtitle code-link">
<span class="is-size-6">see</span>
<a class="is-size-5" target="_blank"
href="https://github.com/ghiscoding/slickgrid-universal/blob/master/examples/vite-demo-vanilla-bundle/src/examples/example27.ts">
<span class="mdi mdi-link-variant"></span> code
</a>
</div>
</h3>

<h6 class="title is-6 italic">
<span class="text-red">(*) NO DATA SHOWN</span>
- just change any of Filters/Sorting/Pages and look at the "GraphQL Query" changing.
Also note that the column Name has a filter with a custom %% operator that behaves like an SQL LIKE operator supporting % wildcards.
Depending on your configuration, your GraphQL Server might already support regex querying (e.g. Hasura <a href="https://hasura.io/docs/latest/queries/postgres/filters/text-search-operators/#_regex">_regex</a>)
or you could add your own implementation (e.g. see this <a href="https://stackoverflow.com/a/37981802/1212166">SO</a>).
</h6>

<div class="row">
<button class="button is-small" data-test="clear-filters-sorting"
onclick.delegate="clearAllFiltersAndSorts()" title="Clear all Filters & Sorts">
<span class="mdi mdi-close"></span>
<span>Clear all Filter &amp; Sorts</span>
</button>

<label for="serverdelay" class="ml-4">Server Delay: </label>
<input id="serverdelay" type="number" data-test="server-delay" class="is-narrow input is-small"
value.bind="serverWaitDelay"
title="input a fake timer delay to simulate slow server response" />

<div class="row col-md-12 mt-2">
<button class="button is-small" onclick.delegate="switchLanguage()" data-test="language-button">
<span class="mdi mdi-translate"></span>
<span>Switch Language</span>
</button>
<b>Locale:</b>
<span class="text-italic" data-test="selected-locale" textcontent.bind="selectedLanguageFile">
</span>

<span class="ml-4">
<b>Metrics:</b>
<span textcontent.bind="metricsEndTime"></span>
<span textcontent.bind="metricsItemCount" data-test="itemCount"></span> of
<span textcontent.bind="metricsTotalItemCount" data-test="totalItemCount"></span> items
<span classname.bind="tagDataClass" data-test="data-loaded-tag">All Data Loaded!!!</span>
</span>
</div>

</div>

<div class="columns mt-2">
<div class="column">
<div class="notification is-info is-light" data-test="alert-graphql-query">
<strong>GraphQL Query:</strong>
<span data-test="graphql-query-result" textcontent.bind="graphqlQuery"></span>
</div>
</div>
<div class="column is-narrow">
<div class.bind="statusClass" data-test="status">
<strong>Status:</strong> <span textcontent.bind="status"></span>
</div>
</div>
</div>

<div class="grid27">
</div>
</div>
8 changes: 8 additions & 0 deletions examples/vite-demo-vanilla-bundle/src/examples/example27.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.demo27 {
.tag-data {
display: none;
&.fully-loaded {
display: inline-flex;
}
}
}
Loading

0 comments on commit a057864

Please sign in to comment.