Adding series and scrolling to quickSwitch
This commit is contained in:
parent
a583f5a124
commit
0417bbd0ff
@ -1,5 +1,6 @@
|
|||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
import { ReactiveVar } from 'meteor/reactive-var';
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
|
import { $ } from 'meteor/jquery';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Template.viewerSection.onCreated(() => {
|
Template.viewerSection.onCreated(() => {
|
||||||
@ -28,6 +29,26 @@ Template.viewerSection.events({
|
|||||||
if (!event.target.classList.contains('sidebarMenu')) return;
|
if (!event.target.classList.contains('sidebarMenu')) return;
|
||||||
|
|
||||||
window.ResizeViewportManager.handleResize();
|
window.ResizeViewportManager.handleResize();
|
||||||
|
},
|
||||||
|
|
||||||
|
'ohif.lesiontracker.timepoint.changeViewType .timepoint-browser-list'(event, instance, viewType) {
|
||||||
|
const $browserList = $(event.currentTarget);
|
||||||
|
const $allBrowserItems = $browserList.find('.timepoint-browser-item');
|
||||||
|
|
||||||
|
// Removes all active classes to collapse the timepoints and studies
|
||||||
|
$allBrowserItems.removeClass('active');
|
||||||
|
|
||||||
|
if (viewType === 'key') {
|
||||||
|
const { timepointIds, currentTimepointId } = OHIF.viewer.data;
|
||||||
|
timepointIds.forEach(timepointId => {
|
||||||
|
const $browserItem = $allBrowserItems.filter(`[data-id=${timepointId}]`);
|
||||||
|
$browserItem.find('.timepoint-item').trigger('ohif.lesiontracker.timepoint.load');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show only current timepoint expanded on key timepoints tab
|
||||||
|
const $browserItem = $allBrowserItems.filter(`[data-id=${currentTimepointId}]`);
|
||||||
|
$browserItem.find('.timepoint-item').trigger('click');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,2 +1,3 @@
|
|||||||
import './scrollArea.html';
|
import './scrollArea.html';
|
||||||
import './scrollArea.js';
|
import './scrollArea.js';
|
||||||
|
import './scrollArea.styl';
|
||||||
|
|||||||
@ -3,5 +3,7 @@
|
|||||||
<div class="scrollable {{this.scrollableClass}} {{#if instance.config.scrollX}}scroll-x{{/if}} {{#if instance.config.scrollY}}scroll-y{{/if}}">
|
<div class="scrollable {{this.scrollableClass}} {{#if instance.config.scrollX}}scroll-x{{/if}} {{#if instance.config.scrollY}}scroll-y{{/if}}">
|
||||||
{{>Template.contentBlock}}
|
{{>Template.contentBlock}}
|
||||||
</div>
|
</div>
|
||||||
|
<div class="scroll-nav scroll-nav-up"></div>
|
||||||
|
<div class="scroll-nav scroll-nav-down"></div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -7,7 +7,8 @@ Template.scrollArea.onCreated(() => {
|
|||||||
const defaultConfig = {
|
const defaultConfig = {
|
||||||
hideScrollbar: true,
|
hideScrollbar: true,
|
||||||
scrollY: true,
|
scrollY: true,
|
||||||
scrollX: false
|
scrollX: false,
|
||||||
|
scrollStep: 100
|
||||||
};
|
};
|
||||||
|
|
||||||
instance.config = _.defaults(data || {}, defaultConfig);
|
instance.config = _.defaults(data || {}, defaultConfig);
|
||||||
@ -26,4 +27,55 @@ Template.scrollArea.onRendered(() => {
|
|||||||
'margin-bottom': 0 - (scrollable.offsetHeight - scrollable.clientHeight) * x
|
'margin-bottom': 0 - (scrollable.offsetHeight - scrollable.clientHeight) * x
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance.$scrollable = instance.$('.scrollable').first();
|
||||||
|
instance.scrollHandler = _.throttle(event => {
|
||||||
|
const $scrollable = event ? $(event.currentTarget) : instance.$scrollable;
|
||||||
|
const $scrollArea = $scrollable.closest('.scroll-area');
|
||||||
|
if ($scrollable[0] !== instance.$('.scrollable')[0]) return;
|
||||||
|
$scrollArea.removeClass('can-scroll-up can-scroll-down');
|
||||||
|
const height = $scrollable.outerHeight();
|
||||||
|
const scrollTop = $scrollable.scrollTop();
|
||||||
|
const { scrollHeight } = $scrollable[0];
|
||||||
|
|
||||||
|
// Stop here if unable to scroll
|
||||||
|
if (scrollHeight <= height) return;
|
||||||
|
|
||||||
|
// Check if can scroll up
|
||||||
|
if (scrollTop) {
|
||||||
|
$scrollArea.addClass('can-scroll-up');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if can scroll down
|
||||||
|
if (scrollTop + height < scrollHeight) {
|
||||||
|
$scrollArea.addClass('can-scroll-down');
|
||||||
|
}
|
||||||
|
}, 300);
|
||||||
|
|
||||||
|
instance.scrollHandler();
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.scrollArea.events({
|
||||||
|
'scroll .scrollable, mouseenter .scrollable, transitionend .scrollable'(event, instance) {
|
||||||
|
instance.scrollHandler(event);
|
||||||
|
},
|
||||||
|
|
||||||
|
'click .scroll-nav-down'(event, instance) {
|
||||||
|
const $scrollable = $(event.currentTarget).siblings('.scrollable');
|
||||||
|
const height = $scrollable.outerHeight();
|
||||||
|
const currentTop = $scrollable.scrollTop();
|
||||||
|
const { scrollHeight } = $scrollable[0];
|
||||||
|
const limit = scrollHeight - height;
|
||||||
|
let scrollTop = currentTop + instance.data.scrollStep;
|
||||||
|
scrollTop = scrollTop > limit ? limit : scrollTop;
|
||||||
|
$scrollable.stop().animate({ scrollTop }, 150, 'swing');
|
||||||
|
},
|
||||||
|
|
||||||
|
'click .scroll-nav-up'(event, instance) {
|
||||||
|
const $scrollable = $(event.currentTarget).siblings('.scrollable');
|
||||||
|
const currentTop = $scrollable.scrollTop();
|
||||||
|
let scrollTop = currentTop - instance.data.scrollStep;
|
||||||
|
scrollTop = scrollTop < 0 ? 0 : scrollTop;
|
||||||
|
$scrollable.stop().animate({ scrollTop }, 150, 'swing');
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@ -0,0 +1,78 @@
|
|||||||
|
@require '{ohif:design}/app'
|
||||||
|
|
||||||
|
$scrollNavSize = 24px
|
||||||
|
|
||||||
|
.scroll-area
|
||||||
|
overflow: hidden
|
||||||
|
position: relative
|
||||||
|
|
||||||
|
.scrollable
|
||||||
|
max-height: inherit
|
||||||
|
overflow: hidden
|
||||||
|
|
||||||
|
&.scroll-x
|
||||||
|
overflow-x: scroll
|
||||||
|
|
||||||
|
&.scroll-y
|
||||||
|
overflow-y: scroll
|
||||||
|
|
||||||
|
&.fit
|
||||||
|
height: 100%
|
||||||
|
width: 100%
|
||||||
|
|
||||||
|
.scrollable
|
||||||
|
bottom: 0
|
||||||
|
left: 0
|
||||||
|
max-height: none
|
||||||
|
position: absolute
|
||||||
|
right: 0
|
||||||
|
top: 0
|
||||||
|
|
||||||
|
.scroll-nav
|
||||||
|
background-color: rgba(0, 0, 0, 0.75)
|
||||||
|
box-shadow(0 0 10px 10px rgba(0, 0, 0, 0.75))
|
||||||
|
cursor: pointer
|
||||||
|
height: $scrollNavSize
|
||||||
|
left: 10px
|
||||||
|
opacity: 0
|
||||||
|
position: absolute
|
||||||
|
right: 10px
|
||||||
|
transition(transform 0.3s ease\, opacity 0.3s ease\, background-color 0.3s ease\, box-shadow 0.3s ease)
|
||||||
|
|
||||||
|
&:after
|
||||||
|
theme('color', '$activeColor')
|
||||||
|
display: block
|
||||||
|
font-family: FontAwesome
|
||||||
|
font-size: 20px
|
||||||
|
text-align: center
|
||||||
|
transition(color 0.3s ease)
|
||||||
|
|
||||||
|
&:hover
|
||||||
|
background-color: rgba(0, 0, 0, 0.9)
|
||||||
|
box-shadow(0 0 10px 10px rgba(0, 0, 0, 0.9))
|
||||||
|
|
||||||
|
&:after
|
||||||
|
theme('color', '$hoverColor')
|
||||||
|
|
||||||
|
.scroll-nav-up
|
||||||
|
border-bottom-left-radius($scrollNavSize / 2)
|
||||||
|
border-bottom-right-radius($scrollNavSize / 2)
|
||||||
|
top: 0
|
||||||
|
transform(translateY(- $scrollNavSize))
|
||||||
|
|
||||||
|
&:after
|
||||||
|
content: '\f102'
|
||||||
|
|
||||||
|
.scroll-nav-down
|
||||||
|
border-top-left-radius($scrollNavSize / 2)
|
||||||
|
border-top-right-radius($scrollNavSize / 2)
|
||||||
|
bottom: 0
|
||||||
|
transform(translateY($scrollNavSize))
|
||||||
|
|
||||||
|
&:after
|
||||||
|
content: '\f103'
|
||||||
|
|
||||||
|
&.can-scroll-up .scroll-nav-up,
|
||||||
|
&.can-scroll-down .scroll-nav-down
|
||||||
|
opacity: 1
|
||||||
|
transform(translateY(0))
|
||||||
@ -1,4 +1,4 @@
|
|||||||
@import "{ohif:design}/app"
|
@require '{ohif:design}/app'
|
||||||
|
|
||||||
html body
|
html body
|
||||||
theme('background-color', '$primaryBackgroundColor')
|
theme('background-color', '$primaryBackgroundColor')
|
||||||
@ -140,16 +140,3 @@ body .select2-container--default .select2-results>.select2-results__options
|
|||||||
|
|
||||||
.flex-grow
|
.flex-grow
|
||||||
flex-grow: 1
|
flex-grow: 1
|
||||||
|
|
||||||
.scroll-area
|
|
||||||
overflow: hidden
|
|
||||||
|
|
||||||
.scrollable
|
|
||||||
max-height: inherit
|
|
||||||
overflow: hidden
|
|
||||||
|
|
||||||
&.scroll-x
|
|
||||||
overflow-x: scroll
|
|
||||||
|
|
||||||
&.scroll-y
|
|
||||||
overflow-y: scroll
|
|
||||||
|
|||||||
@ -16,6 +16,18 @@ animation(a)
|
|||||||
border-radius(r)
|
border-radius(r)
|
||||||
vendorize(border-radius, r)
|
vendorize(border-radius, r)
|
||||||
|
|
||||||
|
border-top-left-radius(r)
|
||||||
|
vendorize(border-top-left-radius, r)
|
||||||
|
|
||||||
|
border-top-right-radius(r)
|
||||||
|
vendorize(border-top-right-radius, r)
|
||||||
|
|
||||||
|
border-bottom-left-radius(r)
|
||||||
|
vendorize(border-bottom-left-radius, r)
|
||||||
|
|
||||||
|
border-bottom-right-radius(r)
|
||||||
|
vendorize(border-bottom-right-radius, r)
|
||||||
|
|
||||||
box-shadow(s)
|
box-shadow(s)
|
||||||
vendorize(box-shadow, s)
|
vendorize(box-shadow, s)
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template name="timepointBrowserItem">
|
<template name="timepointBrowserItem">
|
||||||
<div class="timepoint-browser-item">
|
<div class="timepoint-browser-item" data-id="{{this.timepoint.timepointId}}">
|
||||||
<div class="timepoint-item p-y-2">
|
<div class="timepoint-item p-y-2">
|
||||||
<div class="timepoint-details clearfix">
|
<div class="timepoint-details clearfix">
|
||||||
<div class="timepoint-title pull-left">
|
<div class="timepoint-title pull-left">
|
||||||
|
|||||||
@ -5,6 +5,8 @@ import { $ } from 'meteor/jquery';
|
|||||||
import { _ } from 'meteor/underscore';
|
import { _ } from 'meteor/underscore';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
const studySearchPromises = new Map();
|
||||||
|
|
||||||
Template.timepointBrowserItem.onCreated(() => {
|
Template.timepointBrowserItem.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const { timepoint, timepointApi } = instance.data;
|
const { timepoint, timepointApi } = instance.data;
|
||||||
@ -28,10 +30,22 @@ Template.timepointBrowserItem.onCreated(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const filter = { studyInstanceUid: timepoint.studyInstanceUids };
|
const filter = { studyInstanceUid: timepoint.studyInstanceUids };
|
||||||
instance.loadStudies = () => OHIF.studies.searchStudies(filter).then(studiesData => {
|
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 => {
|
||||||
timepoint.studiesData = studiesData;
|
timepoint.studiesData = studiesData;
|
||||||
timepointApi.timepoints.update(timepoint._id, { $set: { studiesData } });
|
timepointApi.timepoints.update(timepoint._id, { $set: { studiesData } });
|
||||||
instance.loaded = true;
|
instance.loaded = true;
|
||||||
|
instance.setModalitiesSummary();
|
||||||
instance.loading.set(false);
|
instance.loading.set(false);
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
const text = 'An error has occurred while retrieving studies information';
|
const text = 'An error has occurred while retrieving studies information';
|
||||||
@ -45,6 +59,10 @@ Template.timepointBrowserItem.onCreated(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Template.timepointBrowserItem.events({
|
Template.timepointBrowserItem.events({
|
||||||
|
'ohif.lesiontracker.timepoint.load .timepoint-item'(event, instance) {
|
||||||
|
instance.loadStudies();
|
||||||
|
},
|
||||||
|
|
||||||
'click .timepoint-item'(event, instance) {
|
'click .timepoint-item'(event, instance) {
|
||||||
const element = event.currentTarget.parentElement;
|
const element = event.currentTarget.parentElement;
|
||||||
const $element = $(element);
|
const $element = $(element);
|
||||||
@ -55,10 +73,7 @@ Template.timepointBrowserItem.events({
|
|||||||
|
|
||||||
if (!instance.loaded) {
|
if (!instance.loaded) {
|
||||||
instance.summary.set('Loading...');
|
instance.summary.set('Loading...');
|
||||||
instance.loadStudies().then(() => {
|
instance.loadStudies().then(() => Tracker.afterFlush(triggerClick));
|
||||||
Tracker.afterFlush(triggerClick);
|
|
||||||
instance.setModalitiesSummary();
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
triggerClick();
|
triggerClick();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
{{>roundedButtonGroup viewTypeButtonGroupData}}
|
{{>roundedButtonGroup viewTypeButtonGroupData}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{{#scrollArea class='flex-grow' scrollableClass='p-a-1'}}
|
{{#scrollArea class='flex-grow' class='fit' scrollableClass='p-a-1' scrollStep=191}}
|
||||||
{{>timepointBrowserList (extend timepointBrowserData)}}
|
{{>timepointBrowserList (extend timepointBrowserData)}}
|
||||||
{{/scrollArea}}
|
{{/scrollArea}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -11,18 +11,19 @@ Template.timepointBrowserSidebar.onCreated(() => {
|
|||||||
|
|
||||||
Template.timepointBrowserSidebar.onRendered(() => {
|
Template.timepointBrowserSidebar.onRendered(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
|
instance.lastType = '';
|
||||||
|
|
||||||
// Collapse all timepoints but first when timepoint view type changes
|
// Collapse all timepoints but first when timepoint view type changes
|
||||||
|
instance.$browserList = instance.$('.timepoint-browser-list').first();
|
||||||
instance.autorun(() => {
|
instance.autorun(() => {
|
||||||
// Runs this computation every time the timepointViewType is changed
|
// Runs this computation every time the timepointViewType is changed
|
||||||
const type = instance.timepointViewType.get();
|
const type = instance.timepointViewType.get();
|
||||||
|
if (type !== instance.lastType) {
|
||||||
// Removes all active classes to collapse the timepoints and studies
|
const eventKey = 'ohif.lesiontracker.timepoint.changeViewType';
|
||||||
instance.$('.timepoint-browser-item, .study-browser-item').removeClass('active');
|
instance.$browserList.trigger(eventKey, type);
|
||||||
if (type === 'key') {
|
|
||||||
// Show only first timepoint expanded for key timepoints
|
|
||||||
instance.$('.timepoint-browser-item:first .timepoint-item').trigger('click');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
instance.lastType = type;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template name="studyBrowserSidebar">
|
<template name="studyBrowserSidebar">
|
||||||
{{#scrollArea class='full-height' scrollableClass='p-a-1'}}
|
{{#scrollArea class='full-height' class='fit' scrollableClass='p-a-1' scrollStep=191}}
|
||||||
{{>studyBrowserList (clone this studyChildTemplate='studyBrowserSeries')}}
|
{{>studyBrowserList (clone this studyChildTemplate='studyBrowserSeries')}}
|
||||||
{{/scrollArea}}
|
{{/scrollArea}}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -23,7 +23,6 @@ $seriesCountBackgroundColor = #678696
|
|||||||
word-wrap: break-word
|
word-wrap: break-word
|
||||||
|
|
||||||
&.info-only
|
&.info-only
|
||||||
min-height: auto
|
|
||||||
|
|
||||||
.seriesDescription
|
.seriesDescription
|
||||||
display: none
|
display: none
|
||||||
|
|||||||
@ -4,17 +4,15 @@
|
|||||||
<div class="series-switch rp-t-1 rp-x-1">
|
<div class="series-switch rp-t-1 rp-x-1">
|
||||||
<div class="title-label">Series</div>
|
<div class="title-label">Series</div>
|
||||||
<div class="series-box r-font">
|
<div class="series-box r-font">
|
||||||
<div class="series-item"></div>
|
{{#each seriesItem in seriesItems}}
|
||||||
<div class="series-item"></div>
|
<div class="series-item {{seriesItem.class}}">{{seriesItem.value}}</div>
|
||||||
<div class="series-item"></div>
|
{{/each}}
|
||||||
<div class="series-item"></div>
|
{{#scrollArea class='series-browser' scrollStep=201}}
|
||||||
<div class="series-item"></div>
|
<div class="clearfix thumbnails-wrapper">
|
||||||
<div class="series-item"></div>
|
{{#each thumbnail in (studyThumbnails instance.currentStudy.get)}}
|
||||||
<div class="series-item"></div>
|
{{>thumbnailEntry (clone this thumbnail=thumbnail)}}
|
||||||
<div class="series-item"></div>
|
{{/each}}
|
||||||
<div class="series-item count">37</div>
|
</div>
|
||||||
{{#scrollArea class='series-browser'}}
|
|
||||||
<div>BBBBB</div>
|
|
||||||
{{/scrollArea}}
|
{{/scrollArea}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -1,9 +1,57 @@
|
|||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
import { $ } from 'meteor/jquery';
|
import { $ } from 'meteor/jquery';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
// FIXME >>>> REMOVE
|
// FIXME >>>> REMOVE
|
||||||
$(document.body).on('keydown', e => (e.keyCode === 69 && $('.quickSwitchWrapper').toggle()) || 1);
|
$(document.body).on('keydown', e => (e.keyCode === 69 && $('.quickSwitchWrapper').toggle()) || 1);
|
||||||
|
OHIF.cornerstone.renderer = '';
|
||||||
|
|
||||||
|
Template.seriesQuickSwitch.onCreated(() => {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
// Defines the study being shown in the current viewport
|
||||||
|
instance.currentStudy = new ReactiveVar();
|
||||||
|
|
||||||
|
// Gets the viewport data for the given viewport index
|
||||||
|
instance.getViewportData = viewportIndex => {
|
||||||
|
const layoutManager = OHIF.viewerbase.layoutManager;
|
||||||
|
return layoutManager && layoutManager.viewportData && layoutManager.viewportData[viewportIndex];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Gets the current viewport data
|
||||||
|
const viewportIndex = instance.data.viewportIndex;
|
||||||
|
|
||||||
|
instance.study = {};
|
||||||
|
instance.lastStudy = {};
|
||||||
|
|
||||||
|
instance.autorun(() => {
|
||||||
|
OHIF.viewerbase.layoutManager.observer.depend();
|
||||||
|
|
||||||
|
const viewportData = instance.getViewportData(viewportIndex);
|
||||||
|
|
||||||
|
// @TypeSafeStudies
|
||||||
|
if (viewportData) {
|
||||||
|
// Finds the current study and return it
|
||||||
|
instance.study = OHIF.viewer.Studies.findBy({
|
||||||
|
studyInstanceUid: viewportData.studyInstanceUid
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
instance.study = OHIF.viewer.Studies.getElementByIndex(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!instance.study) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance.study.studyInstanceUid !== instance.lastStudy.studyInstanceUid) {
|
||||||
|
// Change the current study to update the thumbnails
|
||||||
|
instance.currentStudy.set(instance.study);
|
||||||
|
|
||||||
|
instance.lastStudy = instance.study;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Template.seriesQuickSwitch.helpers({
|
Template.seriesQuickSwitch.helpers({
|
||||||
shallDisplay() {
|
shallDisplay() {
|
||||||
@ -17,13 +65,54 @@ Template.seriesQuickSwitch.helpers({
|
|||||||
const { columns, viewportIndex } = instance.data;
|
const { columns, viewportIndex } = instance.data;
|
||||||
if (columns === 1) return '';
|
if (columns === 1) return '';
|
||||||
return viewportIndex === 0 ? 'left' : 'right';
|
return viewportIndex === 0 ? 'left' : 'right';
|
||||||
|
},
|
||||||
|
|
||||||
|
seriesItems() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
OHIF.viewerbase.layoutManager.observer.depend();
|
||||||
|
const { viewportIndex } = instance.data;
|
||||||
|
const viewportData = OHIF.viewerbase.layoutManager.viewportData[viewportIndex];
|
||||||
|
const study = instance.currentStudy.get();
|
||||||
|
|
||||||
|
const seriesItems = [];
|
||||||
|
|
||||||
|
const items = study.displaySets.length;
|
||||||
|
for (let i = 0; i < items; i++) {
|
||||||
|
const displaySet = study.displaySets[i];
|
||||||
|
const item = { class: '' };
|
||||||
|
seriesItems.push(item);
|
||||||
|
if (i === 8 && items !== 9) {
|
||||||
|
item.class += ' count';
|
||||||
|
item.value = items;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (displaySet.displaySetInstanceUid === viewportData.displaySetInstanceUid) {
|
||||||
|
item.class += ' active';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return seriesItems;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.seriesQuickSwitch.events({
|
Template.seriesQuickSwitch.events({
|
||||||
'mouseenter .series-switch'(event, instance) {
|
'mouseenter .series-switch'(event, instance) {
|
||||||
|
// Control the width of the series browser
|
||||||
const $switch = $(event.currentTarget);
|
const $switch = $(event.currentTarget);
|
||||||
const browserWidth = $switch.offset().left + $switch.outerWidth();
|
const browserWidth = $switch.offset().left + $switch.outerWidth();
|
||||||
$switch.find('.series-browser').width(browserWidth);
|
const $seriesBrowser = $switch.find('.series-browser');
|
||||||
|
$seriesBrowser.width(browserWidth);
|
||||||
|
|
||||||
|
instance.$('.series-quick-switch').addClass('series-triggered');
|
||||||
|
},
|
||||||
|
|
||||||
|
'mouseleave .series-browser'(event, instance) {
|
||||||
|
$(event.currentTarget).children('.scrollable').stop().animate({ scrollTop: 0 }, 300, 'swing');
|
||||||
|
},
|
||||||
|
|
||||||
|
'mouseleave .series-quick-switch'(event, instance) {
|
||||||
|
$(event.currentTarget).removeClass('series-triggered');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -42,7 +42,13 @@
|
|||||||
right: auto
|
right: auto
|
||||||
transform-origin(1em calc(1em + 15px))
|
transform-origin(1em calc(1em + 15px))
|
||||||
|
|
||||||
.series-box .series-item
|
.thumbnails-wrapper
|
||||||
|
transform-origin(0% 0%)
|
||||||
|
|
||||||
|
.thumbnailEntry
|
||||||
|
float: left
|
||||||
|
|
||||||
|
.series-item
|
||||||
float: left
|
float: left
|
||||||
|
|
||||||
.title-label
|
.title-label
|
||||||
@ -50,8 +56,10 @@
|
|||||||
font-size: 12px
|
font-size: 12px
|
||||||
font-weight: 500
|
font-weight: 500
|
||||||
line-height: 12px
|
line-height: 12px
|
||||||
|
opacity: 1
|
||||||
padding-bottom: 3px
|
padding-bottom: 3px
|
||||||
text-align: center
|
text-align: center
|
||||||
|
transition(opacity 0.3s ease)
|
||||||
|
|
||||||
.series-switch,
|
.series-switch,
|
||||||
.study-switch
|
.study-switch
|
||||||
@ -65,51 +73,114 @@
|
|||||||
width: 285px
|
width: 285px
|
||||||
|
|
||||||
.series-browser
|
.series-browser
|
||||||
background: blue
|
|
||||||
max-width: 711px
|
max-width: 711px
|
||||||
right: 0
|
right: 0
|
||||||
transform-origin(calc(100% - 1em) calc(1em + 15px))
|
transform-origin(calc(100% - 1em) calc(1em + 15px))
|
||||||
|
|
||||||
|
.thumbnails-wrapper
|
||||||
|
transition(transform 0.3s ease)
|
||||||
|
transform-origin(100% 0%)
|
||||||
|
|
||||||
|
.thumbnailEntry
|
||||||
|
float: right
|
||||||
|
|
||||||
|
.seriesDetails
|
||||||
|
opacity: 0
|
||||||
|
transform(translateY(-100%))
|
||||||
|
transition(transform 0.3s ease\, opacity 0.3s ease)
|
||||||
|
|
||||||
|
.scrollable
|
||||||
|
padding-top: 15px
|
||||||
|
transition(padding-bottom 0.3s ease)
|
||||||
|
|
||||||
.series-browser,
|
.series-browser,
|
||||||
.study-browser
|
.study-browser
|
||||||
max-height: 100vh
|
max-height: 100vh
|
||||||
min-height: 120px
|
min-height: 120px
|
||||||
|
opacity: 0
|
||||||
position: absolute
|
position: absolute
|
||||||
top: 0
|
top: 0
|
||||||
transform(scale(0))
|
transform(scale(0))
|
||||||
transition(transform 0.3s ease)
|
transition(transform 0.3s ease\, opacity 0.3s ease)
|
||||||
|
z-index: 3
|
||||||
|
|
||||||
.series-box
|
.series-box,
|
||||||
|
.study-box
|
||||||
height: 57px
|
height: 57px
|
||||||
width: 57px
|
width: 57px
|
||||||
|
|
||||||
.series-item
|
|
||||||
theme('background-color', '$boxBackgroundColor')
|
|
||||||
border-radius(3px)
|
|
||||||
float: right
|
|
||||||
height: 15px
|
|
||||||
margin: 2px
|
|
||||||
width: 15px
|
|
||||||
|
|
||||||
&.count
|
|
||||||
theme('color', '$textPrimaryColor')
|
|
||||||
background-color: transparent
|
|
||||||
font-size: 12px
|
|
||||||
font-weight: 500
|
|
||||||
line-height: 17px
|
|
||||||
text-align: center
|
|
||||||
|
|
||||||
&.active
|
|
||||||
theme('background-color', '$activeColor')
|
|
||||||
|
|
||||||
|
|
||||||
.study-box
|
.study-box
|
||||||
theme('background-color', '$uiGrayDark')
|
theme('background-color', '$uiGrayDark')
|
||||||
theme('border', 'solid 2px $uiBorderColorDark')
|
theme('border', 'solid 2px $uiBorderColorDark')
|
||||||
border-radius: 11px
|
border-radius(11px)
|
||||||
height: 57px
|
|
||||||
width: 57px
|
|
||||||
|
|
||||||
|
.series-item
|
||||||
|
theme('background-color', '$boxBackgroundColor')
|
||||||
|
border-radius(3px)
|
||||||
|
float: right
|
||||||
|
height: 15px
|
||||||
|
margin: 2px
|
||||||
|
transition(opacity 0.3s ease)
|
||||||
|
width: 15px
|
||||||
|
|
||||||
|
&.count
|
||||||
|
theme('color', '$textPrimaryColor')
|
||||||
|
background-color: transparent
|
||||||
|
font-size: 12px
|
||||||
|
font-weight: 500
|
||||||
|
line-height: 17px
|
||||||
|
text-align: center
|
||||||
|
|
||||||
|
&.active
|
||||||
|
theme('background-color', '$activeColor')
|
||||||
|
|
||||||
|
&.series-triggered .series-browser,
|
||||||
.series-switch:hover .series-browser,
|
.series-switch:hover .series-browser,
|
||||||
.study-switch:hover .study-browser
|
.study-switch:hover .study-browser
|
||||||
|
opacity: 1
|
||||||
transform(scale(1))
|
transform(scale(1))
|
||||||
|
|
||||||
|
&.series-triggered .series-item,
|
||||||
|
.series-switch:hover .title-label
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
&.series-triggered
|
||||||
|
.thumbnails-wrapper
|
||||||
|
transform(scale(0.9) translateY(80px))
|
||||||
|
|
||||||
|
.series-browser:not(:hover)
|
||||||
|
&>.scrollable
|
||||||
|
padding-bottom: 80px
|
||||||
|
|
||||||
|
&>.scroll-nav
|
||||||
|
opacity: 0
|
||||||
|
|
||||||
|
.series-switch:hover .series-browser
|
||||||
|
.thumbnails-wrapper
|
||||||
|
transform(scale(1) translateY(0))
|
||||||
|
|
||||||
|
.thumbnailEntry .seriesDetails
|
||||||
|
opacity: 1
|
||||||
|
transform(translateY(0))
|
||||||
|
transition-delay(0.3s)
|
||||||
|
|
||||||
|
@media screen and (max-width: 1599px)
|
||||||
|
.series-quick-switch
|
||||||
|
|
||||||
|
.series-box,
|
||||||
|
.study-box
|
||||||
|
width: 36px
|
||||||
|
height: 36px
|
||||||
|
|
||||||
|
.study-box
|
||||||
|
border-radius(7px)
|
||||||
|
|
||||||
|
.series-item
|
||||||
|
height: 10px
|
||||||
|
margin: 1px
|
||||||
|
width: 10px
|
||||||
|
|
||||||
|
&.count
|
||||||
|
font-size: 10px
|
||||||
|
font-weight: 300
|
||||||
|
line-height: 10px
|
||||||
|
|||||||
@ -18,6 +18,7 @@ export class LayoutManager {
|
|||||||
constructor(parentNode, studies) {
|
constructor(parentNode, studies) {
|
||||||
OHIF.log.info('LayoutManager constructor');
|
OHIF.log.info('LayoutManager constructor');
|
||||||
|
|
||||||
|
this.observer = new Tracker.Dependency();
|
||||||
this.parentNode = parentNode;
|
this.parentNode = parentNode;
|
||||||
this.studies = studies;
|
this.studies = studies;
|
||||||
this.viewportData = [];
|
this.viewportData = [];
|
||||||
@ -30,7 +31,10 @@ export class LayoutManager {
|
|||||||
|
|
||||||
this.isZoomed = false;
|
this.isZoomed = false;
|
||||||
|
|
||||||
const updateSessionFn = () => Tracker.afterFlush(() => Session.set('LayoutManagerUpdated', Math.random()));
|
const updateSessionFn = () => Tracker.afterFlush(() => {
|
||||||
|
Session.set('LayoutManagerUpdated', Math.random());
|
||||||
|
this.observer.changed();
|
||||||
|
});
|
||||||
this.updateSession = _.throttle(updateSessionFn, 300);
|
this.updateSession = _.throttle(updateSessionFn, 300);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user