Skip to content

Commit

Permalink
Updated mixins to native classes; updated handlebars version to lates…
Browse files Browse the repository at this point in the history
…t; swapped ember decorators with built in ember objects
  • Loading branch information
gspain committed Feb 12, 2020
1 parent ba24747 commit 9974045
Show file tree
Hide file tree
Showing 9 changed files with 26,480 additions and 1,142 deletions.
7 changes: 3 additions & 4 deletions addon/decorators/controller-pagination.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import DS from 'ember-data';
import { buildQueryParams, sortDirection } from '@gavant/ember-pagination/utils/query-params';
import { setProperties } from '@ember/object';
import { tryInvoke } from '@ember/utils';
import { reject } from 'rsvp';
import { A } from '@ember/array';
import NativeArray from '@ember/array/-private/native-array';
import { action, computed } from '@ember-decorators/object';
import { readOnly, or } from '@ember-decorators/object/computed';
import { inject as service } from '@ember-decorators/service';
import { action, computed, setProperties } from '@ember/object';
import { readOnly, or } from '@ember/object/computed';
import { inject as service } from '@ember/service';
import Router from '@ember/routing/router-service';

/**
Expand Down
2 changes: 1 addition & 1 deletion addon/decorators/route-pagination.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ export default function routePagination<T extends ConcreteSubclass<any>>(RouteSu
* Get the controller params
* @param routeName The name of the route you want to get the controller parameters for.
* Defaults to current route if nothing is passed in
* Should be passed in using `/` seperators i.e. `accounts/index`
* Should be passed in using `/` separators i.e. `accounts/index`
* @returns - Controller query params
*/
getControllerParams(routeName: string = this.routeName) {
Expand Down
342 changes: 155 additions & 187 deletions addon/mixins/controller-pagination.ts
Original file line number Diff line number Diff line change
@@ -1,215 +1,183 @@
import Mixin from '@ember/object/mixin';
import { inject as service } from '@ember/service';
import { get, set, setProperties, computed } from '@ember/object';
import { action, computed, setProperties } from '@ember/object';
import { readOnly, or } from '@ember/object/computed';
import { tryInvoke } from '@ember/utils';
import NativeArray from '@ember/array/-private/native-array';
import { reject } from 'rsvp';
import { A } from '@ember/array';
import { buildQueryParams, PaginationController, sortDirection } from '@gavant/ember-pagination/utils/query-params';
import DS from 'ember-data';
import RouterService from '@ember/routing/router-service';

export default function ControllerPaginationClass<T extends ConcreteSubclass<any>>(ControllerSubclass: T) {
class PaginationControllerClass extends ControllerSubclass {
@service router!: RouterService;
sort: NativeArray<any> = A();
hasMore: boolean = true;
limit: number = 10;
isLoadingPage = false;

@or('isLoadingPage', 'isLoadingRoute') isLoadingModels!: boolean;
@readOnly('model.length') offset: number | undefined;

@computed('router.currentRouteName')
get isLoadingRoute() {
return this.router.currentRouteName.match(/loading$/);
}

export default Mixin.create({
router: service(),
loadingBar: service(),
sort: A(),
hasMore: true,
limit: 10,
isLoadingPage: false,

isLoadingRoute: computed('router.currentRouteName', function() {
return get(this, 'router.currentRouteName').match(/loading$/);
}),
isLoadingModels: or('isLoadingPage', 'isLoadingRoute'),
offset: readOnly('model.length'),
pagesLoaded: computed('model.length', 'limit', function() {
return Math.ceil(get(this, 'model.length') / get(this, 'limit'));
}),

async _loadModels(this: PaginationController, reset: boolean) {
set(this, 'isLoadingPage', true);
if(reset) {
this.clearModels();
@computed('model.length', 'limit')
get pagesLoaded() {
return Math.ceil(this.model.length / this.limit);
}

const offset = get(this, 'offset');
const limit = get(this, 'limit');
const queryParams = buildQueryParams(this, offset, limit);
let models = [];
try {
const result = await this.fetchModels(queryParams);
models = result.toArray();

setProperties(this, {
metadata: get(result, 'meta'),
hasMore: get(models, 'length') >= limit
});

tryInvoke(get(this, 'model'), 'pushObjects', [models]);
} catch(errors) {
reject(errors);
async _loadModels(this: PaginationController, reset: boolean) {
this.set('isLoadingPage', true);
if(reset) {
this.clearModels();
}

const offset = this.offset;
const limit = this.limit;
const queryParams = buildQueryParams(this, offset, limit);
let models = [];
try {
const result = await this.fetchModels(queryParams);
models = result.toArray();
setProperties(this, {
metadata: result.meta,
hasMore: models.length >= limit
});

tryInvoke(this.model, 'pushObjects', [models]);
} catch(errors) {
reject(errors);
}

this.set('isLoadingPage', false);
return models;
}
set(this, 'isLoadingPage', false);
return models;
},

// loadModelsTask: task(function * (reset, params) {
// get(this, 'loadingBar').start();
// if(reset) {
// this.clearModels();
// }
//
// const offset = get(this, 'offset');
// const limit = get(this, 'limit');
// const queryParams = this.buildQueryParams(this, params, offset, limit);
// const result = yield this.fetchModels(queryParams);
// const models = result.toArray();
//
// setProperties(this, {
// metadata: get(result, 'meta'),
// hasMore: get(models, 'length') >= limit
// });
//
// tryInvoke(get(this, 'model'), 'pushObjects', [models]);
// get(this, 'loadingBar').stop();
// return models;
// }).restartable(),

/**
* Override this method if more complex logic is necessary to retrieve the records
* It should return a promise, which resolves to an array-like object (such as a DS.RecordArray)
* @returns - the result of `store.query`
*/
fetchModels(this: PaginationController, queryParams: any) {
const modelName = get(this, 'modelName');
return get(this, 'store').query(modelName, queryParams);
},

/**
* Change the sorting and call `filterModels`. Will only load models if not currently making an API call
* @param reset - Clear models
* @returns - an array of models
*/
loadModels(this: PaginationController, reset: boolean) {
if (!get(this, 'isLoadingPage')) {
return this._loadModels(reset);
} else {
return [];

/**
* Override this method if more complex logic is necessary to retrieve the records
* It should return a promise, which resolves to an array-like object (such as a DS.RecordArray)
* @returns - the result of `store.query`
*/
fetchModels(this: PaginationController, queryParams: any) {
const modelName = this.modelName as never;
return this.store.query(modelName, queryParams);
}
},

/**
* Clear models
*/
clearModels(this: PaginationController) {
set(this, 'model', A());
},

/**
* Clear and Reload models
* @returns - an array of models
*/
reloadModels(this: PaginationController) {
return this.loadModels(true);
},

/**
* Load another page of models
* @returns - an array of models
*/
loadMoreModels(this: PaginationController) {
return this.loadModels();
},

/**
* Change the sorting and call `filterModels`
* @param model - A `DS.Model` record
* @returns - result of api call
*/
async removeModel(this: PaginationController, model: DS.Model) {
try {
let result = await tryInvoke(model, 'destroyRecord');
get(this, 'model').removeObject(model);
return result;
} catch(error) {
return reject(error);

/**
* Change the sorting and call `filterModels`. Will only load models if not currently making an API call
* @param reset - Clear models
* @returns - an array of models
*/
loadModels(this: PaginationController, reset: boolean = false) {
if (!this.isLoadingPage) {
return this._loadModels(reset);
} else {
return;
}
}
},

/**
* Change the sorting and call `filterModels`
* @param sort - Array of strings
* @param dir - The direction of the sort i.e `asc` or `desc`
* @param isSorted - Is sorted
* @returns - an array of models
*/
changeSorting(this: PaginationController, sort: string[], dir: sortDirection, isSorted: boolean) {
const sorting = get(this, 'sort');
const sortedValue = `${dir === "desc" ? '-' : ''}${sort}`;
const oppositeSortedValue = `${dir === "asc" ? '-' : ''}${sort}`;
if(!isSorted) {
sorting.removeObject(sortedValue);
sorting.removeObject(oppositeSortedValue);
} else if (!sorting.includes(oppositeSortedValue) && !sorting.includes(sortedValue)) {
sorting.unshift(sortedValue);
} else {
//make the new sort column the first one in the list
//so that its sent to the server as the primary sort
sorting.removeObject(oppositeSortedValue);
sorting.unshift(sortedValue);

/**
* Filter models
* @returns - an array of models
*/
filterModels(this: PaginationController) {
return this.loadModels(true);
}
return this.filterModels();
},

/**
* Filter models
* @returns - an array of models
*/
filterModels(this: PaginationController) {
return this.loadModels(true);
},

/**
* Clears the filters and returns the updated model array
* @returns - an array of models
*/
clearFilters(this: PaginationController) {
get(this, 'serverQueryParams').forEach((param: any) => set(this, param, null));
return this.filterModels();
},

/**
* Clears the sort array
*/
clearSorting() {
set(this, 'sort', A());
},

actions: {

/**
* Clears the sort array
*/
clearSorting() {
this.set('sort', A());
}

/**
* Load another page of models
* @returns - an array of models
*/
@action
loadMoreModels(this: PaginationController) {
return this.loadMoreModels();
},
return this.loadModels();
}

/**
* Clear and Reload models
* @returns - an array of models
*/
@action
reloadModels(this: PaginationController) {
return this.reloadModels();
},
return this.loadModels(true);
}

removeModel(this: PaginationController, row: any) {
return this.removeModel(row);
},
/**
* Change the sorting and call `filterModels`
* @param model - A `DS.Model` record
* @returns - result of api call
*/
@action
async removeModel(this: PaginationController, model: DS.Model) {
try {
let result = await tryInvoke(model, 'destroyRecord');
this.model.removeObject(model);
return result;
} catch(error) {
return reject(error);
}
}

/**
* Clear models
*/
@action
clearModels(this: PaginationController) {
this.clearModels();
},
this.set('model', A());
}

@action
filter(this: PaginationController) {
return this.filterModels();
},
}

/**
* Change the sorting and call `filterModels`
* @param sort - Array of strings
* @param dir - The direction of the sort i.e `asc` or `desc`
* @param isSorted - Is sorted
* @returns - an array of models
*/
@action
changeSorting(this: PaginationController, sort: string[], dir: sortDirection, isSorted: boolean) {
return this.changeSorting(sort, dir, isSorted);
},
const sorting = this.sort;
const sortedValue = `${dir === "desc" ? '-' : ''}${sort}`;
const oppositeSortedValue = `${dir === "asc" ? '-' : ''}${sort}`;
if(!isSorted) {
sorting.removeObject(sortedValue);
sorting.removeObject(oppositeSortedValue);
} else if (!sorting.includes(oppositeSortedValue) && !sorting.includes(sortedValue)) {
sorting.unshift(sortedValue);
} else {
//make the new sort column the first one in the list
//so that its sent to the server as the primary sort
sorting.removeObject(oppositeSortedValue);
sorting.unshift(sortedValue);
}
return this.filterModels();
}

/**
* Clears the filters and returns the updated model array
* @returns - an array of models
*/
@action
clearFilters(this: PaginationController) {
return this.clearFilters();
this.serverQueryParams.forEach((param: any) => this.set(param, null));
return this.filterModels();
}
}
});

return PaginationControllerClass;
}

0 comments on commit 9974045

Please sign in to comment.