Lesion Tracker Redesign so far
This commit is contained in:
1 parent
b247e89d8b
commit
a9a4f3f82b
109 files changed
+2972
-936
No files matched your search
@@ -0,0 +1,9 @@
|
||||
<template name="studyTimepoint">
|
||||
<div class="studyTimepointWrapper">
|
||||
<div class="studyTimepoint">
|
||||
{{#each study in (studies this.timepoint)}}
|
||||
{{>studyTimepointStudy study=study}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,58 @@
|
||||
// Initialize the timepoint wrapper max-height to enable CSS transition
|
||||
Template.studyTimepoint.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
const $studies = instance.$('.studyTimepoint');
|
||||
const $wrapper = $studies.closest('.studyTimepointWrapper');
|
||||
const $timepoint = $wrapper.closest('.timepointEntry');
|
||||
const studiesVisible = $studies.is(':visible');
|
||||
|
||||
if (!studiesVisible) {
|
||||
$timepoint.addClass('active');
|
||||
}
|
||||
|
||||
// Recalculates the timepoint height to make CSS transition smoother
|
||||
$studies.trigger('displayStateChanged');
|
||||
|
||||
if (!studiesVisible) {
|
||||
$timepoint.removeClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
Template.studyTimepoint.events({
|
||||
// Changes the selected study
|
||||
'selectionChanged .studyTimepoint'(event, instance, selection) {
|
||||
const $selection = $(selection);
|
||||
const $thumbnails = $selection.find('.studyTimepointThumbnails');
|
||||
const $timepoint = instance.$('.studyTimepoint');
|
||||
|
||||
// Set the max-height to inherit to be able to expand the wrapper on its full height
|
||||
instance.$('.studyTimepointWrapper').css('max-height', 'inherit');
|
||||
|
||||
// Removes selected state from all studies but the triggered study
|
||||
instance.$('.studyTimepointStudy').not(selection).removeClass('active');
|
||||
|
||||
// Toggle selected state for the triggered study
|
||||
$selection.toggleClass('active');
|
||||
|
||||
// Recalculates the timepoint height to make CSS transition smoother
|
||||
$thumbnails.one('transitionend', () => $timepoint.trigger('displayStateChanged'));
|
||||
},
|
||||
// It should be triggered when the timepoint height is changed
|
||||
'displayStateChanged .studyTimepoint'(event, instance) {
|
||||
const $timepoint = $(event.currentTarget);
|
||||
const $wrapper = $timepoint.closest('.studyTimepointWrapper');
|
||||
|
||||
// Set the max-height for the wrapper to make CSS transition smoother
|
||||
$wrapper.css('max-height', $timepoint.height());
|
||||
}
|
||||
});
|
||||
|
||||
Template.studyTimepoint.helpers({
|
||||
studies: function(timepoint) {
|
||||
const query = {
|
||||
selected: true
|
||||
};
|
||||
return ViewerStudies.find(query);
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,8 @@
|
||||
@import "{design}/app"
|
||||
|
||||
.studyTimepointWrapper
|
||||
overflow: hidden
|
||||
transition($sidebarTransition)
|
||||
|
||||
.timepointEntry:not(.active) .studyTimepointWrapper
|
||||
max-height: 0 !important
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
<template name="studyTimepointBrowser">
|
||||
<div class="studyTimepointBrowser">
|
||||
<div class="studyTimepointScrollArea">
|
||||
<div class="p-x-1">
|
||||
{{#each timepoint in timepoints}}
|
||||
{{#if shouldShowTimepoint timepoint @index}}
|
||||
<div class="timepointEntry p-y-2 active">
|
||||
<div class="timepointHeader">
|
||||
<div class="timepointDetails clearfix">
|
||||
<div class="timepointFollowupTitle pull-left">
|
||||
{{timepointTitle timepoint timepoints.count @index}}
|
||||
</div>
|
||||
<div class="expandIcon pull-right">
|
||||
<i class="fa fa-chevron-down"></i>
|
||||
</div>
|
||||
<div class="timepointDate pull-right m-r-1">{{formatDA timepoint.earliestDate 'D-MMM-YYYY'}}</div>
|
||||
</div>
|
||||
<!-- TODO: [design] find out where to get this information -->
|
||||
<div class="timepointModalities">2 MR, 2 CT</div>
|
||||
</div>
|
||||
{{>studyTimepoint timepoint=timepoint index=@index}}
|
||||
</div>
|
||||
<hr class="m-y-1">
|
||||
{{/if}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
Template.studyTimepointBrowser.events({
|
||||
'click .timepointHeader'(event, instance) {
|
||||
const $timepoint = $(event.currentTarget).closest('.timepointEntry');
|
||||
|
||||
// Recalculates the timepoint height to make CSS transition smoother
|
||||
$timepoint.find('.studyTimepoint').trigger('displayStateChanged');
|
||||
|
||||
// Toggle active class to group/ungroup timepoint studies
|
||||
$timepoint.toggleClass('active');
|
||||
}
|
||||
});
|
||||
|
||||
Template.studyTimepointBrowser.helpers({
|
||||
timepoints: function() {
|
||||
const sort = {
|
||||
sort: {
|
||||
earliestDate: -1
|
||||
}
|
||||
};
|
||||
return Timepoints.find({}, sort);
|
||||
},
|
||||
shouldShowTimepoint(timepoint, index) {
|
||||
const instance = Template.instance();
|
||||
if (instance.data.timepointViewType.get() === 'all') {
|
||||
return true;
|
||||
}
|
||||
|
||||
return index < 4 || timepoint.timepointType === 'baseline';
|
||||
},
|
||||
// Build the timepoint title based on its date
|
||||
timepointTitle(timepoint, total, index) {
|
||||
if (timepoint.timepointType === 'baseline') {
|
||||
return 'Baseline';
|
||||
}
|
||||
|
||||
const states = {
|
||||
0: '(Current)',
|
||||
1: '(Prior)',
|
||||
2: '(Nadir)'
|
||||
};
|
||||
// TODO: [design] find out how to define the nadir timepoint
|
||||
const followUp = total - index - 1;
|
||||
const parenthesis = states[index] || '';
|
||||
return `Follow-up ${followUp} ${parenthesis}`;
|
||||
}
|
||||
});
|
||||
+68
@@ -0,0 +1,68 @@
|
||||
@import "{design}/app"
|
||||
|
||||
.studyTimepointBrowser
|
||||
background-color: $primaryBackgroundColor
|
||||
float: left
|
||||
height: calc(100% - 55px - 50px - 30px)
|
||||
overflow: hidden
|
||||
width: 100%
|
||||
|
||||
.timepointEntry
|
||||
&.active
|
||||
.timepointModalities
|
||||
height: 0
|
||||
.timepointDate
|
||||
display: none
|
||||
.expandIcon i
|
||||
transform: rotateX(180deg)
|
||||
.timepointFollowupTitle
|
||||
font-size: 14px
|
||||
color: $textSecondaryColor
|
||||
text-transform: uppercase
|
||||
|
||||
.timepointHeader
|
||||
cursor: pointer
|
||||
font-size: 13px
|
||||
|
||||
&
|
||||
.expandIcon i
|
||||
.timepointFollowupTitle
|
||||
.timepointDate
|
||||
.timepointModalities
|
||||
color: $textSecondaryColor
|
||||
transition($sidebarTransition)
|
||||
|
||||
&:hover
|
||||
&
|
||||
.timepointFollowupTitle
|
||||
.expandIcon i
|
||||
.timepointDate
|
||||
.timepointModalities
|
||||
color: $textPrimaryColor !important
|
||||
|
||||
.timepointDetails
|
||||
.timepointModalities
|
||||
line-height: 25px
|
||||
|
||||
.timepointModalities
|
||||
height: 25px
|
||||
overflow: hidden
|
||||
|
||||
.expandIcon i
|
||||
color: $defaultColor
|
||||
|
||||
.timepointFollowupTitle
|
||||
color: $textPrimaryColor
|
||||
font-family: Roboto
|
||||
padding-top: 2px
|
||||
|
||||
.studyTimepointScrollArea
|
||||
height: 100%
|
||||
overflow-x: hidden
|
||||
overflow-y: auto
|
||||
margin-right: -16px
|
||||
padding-bottom: 20px
|
||||
padding-right: 16px
|
||||
|
||||
&::-webkit-scrollbar
|
||||
display: none
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
<template name="studyTimepointStudy">
|
||||
<div class="studyTimepointStudy">
|
||||
<div class="studyModality">
|
||||
<div class="studyModalityBox">
|
||||
{{this.study.modalities}}
|
||||
</div>
|
||||
<div class="studyModalityText">
|
||||
<div class="studyModalityDate">{{formatDA this.study.studyDate 'D-MMM-YYYY'}}</div>
|
||||
<div class="studyModalityDescription">{{this.study.studyDescription}}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="studyTimepointThumbnails">
|
||||
{{#each thumbnail in (thumbnails this.study)}}
|
||||
{{>thumbnailEntry thumbnail}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,40 @@
|
||||
// Initialize the study wrapper max-height to enable CSS transition
|
||||
Template.studyTimepointStudy.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
const $study = instance.$('.studyTimepointStudy');
|
||||
const $thumbnails = instance.$('.studyTimepointThumbnails');
|
||||
$study.addClass('active');
|
||||
$thumbnails.css('max-height', $thumbnails.height());
|
||||
$study.removeClass('active');
|
||||
});
|
||||
|
||||
Template.studyTimepointStudy.events({
|
||||
// Recalculates the timepoint height to make CSS transition smoother
|
||||
'transitionend .studyTimepointThumbnails'(event, instance) {
|
||||
if (event.target === event.currentTarget) {
|
||||
$(event.currentTarget).closest('.studyTimepoint').trigger('displayStateChanged');
|
||||
}
|
||||
},
|
||||
// Changes the current study selection for the clicked study
|
||||
'click .studyModality'(event, instance) {
|
||||
const $study = $(event.currentTarget).closest('.studyTimepointStudy');
|
||||
const $timepoint = $study.closest('.studyTimepoint');
|
||||
const study = $study[0];
|
||||
$timepoint.trigger('selectionChanged', [study]);
|
||||
}
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
});
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
@import "{design}/app"
|
||||
|
||||
$boxBackgroundColor = #3E5975
|
||||
$boxBorderColor = transparent
|
||||
$boxHoverBackgroundColor = #14191E
|
||||
$boxHoverBorderColor = #2d4660
|
||||
$boxActiveBackgroundColor = $activeColor
|
||||
$boxActiveTextColor = $primaryBackgroundColor
|
||||
$boxActiveBorderColor = #131D29
|
||||
$boxWidth = 50px
|
||||
$borderThickness = 2px
|
||||
$boxBorderRadius = 8px
|
||||
$nestingMargin = 6px
|
||||
$spacerX = 7px
|
||||
$spacerY = 12px
|
||||
|
||||
.studyTimepointStudy
|
||||
|
||||
&.active
|
||||
.studyModality
|
||||
box-shadow: inset 0 0 0 3px $activeColor
|
||||
.studyModalityBox
|
||||
color: $boxActiveTextColor
|
||||
&
|
||||
&:before
|
||||
&:after
|
||||
background-color: $boxActiveBackgroundColor
|
||||
border-color: $boxActiveBorderColor
|
||||
|
||||
&:not(.active) .studyTimepointThumbnails
|
||||
max-height: 0 !important
|
||||
|
||||
.studyTimepointThumbnails
|
||||
overflow: hidden
|
||||
transition($sidebarTransition)
|
||||
|
||||
.studyModality
|
||||
border: 1px solid $boxBorderColor
|
||||
border-radius: 12px
|
||||
cursor: pointer
|
||||
font-family: Roboto
|
||||
padding: $spacerY $spacerX ($spacerY - 1)
|
||||
position: relative
|
||||
transition($sidebarTransition)
|
||||
z-index: 1
|
||||
|
||||
&:hover
|
||||
background-color: $boxHoverBackgroundColor
|
||||
border-color: $boxHoverBorderColor
|
||||
|
||||
.studyModalityText
|
||||
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
|
||||
font-size: 22px
|
||||
line-height: $boxWidth
|
||||
margin-left: $nestingMargin * 2
|
||||
margin-top: $nestingMargin * 2
|
||||
position: relative
|
||||
text-align: center
|
||||
text-transform: uppercase
|
||||
|
||||
&
|
||||
&:before
|
||||
&:after
|
||||
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
|
||||
Reference in new issue
Block a user