Final adjustments on quickSwitch
This commit is contained in:
parent
89f6bd4610
commit
37137b9331
@ -7,13 +7,6 @@
|
||||
|
||||
{{>toolbarSectionTools toolbarButtons=toolbarButtons}}
|
||||
|
||||
{{#if splitView}}
|
||||
{{>studySeriesQuickSwitch (clone this side="right" viewportIndex=1)}}
|
||||
{{>studySeriesQuickSwitch (clone this side="left" viewportIndex=0)}}
|
||||
{{else}}
|
||||
{{>studySeriesQuickSwitch (clone this side="middle" viewportIndex=0)}}
|
||||
{{/if}}
|
||||
|
||||
<div id="toolbarSectionEntry" class="toolbarSectionEntry pull-right rm-l-1 p-x-1">
|
||||
{{>caseProgress}}
|
||||
</div>
|
||||
|
||||
@ -4,19 +4,6 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
import { Viewerbase } from 'meteor/ohif:viewerbase';
|
||||
|
||||
Template.toolbarSection.helpers({
|
||||
// Returns true if the view shall be split in two viewports
|
||||
splitView() {
|
||||
// Run this computation every time the viewports are updated
|
||||
Session.get('LayoutManagerUpdated');
|
||||
|
||||
// Stops here if layout manager is not defined yet
|
||||
if (!Viewerbase.layoutManager) {
|
||||
return;
|
||||
}
|
||||
|
||||
return Viewerbase.layoutManager.viewportData.length > 1;
|
||||
},
|
||||
|
||||
leftSidebarToggleButtonData() {
|
||||
const instance = Template.instance();
|
||||
return {
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.scrollArea.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
@ -16,17 +17,20 @@ Template.scrollArea.onCreated(() => {
|
||||
|
||||
Template.scrollArea.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
const { config } = instance;
|
||||
if (config.hideScrollbar) {
|
||||
const $scrollable = instance.$('.scrollable').first();
|
||||
const scrollable = $scrollable[0];
|
||||
const x = config.scrollX ? 1 : 0;
|
||||
const y = config.scrollY ? 1 : 0;
|
||||
$scrollable.css({
|
||||
'margin-right': 0 - (scrollable.offsetWidth - scrollable.clientWidth) * y,
|
||||
'margin-bottom': 0 - (scrollable.offsetHeight - scrollable.clientHeight) * x
|
||||
});
|
||||
}
|
||||
|
||||
instance.adjustMargins = _.throttle(() => {
|
||||
const { config } = instance;
|
||||
if (config.hideScrollbar) {
|
||||
const $scrollable = instance.$('.scrollable').first();
|
||||
const x = config.scrollX ? 1 : 0;
|
||||
const y = config.scrollY ? 1 : 0;
|
||||
const scrollbarSize = OHIF.ui.getScrollbarSize();
|
||||
$scrollable.css({
|
||||
'margin-right': 0 - (scrollbarSize[0]) * y,
|
||||
'margin-bottom': 0 - (scrollbarSize[1]) * x
|
||||
});
|
||||
}
|
||||
}, 150);
|
||||
|
||||
instance.$scrollable = instance.$('.scrollable').first();
|
||||
instance.scrollHandler = _.throttle(event => {
|
||||
@ -50,9 +54,17 @@ Template.scrollArea.onRendered(() => {
|
||||
if (scrollTop + height < scrollHeight) {
|
||||
$scrollArea.addClass('can-scroll-down');
|
||||
}
|
||||
}, 300);
|
||||
}, 150);
|
||||
|
||||
instance.scrollHandler();
|
||||
|
||||
instance.adjustMargins();
|
||||
$(window).on('resize', instance.adjustMargins);
|
||||
});
|
||||
|
||||
Template.scrollArea.onDestroyed(() => {
|
||||
const instance = Template.instance();
|
||||
$(window).off('resize', instance.adjustMargins);
|
||||
});
|
||||
|
||||
Template.scrollArea.events({
|
||||
|
||||
@ -9,6 +9,7 @@ $scrollNavSize = 24px
|
||||
.scrollable
|
||||
max-height: inherit
|
||||
overflow: hidden
|
||||
zoom: 1
|
||||
|
||||
&.scroll-x
|
||||
overflow-x: scroll
|
||||
|
||||
@ -26,3 +26,45 @@ OHIF.ui.getOffset = element => {
|
||||
top
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the vertical and horizontal scrollbar sizes
|
||||
* Got from https://stackoverflow.com/questions/986937/how-can-i-get-the-browsers-scrollbar-sizes
|
||||
*
|
||||
* @returns {Array} Array containing the scrollbar horizontal and vertical sizes
|
||||
*/
|
||||
OHIF.ui.getScrollbarSize = () => {
|
||||
const inner = document.createElement('p');
|
||||
inner.style.width = '100%';
|
||||
inner.style.height = '100%';
|
||||
|
||||
const outer = document.createElement('div');
|
||||
outer.style.position = 'absolute';
|
||||
outer.style.top = '0px';
|
||||
outer.style.left = '0px';
|
||||
outer.style.visibility = 'hidden';
|
||||
outer.style.width = '100px';
|
||||
outer.style.height = '100px';
|
||||
outer.style.overflow = 'hidden';
|
||||
outer.appendChild(inner);
|
||||
|
||||
document.body.appendChild(outer);
|
||||
|
||||
const w1 = inner.offsetWidth;
|
||||
const h1 = inner.offsetHeight;
|
||||
outer.style.overflow = 'scroll';
|
||||
let w2 = inner.offsetWidth;
|
||||
let h2 = inner.offsetHeight;
|
||||
|
||||
if (w1 === w2) {
|
||||
w2 = outer.clientWidth;
|
||||
}
|
||||
|
||||
if (h1 === h2) {
|
||||
h2 = outer.clientHeight;
|
||||
}
|
||||
|
||||
document.body.removeChild(outer);
|
||||
|
||||
return [(w1 - w2), (h1 - h2)];
|
||||
};
|
||||
|
||||
@ -13,8 +13,8 @@
|
||||
<div class="timepoint-summary">{{choose instance.summary.get 'Click to load'}}</div>
|
||||
</div>
|
||||
{{#if this.timepointChildTemplate}}
|
||||
{{#if and (not instance.loading.get) instance.loaded}}
|
||||
{{>Template.dynamic template=this.timepointChildTemplate data=(clone this studiesInformation=timepoint.studiesData)}}
|
||||
{{#if instance.studiesData.get}}
|
||||
{{>Template.dynamic template=this.timepointChildTemplate data=(clone this studiesInformation=instance.studiesData.get)}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
@ -8,15 +8,28 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
Template.timepointBrowserItem.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
const { timepoint, timepointApi } = instance.data;
|
||||
const { timepointId } = timepoint;
|
||||
|
||||
const hasStudiesData = !!(timepoint.studiesData && timepoint.studiesData.length);
|
||||
instance.summary = new ReactiveVar('');
|
||||
instance.loading = new ReactiveVar(false);
|
||||
instance.loaded = !!(timepoint.studiesData && timepoint.studiesData.length);
|
||||
instance.studiesData = new ReactiveVar(hasStudiesData ? timepoint.studiesData : null);
|
||||
|
||||
const updateStudiesData = newDocument => {
|
||||
const newTimepoint = newDocument || timepointApi.timepoints.findOne({ timepointId });
|
||||
if (newTimepoint && newTimepoint.studiesData && newTimepoint.studiesData.length) {
|
||||
instance.studiesData.set(newTimepoint.studiesData);
|
||||
}
|
||||
};
|
||||
|
||||
timepointApi.timepoints.find({ timepointId }).observe({ changed: updateStudiesData });
|
||||
|
||||
// Build the modalities summary of all timepoint's studies
|
||||
instance.setModalitiesSummary = () => {
|
||||
const studiesData = instance.studiesData.get();
|
||||
if (!studiesData) return;
|
||||
|
||||
const modalities = {};
|
||||
timepoint.studiesData.forEach(study => {
|
||||
studiesData.forEach(study => {
|
||||
const modality = study.modalities || 'UN';
|
||||
modalities[modality] = modalities[modality] + 1 || 1;
|
||||
});
|
||||
@ -29,20 +42,22 @@ Template.timepointBrowserItem.onCreated(() => {
|
||||
|
||||
const filter = { studyInstanceUid: timepoint.studyInstanceUids };
|
||||
instance.loadStudies = () => OHIF.studies.searchStudies(filter).then(studiesData => {
|
||||
timepoint.studiesData = studiesData;
|
||||
instance.studiesData.set(studiesData);
|
||||
timepointApi.timepoints.update(timepoint._id, { $set: { studiesData } });
|
||||
instance.loaded = true;
|
||||
instance.setModalitiesSummary();
|
||||
instance.loading.set(false);
|
||||
}).catch(error => {
|
||||
const text = 'An error has occurred while retrieving studies information';
|
||||
OHIF.ui.notifications.danger({ text });
|
||||
OHIF.log.error(error);
|
||||
});
|
||||
|
||||
if (instance.loaded) {
|
||||
instance.setModalitiesSummary();
|
||||
}
|
||||
updateStudiesData();
|
||||
instance.autorun(() => {
|
||||
const studiesData = instance.studiesData.get();
|
||||
if (studiesData) {
|
||||
instance.setModalitiesSummary();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.timepointBrowserItem.events({
|
||||
@ -58,7 +73,7 @@ Template.timepointBrowserItem.events({
|
||||
$element.trigger('ohif.lesiontracker.timepoint.click', instance.data.timepoint);
|
||||
};
|
||||
|
||||
if (!instance.loaded) {
|
||||
if (!instance.studiesData.get()) {
|
||||
instance.summary.set('Loading...');
|
||||
instance.loadStudies().then(() => Tracker.afterFlush(triggerClick));
|
||||
} else {
|
||||
|
||||
@ -77,3 +77,9 @@
|
||||
.timepoint-title
|
||||
theme('color', '$textPrimaryColor')
|
||||
padding-top: 2px
|
||||
|
||||
.series-quick-switch .timepoint-browser-list
|
||||
padding: 0 10px
|
||||
|
||||
div.timepoint-title
|
||||
text-transform: none
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<template name="timepointBrowserQuickSwitch">
|
||||
{{>timepointBrowserList (extend timepointBrowserData)}}
|
||||
{{#unless instance.showAdditional.get}}
|
||||
<div class='show-additional'>Show additional timepoints</div>
|
||||
{{/unless}}
|
||||
{{#if instance.hasAdditional.get}}
|
||||
<div class='study-item-box additional'>Show additional timepoints</div>
|
||||
{{/if}}
|
||||
</template>
|
||||
|
||||
@ -2,45 +2,66 @@ import { Meteor } from 'meteor/meteor';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { Tracker } from 'meteor/tracker';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.timepointBrowserQuickSwitch.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
instance.showAdditional = new ReactiveVar(false);
|
||||
instance.currentTimepoint = new ReactiveVar();
|
||||
const { timepointApi } = OHIF.viewer;
|
||||
|
||||
instance.updateCurrentTimepoint = studyInstanceUid => {
|
||||
const currentTimepoint = OHIF.viewer.timepointApi.study(studyInstanceUid)[0];
|
||||
instance.currentTimepoint.set(currentTimepoint);
|
||||
instance.hasAdditional = new ReactiveVar(false);
|
||||
instance.showAdditional = new ReactiveVar(false);
|
||||
instance.selectedTimepoint = new ReactiveVar();
|
||||
instance.timepoints = new ReactiveVar([]);
|
||||
|
||||
instance.updateSelectedTimepoint = studyInstanceUid => {
|
||||
const selectedTimepoint = timepointApi.study(studyInstanceUid)[0];
|
||||
instance.selectedTimepoint.set(selectedTimepoint);
|
||||
};
|
||||
|
||||
const currentTimepoint = timepointApi.current();
|
||||
const filter = { latestDate: { $lte: currentTimepoint.latestDate } };
|
||||
instance.keyTimepoints = timepointApi.key(filter);
|
||||
|
||||
const { viewportIndex } = instance.data;
|
||||
instance.autorun(() => {
|
||||
OHIF.viewerbase.layoutManager.observer.depend();
|
||||
const viewportData = OHIF.viewerbase.layoutManager.viewportData[viewportIndex];
|
||||
instance.updateCurrentTimepoint(viewportData.studyInstanceUid);
|
||||
instance.updateSelectedTimepoint(viewportData.studyInstanceUid);
|
||||
});
|
||||
|
||||
instance.autorun(() => {
|
||||
instance.data.currentStudy.dep.depend();
|
||||
instance.showAdditional.set(false);
|
||||
});
|
||||
|
||||
instance.autorun(() => {
|
||||
const showAdditional = instance.showAdditional.get();
|
||||
instance.hasAdditional.set(!showAdditional && instance.keyTimepoints.length > 1);
|
||||
});
|
||||
|
||||
instance.autorun(() => {
|
||||
const selectedTimepoint = instance.selectedTimepoint.get();
|
||||
const showAdditional = instance.showAdditional.get();
|
||||
const timepoints = showAdditional ? instance.keyTimepoints : [selectedTimepoint];
|
||||
instance.timepoints.set(timepoints);
|
||||
});
|
||||
});
|
||||
|
||||
Template.timepointBrowserQuickSwitch.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
instance.autorun(() => {
|
||||
const currentTimepoint = instance.currentTimepoint.get();
|
||||
const currentTimepointId = (currentTimepoint && currentTimepoint.timepointId) || '';
|
||||
const selectedTimepoint = instance.selectedTimepoint.get();
|
||||
const selectedTimepointId = (selectedTimepoint && selectedTimepoint.timepointId) || '';
|
||||
const $allBrowserItems = instance.$('.timepoint-browser-item');
|
||||
const $browserItem = $allBrowserItems.filter(`[data-id=${currentTimepointId}]`);
|
||||
const $browserItem = $allBrowserItems.filter(`[data-id=${selectedTimepointId}]`);
|
||||
if (!$browserItem.hasClass('active')) {
|
||||
$browserItem.find('.timepoint-item').trigger('click');
|
||||
}
|
||||
});
|
||||
|
||||
instance.autorun(() => {
|
||||
instance.updateActiveStudy = () => {
|
||||
const currentStudy = instance.data.currentStudy.get();
|
||||
const studyInstanceUid = (currentStudy && currentStudy.studyInstanceUid) || '';
|
||||
Tracker.afterFlush(() => {
|
||||
@ -48,15 +69,16 @@ Template.timepointBrowserQuickSwitch.onRendered(() => {
|
||||
$studyBrowserItems.removeClass('active');
|
||||
$studyBrowserItems.filter(`[data-uid="${studyInstanceUid}"]`).addClass('active');
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
instance.autorun(instance.updateActiveStudy);
|
||||
});
|
||||
|
||||
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'));
|
||||
$element.toggleClass('active');
|
||||
instance.updateActiveStudy();
|
||||
},
|
||||
|
||||
'ohif.studies.study.click'(event, instance, studyInformation) {
|
||||
@ -65,29 +87,39 @@ Template.timepointBrowserQuickSwitch.events({
|
||||
instance.data.currentStudy.set(study);
|
||||
const $studySwitch = $(event.currentTarget).closest('.study-switch');
|
||||
$studySwitch.siblings('.series-switch').trigger('rescale');
|
||||
instance.updateCurrentTimepoint(studyInformation.studyInstanceUid);
|
||||
instance.updateSelectedTimepoint(studyInformation.studyInstanceUid);
|
||||
|
||||
// Create a hover bridge to prevent quick switch from closing due to scroll height
|
||||
Meteor.defer(() => {
|
||||
const $scrollable = $studySwitch.find('.study-browser>.scrollable');
|
||||
const offsetY = $scrollable.offset().top + $scrollable.outerHeight();
|
||||
if (event.clientY > offsetY) {
|
||||
const hoverHandler = _.throttle(event => {
|
||||
if (event.clientY <= offsetY) {
|
||||
$scrollable.css('padding-bottom', '');
|
||||
$scrollable.off('mousemove', hoverHandler);
|
||||
$scrollable.off('mouseleave', hoverHandler);
|
||||
}
|
||||
}, 100);
|
||||
$scrollable.css('padding-bottom', event.clientY - offsetY + 20);
|
||||
$scrollable.on('mousemove', hoverHandler);
|
||||
$scrollable.one('mouseleave', () => $scrollable.off('mousemove', hoverHandler));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
'click .show-additional'(event, instance) {
|
||||
'click .study-item-box.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,
|
||||
timepoints: instance.timepoints.get(),
|
||||
timepointChildTemplate: 'timepointBrowserStudies'
|
||||
};
|
||||
}
|
||||
|
||||
@ -192,11 +192,11 @@ class TimepointApi {
|
||||
}
|
||||
|
||||
// Return only the key timepoints (current, prior, nadir and baseline)
|
||||
key() {
|
||||
key(filter={}) {
|
||||
const result = [];
|
||||
|
||||
// Get all the timepoints
|
||||
const all = this.all();
|
||||
const all = this.all(filter);
|
||||
|
||||
// Iterate over each timepoint and insert the key ones in the result
|
||||
_.each(all, (timepoint, index) => {
|
||||
|
||||
@ -22,7 +22,13 @@ Template.studyBrowserItem.events({
|
||||
const { studyInformation } = instance.data;
|
||||
const element = event.currentTarget.parentElement;
|
||||
const $element = $(element);
|
||||
const triggerClick = () => $element.trigger('ohif.studies.study.click', studyInformation);
|
||||
const triggerClick = () => {
|
||||
const cloneEvent = _.clone(event);
|
||||
delete cloneEvent.type;
|
||||
cloneEvent.currentTarget = cloneEvent.target = element;
|
||||
const newEvent = $.Event('ohif.studies.study.click', cloneEvent);
|
||||
$element.trigger(newEvent, studyInformation);
|
||||
};
|
||||
|
||||
if (instance.loaded) {
|
||||
triggerClick();
|
||||
|
||||
@ -3,10 +3,6 @@ import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { $ } from 'meteor/jquery';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// FIXME >>>> REMOVE
|
||||
$(document.body).on('keydown', e => (e.keyCode === 69 && $('.quickSwitchWrapper').toggle()) || 1);
|
||||
OHIF.cornerstone.renderer = '';
|
||||
|
||||
Template.seriesQuickSwitch.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user