Skip to content
This repository was archived by the owner on Feb 9, 2026. It is now read-only.

Commit ecf05ce

Browse files
committed
Merge pull request #5 from LabKey/fb_paging
Buddy tested and code reviewed.
2 parents 82b0010 + 5118a04 commit ecf05ce

5 files changed

Lines changed: 226 additions & 7 deletions

File tree

test/src/org/labkey/test/pages/DataGrid.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -145,9 +145,9 @@ public Void apply(Void aVoid)
145145

146146
public void assertRowCount(int count)
147147
{
148-
if (count > 1000)
148+
if (count > 25)
149149
{
150-
_test.waitForElements(Locators.dataRow, 1000);
150+
_test.waitForElements(Locators.dataRow, 25);
151151
Assert.assertEquals("Wrong number of rows in export", count, getExportRowCount());
152152
}
153153
else
@@ -156,11 +156,26 @@ public void assertRowCount(int count)
156156
}
157157
}
158158

159+
public void assertPageTotal(int pages)
160+
{
161+
_test.waitForElement(Locators.totalPages.containing(Integer.toString(pages)));
162+
}
163+
164+
public void assertCurrentPage(int page)
165+
{
166+
_test.waitForFormElementToEqual(Locators.currentPage, Integer.toString(page));
167+
}
168+
159169
public void assertSortPresent(String columnName)
160170
{
161171
_test.waitForElement(Locator.tagWithClassContaining("div", "x-column-header-sort-").withText(columnName));
162172
}
163173

174+
public void assertCellContent(String content)
175+
{
176+
_test.waitForElement(Locators.cellLocator(content));
177+
}
178+
164179
@LogMethod
165180
public void sort(@LoggedParam final String columnName)
166181
{
@@ -191,6 +206,12 @@ public int getExportRowCount()
191206
}
192207
}
193208

209+
public void setCurrentPage(int page)
210+
{
211+
_test.setFormElement(Locators.currentPage, Integer.toString(page));
212+
_test.pressEnter(Locators.currentPage);
213+
}
214+
194215
public File exportGrid()
195216
{
196217
return _test.clickAndWaitForDownload(Locator.css("a.gridexportbtn"));
@@ -211,6 +232,8 @@ public static class Locators
211232
public static Locator.CssLocator grid = Locator.css("div.connector-grid");
212233
public static Locator.CssLocator dataRow = grid.append(Locator.css("tr.x-grid-data-row"));
213234
public static Locator.CssLocator sysmsg = Locator.css("div.sysmsg");
235+
public static Locator.CssLocator totalPages = Locator.css("label.x-box-item");
236+
public static Locator.CssLocator currentPage = Locator.css("input.x-form-field");
214237

215238
public static Locator.XPathLocator columnHeaderLocator(String columnHeaderName)
216239
{

test/src/org/labkey/test/tests/CDSTest.java

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -616,12 +616,31 @@ public void verifyGrid()
616616

617617
CDSHelper.NavigationLink.GRID.makeNavigationSelection(this);
618618

619-
waitForText("Export to see all data."); // grid warning
619+
waitForText("View data grid"); // grid warning
620620

621621
gridColumnSelector.addGridColumn("NAb", "Point IC50", true, true);
622622
gridColumnSelector.addGridColumn("NAb", "Lab", false, true);
623623
grid.ensureColumnsPresent("Point IC50", "Lab");
624624
grid.assertRowCount(2969);
625+
grid.assertPageTotal(119);
626+
627+
//
628+
// Check paging buttons with known dataset. Verify with first and last subject id on page.
629+
//
630+
log("Verify grid paging");
631+
grid.sort("Subject Id");
632+
click(CDSHelper.Locators.cdsButtonLocator(">>"));
633+
grid.assertCurrentPage(119);
634+
grid.assertCellContent("9181");
635+
grid.assertCellContent("9199");
636+
637+
click(CDSHelper.Locators.cdsButtonLocator("<"));
638+
grid.assertCurrentPage(118);
639+
grid.assertCellContent("9156");
640+
grid.assertCellContent("9180");
641+
click(CDSHelper.Locators.cdsButtonLocator("<<"));
642+
grid.assertCellContent("193001");
643+
grid.assertCellContent("193002");
625644

626645
//
627646
// Navigate to Summary to apply a filter
@@ -656,36 +675,56 @@ public void verifyGrid()
656675

657676
grid.setFacet("Race", "White");
658677
grid.assertRowCount(702);
678+
grid.assertPageTotal(29);
659679
_asserts.assertFilterStatusCounts(84,3,3);
660680

681+
//
682+
// Check paging buttons and page selector with filtered dataset.
683+
//
684+
log("Verify grid paging with filtered dataset");
685+
grid.sort("Subject Id");
686+
click(CDSHelper.Locators.cdsButtonLocator(">"));
687+
grid.assertCurrentPage(2);
688+
grid.assertCellContent("9149");
689+
grid.assertCellContent("9102");
690+
691+
grid.setCurrentPage(20);
692+
grid.assertCellContent("193087");
693+
grid.assertCellContent("193088");
694+
661695
log("Change column set and ensure still filtered");
662696
gridColumnSelector.addGridColumn("NAb", "Point IC50", false, true);
663697
grid.ensureColumnsPresent("Point IC50");
664698
grid.assertRowCount(702);
699+
grid.assertPageTotal(29);
665700
_asserts.assertFilterStatusCounts(84, 3, 3);
666701

667702
log("Add a lookup column");
668703
gridColumnSelector.addLookupColumn("NAb", "Lab", "PI");
669704
grid.ensureColumnsPresent("Point IC50", "Lab", "PI");
670705
grid.assertRowCount(702);
706+
grid.assertPageTotal(29);
671707
_asserts.assertFilterStatusCounts(84, 3, 3);
672708

673709
log("Filter on a looked-up column");
674710
grid.setFacet("PI", "Mark Igra");
675711
waitForElement(CDSHelper.Locators.filterMemberLocator("Race: = White"));
676712
waitForElement(CDSHelper.Locators.filterMemberLocator("Lab/PI: = Mark Igra"));
677713
grid.assertRowCount(443);
714+
grid.assertPageTotal(18);
678715
_asserts.assertFilterStatusCounts(15, 2, 2);
679716

680717
log("Filter undo on grid");
681718
cds.clearFilter();
682719
grid.assertRowCount(2969);
720+
grid.assertPageTotal(119);
683721
_asserts.assertDefaultFilterStatusCounts();
684722

685723
click(Locator.linkWithText("Undo"));
686724
waitForElement(CDSHelper.Locators.filterMemberLocator("Race: = White"));
687725
waitForElement(CDSHelper.Locators.filterMemberLocator("Lab/PI: = Mark Igra"));
688726
grid.assertRowCount(443);
727+
grid.assertPageTotal(18);
689728
_asserts.assertFilterStatusCounts(15, 2, 2);
690729

691730
grid.setFilter("Point IC50", "Is Greater Than", "60");
@@ -694,8 +733,10 @@ public void verifyGrid()
694733
grid.assertRowCount(13);
695734
grid.clearFilters("Point IC50");
696735
grid.assertRowCount(2135);
736+
grid.assertPageTotal(86);
697737
grid.clearFilters("PI");
698738
grid.assertRowCount(2969);
739+
grid.assertPageTotal(119);
699740
assertElementPresent(Locator.css(".filterpanel").containing("All subjects")); // ensure there are no app filters remaining
700741

701742
grid.sort("Lab");

test/src/org/labkey/test/util/CDSHelper.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public void enterApplication()
5656
{
5757
_test.goToProjectHome();
5858
_test.clickAndWait(Locator.linkWithText("Application"));
59-
_test.addUrlParameter("maxRows=1000&_showPlotData=true");
59+
_test.addUrlParameter("_showPlotData=true");
6060

6161
_test.assertElementNotPresent(Locator.linkWithText("Home"));
6262
_test.waitForElement(Locator.tagContainingText("h1", "Welcome to the HIV Vaccine"));

webapp/Connector/src/model/Grid.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ Ext.define('Connector.model.Grid', {
184184

185185
getMaxRows : function() {
186186

187-
var max = 500;
187+
var max = 25;
188188
var params = LABKEY.ActionURL.getParameters();
189189

190190
if (Ext.isDefined(params['maxRows'])) {

webapp/Connector/src/view/Grid.js

Lines changed: 157 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ Ext.define('Connector.view.Grid', {
1717

1818
headerHeight: 160,
1919

20+
paging: true,
21+
2022
constructor : function(config) {
2123
this.callParent([config]);
2224
this.addEvents('applyfilter', 'removefilter', 'measureselected');
@@ -123,6 +125,92 @@ Ext.define('Connector.view.Grid', {
123125
});
124126
},
125127

128+
_createFooter : function() {
129+
130+
return Ext.create ('Ext.container.Container', {
131+
height: this.headerHeight,
132+
ui: 'custom',
133+
margin: '10 0 0 15',
134+
id: 'grid-paging-footer',
135+
layout: {
136+
type: 'hbox',
137+
align: 'center'
138+
},
139+
items: [{
140+
// This allows for the following items to be centered
141+
xtype: 'box',
142+
flex: 1,
143+
autoEl: {
144+
tag: 'div'
145+
}
146+
},{
147+
xtype: 'button',
148+
text: '<<',
149+
margin: '0 15 0 0',
150+
handler: this.requestFirstPage,
151+
scope: this
152+
},{
153+
xtype: 'button',
154+
text: '<',
155+
margin: '0 15 0 0',
156+
handler: this.requestPreviousPage,
157+
scope: this
158+
},{
159+
xtype: 'textfield',
160+
id: 'grid-page-number',
161+
hideLabel: true,
162+
width: 30,
163+
value: 1,
164+
enableKeyEvents: true,
165+
listeners: {
166+
specialkey: this.requestPage
167+
}
168+
},{
169+
id: 'grid-page-total',
170+
xtype: 'label',
171+
text: 'of ' + Math.ceil(this.getGrid().getStore().totalCount/this.getGrid().getStore().pageSize),
172+
margin: '5 10 0 5'
173+
174+
},{
175+
xtype: 'button',
176+
text: '>',
177+
margin: '0 15 0 0',
178+
handler: this.requestNextPage,
179+
scope: this
180+
},{
181+
xtype: 'button',
182+
text: '>>',
183+
margin: '0 15 0 0',
184+
handler: this.requestLastPage,
185+
scope: this
186+
},{
187+
// This allows for the following items to be centered
188+
xtype: 'box',
189+
flex: 1,
190+
autoEl: {
191+
tag: 'div'
192+
}
193+
}]
194+
});
195+
},
196+
197+
_updateFooter : function() {
198+
if (this.footer) {
199+
200+
var totalPagesEl = this.footer.getComponent('grid-page-total');
201+
var totalPages = Math.ceil(this.getGrid().getStore().totalCount/this.getGrid().getStore().pageSize);
202+
if (totalPagesEl)
203+
totalPagesEl.setText("of " + totalPages);
204+
205+
var currentPageEl = this.footer.getComponent('grid-page-number');
206+
if (currentPageEl && parseInt(currentPageEl.getValue()) > totalPages) {
207+
this.requestFirstPage()
208+
}
209+
210+
this.updatePageNumber();
211+
}
212+
},
213+
126214
_showOverlay : function() {
127215
if (!this.NO_SHOW) {
128216

@@ -227,10 +315,14 @@ Ext.define('Connector.view.Grid', {
227315

228316
if (prevGridId != null && prevGridId != newGrid.getId()) {
229317
this.remove(prevGridId, true);
318+
if(this.paging && this.footer)
319+
this.remove(this.footer, true);
230320
this._hideOverlay();
231321
}
232322

233323
this.add(newGrid);
324+
if (this.paging)
325+
this.footer = this.add(this._createFooter());
234326

235327
}, this, {single: true});
236328
},
@@ -408,6 +500,7 @@ Ext.define('Connector.view.Grid', {
408500
columns: model.get('columnSet'),
409501
filterArray: model.getFilterArray(true),
410502
maxRows: maxRows,
503+
pageSize: maxRows,
411504
remoteSort: true
412505
};
413506

@@ -437,9 +530,12 @@ Ext.define('Connector.view.Grid', {
437530
this.fireEvent('hideload', this);
438531
}
439532

440-
if (rowCount >= maxRows) {
533+
if (rowCount >= maxRows && !this.paging) {
441534
this.showLimitMessage(maxRows);
442535
}
536+
537+
this._updateFooter();
538+
443539
}, this);
444540

445541
return store;
@@ -449,7 +545,11 @@ Ext.define('Connector.view.Grid', {
449545

450546
var box = this.getBox();
451547
var width = box.width - 27;
452-
var height = box.height - this.headerHeight + 93;
548+
var height;
549+
if (this.paging)
550+
height = box.height - this.headerHeight + 43;
551+
else
552+
height = box.height - this.headerHeight + 93;
453553

454554
return {
455555
width: width,
@@ -672,6 +772,61 @@ Ext.define('Connector.view.Grid', {
672772
}
673773
},
674774

775+
updatePageNumber: function() {
776+
var store = this.getGrid().getStore();
777+
if (this.footer) {
778+
var page = this.footer.getComponent('grid-page-number');
779+
if (page)
780+
{
781+
page.setValue(store.currentPage);
782+
}
783+
}
784+
},
785+
786+
requestFirstPage: function() {
787+
this.getGrid().getStore().loadPage(1);
788+
this.updatePageNumber();
789+
},
790+
791+
requestPreviousPage: function() {
792+
var store = this.getGrid().getStore();
793+
if (store.currentPage > 1)
794+
{
795+
store.previousPage();
796+
this.updatePageNumber();
797+
}
798+
},
799+
800+
requestNextPage: function() {
801+
var store = this.getGrid().getStore();
802+
if (store.currentPage < Math.ceil(store.totalCount/store.pageSize))
803+
{
804+
store.nextPage();
805+
this.updatePageNumber();
806+
}
807+
},
808+
809+
requestLastPage: function() {
810+
var store = this.getGrid().getStore();
811+
store.loadPage(Math.ceil(store.totalCount/store.pageSize));
812+
this.updatePageNumber();
813+
},
814+
815+
requestPage: function(f,e) {
816+
if (e.getKey() == e.ENTER)
817+
{
818+
var main = this.getBubbleParent().getBubbleParent();
819+
var store = main.getGrid().getStore();
820+
821+
var pageNo = parseInt(this.getValue());
822+
if (pageNo <= Math.ceil(store.totalCount / store.pageSize) && pageNo > 0)
823+
{
824+
store.loadPage(pageNo);
825+
main.updatePageNumber();
826+
}
827+
}
828+
},
829+
675830
showLimitMessage : function(max) {
676831

677832
var msg = 'The app only shows up ' + max + ' rows. Export to see all data.';

0 commit comments

Comments
 (0)