Adding studies and timepoints to quickSwitch

This commit is contained in:
Bruno Alves de Faria 2017-10-19 18:32:12 -02:00
parent 0417bbd0ff
commit 89f6bd4610
15 changed files with 204 additions and 34 deletions

View File

@ -8,7 +8,9 @@ Template.viewerSection.onCreated(() => {
instance.isTimepointBrowser = () => !!OHIF.viewer.data.currentTimepointId;
OHIF.viewer.quickSwitchStudyBrowserTemplate = 'timepointBrowserQuickSwitch';
if (!instance.isTimepointBrowser()) {
OHIF.viewer.quickSwitchStudyBrowserTemplate = 'studyBrowserQuickSwitch';
instance.loading = new ReactiveVar(true);
instance.studiesInformation = new ReactiveVar([]);
const filter = { studyInstanceUid: OHIF.viewer.data.studyInstanceUids };

View File

@ -2,6 +2,8 @@ import './item.html';
import './item.js';
import './list.html';
import './list.styl';
import './quickSwitch.html';
import './quickSwitch.js';
import './sidebar.html';
import './sidebar.js';
import './studies.html';

View File

@ -5,8 +5,6 @@ import { $ } from 'meteor/jquery';
import { _ } from 'meteor/underscore';
import { OHIF } from 'meteor/ohif:core';
const studySearchPromises = new Map();
Template.timepointBrowserItem.onCreated(() => {
const instance = Template.instance();
const { timepoint, timepointApi } = instance.data;
@ -30,18 +28,7 @@ Template.timepointBrowserItem.onCreated(() => {
};
const filter = { studyInstanceUid: timepoint.studyInstanceUids };
instance.loadStudies = () => {
const promiseKey = JSON.stringify(filter);
if (studySearchPromises.has(promiseKey)) {
return studySearchPromises.get(promiseKey);
} else {
const promise = instance.performLoad();
studySearchPromises.set(promiseKey, promise);
return promise;
}
};
instance.performLoad = () => OHIF.studies.searchStudies(filter).then(studiesData => {
instance.loadStudies = () => OHIF.studies.searchStudies(filter).then(studiesData => {
timepoint.studiesData = studiesData;
timepointApi.timepoints.update(timepoint._id, { $set: { studiesData } });
instance.loaded = true;

View File

@ -0,0 +1,6 @@
<template name="timepointBrowserQuickSwitch">
{{>timepointBrowserList (extend timepointBrowserData)}}
{{#unless instance.showAdditional.get}}
<div class='show-additional'>Show additional timepoints</div>
{{/unless}}
</template>

View File

@ -0,0 +1,94 @@
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Tracker } from 'meteor/tracker';
import { OHIF } from 'meteor/ohif:core';
Template.timepointBrowserQuickSwitch.onCreated(() => {
const instance = Template.instance();
instance.showAdditional = new ReactiveVar(false);
instance.currentTimepoint = new ReactiveVar();
instance.updateCurrentTimepoint = studyInstanceUid => {
const currentTimepoint = OHIF.viewer.timepointApi.study(studyInstanceUid)[0];
instance.currentTimepoint.set(currentTimepoint);
};
const { viewportIndex } = instance.data;
instance.autorun(() => {
OHIF.viewerbase.layoutManager.observer.depend();
const viewportData = OHIF.viewerbase.layoutManager.viewportData[viewportIndex];
instance.updateCurrentTimepoint(viewportData.studyInstanceUid);
});
instance.autorun(() => {
instance.data.currentStudy.dep.depend();
instance.showAdditional.set(false);
});
});
Template.timepointBrowserQuickSwitch.onRendered(() => {
const instance = Template.instance();
instance.autorun(() => {
const currentTimepoint = instance.currentTimepoint.get();
const currentTimepointId = (currentTimepoint && currentTimepoint.timepointId) || '';
const $allBrowserItems = instance.$('.timepoint-browser-item');
const $browserItem = $allBrowserItems.filter(`[data-id=${currentTimepointId}]`);
if (!$browserItem.hasClass('active')) {
$browserItem.find('.timepoint-item').trigger('click');
}
});
instance.autorun(() => {
const currentStudy = instance.data.currentStudy.get();
const studyInstanceUid = (currentStudy && currentStudy.studyInstanceUid) || '';
Tracker.afterFlush(() => {
const $studyBrowserItems = instance.$('.study-browser-item');
$studyBrowserItems.removeClass('active');
$studyBrowserItems.filter(`[data-uid="${studyInstanceUid}"]`).addClass('active');
});
});
});
Template.timepointBrowserQuickSwitch.events({
'ohif.lesiontracker.timepoint.click'(event, instance) {
const $element = $(event.currentTarget);
// Defer the active class toggling to wait for child template rendering
Meteor.defer(() => $element.toggleClass('active'));
},
'ohif.studies.study.click'(event, instance, studyInformation) {
const { studyInstanceUid } = studyInformation;
const study = OHIF.viewer.Studies.findBy({ studyInstanceUid });
instance.data.currentStudy.set(study);
const $studySwitch = $(event.currentTarget).closest('.study-switch');
$studySwitch.siblings('.series-switch').trigger('rescale');
instance.updateCurrentTimepoint(studyInformation.studyInstanceUid);
},
'click .show-additional'(event, instance) {
instance.showAdditional.set(true);
},
});
Template.timepointBrowserQuickSwitch.helpers({
timepointBrowserData() {
const instance = Template.instance();
const { timepointApi } = OHIF.viewer;
const currentTimepoint = instance.currentTimepoint.get();
let timepoints;
if (instance.showAdditional.get()) {
timepoints = timepointApi.key();
} else {
timepoints = [currentTimepoint];
}
return {
timepointApi,
timepoints,
timepointChildTemplate: 'timepointBrowserStudies'
};
}
});

View File

@ -5,7 +5,7 @@
{{>roundedButtonGroup viewTypeButtonGroupData}}
</div>
</div>
{{#scrollArea class='flex-grow' class='fit' scrollableClass='p-a-1' scrollStep=191}}
{{#scrollArea class='flex-grow fit' scrollableClass='p-a-1' scrollStep=191}}
{{>timepointBrowserList (extend timepointBrowserData)}}
{{/scrollArea}}
</div>

View File

@ -1,7 +1,9 @@
import './list.html';
import './list.styl';
import './item.html';
import './item.js';
import './list.html';
import './list.styl';
import './quickSwitch.html';
import './quickSwitch.js';
import './series.html';
import './series.js';
import './sidebar.html';

View File

@ -0,0 +1,3 @@
<template name="studyBrowserQuickSwitch">
{{>studyBrowserList studyBrowserData}}
</template>

View File

@ -0,0 +1,43 @@
import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
import { Tracker } from 'meteor/tracker';
import { OHIF } from 'meteor/ohif:core';
Template.studyBrowserQuickSwitch.onCreated(() => {
const instance = Template.instance();
instance.studiesInformation = new ReactiveVar();
const filter = { studyInstanceUid: OHIF.viewer.data.studyInstanceUids };
OHIF.studies.searchStudies(filter).then(studies => instance.studiesInformation.set(studies));
});
Template.studyBrowserQuickSwitch.onRendered(() => {
const instance = Template.instance();
instance.autorun(() => {
instance.studiesInformation.dep.depend();
const currentStudy = instance.data.currentStudy.get();
const studyInstanceUid = (currentStudy && currentStudy.studyInstanceUid) || '';
Tracker.afterFlush(() => {
const $studyBrowserItems = instance.$('.study-browser-item');
$studyBrowserItems.removeClass('active');
$studyBrowserItems.filter(`[data-uid="${studyInstanceUid}"]`).addClass('active');
});
});
});
Template.studyBrowserQuickSwitch.events({
'ohif.studies.study.click'(event, instance, studyInformation) {
const { studyInstanceUid } = studyInformation;
const study = OHIF.viewer.Studies.findBy({ studyInstanceUid });
instance.data.currentStudy.set(study);
const $studySwitch = $(event.currentTarget).closest('.study-switch');
$studySwitch.siblings('.series-switch').trigger('rescale');
}
});
Template.studyBrowserQuickSwitch.helpers({
studyBrowserData() {
const instance = Template.instance();
const studiesInformation = instance.studiesInformation.get();
return { studiesInformation };
}
});

View File

@ -1,5 +1,5 @@
<template name="studyBrowserSidebar">
{{#scrollArea class='full-height' class='fit' scrollableClass='p-a-1' scrollStep=191}}
{{#scrollArea class='fit' scrollableClass='p-a-1' scrollStep=191}}
{{>studyBrowserList (clone this studyChildTemplate='studyBrowserSeries')}}
{{/scrollArea}}
</template>

View File

@ -1,18 +1,29 @@
import { Meteor } from 'meteor/meteor';
import { OHIF } from 'meteor/ohif:core';
const studySearchPromises = new Map();
/**
* Search for studies information by the given filter
*
* @param {Object} filter Filter that will be used on search
* @returns {Promise} resolved with an array of studies information or rejected with an error
*/
OHIF.studies.searchStudies = filter => new Promise((resolve, reject) => {
Meteor.call('StudyListSearch', filter, (error, studiesData) => {
if (error) {
reject(error);
} else {
resolve(studiesData);
}
});
});
OHIF.studies.searchStudies = filter => {
const promiseKey = JSON.stringify(filter);
if (studySearchPromises.has(promiseKey)) {
return studySearchPromises.get(promiseKey);
} else {
const promise = new Promise((resolve, reject) => {
Meteor.call('StudyListSearch', filter, (error, studiesData) => {
if (error) {
reject(error);
} else {
resolve(studiesData);
}
});
});
studySearchPromises.set(promiseKey, promise);
return promise;
}
};

View File

@ -5,7 +5,7 @@
<div class="removable">
{{>imageViewerViewport (clone viewport)}}
</div>
{{>seriesQuickSwitch (clone this viewportIndex=@index)}}
{{>seriesQuickSwitch (clone this viewport=viewport viewportIndex=@index)}}
</div>
{{/each}}
</div>

View File

@ -20,7 +20,7 @@
<div class="title-label">Study</div>
<div class="study-box r-font">
{{#scrollArea class='study-browser'}}
<div>AAAAA</div>
{{>Template.dynamic template=studyBrowserTemplate data=(clone this currentStudy=instance.currentStudy)}}
{{/scrollArea}}
</div>
</div>

View File

@ -94,11 +94,15 @@ Template.seriesQuickSwitch.helpers({
}
return seriesItems;
},
studyBrowserTemplate() {
return OHIF.viewer.quickSwitchStudyBrowserTemplate || 'studyBrowserQuickSwitch';
}
});
Template.seriesQuickSwitch.events({
'mouseenter .series-switch'(event, instance) {
'mouseenter .series-switch, rescale .series-switch'(event, instance) {
// Control the width of the series browser
const $switch = $(event.currentTarget);
const browserWidth = $switch.offset().left + $switch.outerWidth();

View File

@ -66,13 +66,27 @@
float: left
position: relative
.study-browser
background: purple
.study-switch:hover:after
content: ''
display: block
height: 100px
left: 0
position: absolute
top: 0
width: 300px
.study-browser
left: 0
margin-top: 100px
max-height: calc(100vh - 100px)
transform-origin(1em calc(1em + 17px))
width: 285px
width: 300px
.study-browser-list
padding: 0 10px
.series-browser
max-height: 100vh
max-width: 711px
right: 0
transform-origin(calc(100% - 1em) calc(1em + 15px))
@ -95,7 +109,6 @@
.series-browser,
.study-browser
max-height: 100vh
min-height: 120px
opacity: 0
position: absolute
@ -164,6 +177,9 @@
transform(translateY(0))
transition-delay(0.3s)
.study-browser-item.active .study-item-box
theme('box-shadow', 'inset 0 0 0 3px $activeColor')
@media screen and (max-width: 1599px)
.series-quick-switch