diff --git a/addon/mixins/controller-pagination.ts b/addon/mixins/controller-pagination.ts index e77e516..507d88a 100644 --- a/addon/mixins/controller-pagination.ts +++ b/addon/mixins/controller-pagination.ts @@ -5,14 +5,46 @@ 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 { buildQueryParams, sortDirection } from '@gavant/ember-pagination/utils/query-params'; import DS from 'ember-data'; import RouterService from '@ember/routing/router-service'; +import Controller from '@ember/controller'; +export type ConcreteSubclass = new (...args: any[]) => T; +export type PaginationControllerClass = ConcreteSubclass; + +export interface PaginationController extends Controller { + offset: number | undefined; + limit: number; + sort: string[]; + hasMore: boolean; + modelName: string; + isLoadingPage: boolean; + pagingRootKey: string | null; + filterRootKey: string | null; + includeKey: string; + fetchModels( + this: PaginationController, + queryParams: any + ): DS.AdapterPopulatedRecordArray & DS.PromiseArray; + clearModels(this: PaginationController): void; + _loadModels(this: PaginationController, reset: boolean): Promise; + loadModels(reset?: boolean): Promise | undefined; + filterModels(this: PaginationController): Promise | undefined; + metadata?: { + [key: string]: any; + }; + serverQueryParams?: any[]; + serverDateFormat?: string; +} + +interface ArrayMeta { + meta: any; +} -export type ConcreteSubclass = new(...args: any[]) => T; +export type SearchQuery = DS.AdapterPopulatedRecordArray & DS.RecordArray & DS.PromiseArray & ArrayMeta; -export default function ControllerPaginationClass>(ControllerSubclass: T) { - class PaginationControllerClass extends ControllerSubclass { +export function ControllerPaginationClass>(ControllerSubclass: U) { + class PaginationControllerClass extends ControllerSubclass implements PaginationController { @service router!: RouterService; sort: NativeArray = A(); hasMore: boolean = true; @@ -21,6 +53,13 @@ export default function ControllerPaginationClass[]; + serverDateFormat = undefined; @or('isLoadingPage', 'isLoadingRoute') isLoadingModels!: boolean; @readOnly('model.length') offset: number | undefined; @@ -35,9 +74,9 @@ export default function ControllerPaginationClass | undefined { if (!this.isLoadingPage) { return this._loadModels(reset); } else { @@ -89,7 +128,7 @@ export default function ControllerPaginationClass this.set(param, null)); + clearFilters() { + this.serverQueryParams?.forEach((param: any) => this.set(param, null)); return this.filterModels(); } } diff --git a/addon/mixins/route-pagination.ts b/addon/mixins/route-pagination.ts index 4d7f2e6..a2a1aed 100644 --- a/addon/mixins/route-pagination.ts +++ b/addon/mixins/route-pagination.ts @@ -1,18 +1,20 @@ import { set, setProperties } from '@ember/object'; import { assert } from '@ember/debug'; import DS from 'ember-data'; -import { PaginationController, buildQueryParams } from '@gavant/ember-pagination/utils/query-params'; +import { buildQueryParams } from '@gavant/ember-pagination/utils/query-params'; +import Route from '@ember/routing/route'; +import { PaginationControllerClass, SearchQuery } from './controller-pagination'; -export type ConcreteSubclass = new(...args: any[]) => T; - -export default function RoutePaginationClass>(RouteSubclass: T) { +export type ConcreteSubclass = new (...args: any[]) => T; +export type PaginationRoute = ConcreteSubclass; +export default function RoutePaginationClass>(RouteSubclass: T) { class PaginationRouteClass extends RouteSubclass { /** * Adds functionality `modelName`, `metadata`, and `hasMore` to the controller * @param controller - The controller you want the functionality to be added on to * @param model - The result returned from a `store.query` */ - setupController(controller: PaginationController, model: any) { + setupController(controller: InstanceType, model: any) { assert( 'Model is not an instanceof DS.AdapterPopulatedRecordArray. In order to use the RoutePaginationMixin, the model returned must be an instance of DS.AdapterPopulatedRecordArray or DS.RecordArray which comes from using store.query', model instanceof DS.AdapterPopulatedRecordArray || model instanceof DS.RecordArray @@ -35,8 +37,8 @@ export default function RoutePaginationClass>(Ro * Should be passed in using `/` separators i.e. `accounts/index` * @returns - Controller query params */ - getControllerParams(this: PaginationController, routeName: string = this.routeName): any { - const controller = this.controllerFor(routeName); + getControllerParams(this: InstanceType, routeName: string = this.routeName): any { + const controller = this.controllerFor(routeName) as InstanceType; return buildQueryParams(controller); } @@ -45,8 +47,8 @@ export default function RoutePaginationClass>(Ro * @param controller - The controller you want the functionality to be added on to * @param isExiting - Is the controller exiting */ - resetController(controller: PaginationController, isExiting: boolean) { - super.resetController(controller, isExiting); + resetController(controller: InstanceType, isExiting: boolean, transition: any) { + super.resetController(controller, isExiting, transition); if (isExiting) { set(controller, 'model', null); diff --git a/addon/utils/query-params.ts b/addon/utils/query-params.ts index 848a000..620e219 100644 --- a/addon/utils/query-params.ts +++ b/addon/utils/query-params.ts @@ -2,17 +2,8 @@ import { get, set, getWithDefault } from '@ember/object'; import { isArray } from '@ember/array'; import { isEmpty } from '@ember/utils'; import moment from 'moment'; +import { PaginationController, PaginationControllerClass } from '../mixins/controller-pagination'; -export interface PaginationController { - offset: number | undefined; - limit: number; - sort: string[]; - modelName: string; - pagingRootKey: string | null; - filterRootKey: string | null; - includeKey: string; - [key: string]: any; -} export enum sortDirection { ascending = "asc", @@ -28,14 +19,14 @@ export enum sortDirection { * @returns - Object with query params to send to server */ export function buildQueryParams( - controller: PaginationController, + controller: InstanceType, offset: number = 0, limit: number = 10, queryParamListName: string = 'serverQueryParams', includeListName: string = 'include' ) { - const filterList: string[] = controller[queryParamListName]; - const includeList: string[] = controller[includeListName]; + const filterList: string[] = controller[queryParamListName as keyof PaginationController] ; + const includeList: string[] = controller[includeListName as keyof PaginationController]; let queryParams = getParamsObject(filterList, controller); let pagingRoot = queryParams; @@ -60,7 +51,7 @@ export function buildQueryParams( * @param context - The pagination controller instance * @returns - Object with query params to send to server */ -export function getParamsObject(parameters: string[] | undefined, context: PaginationController) { +export function getParamsObject(parameters: string[] | undefined, context: InstanceType) { let params: any = {}; let filterRoot = params; @@ -79,7 +70,7 @@ export function getParamsObject(parameters: string[] | undefined, context: Pagin key = paramArray[0]; valueKey = paramArray[1]; } - let value = get(context, valueKey); + let value = get(context, valueKey as keyof PaginationController); if (moment.isMoment(value) || moment.isDate(value)) { let serverDateFormat = getWithDefault(context, 'serverDateFormat', 'YYYY-MM-DDTHH:mm:ss'); value = moment(value).format(serverDateFormat);