<div class="row" id="patron-search-form-row">
<div class="col-md-11">
- <form ng-submit="search(args)" id="patron-search-form"
+ <form ng-submit="search(searchArgs)" id="patron-search-form"
role="form" class="form-horizontal">
<div class="form-group">
<div class="col-md-2">
- <input type="text" class="form-control" ng-model="args.card"
+ <input type="text" class="form-control" ng-model="searchArgs.card"
placeholder="[% l('Barcode') %]" focus-me="focusMe"/><!--"vim-->
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.family_name" placeholder="[% l('Last Name') %]"/>
+ ng-model="searchArgs.family_name" placeholder="[% l('Last Name') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.first_given_name" placeholder="[% l('First Name') %]"/>
+ ng-model="searchArgs.first_given_name" placeholder="[% l('First Name') %]"/>
</div>
<div class="col-md-2">
</div>
<div class="col-md-2">
- <input type="reset" class="btn btn-default" ng-click="args={}"
+ <input type="reset" class="btn btn-default" ng-click="searchArgs={}"
value="[% l('Clear Form') %]"/>
</div>
<div class="form-group" ng-show="showExtras">
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.second_given_name" placeholder="[% l('Middle Name') %]"/>
+ ng-model="searchArgs.second_given_name" placeholder="[% l('Middle Name') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.alias" placeholder="[% l('Alias') %]"/>
+ ng-model="searchArgs.alias" placeholder="[% l('Alias') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.usrname" placeholder="[% l('Username') %]"/>
+ ng-model="searchArgs.usrname" placeholder="[% l('Username') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.email" placeholder="[% l('Email') %]"/>
+ ng-model="searchArgs.email" placeholder="[% l('Email') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.ident" placeholder="[% l('Identification') %]"/>
+ ng-model="searchArgs.ident" placeholder="[% l('Identification') %]"/>
</div>
</div>
<div class="form-group" ng-show="showExtras">
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.id" placeholder="[% l('Database ID') %]"/>
+ ng-model="searchArgs.id" placeholder="[% l('Database ID') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.phone" placeholder="[% l('Phone') %]"/>
+ ng-model="searchArgs.phone" placeholder="[% l('Phone') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.street1" placeholder="[% l('Street 1') %]"/>
+ ng-model="searchArgs.street1" placeholder="[% l('Street 1') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.street2" placeholder="[% l('Street 2') %]"/>
+ ng-model="searchArgs.street2" placeholder="[% l('Street 2') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
- ng-model="args.city" placeholder="[% l('City') %]"/>
+ ng-model="searchArgs.city" placeholder="[% l('City') %]"/>
</div>
</div>
<div class="form-group" ng-show="showExtras">
<div class="col-md-2">
- <input type="text" class="form-control" ng-model="args.state"
+ <input type="text" class="form-control" ng-model="searchArgs.state"
placeholder="[% l('State') %]" title="[% l('State') %]"/>
</div>
<div class="col-md-2">
- <input type="text" class="form-control" ng-model="args.post_code"
+ <input type="text" class="form-control" ng-model="searchArgs.post_code"
placeholder="[% l('Post Code') %]" title="[% l('Post Code') %]"/>
</div>
<div class="col-md-2">
<input type="text" class="form-control"
placeholder="[% l('Profile Group') %]"
- ng-model="args.profile"
+ ng-model="searchArgs.profile"
typeahead="grp as grp.name for grp in profiles | filter:$viewValue"
typeahead-editable="false" />
</div>
<div class="col-md-2">
<input type="text" class="form-control"
placeholder="[% l('Home Library') %]"
- ng-model="args.home_ou"
+ ng-model="searchArgs.home_ou"
typeahead="org as org.shortname for org in org_units | filter:$viewValue"
typeahead-editable="false" />
</div>
<div class="col-md-2">
<div class="checkbox">
<label>
- <input type="checkbox" ng-model="args.inactive"/>
+ <input type="checkbox" ng-model="searchArgs.inactive"/>
[% l('Include Inactive?') %]
</label>
</div>
<eg-grid
idl-class="au" sort="[]" id-field="id"
- initial-offset="cachedSearchOffset"
- features="-sort,-display"
+ features="-sort,-display,-multisort"
main-label="[% l('Patron Search Results') %]"
items-provider="patronSearchGridProvider"
persist-key="eg.staff.circ.patron.search">
<eg-grid-field label="[% ('ID') %]" path='id' visible></eg-grid-field>
<eg-grid-field label="[% ('Card') %]" path='card.barcode' visible></eg-grid-field>
- <eg-grid-field label="[% ('Last Name') %]" path='family_name' visible sortable></eg-grid-field>
- <eg-grid-field label="[% ('First Name') %]" path='first_given_name' visible sortable></eg-grid-field>
- <eg-grid-field label="[% ('Middle Name') %]" path='second_given_name' visible sortable></eg-grid-field>
- <eg-grid-field label="[% ('DoB') %]" path='dob' visible sortable></eg-grid-field>
+ <eg-grid-field label="[% ('Last Name') %]" path='family_name' visible sortable multisortable></eg-grid-field>
+ <eg-grid-field label="[% ('First Name') %]" path='first_given_name' visible sortable multisortable></eg-grid-field>
+ <eg-grid-field label="[% ('Middle Name') %]" path='second_given_name' visible sortable multisortable></eg-grid-field>
+ <eg-grid-field label="[% ('DoB') %]" path='dob' visible sortable multisortable></eg-grid-field>
<eg-grid-field label="[% ('Home Library') %]" path='home_ou.shortname' visible></eg-grid-field>
- <eg-grid-field label="[% ('Created On') %]" path='create_date' visible sortable></eg-grid-field>
+ <eg-grid-field label="[% ('Created On') %]" path='create_date' visible sortable multisortable></eg-grid-field>
<eg-grid-field label="[% ('Mailing:Street 1') %]" path='mailing_address.street1' visible></eg-grid-field>
<eg-grid-field label="[% ('Mailing:Street 2') %]" path='mailing_address.street2'></eg-grid-field>
style="flex:{{grid.indexFlex + grid.selectorFlex}}">
<div class="eg-grid-conf-cell-entry">[% l('Expand') %]</div>
<div class="eg-grid-conf-cell-entry">[% l('Shrink') %]</div>
- <div class="eg-grid-conf-cell-entry">[% l('Sort') %]</div>
+ <div class="eg-grid-conf-cell-entry" ng-if="!grid.disableMultiSort">[% l('Sort') %]</div>
</div>
<div class="eg-grid-cell"
ng-repeat="col in grid.columnsProvider.columns"
<span class="glyphicon glyphicon-fast-backward"></span>
</a>
</div>
- <div class="eg-grid-conf-cell-entry">
- <input type='number' ng-model="col.sort"
- title="[% l('Sort Priority / Direction') %]" style='width:2.3em'/>
+ <div class="eg-grid-conf-cell-entry" ng-if="!grid.disableMultiSort">
+ <div ng-if="col.multisortable">
+ <input type='number' ng-model="col.sort"
+ title="[% l('Sort Priority / Direction') %]" style='width:2.3em'/>
+ </div>
</div>
</div>
</div>
*/
.controller('PatronSearchCtrl',
['$scope','$q','$routeParams','$timeout','$window','$location','egEnv',
- '$filter','egIDL','egNet','egAuth','egEvent','egList','egUser','patronSvc',
- 'egGridFlatDataProvider',
+ '$filter','egIDL','egNet','egAuth','egEvent','egList','egUser',
+ 'patronSvc', 'egGridFlatDataProvider',
function($scope, $q, $routeParams, $timeout, $window, $location, egEnv,
- $filter, egIDL, egNet, egAuth, egEvent, egList, egUser, patronSvc,
- egGridFlatDataProvider) {
+ $filter, egIDL, egNet, egAuth, egEvent, egList, egUser,
+ patronSvc , egGridDataProvider) {
$scope.initTab('search');
$scope.focusMe = true;
- $scope.args = $location.search();
+ $scope.searchArgs = {};
- console.log('PatronSearchCtrl');
-
- // our data provider is a modified flat data provider
- var provider = egGridFlatDataProvider.instance({});
+ if (patronSvc.lastSearch) {
+ // populate the search form with our cached search info
+ angular.forEach(patronSvc.lastSearch.search, function(val, key) {
+ $scope.searchArgs[key] = val.value;
+ });
+ }
+
+ var provider = egGridDataProvider.instance({});
+ provider.initialize = function() {
+ return {offset : 0};
+ }
+
+ // show the user summary for the first selected user
provider.select = function(items) {
if (items[0]) {
var user = items[0];
}
provider.get = function(offset, count, onitem) {
- console.log('get ' + $location.search() + ' : ' + provider._revision);
var deferred = $q.defer();
- /*
- if (args.id) {
- retrieveUsers([args.id]);
- egUser.get(id).then(function(user) {
- patronSvc.localFlesh(user);
- $scope.patrons.items[idx] = user;
- });
-
- } else {
- sendSearch(args);
- }
- */
-
- var search = compileSearch($location.search());
-
- /*
- if (Object.keys(search).length == 0 &&
- offset == patronSvc.cachedSearchOffset &&
- patronSvc.patrons.length) {
- // accessing the page without a cached search
- // see if we have a cached result set
- angular.forEach(patronSvc.patrons, function(p) { onitem(p) });
- return;
- }
- */
-
- //patronSvc.cachedSearchOffset = offset;
- patronSvc.patrons = [];
+ var search = compileSearch($scope.searchArgs);
+ if (Object.keys(search) == 0) return $q.when();
var home_ou = search.home_ou;
delete search.home_ou;
var inactive = search.inactive;
delete search.inactive;
- console.debug('patron search ' + js2JSON(search));
+ var fullSearch = {
+ search : search,
+ count : count,
+ sort : compileSort(),
+ inactive : inactive,
+ home_ou : home_ou,
+ offset : offset
+ };
+
+ if (patronSvc.lastSearch) {
+ // search repeated, return the cached results
+ if (angular.equals(fullSearch, patronSvc.lastSearch)) {
+ console.log('patron search returning ' +
+ patronSvc.patrons.length + ' cached results');
+
+ // notify has to happen after returning the promise
+ $timeout(
+ function() {
+ angular.forEach(patronSvc.patrons, function(user) {
+ deferred.notify(user);
+ });
+ deferred.resolve();
+ }
+ );
+ return deferred.promise;
+ }
+ } else {
+ patronSvc.lastSearch = fullSearch;
+ }
+
+ if (fullSearch.search.id) {
+ // search by user id performs a direct ID lookup
+ var userId = fullSearch.search.id.value;
+ $timeout(
+ function() {
+ egUser.get(userId).then(function(user) {
+ patronSvc.localFlesh(user);
+ patronSvc.patrons = [user];
+ deferred.notify(user);
+ deferred.resolve();
+ });
+ }
+ );
+ return deferred.promise;
+ }
+
+ patronSvc.patrons = [];
egNet.request(
'open-ils.actor',
'open-ils.actor.patron.search.advanced.fleshed',
egAuth.token(),
- search,
- count,
- compileSort(),
- inactive,
- home_ou,
+ fullSearch.search,
+ fullSearch.count,
+ fullSearch.sort,
+ fullSearch.inactive,
+ fullSearch.home_ou,
egUser.defaultFleshFields,
- offset
+ fullSearch.offset
).then(
function() { deferred.resolve() },
null, // onerror
function(user) {
patronSvc.localFlesh(user); // inline
+ patronSvc.patrons.push(user);
deferred.notify(user);
}
);
provider.itemFieldValue = function(item, column) {
return provider.nestedItemFieldValue(item, column);
};
+
$scope.patronSearchGridProvider = provider;
// typeahead doesn't filter correctly with full hash objects, so
angular.forEach(args, function(val, key) {
if (!val) return;
if (key == 'profile') {
- //search.profile = {value : args.profile.id, group : 0};
- search.profile = {value : search.profile, group : 0};
+ search.profile = {value : args.profile.id, group : 0};
+ //search.profile = {value : search.profile, group : 0};
} else if (key == 'home_ou') {
- //search.home_ou = args.home_ou.id; // passed separately
+ search.home_ou = args.home_ou.id; // passed separately
} else if (key == 'inactive') {
search.inactive = val;
} else {
}
);
- console.log('sort = ' + js2JSON(sort));
return sort;
}
- // alt form which receives fleshed user objects
- /*
- function sendSearch(args) {
- search = compileSearch(args);
-
- var home_ou = search.home_ou;
- delete search.home_ou;
- var inactive = search.inactive;
- delete search.inactive;
-
- console.debug('patron search ' + js2JSON(search));
- egNet.request(
- 'open-ils.actor',
- 'open-ils.actor.patron.search.advanced.fleshed',
- egAuth.token(),
- search,
- 50 //
- compileSort(),
- inactive,
- home_ou,
- egUser.defaultFleshFields
-
- ).then(null, null, function(user) {
- patronSvc.localFlesh(user);
- $scope.patrons.items[$scope.patrons.items.length] = user;
+ // search form submit action; tells the results grid to
+ // refresh itself.
+ $scope.search = function(args) { // args === $scope.searchArgs
+ if (args && Object.keys(args).length)
$scope.patronSearchGridProvider.increment();
- });
- };
- */
-
- // fetch users by id and add them to the patrons list
- /*
- function retrieveUsers(ids) {
- angular.forEach(ids, function(id, idx) {
- // capture idx to maintain search results order
- egUser.get(id).then(function(user) {
- patronSvc.localFlesh(user);
- $scope.patrons.items[idx] = user;
- });
- });
}
- */
-
- // collect form args fire patron search
- $scope.search = function(args) {
- if (args && Object.keys(args).length) {
- //$scope.searchArgs = args;
- //$scope.patronSearchGridProvider.increment();
-
- if (args.profile) args.profile = args.profile.id;
- if (args.home_ou) args.home_ou = args.home_ou.id;
-
- $location.search(args);
-
- /*
- $scope.
- $scope.patrons.reset();
- if (args.id) {
- retrieveUsers([args.id]);
- } else {
- sendSearch(args);
- }
- */
- }
- }
-
- // manage table row selection
- /*
- $scope.onPatronClick = function($event, user) {
- $scope.lastSelected = user;
-
- // control-click / command-click (mac) selects
- // or deselects a row without altering other rows
- if ($event.ctrlKey || $event.metaKey) {
- $scope.patrons.toggleOneSelection(user.id());
-
- // middle-click opens new tab for the patron
- } else if ($event.which == 2) {
-
- var url = $location.absUrl().replace(
- /patron\/search.*$/,
- 'patron/' + user.id() + '/checkout'
- );
- $window.open(url);
-
- } else {
- // vanilla click selects the patron as the current default
- $scope.patrons.selectOne(user.id());
- patronSvc.setDefault(null, user);
- }
- }
- */
+ // TODO: move this into the (forthcoming) grid row activate action
$scope.onPatronDblClick = function($event, user) {
$location.path('/circ/patron/' + user.id() + '/checkout');
}
-
- // opens a new tab for each selected user at /checkout
- // TODO: Chrome will only open one tab per user action (click,
- // etc.). subsequent tabs open new windows (blocked by default).
- // The only way around this I'm seeing is to use a chrome extension
- // http://stackoverflow.com/questions/16749907/window-open-behaviour-in-chrome-tabs-windows
- // for now, skip this feature and support control-click to open
- // multiple patrons instead.
- /*
- $scope.openSelectedPatrons = function() {
- angular.forEach(
- $scope.patrons.selectedItems(),
- function(patron) {
- var url = $location.absUrl();
- url = url.replace(/patron\/search.*$/,
- 'patron/' + patron.id() + '/checkout');
- $window.open(url);
- }
- );
- }
- */
-
- // handled up/down arrow events while the patrons results table is focused.
- // disabled for now, since there are some UI issues to work out first:
- // 1. up/down while a browser scroll bar is visible causes the browser to
- // scroll, which makes sense, but is a little jarring. An overflow/scroll
- // container would be better -- requires a non-table solution.. TODO
- // 2. if table hover Bootstrap css is used, even though the currently
- // selected row changes with arrow up/down, the mouse continues to
- // hover in its original position, making the hovered row appear to be
- // selected (style-wise) even when it's not. Disabling table-hover
- // CSS works, but table-hover is useful, so...
-
- /* TODO: MOVE ME INTO GRID.js
- $scope.navigateResults = function($event) {
- // we can't select the next/previous user if we don't know
- // which user was selected last. this should never happen, though.
- if (!$scope.lastSelected) return;
-
- var user;
- if ($event.which == 40) { // down arrow
- angular.forEach(
- $scope.patrons.items,
- function(item, idx) {
- if (item.id() == $scope.lastSelected.id())
- user = $scope.patrons.items[idx+1];
- }
- )
- } else if ($event.which == 38) { // up arrow
- angular.forEach(
- $scope.patrons.items,
- function(item, idx) {
- if (item.id() == $scope.lastSelected.id())
- user = $scope.patrons.items[idx-1];
- }
- )
- }
-
- if (user) $scope.onPatronClick($event, user);
- }
- */
-
}])
/** * Manages patron summary view
['$scope','$q','egNet','egAuth','egEvent','patronSvc',
function($scope, $q, egNet, egAuth, egEvent, patronSvc) {
// may not need this ctrl at all, since all data
- // come directly from the scope
+ // comes directly from the scope
}])
/**
itemsProvider : '=',
// comma-separated list of supported or disabled grid features
- // TODO: examples
+ // supported features:
+ // -display : columns are hidden by default
+ // -sort : columns are unsortable by default
+ // -multisort : sort priorities config disabled by default
features : '@',
initialOffset : '=',
var grid = this;
grid.init = function() {
- grid.offset = $scope.initialOffset || 0;
+ grid.offset = 0;
grid.limit = 25;
grid.items = [];
grid.selected = {}; // idField-based
grid.columnsProvider = egGridColumnsProvider.instance({
idlClass : grid.idlClass,
defaultToHidden : (grid.features.indexOf('-display') > -1),
- defaultToNoSort : (grid.features.indexOf('-sort') > -1)
+ defaultToNoSort : (grid.features.indexOf('-sort') > -1),
+ defaultToNoMultiSort : (grid.features.indexOf('-multisort') > -1)
});
if ($scope.autoFields) {
});
}
+ // this allows the caller to pass in initializtion
+ // values, like offset, for cases when the caller may
+ // be caching grid data between route loads.
+ var conf = grid.dataProvider.initialize();
+ if (conf) {
+ angular.forEach(conf, function(val, key) {
+ if (val !== null) grid[key] = val;
+ });
+ }
+
grid.compileSort();
$scope.grid = grid;
}
grid.toggleConfDisplay = function() {
if (grid.showGridConf) {
grid.showGridConf = false;
- grid.compileSort();
- grid.collect();
+ if (grid.columnsProvider.hasSortableColumn()) {
+ // only refresh the grid if the user has the
+ // ability to modify the sort priorities.
+ grid.compileSort();
+ grid.collect();
+ }
} else {
grid.showGridConf = true;
}
// boolean fields are presented as value-less attributes
angular.forEach(
- ['visible', 'hidden', 'sortable', 'nonsortable'],
+ [
+ 'visible',
+ 'hidden',
+ 'sortable',
+ 'nonsortable',
+ 'multisortable',
+ 'nonmultisortable',
+ ],
function(field) {
if (angular.isDefined(attrs[field]))
scope[field] = true;
cols.idlClass = args.idlClass;
cols.defaultToHidden = args.defaultToHidden;
cols.defaultToNoSort = args.defaultToNoSort;
+ cols.defaultToNoMultiSort = args.defaultToNoMultiSort;
+
+ // returns true if any columns are sortable
+ cols.hasSortableColumn = function() {
+ return cols.columns.filter(
+ function(col) {
+ return col.sortable || col.multisortable;
+ }
+ ).length > 0;
+ }
cols.showAllColumns = function() {
angular.forEach(cols.columns, function(column) {
path : colSpec.path,
flex : Number(colSpec.flex) || 2,
sort : Number(colSpec.sort) || 0,
- sortable : colSpec.sortable,
- nonsortable : colSpec.nonsortable,
- visible : colSpec.visible,
- hidden : colSpec.hidden,
- datatype : colSpec.datatype
+ visible : colSpec.visible,
+ hidden : colSpec.hidden,
+ datatype : colSpec.datatype,
+ sortable : colSpec.sortable,
+ nonsortable : colSpec.nonsortable,
+ multisortable : colSpec.multisortable,
+ nonmultisortable : colSpec.nonmultisortable
};
if (!column.name) column.name = column.path;
if (column.sortable || (!cols.defaultToNoSort && !column.nonsortable))
column.sortable = true;
+ if (column.multisortable ||
+ (!cols.defaultToNoMultiSort && !column.nonmultisortable))
+ column.multisortable = true;
+
cols.columns.push(column);
if (fromIDL) return;
}
}])
-// Factory service for egGridDataManager instances, which are
-// responsible for collecting flattened grid data.
-.factory('egGridFlatDataProvider',
+
+/*
+ * Generic data provider template class. This is basically an abstract
+ * class factory service whose instances can be locally modified to
+ * meet the needs of each individual grid.
+ */
+.factory('egGridDataProvider',
['$filter','egNet','egAuth','egIDL',
function($filter , egNet , egAuth , egIDL) {
- function FlatDataProvider(args) {
+ function GridDataProvider(args) {
var gridData = this;
- gridData.idlClass = args.idlClass;
- gridData.query = args.query;
- gridData.columnsProvider = args.columnsProvider;
gridData.sort = [];
gridData._revision = 0;
+ gridData.query = args.query;
+ gridData.idlClass = args.idlClass;
+ gridData.columnsProvider = args.columnsProvider;
+
+ gridData.initialize = function() {
+ return {};
+ }
gridData.revision = function() {
return gridData._revision;
}
+ // incrementing the revision tells the grid that a data
+ // refresh is needed.
gridData.increment = function() {
gridData._revision++;
}
- gridData.get = function(index, count, onresponse) {
-
- // fetch data for all currently visible columns
- var queryFields = {}
- angular.forEach(gridData.columnsProvider.columns, function(col) {
- if (gridData.columnsProvider.visible[col.name])
- queryFields[col.name] = col.path;
- });
+ // returns a promise whose notify() delivers items
+ gridData.get = function(index, count) {
+ console.error("egGridDataProvider.get() not implemented");
+ }
- return egNet.request(
- 'open-ils.fielder',
- 'open-ils.fielder.flattened_search',
- egAuth.token(), gridData.idlClass, queryFields,
- gridData.query,
- { sort : gridData.sort,
- limit : count,
- offset : index
- }
- );
+ // called when one or more items are selected in the grid
+ gridData.select = function(items) {
}
- gridData.itemFieldValue = function(item, column) {
- // all of our data is flat
+ gridData.flatItemFieldValue = function(item, column) {
return item[column.name];
}
- // utility function which may be useful for other grid data
- // providers.
// given an object and a dot-separated path to a field,
// extract the value of the field. The path can refer
// to function names or object attributes. If the final
return {
instance : function(args) {
- return new FlatDataProvider(args);
+ return new GridDataProvider(args);
+ }
+ };
+ }
+])
+
+
+// Factory service for egGridDataManager instances, which are
+// responsible for collecting flattened grid data.
+.factory('egGridFlatDataProvider',
+ ['egNet','egAuth','egGridDataProvider',
+ function(egNet , egAuth , egGridDataProvider) {
+
+ return {
+ instance : function(args) {
+ var provider = egGridDataProvider.instance(args);
+
+ provider.get = function(offset, count) {
+
+ // find all of the currently visible columns
+ var queryFields = {}
+ angular.forEach(provider.columnsProvider.columns,
+ function(col) {
+ if (provider.columnsProvider.visible[col.name])
+ queryFields[col.name] = col.path;
+ }
+ );
+
+ return egNet.request(
+ 'open-ils.fielder',
+ 'open-ils.fielder.flattened_search',
+ egAuth.token(), provider.idlClass, queryFields,
+ provider.query,
+ { sort : provider.sort,
+ limit : count,
+ offset : index
+ }
+ );
+ }
+ provider.itemFieldValue = provider.flatItemFieldValue;
+ return provider;
}
};
}