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:
parent
6ad7586d25
commit
99041bebde
@ -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>
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -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')
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
Npm.depends({
|
Npm.depends({
|
||||||
'twbs-pagination': '1.4.1',
|
|
||||||
'isomorphic-base64': '1.0.2',
|
'isomorphic-base64': '1.0.2',
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -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'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@ -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);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user