LT-251: Showing only the active timepoint and creating 'Show additional timepoints' button and behavior

This commit is contained in:
Bruno Alves de Faria 2016-06-17 08:29:56 -03:00 committed by Erik Ziegler
parent b6cb2051b8
commit 4b307598e9
12 changed files with 193 additions and 154 deletions

View File

@ -7,13 +7,13 @@
<div class="studyBox"></div> <div class="studyBox"></div>
<div class="switchHover studyHover clearfix"> <div class="switchHover studyHover clearfix">
<div class="scrollArea"> <div class="scrollArea">
{{>studyTimepointBrowser timepointViewType=timepointViewType viewportIndex=viewportIndex}} {{>studyTimepointBrowser timepointViewType=this.timepointViewType currentStudy=this.currentStudy viewportIndex=this.viewportIndex}}
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="switchSection rm-x-1 {{#if eq side 'left'}}pull-right{{else}}pull-left{{/if}}"> <div class="switchSection rm-x-1 {{#if eq side 'left'}}pull-right{{else}}pull-left{{/if}}">
{{#let thumbnailsList=(thumbnails currentStudy)}} {{#let thumbnailsList=(studyThumbnails currentStudy)}}
<div class="label">Series</div> <div class="label">Series</div>
<div class="seriesSwitch clearfix"> <div class="seriesSwitch clearfix">
{{#each thumbnail in thumbnailsList}} {{#each thumbnail in thumbnailsList}}

View File

@ -1,67 +1,44 @@
Template.studySeriesQuickSwitch.onCreated(() => { Template.studySeriesQuickSwitch.onCreated(() => {
const instance = Template.instance(); const instance = Template.instance();
instance.data.timepointViewType = new ReactiveVar(); // Defines the study being shown in the current viewport
instance.data.timepointViewType.set('key'); instance.data.currentStudy = new ReactiveVar();
// Shows only the key timepoints
instance.data.timepointViewType = new ReactiveVar('key');
// Gets the viewport data for the given viewport index
instance.getViewportData = viewportIndex => { instance.getViewportData = viewportIndex => {
const layoutManager = window.layoutManager;
return layoutManager && layoutManager.viewportData && layoutManager.viewportData[viewportIndex]; return layoutManager && layoutManager.viewportData && layoutManager.viewportData[viewportIndex];
}; };
// Get the current study being shown in the current viewport
instance.getCurrentStudy = () => { instance.getCurrentStudy = () => {
const viewportIndex = instance.data.viewportIndex; const viewportIndex = instance.data.viewportIndex;
// Runs this computation everytime the current viewport is changed
Session.get('CornerstoneNewImage' + viewportIndex); Session.get('CornerstoneNewImage' + viewportIndex);
layoutManager = window.layoutManager; // Gets the current viewport data
if (!layoutManager) {
return;
}
const viewportData = instance.getViewportData(viewportIndex); const viewportData = instance.getViewportData(viewportIndex);
if (!viewportData) { if (!viewportData) {
return; return;
} }
const study = ViewerStudies.findOne({ // Fins the current study and return it
return ViewerStudies.findOne({
studyInstanceUid: viewportData.studyInstanceUid studyInstanceUid: viewportData.studyInstanceUid
}); });
return study;
}; };
}); });
Template.studySeriesQuickSwitch.helpers({ Template.studySeriesQuickSwitch.helpers({
seriesOpen() { // Get the current study and change the reactive variable
return Template.instance().seriesOpen.get();
},
currentStudy() { currentStudy() {
return Template.instance().getCurrentStudy;
},
currentTimepoint() {
const instance = Template.instance(); const instance = Template.instance();
const currentStudy = instance.getCurrentStudy();
const study = instance.getCurrentStudy(); instance.data.currentStudy.set(currentStudy);
return currentStudy;
const timepoint = Timepoint.findOne({
timepointId: study.timepointId
});
console.warn('>>>>TIMEPOINT', timepoint);
return timepoint;
},
thumbnails: function(study) {
const stacks = createStacks(study);
const array = [];
stacks.forEach(function(stack, index) {
array.push({
thumbnailIndex: index,
stack: stack
});
});
return array;
} }
}); });

View File

@ -22,6 +22,11 @@
<hr class="m-y-1"> <hr class="m-y-1">
{{/if}} {{/if}}
{{/each}} {{/each}}
{{#if and this.currentStudy (not showAdditionalTimepoints)}}
<div class="studyModality additional">
Show additional timepoints
</div>
{{/if}}
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,6 +1,9 @@
Template.studyTimepointBrowser.onCreated(() => { Template.studyTimepointBrowser.onCreated(() => {
const instance = Template.instance(); const instance = Template.instance();
// Defines whether to show all key timepoints or only the current one
instance.showAdditionalTimepoints = new ReactiveVar(true);
// Get the studies for a specific timepoint // Get the studies for a specific timepoint
instance.getStudies = timepoint => { instance.getStudies = timepoint => {
return timepoint.studyInstanceUids.map(studyInstanceUid => { return timepoint.studyInstanceUids.map(studyInstanceUid => {
@ -27,6 +30,7 @@ Template.studyTimepointBrowser.onCreated(() => {
Template.studyTimepointBrowser.onRendered(() => { Template.studyTimepointBrowser.onRendered(() => {
const instance = Template.instance(); const instance = Template.instance();
instance.autorun(() => { instance.autorun(() => {
// Runs this computation everytime the timepointViewType is changed // Runs this computation everytime the timepointViewType is changed
const type = instance.data.timepointViewType.get(); const type = instance.data.timepointViewType.get();
@ -38,6 +42,18 @@ Template.studyTimepointBrowser.onRendered(() => {
instance.$('.timepointEntry:first').addClass('active'); instance.$('.timepointEntry:first').addClass('active');
} }
}); });
let lastStudy;
instance.autorun(() => {
// Runs this computation everytime the curenty study is changed
const currentStudy = instance.data.currentStudy && instance.data.currentStudy.get();
// Check if the study really changed and update the last study
if (currentStudy !== lastStudy) {
instance.showAdditionalTimepoints.set(false);
lastStudy = currentStudy;
}
});
}); });
Template.studyTimepointBrowser.events({ Template.studyTimepointBrowser.events({
@ -49,11 +65,32 @@ Template.studyTimepointBrowser.events({
// Toggle active class to group/ungroup timepoint studies // Toggle active class to group/ungroup timepoint studies
$timepoint.toggleClass('active'); $timepoint.toggleClass('active');
},
'click .studyModality.additional'(event, instance) {
// Show all key timepoints
instance.showAdditionalTimepoints.set(true);
} }
}); });
Template.studyTimepointBrowser.helpers({ Template.studyTimepointBrowser.helpers({
// Defines whether to show all key timepoints or only the current one
showAdditionalTimepoints() {
return Template.instance().showAdditionalTimepoints.get();
},
// Get the timepoints to be listed
timepoints() { timepoints() {
const instance = Template.instance();
// Get the current study
const currentStudy = instance.data.currentStudy && instance.data.currentStudy.get();
// Build the query
const query = {};
if (currentStudy && !instance.showAdditionalTimepoints.get()) {
query['studyInstanceUids'] = {
$in: [currentStudy.studyInstanceUid]
};
}
// Sort timepoints based on timeline and type // Sort timepoints based on timeline and type
const sort = { const sort = {
sort: { sort: {
@ -61,12 +98,14 @@ Template.studyTimepointBrowser.helpers({
} }
}; };
// Returns all timepoints with sorting // Returns all timepoints with sorting
return Timepoints.find({}, sort).fetch().reverse(); return Timepoints.find(query, sort).fetch().reverse();
}, },
// Get the studies for a specific timepoint // Get the studies for a specific timepoint
studies(timepoint) { studies(timepoint) {
return Template.instance().getStudies(timepoint); return Template.instance().getStudies(timepoint);
}, },
// Decides if a timepoint should be shown or omitted // Decides if a timepoint should be shown or omitted
shouldShowTimepoint(timepoint, index) { shouldShowTimepoint(timepoint, index) {
const instance = Template.instance(); const instance = Template.instance();
@ -79,6 +118,7 @@ Template.studyTimepointBrowser.helpers({
// Show only the latest timepoints and baseline // Show only the latest timepoints and baseline
return index < 3 || timepoint.timepointType === 'baseline'; return index < 3 || timepoint.timepointType === 'baseline';
}, },
// Build the timepoint title based on its date // Build the timepoint title based on its date
timepointTitle(timepoint, total, index) { timepointTitle(timepoint, total, index) {
const timepointName = getTimepointName(timepoint); const timepointName = getTimepointName(timepoint);
@ -91,6 +131,7 @@ Template.studyTimepointBrowser.helpers({
const parenthesis = states[index] || ''; const parenthesis = states[index] || '';
return `${timepointName} ${parenthesis}`; return `${timepointName} ${parenthesis}`;
}, },
// Build the modalities summary for all timepoint's studies // Build the modalities summary for all timepoint's studies
modalitiesSummary(timepoint) { modalitiesSummary(timepoint) {
const instance = Template.instance(); const instance = Template.instance();

View File

@ -15,7 +15,7 @@
</div> </div>
</div> </div>
<div class="studyTimepointThumbnails"> <div class="studyTimepointThumbnails">
{{#each thumbnail in (thumbnails this.study)}} {{#each thumbnail in (studyThumbnails this.study)}}
{{>thumbnailEntry thumbnail=thumbnail viewportIndex=viewportIndex}} {{>thumbnailEntry thumbnail=thumbnail viewportIndex=viewportIndex}}
{{/each}} {{/each}}
</div> </div>

View File

@ -56,18 +56,3 @@ Template.studyTimepointStudy.events({
} }
} }
}); });
Template.studyTimepointStudy.helpers({
thumbnails: function(study) {
var stacks = createStacks(study);
var array = [];
stacks.forEach(function(stack, index) {
array.push({
thumbnailIndex: index,
stack: stack
});
});
return array;
}
});

View File

@ -53,66 +53,78 @@ $spacerY = 12px
overflow: hidden overflow: hidden
transition($sidebarTransition) transition($sidebarTransition)
.studyModality .studyModality
border: 1px solid $boxBorderColor border: 1px solid $boxBorderColor
border-radius: 12px border-radius: 12px
cursor: pointer cursor: pointer
font-family: Roboto font-family: Roboto
padding: $spacerY $spacerX ($spacerY - 1) padding: $spacerY $spacerX ($spacerY - 1)
position: relative position: relative
transition($sidebarTransition) transition($sidebarTransition)
z-index: 1 z-index: 1
&:hover &:hover
background-color: $boxHoverBackgroundColor background-color: $boxHoverBackgroundColor
border-color: $boxHoverBorderColor border-color: $boxHoverBorderColor
.studyModalityText &.additional
font-size: 13px
left: ($spacerX * 3) + $boxWidth + ($nestingMargin * 3)
line-height: 14px
position: absolute
right: $spacerX
top: $spacerY
.studyModalityDate
margin-top: 8px
color: $textSecondaryColor
.studyModalityDescription
margin-top: 8px
color: $textPrimaryColor
.studyModalityBox
color: $textSecondaryColor color: $textSecondaryColor
font-size: 22px
line-height: $boxWidth
margin-left: $nestingMargin * 2
margin-top: $nestingMargin * 2
position: relative
text-align: center
text-transform: uppercase
& &.additional
&:before color: $textPrimaryColor
&:after font-size: 16px
background-color: $boxBackgroundColor font-weight: normal
border: $borderThickness solid $primaryBackgroundColor height: 91px
border-radius: $boxBorderRadius line-height: 91px
height: $boxWidth + ($borderThickness * 2) padding: 0
transition($sidebarTransition) text-align: center
width: $boxWidth + ($borderThickness * 2)
&:before .studyModalityText
&:after font-size: 13px
display: block left: ($spacerX * 3) + $boxWidth + ($nestingMargin * 3)
content: '' line-height: 14px
position: absolute position: absolute
right: $spacerX
top: $spacerY
.studyModalityDate
margin-top: 8px
color: $textSecondaryColor
.studyModalityDescription
margin-top: 8px
color: $textPrimaryColor
&:before .studyModalityBox
top: -($borderThickness + $nestingMargin) color: $textSecondaryColor
left: -($borderThickness + $nestingMargin) font-size: 22px
z-index: -1 line-height: $boxWidth
margin-left: $nestingMargin * 2
margin-top: $nestingMargin * 2
position: relative
text-align: center
text-transform: uppercase
&:after &
top: -($borderThickness + ($nestingMargin * 2)) &:before
left: -($borderThickness + ($nestingMargin * 2)) &:after
z-index: -2 background-color: $boxBackgroundColor
border: $borderThickness solid $primaryBackgroundColor
border-radius: $boxBorderRadius
height: $boxWidth + ($borderThickness * 2)
transition($sidebarTransition)
width: $boxWidth + ($borderThickness * 2)
&:before
&:after
display: block
content: ''
position: absolute
&:before
top: -($borderThickness + $nestingMargin)
left: -($borderThickness + $nestingMargin)
z-index: -1
&:after
top: -($borderThickness + ($nestingMargin * 2))
left: -($borderThickness + ($nestingMargin * 2))
z-index: -2

View File

@ -2,7 +2,7 @@
<div class="studyBrowser"> <div class="studyBrowser">
<div class="scrollableStudyThumbnails"> <div class="scrollableStudyThumbnails">
{{#each study in studies}} {{#each study in studies}}
{{#each thumbnail in thumbnails}} {{#each thumbnail in (studyThumbnails study)}}
{{>thumbnailEntry thumbnail=thumbnail}} {{>thumbnailEntry thumbnail=thumbnail}}
{{/each}} {{/each}}
{{/each}} {{/each}}

View File

@ -1,18 +1,7 @@
Template.studyBrowser.helpers({ Template.studyBrowser.helpers({
studies : function() { studies() {
return ViewerStudies.find({selected: true}); return ViewerStudies.find({
}, selected: true
thumbnails: function() {
var study = this;
var stacks = createStacks(study);
var array = [];
stacks.forEach(function(stack, index) {
array.push({
thumbnailIndex: index,
stack: stack
});
}); });
return array;
} }
}); });

View File

@ -1,55 +1,64 @@
Template.registerHelper('choose', function() { /**
let result; * Global Blaze UI helpers to work with logical operations
_.each(_.initial(arguments, 1), function(value) { */
return value && (result = value);
});
return result;
});
Template.registerHelper('bool', function(value) { // Convert any value into a boolean value
Template.registerHelper('bool', value => {
return !!value; return !!value;
}); });
Template.registerHelper('eq', function(a, b) { // Check if two values are identical
Template.registerHelper('eq', (a, b) => {
return a === b; return a === b;
}); });
Template.registerHelper('ne', function(a, b) { // Check if two values are different
Template.registerHelper('ne', (a, b) => {
return a === b; return a === b;
}); });
Template.registerHelper('gt', function(a, b) { // Check if the first value is greater than the second one
Template.registerHelper('gt', (a, b) => {
return a > b; return a > b;
}); });
Template.registerHelper('lt', function(a, b) { // Check if the first value is lesser than the second one
Template.registerHelper('lt', (a, b) => {
return a < b; return a < b;
}); });
Template.registerHelper('gte', function(a, b) { // Check if the first value is greater than or equals the second one
Template.registerHelper('gte', (a, b) => {
return a >= b; return a >= b;
}); });
Template.registerHelper('lte', function(a, b) { // Check if the first value is lesser than or equals the second one
Template.registerHelper('lte', (a, b) => {
return a <= b; return a <= b;
}); });
Template.registerHelper('not', function(value) { // Get the boolean negation for the given value
Template.registerHelper('not', value => {
return !value; return !value;
}); });
Template.registerHelper('and', function() { // Check if all the given values are true
Template.registerHelper('and', (...values) => {
let result = true; let result = true;
_.each(_.initial(arguments, 1), function(value) { _.each(_.initial(values, 1), value => value || (result = false));
return value || (result = false);
});
return result; return result;
}); });
Template.registerHelper('or', function() { // Check if one of the given values is true
Template.registerHelper('or', (...values) => {
let result = false; let result = false;
_.each(_.initial(arguments, 1), function(value) { _.each(_.initial(values, 1), value => value && (result = true));
return value && (result = true); return result;
}); });
// Choose the first truthy value in the given values
Template.registerHelper('choose', (...values) => {
let result;
_.each(_.initial(values, 1), value => value && (result = value));
return result; return result;
}); });

View File

@ -0,0 +1,20 @@
/**
* A global Blaze UI helper to get the thumbnails for the given study
*/
Template.registerHelper('studyThumbnails', study => {
// Creates the series stacks
const stacks = createStacks(study);
// Defines the resulting thumbnails list
const thumbnails = [];
// Iterate over the stacks and add one by one with its index
_.each(stacks, (stack, index) => {
thumbnails.push({
thumbnailIndex: index,
stack: stack
});
});
return thumbnails;
});

View File

@ -189,6 +189,7 @@ Package.onUse(function(api) {
'lib/helpers/objectEach.js', 'lib/helpers/objectEach.js',
'lib/helpers/ifTypeIs.js', 'lib/helpers/ifTypeIs.js',
'lib/helpers/prettyPrintStringify.js', 'lib/helpers/prettyPrintStringify.js',
'lib/helpers/studyThumbnails.js',
'lib/helpers/formatPN.js' 'lib/helpers/formatPN.js'
], 'client'); ], 'client');
api.export('formatPN', 'client'); api.export('formatPN', 'client');