Allowing lazy-loading on viewer
This commit is contained in:
parent
ed0bde0404
commit
bde625a961
@ -111,7 +111,7 @@ Template.viewer.onCreated(() => {
|
|||||||
const studyMetadata = new OHIF.metadata.StudyMetadata(study, study.studyInstanceUid);
|
const studyMetadata = new OHIF.metadata.StudyMetadata(study, study.studyInstanceUid);
|
||||||
let displaySets = study.displaySets;
|
let displaySets = study.displaySets;
|
||||||
|
|
||||||
if(!study.displaySets) {
|
if (!study.displaySets) {
|
||||||
displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(studyMetadata);
|
displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(studyMetadata);
|
||||||
study.displaySets = displaySets;
|
study.displaySets = displaySets;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template name="timepointBrowserQuickSwitch">
|
<template name="timepointBrowserQuickSwitch">
|
||||||
{{>timepointBrowserList (extend timepointBrowserData)}}
|
{{>timepointBrowserList (extend timepointBrowserData)}}
|
||||||
{{#if instance.hasAdditional.get}}
|
{{#if instance.hasAdditional.get}}
|
||||||
<div class='study-item-box additional'>Show additional timepoints</div>
|
<div class="study-item-box additional">Show additional timepoints</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -27,7 +27,17 @@ Template.timepointBrowserQuickSwitch.onCreated(() => {
|
|||||||
instance.autorun(() => {
|
instance.autorun(() => {
|
||||||
OHIF.viewerbase.layoutManager.observer.depend();
|
OHIF.viewerbase.layoutManager.observer.depend();
|
||||||
const viewportData = OHIF.viewerbase.layoutManager.viewportData[viewportIndex];
|
const viewportData = OHIF.viewerbase.layoutManager.viewportData[viewportIndex];
|
||||||
instance.updateSelectedTimepoint(viewportData.studyInstanceUid);
|
let { studyInstanceUid } = viewportData;
|
||||||
|
if (!studyInstanceUid) {
|
||||||
|
Tracker.nonreactive(() => {
|
||||||
|
const currentStudy = instance.data.currentStudy.get();
|
||||||
|
if (currentStudy) {
|
||||||
|
studyInstanceUid = currentStudy.studyInstanceUid;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
instance.updateSelectedTimepoint(studyInstanceUid);
|
||||||
});
|
});
|
||||||
|
|
||||||
instance.autorun(() => {
|
instance.autorun(() => {
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import './item.html';
|
import './item.html';
|
||||||
import './item.js';
|
import './item.js';
|
||||||
import './list.html';
|
import './list.html';
|
||||||
|
import './list.js';
|
||||||
import './list.styl';
|
import './list.styl';
|
||||||
import './quickSwitch.html';
|
import './quickSwitch.html';
|
||||||
import './quickSwitch.js';
|
import './quickSwitch.js';
|
||||||
|
|||||||
@ -4,18 +4,20 @@
|
|||||||
{{#if isLoading}}
|
{{#if isLoading}}
|
||||||
{{>loadingText}}
|
{{>loadingText}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
<div class="study-item-box">
|
{{#let studyData=instance.studyData.get}}
|
||||||
<div class="study-modality">
|
<div class="study-item-box">
|
||||||
<div class="study-modality-text" style="{{modalityStyle}}">{{instance.modalities}}</div>
|
<div class="study-modality">
|
||||||
|
<div class="study-modality-text" style="{{modalityStyle studyData.modalities}}">{{studyData.modalities}}</div>
|
||||||
|
</div>
|
||||||
|
<div class="study-text">
|
||||||
|
<div class="study-date">{{formatDA studyData.studyDate 'D-MMM-YYYY'}}</div>
|
||||||
|
<div class="study-description">{{studyData.studyDescription}}</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="study-text">
|
{{/let}}
|
||||||
<div class="study-date">{{formatDA this.studyInformation.studyDate 'D-MMM-YYYY'}}</div>
|
|
||||||
<div class="study-description">{{this.studyInformation.studyDescription}}</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
{{#if this.studyChildTemplate}}
|
{{#if this.studyChildTemplate}}
|
||||||
{{#if and (not isLoading) instance.loaded}}
|
{{#if and (not isLoading) instance.studyData.get instance.loaded}}
|
||||||
{{>Template.dynamic template=this.studyChildTemplate data=(clone this)}}
|
{{>Template.dynamic template=this.studyChildTemplate data=(clone this)}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
@ -7,12 +7,42 @@ import { OHIF } from 'meteor/ohif:core';
|
|||||||
|
|
||||||
Template.studyBrowserItem.onCreated(() => {
|
Template.studyBrowserItem.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
|
const { studyInformation } = instance.data;
|
||||||
|
const { studyInstanceUid } = studyInformation;
|
||||||
|
|
||||||
instance.loaded = false;
|
instance.loaded = false;
|
||||||
instance.loading = new ReactiveVar(false);
|
instance.loading = new ReactiveVar(false);
|
||||||
|
|
||||||
const modalities = instance.data.studyInformation.modalities || 'UN';
|
instance.studyData = new ReactiveVar(studyInformation);
|
||||||
instance.modalities = _.uniq(modalities.split(/[^A-Za-z]+/g)).join(' ');
|
|
||||||
|
instance.studyMetadata = null;
|
||||||
|
instance.getStudyMetadata = () => {
|
||||||
|
instance.loading.dep.depend();
|
||||||
|
|
||||||
|
if (!instance.studyMetadata) {
|
||||||
|
instance.studyMetadata = OHIF.viewer.Studies.findBy({ studyInstanceUid }) || null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance.studyMetadata;
|
||||||
|
};
|
||||||
|
|
||||||
|
instance.autorun(() => {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
OHIF.studies.loadedDict.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 = true;
|
||||||
|
instance.loading.set(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.studyBrowserItem.events({
|
Template.studyBrowserItem.events({
|
||||||
@ -49,10 +79,14 @@ Template.studyBrowserItem.helpers({
|
|||||||
return Template.instance().loading.get();
|
return Template.instance().loading.get();
|
||||||
},
|
},
|
||||||
|
|
||||||
modalityStyle() {
|
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
|
// Responsively styles the Modality Acronyms for studies with more than one modality
|
||||||
const instance = Template.instance();
|
const numModalities = modalities.split(/\s/g).length;
|
||||||
const numModalities = instance.modalities.split(/\s/g).length;
|
|
||||||
|
|
||||||
if (numModalities === 1) {
|
if (numModalities === 1) {
|
||||||
// If we have only one modality, it should take up the whole div
|
// If we have only one modality, it should take up the whole div
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
<template name="studyBrowserList">
|
<template name="studyBrowserList">
|
||||||
<div class="study-browser-list {{this.class}}">
|
<div class="study-browser-list {{this.class}}">
|
||||||
{{#each studyInformation in studiesInformation}}
|
{{#each studyInformation in getStudiesInformation}}
|
||||||
{{>studyBrowserItem (clone this studyInformation=studyInformation)}}
|
{{>studyBrowserItem (clone this studyInformation=studyInformation)}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -0,0 +1,11 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
Template.studyBrowserList.helpers({
|
||||||
|
getStudiesInformation() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
const { studiesInformation } = instance.data;
|
||||||
|
const result = new Map();
|
||||||
|
studiesInformation.forEach(item => result.set(item.studyInstanceUid, item));
|
||||||
|
return Array.from(result.values());
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -33,7 +33,8 @@ $spacerY = 12px
|
|||||||
height: 100%
|
height: 100%
|
||||||
left: 0
|
left: 0
|
||||||
opacity: 0.75
|
opacity: 0.75
|
||||||
right: 16px
|
top: 0
|
||||||
|
width: 100%
|
||||||
|
|
||||||
.study-item-box
|
.study-item-box
|
||||||
opacity: 0.2
|
opacity: 0.2
|
||||||
@ -72,7 +73,7 @@ $spacerY = 12px
|
|||||||
padding: $spacerY $spacerX ($spacerY - 1)
|
padding: $spacerY $spacerX ($spacerY - 1)
|
||||||
position: relative
|
position: relative
|
||||||
transition($sidebarTransition)
|
transition($sidebarTransition)
|
||||||
z-index: 1
|
z-index: 0
|
||||||
|
|
||||||
&:hover
|
&:hover
|
||||||
background-color: $boxHoverBackgroundColor
|
background-color: $boxHoverBackgroundColor
|
||||||
|
|||||||
@ -2,7 +2,7 @@
|
|||||||
<div class="study-browser-series">
|
<div class="study-browser-series">
|
||||||
<div class="study-series-container">
|
<div class="study-series-container">
|
||||||
{{#each thumbnail in instance.thumbnails.get}}
|
{{#each thumbnail in instance.thumbnails.get}}
|
||||||
{{>thumbnailEntry (clone '' thumbnail=thumbnail)}}
|
{{>thumbnailEntry (clone this thumbnail=thumbnail)}}
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -5,18 +5,43 @@ import { OHIF } from 'meteor/ohif:core';
|
|||||||
|
|
||||||
Template.studyBrowserSeries.onCreated(() => {
|
Template.studyBrowserSeries.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const { studyInformation } = instance.data;
|
const { studyInformation, studyMetadata } = instance.data;
|
||||||
const { studyInstanceUid } = studyInformation;
|
const studyInstanceUid = (studyMetadata && studyMetadata.studyInstanceUid) || (studyInformation && studyInformation.studyInstanceUid);
|
||||||
|
|
||||||
instance.thumbnails = new ReactiveVar([]);
|
instance.thumbnails = new ReactiveVar([]);
|
||||||
|
|
||||||
// Get the study metadata and update the study thumbnails
|
// Get the study metadata and update the study thumbnails
|
||||||
instance.autorun(() => {
|
instance.autorun(() => {
|
||||||
const studyMetadata = OHIF.viewer.Studies.findBy({ studyInstanceUid });
|
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.getDisplaySets();
|
||||||
|
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
|
// Defines the resulting thumbnails list
|
||||||
const thumbnails = [];
|
const thumbnails = [];
|
||||||
studyMetadata.displaySets.forEach((stack, thumbnailIndex) => {
|
displaySets.forEach((stack, thumbnailIndex) => {
|
||||||
thumbnails.push({
|
thumbnails.push({
|
||||||
thumbnailIndex,
|
thumbnailIndex,
|
||||||
stack
|
stack
|
||||||
|
|||||||
@ -1,5 +1,9 @@
|
|||||||
|
import { ReactiveDict } from 'meteor/reactive-dict';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
// Create a studies loaded state dictionary to enable reactivity
|
||||||
|
OHIF.studies.loadedDict = new ReactiveDict();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load the study metadata and store its information locally
|
* Load the study metadata and store its information locally
|
||||||
*
|
*
|
||||||
@ -8,6 +12,16 @@ import { OHIF } from 'meteor/ohif:core';
|
|||||||
*/
|
*/
|
||||||
OHIF.studies.loadStudy = studyInstanceUid => new Promise((resolve, reject) => {
|
OHIF.studies.loadStudy = studyInstanceUid => new Promise((resolve, reject) => {
|
||||||
OHIF.studies.retrieveStudyMetadata(studyInstanceUid).then(study => {
|
OHIF.studies.retrieveStudyMetadata(studyInstanceUid).then(study => {
|
||||||
|
// Add the display sets to the study if not present
|
||||||
|
if (!study.displaySets) {
|
||||||
|
const displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(study);
|
||||||
|
study.displaySets = displaySets;
|
||||||
|
study.setDisplaySets(displaySets);
|
||||||
|
study.forEachDisplaySet(displaySet => {
|
||||||
|
OHIF.viewerbase.stackManager.makeAndAddStack(study, displaySet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Double check to make sure this study wasn't already inserted into OHIF.viewer.Studies
|
// Double check to make sure this study wasn't already inserted into OHIF.viewer.Studies
|
||||||
// so we don't cause duplicate entry errors
|
// so we don't cause duplicate entry errors
|
||||||
const loaded = OHIF.viewer.Studies.findBy({ studyInstanceUid: study.studyInstanceUid });
|
const loaded = OHIF.viewer.Studies.findBy({ studyInstanceUid: study.studyInstanceUid });
|
||||||
@ -15,6 +29,9 @@ OHIF.studies.loadStudy = studyInstanceUid => new Promise((resolve, reject) => {
|
|||||||
OHIF.viewer.Studies.insert(study);
|
OHIF.viewer.Studies.insert(study);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add the studyInstanceUid to the loaded state dictionary
|
||||||
|
OHIF.studies.loadedDict.set(study.studyInstanceUid, true);
|
||||||
|
|
||||||
resolve(study);
|
resolve(study);
|
||||||
}).catch(reject);
|
}).catch(reject);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -463,11 +463,27 @@ const loadDisplaySetIntoViewport = (data, templateData) => {
|
|||||||
*/
|
*/
|
||||||
const setDisplaySet = (data, displaySetInstanceUid, templateData) => {
|
const setDisplaySet = (data, displaySetInstanceUid, templateData) => {
|
||||||
const study = data.study;
|
const study = data.study;
|
||||||
if (!study || !study.displaySets) {
|
|
||||||
throw new OHIFError('Study does not exist or has no display sets');
|
if (!study) {
|
||||||
|
throw new OHIFError('Study does not exist');
|
||||||
}
|
}
|
||||||
|
|
||||||
study.displaySets.every(displaySet => {
|
let displaySets = study.getDisplaySets();
|
||||||
|
if (!displaySets.length) {
|
||||||
|
displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(study);
|
||||||
|
study.displaySets = displaySets;
|
||||||
|
study.setDisplaySets(displaySets);
|
||||||
|
|
||||||
|
study.forEachDisplaySet(displaySet => {
|
||||||
|
OHIF.viewerbase.stackManager.makeAndAddStack(study, displaySet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!displaySets) {
|
||||||
|
throw new OHIFError('Study has no display sets');
|
||||||
|
}
|
||||||
|
|
||||||
|
displaySets.every(displaySet => {
|
||||||
if (displaySet.displaySetInstanceUid === displaySetInstanceUid) {
|
if (displaySet.displaySetInstanceUid === displaySetInstanceUid) {
|
||||||
data.displaySet = displaySet;
|
data.displaySet = displaySet;
|
||||||
return false;
|
return false;
|
||||||
@ -478,7 +494,7 @@ const setDisplaySet = (data, displaySetInstanceUid, templateData) => {
|
|||||||
|
|
||||||
// If we didn't find anything, stop here
|
// If we didn't find anything, stop here
|
||||||
if (!data.displaySet) {
|
if (!data.displaySet) {
|
||||||
data.displaySet = study.displaySets[0];
|
data.displaySet = displaySets[0];
|
||||||
// throw new OHIFError('Display set not found in specified study!');
|
// throw new OHIFError('Display set not found in specified study!');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -9,9 +9,7 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
{{#scrollArea class='series-browser' scrollStep=201}}
|
{{#scrollArea class='series-browser' scrollStep=201}}
|
||||||
<div class="clearfix thumbnails-wrapper">
|
<div class="clearfix thumbnails-wrapper">
|
||||||
{{#each thumbnail in (studyThumbnails instance.currentStudy.get)}}
|
{{>studyBrowserSeries (clone this studyMetadata=instance.currentStudy)}}
|
||||||
{{>thumbnailEntry (clone this thumbnail=thumbnail)}}
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
</div>
|
||||||
{{/scrollArea}}
|
{{/scrollArea}}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -32,7 +32,9 @@ Template.seriesQuickSwitch.onCreated(() => {
|
|||||||
instance.study = OHIF.viewer.Studies.findBy({
|
instance.study = OHIF.viewer.Studies.findBy({
|
||||||
studyInstanceUid: viewportData.studyInstanceUid
|
studyInstanceUid: viewportData.studyInstanceUid
|
||||||
});
|
});
|
||||||
} else {
|
}
|
||||||
|
|
||||||
|
if (!instance.study) {
|
||||||
instance.study = OHIF.viewer.Studies.getElementByIndex(0);
|
instance.study = OHIF.viewer.Studies.getElementByIndex(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -73,9 +75,20 @@ Template.seriesQuickSwitch.helpers({
|
|||||||
|
|
||||||
const seriesItems = [];
|
const seriesItems = [];
|
||||||
|
|
||||||
const items = study.displaySets.length;
|
let displaySets = study.getDisplaySets();
|
||||||
|
if (!displaySets.length) {
|
||||||
|
displaySets = OHIF.viewerbase.sortingManager.getDisplaySets(study);
|
||||||
|
study.displaySets = displaySets;
|
||||||
|
study.setDisplaySets(displaySets);
|
||||||
|
|
||||||
|
study.forEachDisplaySet(displaySet => {
|
||||||
|
OHIF.viewerbase.stackManager.makeAndAddStack(study, displaySet);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const items = displaySets.length;
|
||||||
for (let i = 0; i < items; i++) {
|
for (let i = 0; i < items; i++) {
|
||||||
const displaySet = study.displaySets[i];
|
const displaySet = displaySets[i];
|
||||||
const item = { class: '' };
|
const item = { class: '' };
|
||||||
seriesItems.push(item);
|
seriesItems.push(item);
|
||||||
if (i === 8 && items !== 9) {
|
if (i === 8 && items !== 9) {
|
||||||
@ -105,7 +118,10 @@ Template.seriesQuickSwitch.events({
|
|||||||
const $seriesBrowser = $switch.find('.series-browser');
|
const $seriesBrowser = $switch.find('.series-browser');
|
||||||
$seriesBrowser.width(browserWidth - (browserWidth % 237));
|
$seriesBrowser.width(browserWidth - (browserWidth % 237));
|
||||||
|
|
||||||
instance.$('.series-quick-switch').addClass('series-triggered');
|
const $quickSwitch = instance.$('.series-quick-switch');
|
||||||
|
if ($quickSwitch.is(':hover')) {
|
||||||
|
$quickSwitch.addClass('series-triggered');
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
'mouseleave .series-browser'(event, instance) {
|
'mouseleave .series-browser'(event, instance) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user