fix(study-list): Use offset and limit in the dicomweb queries used to search studies with next/prev pagination in study list (#290)

This commit is contained in:
Evren Ozkan 2018-11-08 17:43:26 -05:00
parent 6ad7586d25
commit 99041bebde
6 changed files with 97 additions and 66 deletions

View File

@ -8,13 +8,22 @@
<span>rows per page</span> <span>rows per page</span>
</div> </div>
</div> </div>
<div class="col-xs-8 col-sm-9 col-md-9"> {{#if paginationButtonsEnabled}}
<div class="form-inline form-group page-number"> <div class="col-xs-8 col-sm-9 col-md-9">
<label> <div class="form-inline form-group page-buttons noselect">
<ul class="pagination-control no-margins"></ul> <label>
</label> <ul class="pagination-control no-margins">
<li class="page-item prev disabled">
<a href="#" class="page-link">Previous</a>
</li>
<li class="page-item next disabled">
<a href="#" class="page-link">Next</a>
</li>
</ul>
</label>
</div>
</div> </div>
</div> {{/if}}
</div> </div>
{{/form}} {{/form}}
</template> </template>

View File

@ -1,8 +1,6 @@
import { Template } from 'meteor/templating'; import { Template } from 'meteor/templating';
import { SimpleSchema } from 'meteor/aldeed:simple-schema'; import { SimpleSchema } from 'meteor/aldeed:simple-schema';
import 'twbs-pagination'; import { $ } from 'meteor/jquery';
const visiblePages = 10;
Template.paginationArea.onCreated(function() { Template.paginationArea.onCreated(function() {
const instance = Template.instance(); const instance = Template.instance();
@ -19,60 +17,66 @@ Template.paginationArea.onCreated(function() {
Template.paginationArea.onRendered(() => { Template.paginationArea.onRendered(() => {
const instance = Template.instance(); const instance = Template.instance();
instance.$paginationControl = instance.$('.pagination-control');
// Track changes on recordCount and rowsPerPage // Track changes on recordCount and rowsPerPage
instance.autorun(() => { instance.autorun(() => {
const recordCount = instance.data.recordCount.get(); const recordCount = instance.data.recordCount.get();
const rowsPerPage = instance.data.rowsPerPage.get(); const rowsPerPage = instance.data.rowsPerPage.get();
const currentPage = instance.data.currentPage.get();
// Destroy plugin if exists Meteor.defer(() => {
if (instance.$paginationControl.data().twbsPagination) { const prevButton = instance.$('.prev')[0];
instance.$paginationControl.twbsPagination('destroy'); const nextButton = instance.$('.next')[0];
} if (!prevButton || !nextButton) {
return;
}
if (recordCount && rowsPerPage) { // Enable if there are potentially more records, otherwise disable it
const totalPages = Math.ceil(recordCount / rowsPerPage); if (recordCount >= rowsPerPage) {
nextButton.classList.remove('disabled');
} else {
nextButton.classList.add('disabled');
}
// Initialize plugin // Enable the previous button if it is not the first page, otherwise disable it
instance.$paginationControl.twbsPagination({ if (currentPage > 0) {
totalPages, prevButton.classList.remove('disabled');
visiblePages, } else {
onPageClick: (event, page) => { prevButton.classList.add('disabled');
// Update currentPage }
// Decrease page by 1 to set currentPage });
// Since reactive table current page index starts by 0
instance.data.currentPage.set(page - 1);
}
});
}
}); });
}); });
Template.paginationArea.onDestroyed(() => {
const instance = Template.instance();
if (instance.$paginationControl.data().twbsPagination) {
instance.$paginationControl.twbsPagination('destroy');
}
});
Template.paginationArea.helpers({ Template.paginationArea.helpers({
recordCount() { paginationButtonsEnabled() {
const instance = Template.instance(); const instance = Template.instance();
return instance.data.recordCount.get();
},
isRowsPerPageSelected(rowsPerPage) { const recordCount = instance.data.recordCount.get();
const instance = Template.instance(); const rowsPerPage = instance.data.rowsPerPage.get();
return rowsPerPage === instance.data.rowsPerPage.get(); const currentPage = instance.data.currentPage.get();
// Show pagination if it is not first page or there are potentially more records
return currentPage > 0 || recordCount >= rowsPerPage;
} }
}); });
Template.paginationArea.events({ Template.paginationArea.events({
'click .prev > a'(event, instance) {
const currentPage = instance.data.currentPage.get();
instance.data.currentPage.set(currentPage - 1);
},
'click .next > a'(event, instance) {
const currentPage = instance.data.currentPage.get();
instance.data.currentPage.set(currentPage + 1);
},
'change [data-key=rowsPerPage]'(event, instance) { 'change [data-key=rowsPerPage]'(event, instance) {
const rowsPerPage = $(event.currentTarget).data('component').value(); const rowsPerPage = $(event.currentTarget).data('component').value();
// Update rowsPerPage // Update rowsPerPage
instance.data.rowsPerPage.set(parseInt(rowsPerPage, 10)); instance.data.rowsPerPage.set(parseInt(rowsPerPage, 10));
instance.data.currentPage.set(0);
} }
}); });

View File

@ -18,7 +18,7 @@
select select
width: 42px width: 42px
.page-number .page-buttons
margin: 0 margin: 0
text-align: right text-align: right
@ -29,28 +29,34 @@
margin: 0 margin: 0
li li
display: table-cell
padding: 5px 2px
a a
padding: 4px 8px padding: 4px 8px
theme('background-color', '$primaryBackgroundColor') theme('background-color', '$primaryBackgroundColor')
theme('border-color', '$uiGray') theme('border-color', '$uiGray')
theme('background-color', '$uiGrayDarkest') theme('background-color', '$uiGrayDarkest')
color: white color: white
padding: 4px 8px text-decoration: none
&:hover &:hover
theme('color', '$activeColor') theme('color', '$activeColor')
.active .active
a a
theme('background-color', '$uiGray') theme('background-color', '$uiGray')
border-color: #ddd border-color: #ddd
color: white color: white
.disabled .disabled
cursor: not-allowed
a, a:hover, a:focus, a:active a, a:hover, a:focus, a:active
theme('background-color', '$uiGrayDarkest') theme('background-color', '$uiGrayDarkest')
theme('border-color', '$uiGray') theme('border-color', '$uiGray')
theme('color', '$uiGrayLight') theme('color', '$uiGrayLight')
pointer-events: none
&:not(.disabled):hover a &:not(.disabled):hover a
theme('background-color', '$uiGrayDark') theme('background-color', '$uiGrayDark')

View File

@ -1,5 +1,4 @@
Npm.depends({ Npm.depends({
'twbs-pagination': '1.4.1',
'isomorphic-base64': '1.0.2', 'isomorphic-base64': '1.0.2',
}); });

View File

@ -32,8 +32,8 @@ function dateToString(date) {
* Produces a QIDO URL given server details and a set of specified search filter * Produces a QIDO URL given server details and a set of specified search filter
* items * items
* *
* @param server
* @param filter * @param filter
* @param serverSupportsQIDOIncludeField
* @returns {string} The URL with encoded filter query data * @returns {string} The URL with encoded filter query data
*/ */
function getQIDOQueryParams(filter, serverSupportsQIDOIncludeField) { function getQIDOQueryParams(filter, serverSupportsQIDOIncludeField) {
@ -50,6 +50,7 @@ function getQIDOQueryParams(filter, serverSupportsQIDOIncludeField) {
StudyDescription: filter.studyDescription, StudyDescription: filter.studyDescription,
ModalitiesInStudy: filter.modalitiesInStudy, ModalitiesInStudy: filter.modalitiesInStudy,
limit: filter.limit, limit: filter.limit,
offset: filter.offset,
includefield: serverSupportsQIDOIncludeField ? commaSeparatedFields : 'all' includefield: serverSupportsQIDOIncludeField ? commaSeparatedFields : 'all'
}; };

View File

@ -25,12 +25,6 @@ Template.studylistResult.helpers({
sortOption = Session.get('sortOption'); sortOption = Session.get('sortOption');
} }
// Pagination parameters
const rowsPerPage = instance.paginationData.rowsPerPage.get();
const currentPage = instance.paginationData.currentPage.get();
const offset = rowsPerPage * currentPage;
const limit = offset + rowsPerPage;
const studies = OHIF.studylist.collections.Studies.find({}, { const studies = OHIF.studylist.collections.Studies.find({}, {
sort: sortOption sort: sortOption
}).fetch(); }).fetch();
@ -42,8 +36,7 @@ Template.studylistResult.helpers({
// Update record count // Update record count
instance.paginationData.recordCount.set(studies.length); instance.paginationData.recordCount.set(studies.length);
// Limit studies return studies;
return studies.slice(offset, limit);
}, },
numberOfStudies() { numberOfStudies() {
@ -104,7 +97,7 @@ function replaceUndefinedColumnValue(text) {
* Runs a search for studies matching the studylist query parameters * Runs a search for studies matching the studylist query parameters
* Inserts the identified studies into the Studies Collection * Inserts the identified studies into the Studies Collection
*/ */
function search() { function search(instance) {
OHIF.log.info('search()'); OHIF.log.info('search()');
// Show loading message // Show loading message
@ -113,8 +106,14 @@ function search() {
// Hiding error message // Hiding error message
Session.set('serverError', false); Session.set('serverError', false);
// Pagination parameters
const rowsPerPage = instance.paginationData.rowsPerPage.get();
const currentPage = instance.paginationData.currentPage.get();
// Create the filters to be used for the StudyList Search // Create the filters to be used for the StudyList Search
filter = { filter = {
offset: rowsPerPage * currentPage,
limit: rowsPerPage,
patientName: getFilter($('input#patientName').val()), patientName: getFilter($('input#patientName').val()),
patientId: getFilter($('input#patientId').val()), patientId: getFilter($('input#patientId').val()),
accessionNumber: getFilter($('input#accessionNumber').val()), accessionNumber: getFilter($('input#accessionNumber').val()),
@ -259,7 +258,20 @@ Template.studylistResult.onRendered(() => {
} }
}).data('daterangepicker'); }).data('daterangepicker');
search(); search(instance);
// Search when rowsPerPage or currentPage is changed
instance.autorun(computation => {
instance.paginationData.rowsPerPage.dep.depend();
instance.paginationData.currentPage.dep.depend();
// Stop here if it is the first run
if (computation.firstRun) {
return;
}
search(instance);
});
}); });
Template.studylistResult.onDestroyed(() => { Template.studylistResult.onDestroyed(() => {
@ -278,17 +290,17 @@ function resetSortingColumns(instance, sortingColumn) {
} }
Template.studylistResult.events({ Template.studylistResult.events({
'keydown input'(event) { 'keydown input'(event, instance) {
if (event.which === 13) { // Enter if (event.which === 13) { // Enter
search(); search(instance);
} }
}, },
'onsearch input'() { 'onsearch input'(event, instance) {
search(); search(instance);
}, },
'change #studyDate'(event) { 'change #studyDate'(event, instance) {
let dateRange = $(event.currentTarget).val(); let dateRange = $(event.currentTarget).val();
// Remove all space chars // Remove all space chars
@ -300,7 +312,7 @@ Template.studylistResult.events({
studyDateTo = dates[1]; studyDateTo = dates[1];
if (dateRange !== '') { if (dateRange !== '') {
search(); search(instance);
} }
}, },