feat(google-cloud): Add support for Google Cloud Healthcare API DICOM Store Switch (#325)

* NOTASK: PoC for loading data from Healthcare API

* NOTASK: PoC for loading data from Healthcare API fix

* Add sample dialog for loading test dicom-picker

* Fix incorrect promise resolving

* NOTASK: PoC for loading dicom store

* Add web-components as git submodules. (Probably will be changed later)

* Add rough dicomStore picker

* Add dataset selector

* NOTASK: QIDO metadata first draft

* NOTASK: Not Implemented error for color images

* NOTASK: clean-up

* Dicom files uploader intermediate version

* NOTASK: Accept header

* NOTASK: docker configs

* NOTASK: fix

* NOTASK: howTo

* Add draft of DICOM uploader

* Add missing files

* Fix error with missing clientId

* Update submodule

* NOTASK: HowTo

* NOTASK: config for dev

* NOTASK: new docker file

* clean-up

* Update GCP web-components

* Add integration with async web components

* Fix errors in nginx.conf

* Structured reports views basic implementation

* NOTASK: qido -> wado

* NOTASK: config fix

* NOTASK: dirty copy-paste implementation

* Add "Change dicom store" button.
Add an ability to clear date.
Fix bug, when OAuth dosn't work if URL is not /

* Fix studylist filtering

* Fix dockerfile

* NOTASK: meteor update

* NOTASK: fix of package structure

* NOTASK: merge fix

* improvements

Move check for now SR into SR modal
Use simple button to open SR modal
Remove button styling
cleanup

* copy SR data retrieval to wado

* make search of SR simpler

* Codestyle fix

* NOTASK: palette color error message

* Fix date filter.
Fix server settings on first loading.
Add SR and PS buttons

* NOTASK: PS is now hidden by default

* NOTASK: dirty solution

* NOTASK:  new wadoimage lib version

* Fix PS and SR buttons

* Make modal dialogs vertically centered

* Update web components. Quick UI fixes

* Add missing files to the previous commit

* NOTASK:  show-hide for PS

* NOTASK:  show-hide for PS

* NOTASK:  fix of min-max PixelValue bug

* Add "sign out" functionality for Google OAuth. Update web-components.

* intermediate commit

* Add demo signin page

* Beautifying demo sign in page

* NOTASK:  merge

* NOTASK:  clean-up

* Use npm for getting healthcare-api-adapter instead of git submodule.

* NOTASK:  clean-up

* meteor update

* clean-up

* clean-up

* Clean up code

* Update healthcare-api-adapter version. Add location to dicom store path. Fix buttons style.

* Downgrade meteor and packages to master version. Use meteor-build-client-fixed2
This commit is contained in:
Egor Lezhnin authored and Erik Ziegler committed 2019-03-22 16:42:26 +01:00
1 parent 1783351f57
commit 9486522552
68 files changed
+1422 -514

No files matched your search

@@ -1,6 +1,9 @@
<template name="studylistResult">
<div class="studyListToolbar clearfix">
<div class="header pull-left">Study List</div>
<div class="header pull-left">
<span>Study List</span>
<span class="dicom-source">{{dicomSource}}</span>
</div>
<div class="studyCount pull-right">{{numberOfStudies}}</div>
<div class="pull-right">{{>studylistToolbar}}</div>
</div>
@@ -56,7 +59,7 @@
class="form-control studylist-search"
id="modality">
</th>
<th class="studyDescription">
<!-- <th class="studyDescription">
<div id="_studyDescription" class="sortingCell">
<span>Study Description</span>
<i class="{{sortingColumnsIcons.studyDescription}}">&nbsp;</i>
@@ -64,7 +67,7 @@
<input type="text"
class="form-control studylist-search"
id="studyDescription">
</th>
</th> -->
</tr>
</thead>
<tbody id="studyListData">
@@ -6,6 +6,7 @@ import { ReactiveDict } from 'meteor/reactive-dict';
import { moment } from 'meteor/momentjs:moment';
import { OHIF } from 'meteor/ohif:core';
Session.setDefault('showLoadingText', true);
Session.setDefault('serverError', false);
@@ -39,6 +40,13 @@ Template.studylistResult.helpers({
return studies;
},
dicomSource() {
const config = Session.get('GCP_HEALTHCARE_CONFIG');;
if (!config)
return '';
return config.project + ' / ' + config.location + ' / ' + config.dataset + ' / ' + config.dicomStore
},
numberOfStudies() {
return OHIF.studylist.collections.Studies.find().count();
},
@@ -75,8 +83,11 @@ let filter;
* @returns {*}
*/
function getFilter(filter) {
if (filter && filter.length && filter.substr(filter.length - 1) !== '*') {
filter += '*';
const server = OHIF.servers.getCurrentServer();
if (!server.isCloud) {
if (filter && filter.length && filter.substr(filter.length - 1) !== '*') {
filter += '*';
}
}
return filter;
@@ -100,6 +111,9 @@ function replaceUndefinedColumnValue(text) {
function search(instance) {
OHIF.log.info('search()');
// Clear all current studies
OHIF.studylist.collections.Studies.remove({});
// Show loading message
Session.set('showLoadingText', true);
@@ -111,10 +125,9 @@ function search(instance) {
const currentPage = instance.paginationData.currentPage.get();
// Create the filters to be used for the StudyList Search
const reverseFormatPN = Blaze._getGlobalHelper('reverseFormatPN');
filter = {
offset: rowsPerPage * currentPage,
limit: rowsPerPage,
patientName: getFilter($('input#patientName').val()),
patientName: reverseFormatPN(getFilter($('input#patientName').val())),
patientId: getFilter($('input#patientId').val()),
accessionNumber: getFilter($('input#accessionNumber').val()),
studyDescription: getFilter($('input#studyDescription').val()),
@@ -122,7 +135,11 @@ function search(instance) {
studyDateTo,
modalitiesInStudy: $('input#modality').val() ? $('input#modality').val() : ''
};
const server = OHIF.servers.getCurrentServer();
if (!server.isCloud) {
filter.offset=rowsPerPage * currentPage;
filter.limit=rowsPerPage;
}
// Make sure that modality has a reasonable value, since it is occasionally
// returned as 'undefined'
const modality = replaceUndefinedColumnValue($('input#modality').val());
@@ -143,10 +160,7 @@ function search(instance) {
// Loop through all identified studies
studies.forEach(study => {
// TODO: Why is this Modality filter different from QIDO?
if (!modality && !study.modalities.includes(modality)) {
return;
}
// Sometimes DICOM studies have incorrect Date entries with
// periods such as '1990.10.04'
@@ -247,16 +261,30 @@ Template.studylistResult.onRendered(() => {
}
instance.datePicker = $studyDate.daterangepicker({
maxDate: today,
autoUpdateInput: true,
startDate: startDate,
endDate: endDate,
maxDate: false,
autoUpdateInput: false,
// startDate: startDate,
// endDate: endDate,
ranges: {
Empty: [],
Today: [today, today],
'Last 7 Days': [lastWeek, today],
'Last 30 Days': [lastMonth, today]
}
},
locale: { cancelLabel: 'Clear' }
}).data('daterangepicker');
instance.datePicker.autoUpdateInput = true;
$studyDate.on('apply.daterangepicker', function(ev, picker) {
if (picker.chosenLabel === 'Empty')
$(this).val('');
else
$(this).val(picker.startDate.format('MM/DD/YYYY') + ' - ' + picker.endDate.format('MM/DD/YYYY'));
$studyDate.trigger('change');
});
$studyDate.on('cancel.daterangepicker', function(ev, picker) {
$(this).val('');
$studyDate.trigger('change');
});
search(instance);
@@ -307,9 +335,15 @@ Template.studylistResult.events({
dateRange = dateRange.replace(/ /g, '');
// Split dateRange into subdates
const dates = dateRange.split('-');
studyDateFrom = dates[0];
studyDateTo = dates[1];
if (dateRange) {
// Split dateRange into subdates
const dates = dateRange.split('-');
studyDateFrom = dates[0];
studyDateTo = dates[1];
} else {
studyDateFrom = '';
studyDateTo = '';
}
if (dateRange !== '') {
search(instance);
@@ -25,6 +25,11 @@ $bodyCellHeight = 40px
color: $tableTextSecondaryColor
line-height: $studyListToolbarHeight
.dicom-source
font-size: 18px;
font-weight: 400;
margin: 0 30px;
.studylistToolbar
height: $studyListToolbarHeight
line-height: $studyListToolbarHeight
@@ -8,5 +8,11 @@
<input id="btnImport" class='js-import-files' type="file" webkitdirectory directory multiple>
</div>
{{/if}}
{{#if changeDicomStoreSupported}}
{{#button class='btn btn-primary changeDicomStoreBtn'}}Change dicom store{{/button}}
{{/if}}
{{#if uploadSupported}}
{{#button class='btn btn-primary uploadStudiesBtn'}}Upload studies{{/button}}
{{/if}}
</div>
</template>
@@ -1,5 +1,6 @@
import { OHIF } from 'meteor/ohif:core';
import { Template } from 'meteor/templating';
import { Router } from 'meteor/clinical:router';
import { Meteor } from 'meteor/meteor';
import { Session } from 'meteor/session';
import { $ } from 'meteor/jquery';
@@ -25,6 +26,21 @@ Template.studylistToolbar.events({
'click .js-import-files'(event) {
// Reset file input
$(event.currentTarget).val('');
},
'click .uploadStudiesBtn'() {
OHIF.gcloud.showUploadStudiesDialog();
},
'click .changeDicomStoreBtn'() {
OHIF.gcloud.showDicomStorePicker({canClose:true}).then(config => {
if (!config)
return;
Session.set("IsStudyListReady", false);
OHIF.studylist.collections.Studies.remove({});
OHIF.servers.applyCloudServerConfig(config);
setImmediate(() => Session.set("IsStudyListReady", true));
});
}
});
@@ -32,5 +48,11 @@ Template.studylistToolbar.helpers({
importSupported() {
const importSupported = Session.get('importSupported');
return (importSupported && OHIF.uiSettings.studyListFunctionsEnabled);
},
uploadSupported() {
return !!(OHIF.gcloud && OHIF.gcloud.isEnabled());
},
changeDicomStoreSupported() {
return !!(OHIF.gcloud && OHIF.gcloud.isEnabled());
}
});
@@ -25,3 +25,6 @@
overflow: hidden
position: absolute
z-index: -1
.uploadStudiesBtn
margin 0 20px