Skip to content
This repository has been archived by the owner on May 11, 2021. It is now read-only.

Commit

Permalink
Fix pagination to account for changes in preview endpoint
Browse files Browse the repository at this point in the history
Signed-off-by: Don Naegely <naegelyd@gmail.com>
  • Loading branch information
naegelyd committed Nov 14, 2015
1 parent 5ae2867 commit 2c2c765
Show file tree
Hide file tree
Showing 8 changed files with 145 additions and 35 deletions.
1 change: 1 addition & 0 deletions src/js/cilantro/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ require({
}),

results: new c.ui.ResultsWorkflow({
context: this.data.contexts.session,
view: this.data.views.session,
// The differences in these names are noted
results: this.data.preview
Expand Down
14 changes: 0 additions & 14 deletions src/js/cilantro/models/paginator.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,6 @@ define([
return (1 <= num && num <= this.numPages);
},

// Checks the a _next_ page exists for num (or the current page)
hasNextPage: function(num) {
if (!num) num = this.currentPageNum;

return num < this.numPages;
},

// Checks the a _previous_ page exists for num (or the current page)
hasPreviousPage: function(num) {
if (!num) num = this.currentPageNum;

return num > 1;
},

// Set the current page which triggers the 'change:page' event
setCurrentPage: function(num) {
if (num === this.currentPageNum) return;
Expand Down
82 changes: 79 additions & 3 deletions src/js/cilantro/models/results.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ define([
], function(_, Backbone, c, constants, structs, paginator) {

var ResultsPage = structs.Frame.extend({
idAttribute: 'page_num',
idAttribute: 'page',

url: function() {
var url = _.result(this.collection, 'url');
Expand All @@ -26,6 +26,10 @@ define([
// collection including the frame size, number of possible frames, etc. A
// refresh resets the collection as well as changes to the frame size.
var Results = structs.FrameArray.extend({
currentPageNum: 1,
limit: 20,
numPages: undefined,

initialize: function() {
_.bindAll(this, 'fetch', 'markAsDirty', 'onWorkspaceUnload',
'onWorkspaceLoad', 'refresh');
Expand Down Expand Up @@ -115,25 +119,97 @@ define([
}
};
}
},

url: function() {
return c.utils.alterUrlParams(_.result(this, '_url'), {
page: this.currentPageNum,
limit: this.limit
});
},

setResultCount: function(count) {
if (count !== undefined) {
this.numPages = Math.ceil(count / this.limit);
}
else {
this.numPages = undefined;
}
this.trigger('change:pagecount', this, this.numPages);
}
});

// Mix-in paginator functionality for results.
_.extend(Results.prototype, paginator.PaginatorMixin);

Results.prototype.setCurrentPage = function(num) {
// Don't bother if we are already on the requested page.
if (num === this.currentPageNum) return;

// If we don't know how many pages there are yet then we can't
// really trust the output of hasPage since it is using incomplete
// boundary information.
if (this.numPages && !this.hasPage(num)) {
throw new Error('Cannot set the current page out of bounds');
}

this.previousPageNum = this.currentPageNum;
this.currentPageNum = num;

return this.trigger.apply(this, ['change:currentpage', this].concat(
[].slice.call(this.getCurrentPageStats())));
};

Results.prototype.parse = function(resp, options) {
if (!options.reset) {
// TODO Smartly shuffle pages when only the size changes.
// The data is not invalid, just broken up differently.
this.reset(null, {
silent: true
});
}

if (resp) {
this.currentPageNum = null;
this.setCurrentPage(resp.page); // jshint ignore:line

return [resp];
}
};

Results.prototype.getCurrentPageStats = function() {
// If we don't know how many pages there are then we have to
// always assume we are on the last page since we have no idea
// how to actually request the last page. The reason this doesn't
// affect next is because we can continue to request pages well
// beyond the last one and just get no results.
return [
this.currentPageNum, {
previous: this.previousPageNum,
first: this.currentPageNum === 1,
next: this.currentPageNum === this.numPages,
last: (this.currentPageNum === this.numPages ||
this.numPages === undefined)
}
];
};

// Override the default getPage behavior to respect the preview config
// options. Without this, requests for different pages will not use the
// view set in the config option and will use the session view instead
// resulting in disparity between the first page and all other pages.
Results.prototype.getPage = function(num, options) {
if (!options) options = {};

if (!this.hasPage(num)) return;
// If we don't know how many pages there are yet then we can't
// really trust the output of hasPage since it is using incomplete
// boundary information.
if (this.numPages !== undefined && !this.hasPage(num)) return;

var model = this.get(num);
if (!model && options.load !== false) {
model = new this.model({
page_num: num // jshint ignore:line
page: num // jshint ignore:line
});

model.pending = true;
Expand Down
8 changes: 7 additions & 1 deletion src/js/cilantro/session.js
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,13 @@ define([
_.each(model.links, function(url, name) {
if ((Collection = collectionLinkMap[name])) {
this.data[name] = new Collection();
this.data[name].url = url;
// TODO: There should be a better way to do this, right?
if (name === 'preview') {
this.data[name]._url = url;
}
else {
this.data[name].url = url;
}
this.data[name].fetch({reset: true});
}
}, this);
Expand Down
2 changes: 1 addition & 1 deletion src/js/cilantro/ui/charts/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ define([
var parseDate = function(str) {
// Short-circut if the string is empty or if it does not conform to
// the expected YYYY-MM-DD format.
if (!str || str.length != 10) return;
if (!str || str.length !== 10) return;

var year = parseInt(str.substr(0, 4));
var month = parseInt(str.substr(5, 2)) -1;
Expand Down
2 changes: 1 addition & 1 deletion src/js/cilantro/ui/numbers.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ define([
var renderCount = function($el, count, fallback) {
if (!fallback) fallback = '<em>n/a</em>';

if (!count) {
if (count === null || count === undefined) {
$el.html(fallback);
}
else {
Expand Down
2 changes: 1 addition & 1 deletion src/js/cilantro/ui/tables/table.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ define([
this.$el.append(this.header.el, this.footer.el);

this.listenTo(this.collection, 'reset', function() {
if (this.collection.objectCount === 0) {
if (this.collection.numPages === 0) {
this.$el.hide();
}
else {
Expand Down
69 changes: 55 additions & 14 deletions src/js/cilantro/ui/workflows/results.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,58 @@ define([
label: '.count-label'
},

modelEvents: {
'change:objectcount': 'renderCount'
initialize: function() {
this.model.stats.on('sync', this.onContextSynced, this);
},

onRender: function() {
if (this.model.objectCount !== undefined) {
this.renderCount(this.model, this.model.objectCount);
}
else {
this.renderCount(this.model, '');
}
onContextSynced: function() {
var count = this.model.stats.get('count');
this.collection.setResultCount(count);
numbers.renderCount(
this.ui.count,
count,
'all'
);
this.ui.label.text('records');
}
});


var ResultsPaginator = paginator.Paginator.extend({
renderPageCount: function(model, value) {
var text = value;

// If the page count is undefined then we don't know how many
// pages there are so we can just claim to be showing all pages
// for now until we get an actual value.
if (value === undefined) text = 'all';

// If there are no pages, just lie and claim there is a single page
// since the current page will be 1 in this case and showing page
// 1 / 0 would be a little confusing to the user.
if (value === 0) text = 1;

this.ui.pageCount.text(text);
},

renderCount: function(model, count) {
numbers.renderCount(this.ui.count, count);
this.ui.label.text('records');
renderCurrentPage: function(model, value, options) {
this.ui.currentPage.text(value);
this.ui.first.prop('disabled', !!options.first);
this.ui.prev.prop('disabled', !!options.first);
this.ui.next.prop('disabled', !!options.next);
this.ui.last.prop('disabled', !!options.last);

// If we have disabled the buttons then we need to force hide the
// tooltip to prevent it from being permanently visible.
if (!!options.first) {
this.ui.first.tooltip('hide');
this.ui.prev.tooltip('hide');
}

if (!!options.last) {
this.ui.next.tooltip('hide');
this.ui.last.tooltip('hide');
}
}
});

Expand Down Expand Up @@ -89,6 +125,10 @@ define([

this.data = {};

if (!(this.data.context = this.options.context)) {
throw new Error('context model required');
}

if (!(this.data.view = this.options.view)) {
throw new Error('view model required');
}
Expand Down Expand Up @@ -235,12 +275,13 @@ define([
onRender: function() {
$(document).on('scroll', this.onPageScroll);

this.paginator.show(new paginator.Paginator({
this.paginator.show(new ResultsPaginator({
model: this.data.results
}));

this.count.show(new ResultCount({
model: this.data.results
model: this.data.context,
collection: this.data.results
}));

this.table.show(new tables.Table({
Expand Down

0 comments on commit 2c2c765

Please sign in to comment.