reorganize packages, start converting overall app to react (very broken at the moment)
This commit is contained in:
1 parent
024fe1a448
commit
5f30f7bd35
479 files changed
+5364
-11611
No files matched your search
@@ -0,0 +1,11 @@
|
||||
import './item.html';
|
||||
import './item.js';
|
||||
import './list.html';
|
||||
import './list.js';
|
||||
import './list.styl';
|
||||
import './quickSwitch.html';
|
||||
import './quickSwitch.js';
|
||||
import './series.html';
|
||||
import './series.js';
|
||||
import './sidebar.html';
|
||||
import './sidebar.js';
|
||||
@@ -0,0 +1,29 @@
|
||||
<template name="studyBrowserItem">
|
||||
<div class="study-browser-item {{this.studyItemClass}} {{#if isActive}}active{{/if}} {{#if isLoading}}loading{{/if}}" data-uid="{{this.studyInformation.studyInstanceUid}}">
|
||||
<div class="study-item">
|
||||
{{#if isLoading}}
|
||||
{{>loadingText}}
|
||||
{{/if}}
|
||||
{{#let studyData=instance.studyData.get}}
|
||||
<div class="study-item-box">
|
||||
<div class="study-modality">
|
||||
<div class="study-modality-text" style="{{modalityStyle studyData.modalities}}">{{studyData.modalities}}</div>
|
||||
</div>
|
||||
<div class="study-text">
|
||||
{{#if (or isLoaded hasDescriptionAndDate)}}
|
||||
<div class="study-date">{{formatDA studyData.studyDate 'D-MMM-YYYY'}}</div>
|
||||
<div class="study-description">{{studyData.studyDescription}}</div>
|
||||
{{else}}
|
||||
<div class="study-availability">{{#if eq studyAvailable false}}N/A{{else}}Click to load{{/if}}</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
</div>
|
||||
{{/let}}
|
||||
</div>
|
||||
{{#if this.studyChildTemplate}}
|
||||
{{#if and (not isLoading) instance.studyData.get instance.loaded}}
|
||||
{{>Template.dynamic template=this.studyChildTemplate data=(clone this)}}
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,140 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { Tracker } from 'meteor/tracker';
|
||||
import $ from 'jquery';
|
||||
import _ from 'underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.studyBrowserItem.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
const { studyInformation } = instance.data;
|
||||
const { studyInstanceUid } = studyInformation;
|
||||
|
||||
instance.loaded = new ReactiveVar(false);
|
||||
instance.loading = new ReactiveVar(false);
|
||||
|
||||
instance.studyData = new ReactiveVar(studyInformation);
|
||||
|
||||
// Try to load the study data from an external source if available
|
||||
if (OHIF.studies.getStudyBoxData) {
|
||||
OHIF.studies.getStudyBoxData(studyInformation).then(studyData => {
|
||||
if (!instance.loaded.get()) {
|
||||
instance.studyData.set(studyData);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
instance.studyMetadata = null;
|
||||
instance.getStudyMetadata = () => {
|
||||
instance.loading.dep.depend();
|
||||
|
||||
if (!instance.studyMetadata) {
|
||||
let study = OHIF.viewer.Studies.findBy({ studyInstanceUid }) || null;
|
||||
if (study && !(study instanceof OHIF.viewerbase.metadata.StudyMetadata)) {
|
||||
study = new OHIF.metadata.StudyMetadata(study, study.studyInstanceUid);
|
||||
}
|
||||
|
||||
instance.studyMetadata = study;
|
||||
}
|
||||
|
||||
return instance.studyMetadata;
|
||||
};
|
||||
|
||||
instance.autorun(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
OHIF.studies.loadingDict.get(studyInstanceUid);
|
||||
const studyMetadata = instance.getStudyMetadata();
|
||||
if (studyMetadata) {
|
||||
const firstInstance = studyMetadata.getFirstInstance();
|
||||
instance.studyData.set({
|
||||
studyDate: firstInstance.getRawValue('x00080020') || '',
|
||||
studyDescription: firstInstance.getRawValue('x00081030') || '',
|
||||
modalities: firstInstance.getRawValue('x00080060') || '',
|
||||
});
|
||||
|
||||
instance.loaded.set(true);
|
||||
instance.loading.set(false);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.studyBrowserItem.events({
|
||||
'click .study-item'(event, instance) {
|
||||
if (instance.loading.get()) return;
|
||||
|
||||
const { studyInformation } = instance.data;
|
||||
|
||||
// Skip if study is not available (set to false explicitly)
|
||||
if (studyInformation.available === false) {
|
||||
return;
|
||||
}
|
||||
|
||||
const element = event.currentTarget.parentElement;
|
||||
const $element = $(element);
|
||||
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.get()) {
|
||||
triggerClick();
|
||||
} else {
|
||||
instance.loading.set(true);
|
||||
OHIF.studies.loadStudy(studyInformation.studyInstanceUid).then(() => {
|
||||
instance.loaded.set(true);
|
||||
instance.loading.set(false);
|
||||
$element.trigger('ohif.studies.study.load', studyInformation);
|
||||
Tracker.afterFlush(triggerClick);
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.studyBrowserItem.helpers({
|
||||
isLoaded() {
|
||||
return Template.instance().loaded.get();
|
||||
},
|
||||
|
||||
hasDescriptionAndDate() {
|
||||
const studyData = Template.instance().studyData.get();
|
||||
return studyData.studyDescription && studyData.studyDate;
|
||||
},
|
||||
|
||||
isLoading() {
|
||||
return Template.instance().loading.get();
|
||||
},
|
||||
|
||||
modalitiesText(modalities) {
|
||||
const text = modalities || 'UN';
|
||||
return _.uniq(text.split(/[^A-Za-z]+/g)).join(' ');
|
||||
},
|
||||
|
||||
modalityStyle(modalities) {
|
||||
// Responsively styles the Modality Acronyms for studies with more than one modality
|
||||
const numModalities = modalities ? modalities.split(/\s/g).length : 1;
|
||||
|
||||
if (numModalities === 1) {
|
||||
// If we have only one modality, it should take up the whole div
|
||||
return 'font-size:1em';
|
||||
} else if (numModalities === 2) {
|
||||
// If we have two modalities, let them sit side-by-side
|
||||
return 'font-size:0.7em';
|
||||
} else {
|
||||
// If we have more than two modalities, change the line height to display multiple rows
|
||||
return 'font-size:0.7em;line-height:1.4em;padding-top:0.5em';
|
||||
}
|
||||
},
|
||||
|
||||
studyAvailable() {
|
||||
const { studyInformation } = Template.instance().data;
|
||||
if (!studyInformation) {
|
||||
return;
|
||||
}
|
||||
|
||||
return studyInformation.available;
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,7 @@
|
||||
<template name="studyBrowserList">
|
||||
<div class="study-browser-list {{this.class}}">
|
||||
{{#each studyInformation in getStudiesInformation}}
|
||||
{{>studyBrowserItem (clone this studyInformation=studyInformation)}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,26 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
|
||||
Template.studyBrowserList.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
if (instance.data.studiesData) {
|
||||
instance.studiesData = instance.data.studiesData;
|
||||
}
|
||||
});
|
||||
|
||||
Template.studyBrowserList.helpers({
|
||||
getStudiesInformation() {
|
||||
const instance = Template.instance();
|
||||
|
||||
let studiesInformation;
|
||||
if (instance.studiesData) {
|
||||
studiesInformation = instance.studiesData.get() || [];
|
||||
} else {
|
||||
studiesInformation = instance.data.studiesInformation || [];
|
||||
}
|
||||
|
||||
const result = new Map();
|
||||
studiesInformation.forEach(item => result.set(item.studyInstanceUid, item));
|
||||
return Array.from(result.values());
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,149 @@
|
||||
@require '{ohif:viewerbase}/app'
|
||||
|
||||
$boxBorderColor = transparent
|
||||
$boxHoverBackgroundColor = #14191E
|
||||
$boxHoverBorderColor = #2d4660
|
||||
$boxActiveBorderColor = #131D29
|
||||
$boxWidth = 50px
|
||||
$borderThickness = 2px
|
||||
$boxBorderRadius = 8px
|
||||
$nestingMargin = 6px
|
||||
$spacerX = 7px
|
||||
$spacerY = 12px
|
||||
|
||||
.study-browser-item
|
||||
position: relative
|
||||
// required transformation to make inner fixed elements relative to this one
|
||||
transform(scale(1))
|
||||
|
||||
.loadingTextDiv
|
||||
theme('color', '$textSecondaryColor')
|
||||
background-color: $boxHoverBackgroundColor
|
||||
border-radius: 12px
|
||||
font-size: 32px
|
||||
opacity: 0
|
||||
margin: 0
|
||||
padding: 25px
|
||||
position: absolute
|
||||
pointer-events: none
|
||||
z-index: 100
|
||||
|
||||
&.loading
|
||||
.loadingTextDiv
|
||||
height: 100%
|
||||
left: 0
|
||||
opacity: 0.75
|
||||
top: 0
|
||||
width: 100%
|
||||
|
||||
.study-item-box
|
||||
opacity: 0.2
|
||||
|
||||
&.active
|
||||
.study-item-box
|
||||
.study-modality
|
||||
theme('color', '$primaryBackgroundColor')
|
||||
&
|
||||
&:before
|
||||
&:after
|
||||
theme('background-color', '$activeColor')
|
||||
border-color: $boxActiveBorderColor
|
||||
|
||||
&:not(.active) .study-browser-series
|
||||
max-height: 0 !important
|
||||
|
||||
.study-series-container
|
||||
opacity: 0
|
||||
transform(translateY(-100%))
|
||||
|
||||
.study-browser-series
|
||||
overflow: hidden
|
||||
transition(max-height 0.3s ease)
|
||||
|
||||
.study-series-container
|
||||
opacity: 1
|
||||
transition(opacity 0.3s ease\, transform 0.3s ease)
|
||||
transform(translateY(0))
|
||||
transform-origin(50% 0%)
|
||||
|
||||
.study-item-box
|
||||
border: 1px solid $boxBorderColor
|
||||
border-radius: 12px
|
||||
cursor: pointer
|
||||
padding: $spacerY $spacerX ($spacerY - 1)
|
||||
position: relative
|
||||
transition($sidebarTransition)
|
||||
z-index: 0
|
||||
|
||||
&:hover
|
||||
background-color: $boxHoverBackgroundColor
|
||||
border-color: $boxHoverBorderColor
|
||||
|
||||
&.additional
|
||||
theme('color', '$textSecondaryColor')
|
||||
|
||||
&.additional
|
||||
theme('color', '$textPrimaryColor')
|
||||
font-size: 16px
|
||||
font-weight: normal
|
||||
height: 91px
|
||||
line-height: 91px
|
||||
padding: 0
|
||||
text-align: center
|
||||
|
||||
.study-text
|
||||
font-size: 13px
|
||||
left: ($spacerX * 3) + $boxWidth + ($nestingMargin * 3)
|
||||
line-height: 14px
|
||||
position: absolute
|
||||
right: $spacerX
|
||||
top: $spacerY
|
||||
.study-date
|
||||
margin-top: 8px
|
||||
theme('color', '$textSecondaryColor')
|
||||
.study-description
|
||||
margin-top: 8px
|
||||
theme('color', '$textPrimaryColor')
|
||||
.study-availability
|
||||
margin-top: 24px
|
||||
theme('color', '$textPrimaryColor')
|
||||
|
||||
.study-modality
|
||||
theme('color', '$textSecondaryColor')
|
||||
font-size: 20px
|
||||
line-height: $boxWidth
|
||||
margin-left: $nestingMargin * 2
|
||||
margin-top: $nestingMargin * 2
|
||||
position: relative
|
||||
|
||||
.study-modality-text
|
||||
height: 100%
|
||||
overflow: hidden
|
||||
text-align: center
|
||||
text-transform: uppercase
|
||||
|
||||
&
|
||||
&:before
|
||||
&:after
|
||||
theme('border', '%s solid $primaryBackgroundColor' % $borderThickness)
|
||||
theme('background-color', '$boxBackgroundColor')
|
||||
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
|
||||
@@ -0,0 +1,3 @@
|
||||
<template name="studyBrowserQuickSwitch">
|
||||
{{>studyBrowserList studyBrowserData}}
|
||||
</template>
|
||||
@@ -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 };
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,9 @@
|
||||
<template name="studyBrowserSeries">
|
||||
<div class="study-browser-series">
|
||||
<div class="study-series-container">
|
||||
{{#each thumbnail in instance.thumbnails.get}}
|
||||
{{>thumbnailEntry (clone this thumbnail=thumbnail)}}
|
||||
{{/each}}
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,65 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { Tracker } from 'meteor/tracker';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.studyBrowserSeries.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
const { studyInformation, studyMetadata } = instance.data;
|
||||
const studyInstanceUid = (studyMetadata && studyMetadata.studyInstanceUid) || (studyInformation && studyInformation.studyInstanceUid);
|
||||
|
||||
instance.thumbnails = new ReactiveVar([]);
|
||||
|
||||
// Get the study metadata and update the study thumbnails
|
||||
instance.autorun(() => {
|
||||
let metadata = studyMetadata;
|
||||
|
||||
// Check for reactivity
|
||||
if (metadata instanceof ReactiveVar) {
|
||||
metadata = metadata.get();
|
||||
}
|
||||
|
||||
// Retrieve the study metadata
|
||||
if (!metadata) {
|
||||
metadata = OHIF.viewer.Studies.findBy({ studyInstanceUid });
|
||||
}
|
||||
|
||||
// Stop here if there's no study metadata
|
||||
if (!metadata) return;
|
||||
|
||||
// Get the study display sets
|
||||
let displaySets = metadata.displaySets;
|
||||
if (!displaySets.length) {
|
||||
displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(metadata);
|
||||
metadata.displaySets = displaySets;
|
||||
metadata.setDisplaySets(displaySets);
|
||||
|
||||
metadata.forEachDisplaySet(displaySet => {
|
||||
OHIF.viewerbase.stackManager.makeAndAddStack(metadata, displaySet);
|
||||
});
|
||||
}
|
||||
|
||||
// Defines the resulting thumbnails list
|
||||
const thumbnails = [];
|
||||
displaySets.forEach((stack, thumbnailIndex) => {
|
||||
thumbnails.push({
|
||||
thumbnailIndex,
|
||||
stack
|
||||
});
|
||||
});
|
||||
|
||||
instance.thumbnails.set(thumbnails);
|
||||
});
|
||||
});
|
||||
|
||||
Template.studyBrowserSeries.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
// Run this computation every time the thumbnails are changed
|
||||
instance.autorun(() => {
|
||||
instance.thumbnails.get();
|
||||
Tracker.afterFlush(() => {
|
||||
instance.$('.study-browser-series').adjustMax('height');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,5 @@
|
||||
<template name="studyBrowserSidebar">
|
||||
{{#scrollArea class='fit noselect' scrollableClass='p-a-1' scrollStep=191}}
|
||||
{{>studyBrowserList (clone this studyChildTemplate='studyBrowserSeries')}}
|
||||
{{/scrollArea}}
|
||||
</template>
|
||||
@@ -0,0 +1,13 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
|
||||
Template.studyBrowserSidebar.events({
|
||||
'ohif.studies.study.click'(event, instance) {
|
||||
const $element = $(event.currentTarget);
|
||||
|
||||
// Remove active class from sibling studies
|
||||
$element.siblings().removeClass('active');
|
||||
|
||||
// Toggle the active class on clicked study
|
||||
$element.toggleClass('active');
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user