Remove tabbed layout in favour of current Lesion Tracker design (OHIF-49)
This commit is contained in:
parent
8b364ce9d0
commit
82e374b1e3
@ -1,20 +1,2 @@
|
||||
body
|
||||
background-color: black
|
||||
|
||||
/* Mobile devices */
|
||||
@media only screen and (min-device-width : 375px) and (max-device-width : 768px)
|
||||
.logoContainer
|
||||
width: 15%
|
||||
|
||||
table#tblStudyList
|
||||
table-layout: fixed
|
||||
font-size: 0.7em
|
||||
|
||||
#tablist
|
||||
width: 85%
|
||||
overflow-x: auto
|
||||
|
||||
@media (max-device-width: 667px)
|
||||
#toolbar .btn-group button
|
||||
width: 35px
|
||||
height: 35px
|
||||
background-color: black
|
||||
@ -11,4 +11,7 @@
|
||||
<meta name="MobileOptimized" content="320">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||
<link href='http://fonts.googleapis.com/css?family=Sanchez:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||
</head>
|
||||
|
||||
@ -14,8 +14,8 @@ Object.keys(ViewerData).forEach(function(contentId) {
|
||||
});
|
||||
|
||||
Router.configure({
|
||||
layoutTemplate: 'lesionTrackerLayout',
|
||||
loadingTemplate: 'lesionTrackerLayout'
|
||||
layoutTemplate: 'layout',
|
||||
loadingTemplate: 'layout'
|
||||
});
|
||||
|
||||
Router.onBeforeAction('loading');
|
||||
@ -50,7 +50,7 @@ Router.route('/', function() {
|
||||
});
|
||||
|
||||
Router.route('/viewer/timepoints/:_id', {
|
||||
layoutTemplate: 'lesionTrackerLayout',
|
||||
layoutTemplate: 'layout',
|
||||
name: 'viewer',
|
||||
onBeforeAction: function() {
|
||||
var timepointId = this.params._id;
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
Template.flexboxLayout.events({
|
||||
'transitionend .sidebarMenu'(event, instance) {
|
||||
'transitionend .sidebarMenu'() {
|
||||
handleResize();
|
||||
},
|
||||
'transitionend .sidebar-option'(event, instance) {
|
||||
'transitionend .sidebar-option'(event) {
|
||||
// Prevent this event from bubbling
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
@ -1,13 +0,0 @@
|
||||
<template name="layout">
|
||||
<nav class="topBar noselect" role="navigation">
|
||||
<div class="clearfix p-x-1 p-t-1">
|
||||
<a class="brandSection pull-left" href="http://www.ohif.org">
|
||||
<img class="logoImage" src="/images/logo.png">
|
||||
<div class="logoText">
|
||||
Open Health Imaging Foundation
|
||||
</div>
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
{{> yield}}
|
||||
</template>
|
||||
@ -1,27 +0,0 @@
|
||||
@import "{design}/app"
|
||||
|
||||
.topBar
|
||||
margin-bottom: 0
|
||||
border-radius: 0
|
||||
background-color: $primaryBackgroundColor
|
||||
border: none
|
||||
height: $topBarHeight
|
||||
color: $textPrimaryColor
|
||||
transition(all 0.3s ease)
|
||||
|
||||
.brandSection
|
||||
display: inline-block
|
||||
height: 30px
|
||||
text-decoration: none
|
||||
|
||||
img.logoImage
|
||||
display: inline-block
|
||||
height: 100%
|
||||
max-height: 50px
|
||||
margin: 0 5px
|
||||
|
||||
div.logoText
|
||||
display: inline-block
|
||||
font-family: $logoFontFamily
|
||||
font-weight: $logoFontWeight
|
||||
color: $textPrimaryColor
|
||||
18
OHIFViewer/client/components/ohifViewer/ohifViewer.html
Normal file
18
OHIFViewer/client/components/ohifViewer/ohifViewer.html
Normal file
@ -0,0 +1,18 @@
|
||||
<template name="ohifViewer">
|
||||
<div class="topBar noselect {{#if onStudyList}}studyList{{/if}}">
|
||||
<div class="clearfix p-x-1 p-t-1">
|
||||
<a class="brandSection pull-left" href="http://ohif.org">
|
||||
<img class="logoImage" src="/images/logo.png">
|
||||
<div class="logoText">
|
||||
Open Health Imaging Foundation
|
||||
</div>
|
||||
</a>
|
||||
{{ #if studyListToggleText }}
|
||||
<div class="studyListLinkSection pull-left m-x-1 p-x-2 js-toggle-studyList">
|
||||
{{studyListToggleText}}
|
||||
</div>
|
||||
{{ /if }}
|
||||
</div>
|
||||
</div>
|
||||
{{> worklist }}
|
||||
</template>
|
||||
58
OHIFViewer/client/components/ohifViewer/ohifViewer.js
Normal file
58
OHIFViewer/client/components/ohifViewer/ohifViewer.js
Normal file
@ -0,0 +1,58 @@
|
||||
const worklistContentId = 'worklistTab';
|
||||
const viewerContentId = 'viewerTab';
|
||||
|
||||
// Define the ViewerData global object
|
||||
// If there is currently any Session data for this object,
|
||||
// use this to repopulate the variable
|
||||
Template.ohifViewer.onCreated(() => {
|
||||
ViewerData = Session.get('ViewerData') || {};
|
||||
});
|
||||
|
||||
Template.ohifViewer.onRendered(() => {
|
||||
const templateData = Template.currentData();
|
||||
if (templateData && templateData.studyInstanceUid) {
|
||||
const studyInstanceUid = templateData.studyInstanceUid;
|
||||
openNewTab(studyInstanceUid, studyInstanceUid);
|
||||
} else {
|
||||
// If there is a tab set as active in the Session,
|
||||
// switch to that now.
|
||||
const contentId = Session.get('activeContentId');
|
||||
|
||||
// TODO: Fix this it seems to be forcing two switches
|
||||
switchToTab(contentId);
|
||||
}
|
||||
});
|
||||
|
||||
Template.ohifViewer.events({
|
||||
'click .js-toggle-studyList'() {
|
||||
const contentId = Session.get('activeContentId');
|
||||
|
||||
if (contentId !== worklistContentId) {
|
||||
switchToTab(worklistContentId);
|
||||
} else {
|
||||
switchToTab(viewerContentId);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Template.ohifViewer.helpers({
|
||||
studyListToggleText() {
|
||||
const contentId = Session.get('activeContentId');
|
||||
|
||||
// If the Viewer has not been opened yet, 'Back to viewer' should
|
||||
// not be displayed
|
||||
const viewerContentExists = !!Object.keys(ViewerData).length;
|
||||
if (!viewerContentExists) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (contentId === worklistContentId) {
|
||||
return 'Back to viewer';
|
||||
} else {
|
||||
return 'Study list';
|
||||
}
|
||||
},
|
||||
onStudyList() {
|
||||
return (Session.get('activeContentId') === 'worklistTab');
|
||||
}
|
||||
});
|
||||
74
OHIFViewer/client/components/ohifViewer/ohifViewer.styl
Normal file
74
OHIFViewer/client/components/ohifViewer/ohifViewer.styl
Normal file
@ -0,0 +1,74 @@
|
||||
@import "{design}/app"
|
||||
|
||||
$expandedHeight = 160px
|
||||
|
||||
img.logoImage
|
||||
display: inline-block
|
||||
height: 100%
|
||||
|
||||
.topBar
|
||||
height: $topBarHeight
|
||||
color: $textPrimaryColor
|
||||
background-color: $primaryBackgroundColor
|
||||
transition(all 0.5s ease)
|
||||
|
||||
.brandSection
|
||||
height: 30px
|
||||
display: inline-block
|
||||
text-decoration: none
|
||||
|
||||
img.logoImage
|
||||
margin: 0 5px
|
||||
|
||||
.logoText
|
||||
display: inline-block
|
||||
font-family: $logoFontFamily
|
||||
font-weight: $logoFontWeight
|
||||
color: $textPrimaryColor
|
||||
|
||||
.studyListLinkSection
|
||||
border-left: $uiBorderThickness solid $uiBorderColor;
|
||||
color: $textSecondaryColor
|
||||
cursor: pointer
|
||||
font-size: 13px
|
||||
font-weight: 500
|
||||
line-height: 26px
|
||||
margin-top: 3px
|
||||
|
||||
&:hover
|
||||
color: $hoverColor
|
||||
|
||||
&:active
|
||||
color: $activeColor
|
||||
|
||||
&.studyList
|
||||
background-color: rgba(21, 25, 30, 0.7)
|
||||
height: $expandedHeight
|
||||
|
||||
.brandSection
|
||||
height: 100%
|
||||
width: 80%
|
||||
padding-left: 50px
|
||||
line-height: $expandedHeight
|
||||
|
||||
img.logoImage
|
||||
margin: 5px 5px 15px 5px
|
||||
|
||||
.logoText
|
||||
font-size: 30px
|
||||
|
||||
.studyListLinkSection
|
||||
position: absolute
|
||||
border: none
|
||||
top: 5px
|
||||
left: 5px
|
||||
|
||||
#worklistTabs
|
||||
height: "calc(100% - %s)" % $topBarHeight
|
||||
|
||||
.tab-pane
|
||||
.viewerContainer
|
||||
.loadingTextDiv
|
||||
color: $textSecondaryColor
|
||||
font-size: 30px
|
||||
font-weight: 200
|
||||
@ -4,9 +4,11 @@
|
||||
<div class="pull-left m-t-1">
|
||||
{{>roundedButtonGroup leftSidebarToggleButtonData}}
|
||||
</div>
|
||||
{{> toolbarSectionTools toolbarButtons=toolbarButtons extraToolbarButtons=extraToolbarButtons}}
|
||||
{{> toolbarSectionTools
|
||||
toolbarButtons=toolbarButtons
|
||||
extraToolbarButtons=extraToolbarButtons}}
|
||||
<div class="pull-right m-t-1 rm-x-1">
|
||||
{{>roundedButtonGroup rightSidebarToggleButtonData}}
|
||||
{{> roundedButtonGroup rightSidebarToggleButtonData}}
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
{{> toolbarSectionTools toolbarButtons=hangingProtocolButtons}}
|
||||
|
||||
@ -9,6 +9,6 @@
|
||||
{{> flexboxLayout (clone this)}}
|
||||
</div>
|
||||
{{else}}
|
||||
{{>loadingText}}
|
||||
{{> loadingText}}
|
||||
{{/if}}
|
||||
</template>
|
||||
@ -29,23 +29,11 @@ Template.viewer.onCreated(() => {
|
||||
instance.data.state.set('leftSidebar', Session.get('leftSidebar'));
|
||||
instance.data.state.set('rightSidebar', Session.get('rightSidebar'));
|
||||
|
||||
Meteor.subscribe('hangingprotocols');
|
||||
|
||||
log.info('viewer onCreated');
|
||||
|
||||
if (isTouchDevice()) {
|
||||
OHIF.viewer.tooltipConfig = {
|
||||
trigger: 'manual'
|
||||
};
|
||||
} else {
|
||||
OHIF.viewer.tooltipConfig = {
|
||||
trigger: 'hover'
|
||||
};
|
||||
}
|
||||
instance.subscribe('hangingprotocols');
|
||||
|
||||
const contentId = instance.data.contentId;
|
||||
|
||||
if (ViewerData[contentId].loadedSeriesData) {
|
||||
if (ViewerData[contentId] && ViewerData[contentId].loadedSeriesData) {
|
||||
log.info('Reloading previous loadedSeriesData');
|
||||
|
||||
OHIF.viewer.loadedSeriesData = ViewerData[contentId].loadedSeriesData;
|
||||
@ -53,7 +41,7 @@ Template.viewer.onCreated(() => {
|
||||
} else {
|
||||
log.info('Setting default ViewerData');
|
||||
OHIF.viewer.loadedSeriesData = {};
|
||||
|
||||
ViewerData[contentId] = {};
|
||||
ViewerData[contentId].loadedSeriesData = OHIF.viewer.loadedSeriesData;
|
||||
|
||||
// Update the viewer data object
|
||||
@ -85,4 +73,4 @@ Template.viewer.events({
|
||||
const current = instance.data.state.get('rightSidebar');
|
||||
instance.data.state.set('rightSidebar', !current);
|
||||
},
|
||||
})
|
||||
});
|
||||
@ -1,31 +1,11 @@
|
||||
@import "{design}/app.styl"
|
||||
@import "{design}/app"
|
||||
|
||||
#viewer
|
||||
border-top: 1px solid #525252
|
||||
height: 100%
|
||||
width: 100%
|
||||
align-items: stretch
|
||||
background-color: black
|
||||
display: flex
|
||||
flex-flow: column wrap
|
||||
height: 100%
|
||||
width: 100%
|
||||
margin: 0
|
||||
padding: 0
|
||||
|
||||
#toolbar
|
||||
float: left
|
||||
height: 30px
|
||||
|
||||
a.btn
|
||||
text-align: center
|
||||
color: $defaultColor
|
||||
background-color: $primaryBackgroundColor
|
||||
transition(all 0.1s ease)
|
||||
|
||||
// Prevent the blue outline in Chrome when a viewport is selected
|
||||
outline: 0 !important
|
||||
|
||||
&:hover
|
||||
color: $hoverColor
|
||||
|
||||
&.active, &:active
|
||||
color: $activeColor
|
||||
padding: 0
|
||||
@ -8,4 +8,7 @@
|
||||
<meta name="MobileOptimized" content="320">
|
||||
<meta name="HandheldFriendly" content="True">
|
||||
<meta name="apple-mobile-web-app-capable" content="yes">
|
||||
|
||||
<link href='http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||
<link href='http://fonts.googleapis.com/css?family=Sanchez:400,700&subset=latin,latin-ext' rel='stylesheet' type='text/css'>
|
||||
</head>
|
||||
|
||||
@ -17,13 +17,12 @@ Router.configure({
|
||||
});
|
||||
|
||||
Router.onBeforeAction('loading');
|
||||
|
||||
Router.route('/', function() {
|
||||
this.render('worklist');
|
||||
Router.onBeforeAction(function() {
|
||||
this.next();
|
||||
});
|
||||
|
||||
Router.route('/worklist', function() {
|
||||
this.render('worklist');
|
||||
Router.route('/', function() {
|
||||
this.render('ohifViewer');
|
||||
});
|
||||
|
||||
Router.route('/viewer/:_id', {
|
||||
@ -37,11 +36,12 @@ Router.route('/viewer/:_id', {
|
||||
var tabs = WorklistTabs.find({
|
||||
studyInstanceUid: studyInstanceUid
|
||||
});
|
||||
|
||||
if (tabs.count()) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.render('worklist', {
|
||||
this.render('ohifViewer', {
|
||||
data: function() {
|
||||
return {
|
||||
studyInstanceUid: studyInstanceUid
|
||||
@ -49,10 +49,4 @@ Router.route('/viewer/:_id', {
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Router.onBeforeAction(function() {
|
||||
|
||||
// User is logged in, go ahead and route them
|
||||
this.next();
|
||||
});
|
||||
@ -1,2 +1,4 @@
|
||||
@import url(http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic&subset=latin,latin-ext)
|
||||
@import url(http://fonts.googleapis.com/css?family=Sanchez:400,700&subset=latin,latin-ext)
|
||||
// TODO: Find out why Meteor is complaining about these?
|
||||
// Replaced them with <link>'s in the HEAD.html of each application, for now.
|
||||
//@import url(http://fonts.googleapis.com/css?family=Roboto:400,100,100italic,300,300italic,400italic,500,500italic,700,700italic,900,900italic&subset=latin,latin-ext)
|
||||
//@import url(http://fonts.googleapis.com/css?family=Sanchez:400,700&subset=latin,latin-ext)
|
||||
|
||||
@ -1,10 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.matchedProtocols.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
instance.$('#matchedProtocols button').tooltip(OHIF.viewer.tooltipConfig);
|
||||
});
|
||||
|
||||
Template.matchedProtocols.helpers({
|
||||
/**
|
||||
* Reactively re-render the MatchedProtocols Collection contents
|
||||
|
||||
@ -6,7 +6,7 @@ ViewerData = Session.get('ViewerData') || {};
|
||||
const worklistContentId = 'worklistTab';
|
||||
const viewerContentId = 'viewerTab';
|
||||
|
||||
Template.lesionTracker.onRendered(function() {
|
||||
Template.lesionTracker.onRendered(() => {
|
||||
const templateData = Template.currentData();
|
||||
if (templateData && templateData.studyInstanceUid) {
|
||||
const studyInstanceUid = templateData.studyInstanceUid;
|
||||
@ -19,12 +19,10 @@ Template.lesionTracker.onRendered(function() {
|
||||
// TODO: Fix this it seems to be forcing two switches
|
||||
switchToTab(contentId);
|
||||
}
|
||||
|
||||
Meteor.subscribe('hangingprotocols');
|
||||
});
|
||||
|
||||
Template.lesionTracker.events({
|
||||
'click .js-toggle-studyList': function() {
|
||||
'click .js-toggle-studyList'() {
|
||||
const contentId = Session.get('activeContentId');
|
||||
|
||||
if (contentId !== worklistContentId) {
|
||||
@ -38,7 +36,7 @@ Template.lesionTracker.events({
|
||||
Session.set('defaultSignInMessage', 'Tumor tracking in your browser.');
|
||||
|
||||
Template.lesionTracker.helpers({
|
||||
studyListToggleText: function() {
|
||||
studyListToggleText() {
|
||||
const contentId = Session.get('activeContentId');
|
||||
|
||||
// If the Viewer has not been opened yet, 'Back to viewer' should
|
||||
@ -54,7 +52,7 @@ Template.lesionTracker.helpers({
|
||||
return 'Study list';
|
||||
}
|
||||
},
|
||||
onStudyList: function() {
|
||||
onStudyList() {
|
||||
return (Session.get('activeContentId') === 'worklistTab');
|
||||
}
|
||||
});
|
||||
|
||||
@ -72,14 +72,3 @@ img.logoImage
|
||||
color: $textSecondaryColor
|
||||
font-size: 30px
|
||||
font-weight: 200
|
||||
|
||||
// Override Viewerbase's borders
|
||||
#imageViewerViewports .viewportContainer
|
||||
border: none !important
|
||||
outline: 0 !important // Prevent blue outline in Chrome
|
||||
|
||||
&:hover
|
||||
&.active
|
||||
&:hover.active
|
||||
border: none !important
|
||||
outline: 0 !important // Prevent blue outline in Chrome
|
||||
|
||||
@ -1,3 +0,0 @@
|
||||
<template name="lesionTrackerLayout">
|
||||
{{>yield }}
|
||||
</template>
|
||||
@ -26,6 +26,8 @@ Template.viewer.onCreated(() => {
|
||||
instance.data.state.set('leftSidebar', Session.get('leftSidebar'));
|
||||
instance.data.state.set('rightSidebar', Session.get('rightSidebar'));
|
||||
|
||||
instance.subscribe('hangingprotocols');
|
||||
|
||||
Session.set('currentTimepointId', instance.data.currentTimepointId);
|
||||
|
||||
const contentId = instance.data.contentId;
|
||||
@ -49,18 +51,6 @@ Template.viewer.onCreated(() => {
|
||||
OHIF.viewer.defaultHotkeys.bidirectional = 'T'; // Target
|
||||
OHIF.viewer.defaultHotkeys.nonTarget = 'N'; // Non-target
|
||||
|
||||
if (isTouchDevice()) {
|
||||
OHIF.viewer.tooltipConfig = {
|
||||
trigger: 'manual'
|
||||
};
|
||||
} else {
|
||||
OHIF.viewer.tooltipConfig = {
|
||||
trigger: 'hover'
|
||||
};
|
||||
}
|
||||
|
||||
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.updateImageSynchronizer);
|
||||
|
||||
if (ViewerData[contentId].loadedSeriesData) {
|
||||
log.info('Reloading previous loadedSeriesData');
|
||||
OHIF.viewer.loadedSeriesData = ViewerData[contentId].loadedSeriesData;
|
||||
@ -68,20 +58,7 @@ Template.viewer.onCreated(() => {
|
||||
} else {
|
||||
log.info('Setting default ViewerData');
|
||||
OHIF.viewer.loadedSeriesData = {};
|
||||
|
||||
ViewerData[contentId].loadedSeriesData = OHIF.viewer.loadedSeriesData;
|
||||
|
||||
// Update the viewer data object
|
||||
if (!instance.data.timepointIds || instance.data.timepointIds.length <= 1) {
|
||||
// Update the viewer data object
|
||||
ViewerData[contentId].viewportColumns = 1;
|
||||
ViewerData[contentId].viewportRows = 1;
|
||||
} else if (instance.data.timepointIds.length > 1) {
|
||||
ViewerData[contentId].viewportColumns = 2;
|
||||
ViewerData[contentId].viewportRows = 1;
|
||||
}
|
||||
|
||||
ViewerData[contentId].activeViewport = 0;
|
||||
ViewerData[contentId].loadedSeriesData = {};
|
||||
Session.set('ViewerData', ViewerData);
|
||||
}
|
||||
|
||||
@ -108,11 +85,8 @@ Template.viewer.onCreated(() => {
|
||||
instance.subscribe('singlePatientMeasurements', dataContext.studies[0].patientId);
|
||||
instance.subscribe('singlePatientImageMeasurements', dataContext.studies[0].patientId);
|
||||
instance.subscribe('singlePatientAdditionalFindings', dataContext.studies[0].patientId);
|
||||
|
||||
const subscriptionsReady = instance.subscriptionsReady();
|
||||
log.info('autorun viewer.js. Ready: ' + subscriptionsReady);
|
||||
|
||||
if (subscriptionsReady) {
|
||||
|
||||
if (instance.subscriptionsReady()) {
|
||||
// Set buttons as enabled/disabled when Timepoints collection is ready
|
||||
timepointAutoCheck(dataContext);
|
||||
|
||||
|
||||
@ -6,6 +6,23 @@
|
||||
display: flex
|
||||
flex-flow: column wrap
|
||||
height: 100%
|
||||
width: 100%
|
||||
margin: 0
|
||||
padding: 0
|
||||
width: 100%
|
||||
|
||||
|
||||
#imageViewerViewports
|
||||
.viewportContainer
|
||||
border: none !important
|
||||
outline: 0 !important // Prevent blue outline in Chrome
|
||||
|
||||
&:hover
|
||||
&.active
|
||||
&:hover.active
|
||||
border: none !important
|
||||
outline: 0 !important // Prevent blue outline in Chrome
|
||||
|
||||
&:not(:last-child)
|
||||
.removable
|
||||
.imageViewerViewport
|
||||
border-right: $uiBorderThickness solid #436270
|
||||
|
||||
@ -3,7 +3,7 @@ Meteor.startup(function() {
|
||||
mouse: cornerstoneTools.bidirectional,
|
||||
touch: cornerstoneTools.bidirectionalTouch
|
||||
});
|
||||
|
||||
|
||||
toolManager.addTool('nonTarget', {
|
||||
mouse: cornerstoneTools.nonTarget,
|
||||
touch: cornerstoneTools.nonTargetTouch
|
||||
@ -44,4 +44,4 @@ Meteor.startup(function() {
|
||||
|
||||
states.activate.push('deleteLesionKeyboardTool');
|
||||
toolManager.setToolDefaultStates(states);
|
||||
});
|
||||
});
|
||||
@ -55,6 +55,8 @@ Package.onUse(function(api) {
|
||||
], 'client', {
|
||||
bare: true
|
||||
});
|
||||
|
||||
api.addFiles('client/tools.js', 'client');
|
||||
|
||||
// UI Components
|
||||
api.addFiles('client/components/viewer/viewer.html', 'client');
|
||||
@ -81,8 +83,6 @@ Package.onUse(function(api) {
|
||||
api.addFiles('client/components/lesionTracker/lesionTracker.styl', 'client');
|
||||
api.addFiles('client/components/lesionTracker/lesionTracker.js', 'client');
|
||||
|
||||
api.addFiles('client/components/lesionTrackerLayout/lesionTrackerLayout.html', 'client');
|
||||
|
||||
api.addFiles('client/components/additionalFindings/additionalFindings.html', 'client');
|
||||
api.addFiles('client/components/additionalFindings/additionalFindings.styl', 'client');
|
||||
api.addFiles('client/components/additionalFindings/additionalFindings.js', 'client');
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
<template name="layout">
|
||||
{{>yield }}
|
||||
</template>
|
||||
@ -1,11 +0,0 @@
|
||||
<template name="relatedStudySelect">
|
||||
<div class="relatedStudySelect">
|
||||
<label>Study:</label>
|
||||
<span class="loading"><i class="fa fa-spinner fa-spin"></i></span>
|
||||
<select id="selectStudyDate">
|
||||
{{#each relatedStudies}}
|
||||
<option value="{{studyInstanceUid}}" selected={{selected}}>{{formatDA studyDate}}: {{studyDescription}}</option>
|
||||
{{/each}}
|
||||
</select>
|
||||
</div>
|
||||
</template>
|
||||
@ -1,105 +0,0 @@
|
||||
Template.relatedStudySelect.helpers({
|
||||
/**
|
||||
* Returns an array of studies that are related to the current study by patient ID.
|
||||
* The value for 'selected' for the currently loaded study is set to true, so that
|
||||
* this becomes the current option in the combo box.
|
||||
*
|
||||
* @returns {*} Array of studies that are related to the current study by patient ID
|
||||
*/
|
||||
relatedStudies: function() {
|
||||
// Check which study is currently loaded into the study browser
|
||||
var currentStudyInBrowser = ViewerStudies.findOne({
|
||||
selected: true
|
||||
});
|
||||
|
||||
// Find all studies in the Worklist which have the same patientId as the currently selected study
|
||||
var relatedStudies = WorklistStudies.find({
|
||||
patientId: currentStudyInBrowser.patientId
|
||||
}, {
|
||||
sort: {
|
||||
studyDate: -1
|
||||
}
|
||||
}).fetch();
|
||||
|
||||
// If no Study / Timepoint associated studies exist, just
|
||||
// return the list of loaded studies
|
||||
if (!relatedStudies.length) {
|
||||
return ViewerStudies.find();
|
||||
}
|
||||
|
||||
// Modify the array of related studies so the default option is the currently selected study
|
||||
relatedStudies.forEach(function(study, index) {
|
||||
// If the studyInstanceUid matches that of the current study in the browser,
|
||||
// Set this to 'selected', so that it becomes the default option
|
||||
if (study.studyInstanceUid === currentStudyInBrowser.studyInstanceUid) {
|
||||
relatedStudies[index].selected = true;
|
||||
}
|
||||
});
|
||||
|
||||
// Use this array to populate the combo box
|
||||
return relatedStudies;
|
||||
}
|
||||
});
|
||||
|
||||
Template.relatedStudySelect.events({
|
||||
/**
|
||||
* When the study date selector combo box is changed, we will
|
||||
* hide the select box, temporarily display a loading sign, and grab
|
||||
* the selected study. Once the study has been retrieved it is added
|
||||
* into the ViewerStudies collection and set as selected. This reactively
|
||||
* populated the thumbnail browser.
|
||||
*
|
||||
* @param e The select box change event
|
||||
*/
|
||||
'change select#selectStudyDate': function(e) {
|
||||
var selectBox = $(e.currentTarget);
|
||||
var studyInstanceUid = selectBox.val();
|
||||
|
||||
// Hide the select box
|
||||
selectBox.css('display', 'none');
|
||||
|
||||
// Show the loading indicator
|
||||
var loadingIndicator = selectBox.siblings('.loading');
|
||||
loadingIndicator.css('display', 'block');
|
||||
|
||||
getStudyMetadata(studyInstanceUid, function(study) {
|
||||
sortStudy(study);
|
||||
|
||||
// Hide the loading indicator
|
||||
loadingIndicator.css('display', 'none');
|
||||
|
||||
// Show the select box again
|
||||
selectBox.css('display', 'block');
|
||||
|
||||
// Set "Selected" to false for the entire collection
|
||||
ViewerStudies.update({}, {
|
||||
$set: {
|
||||
selected: false
|
||||
}
|
||||
}, {
|
||||
multi: true
|
||||
});
|
||||
|
||||
// Check if this study already exists in the ViewerStudies collection
|
||||
// of loaded studies. If it does, set it's 'selected' value to true.
|
||||
var existingStudy = ViewerStudies.findOne({
|
||||
studyInstanceUid: studyInstanceUid
|
||||
});
|
||||
|
||||
if (existingStudy) {
|
||||
// Set the current finding in the collection to true
|
||||
ViewerStudies.update(existingStudy._id, {
|
||||
$set: {
|
||||
selected: true
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// If the study does not exist, add the 'selected' key to the object
|
||||
// with the value True, and insert it into the ViewerStudies Collection
|
||||
study.selected = true;
|
||||
ViewerStudies.insert(study);
|
||||
});
|
||||
}
|
||||
});
|
||||
@ -1,23 +0,0 @@
|
||||
.relatedStudySelect
|
||||
margin: 0 auto 15px
|
||||
text-align: center
|
||||
width: 100px
|
||||
|
||||
#selectStudyDate
|
||||
color: black
|
||||
background-color: #666
|
||||
border-color: #666
|
||||
width: 96%
|
||||
margin: 0 auto
|
||||
|
||||
label
|
||||
font-weight: normal
|
||||
color: #666
|
||||
float: left
|
||||
padding-left: 2%
|
||||
|
||||
.loading
|
||||
display: none
|
||||
color: white
|
||||
text-align: center
|
||||
|
||||
@ -29,12 +29,4 @@ Template.gridLayout.helpers({
|
||||
|
||||
return viewportData;
|
||||
}
|
||||
});
|
||||
|
||||
Template.gridLayout.onRendered(function() {
|
||||
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.updateImageSynchronizer);
|
||||
});
|
||||
|
||||
Template.gridLayout.onDestroyed(function() {
|
||||
OHIF.viewer.updateImageSynchronizer.destroy();
|
||||
});
|
||||
});
|
||||
@ -2,19 +2,4 @@
|
||||
|
||||
#imageViewerViewports
|
||||
height: 100%
|
||||
width: 100%
|
||||
|
||||
.viewportContainer
|
||||
float: left
|
||||
border: $viewportBorderThickness solid $viewportBorderColor
|
||||
|
||||
&.active, &:hover.active
|
||||
border: $viewportBorderThickness solid $viewportBorderColorActive
|
||||
|
||||
&:hover
|
||||
border: $viewportBorderThickness solid $viewportBorderColorHover
|
||||
|
||||
.removable
|
||||
width: 100%
|
||||
height: 100%
|
||||
position: relative // Necessary so that the viewportOverlay is on top of the viewports
|
||||
width: 100%
|
||||
@ -25,6 +25,11 @@ function loadSeriesIntoViewport(data, templateData) {
|
||||
var viewportIndex = $('.imageViewerViewport').index(element);
|
||||
|
||||
layoutManager = layoutManager || window.layoutManager;
|
||||
layoutManager.viewportData = layoutManager.viewportData || {};
|
||||
if (layoutManager.viewportData[viewportIndex] === undefined) {
|
||||
layoutManager.viewportData[viewportIndex] = {};
|
||||
}
|
||||
|
||||
layoutManager.viewportData[viewportIndex].viewportIndex = viewportIndex;
|
||||
|
||||
// Get the contentID of the current worklist tab, if the viewport is running
|
||||
|
||||
@ -1,6 +1,9 @@
|
||||
Template.viewerMain.onCreated(() => {
|
||||
// Attach the Window resize listener
|
||||
$(window).on('resize', handleResize);
|
||||
|
||||
// Create the synchronizer used to update reference lines
|
||||
OHIF.viewer.updateImageSynchronizer = new cornerstoneTools.Synchronizer('CornerstoneNewImage', cornerstoneTools.updateImageSynchronizer);
|
||||
});
|
||||
|
||||
Template.viewerMain.onRendered(() => {
|
||||
@ -21,6 +24,6 @@ Template.viewerMain.onDestroyed(() => {
|
||||
// Remove the Window resize listener
|
||||
$(window).off('resize', handleResize);
|
||||
|
||||
// Destory the synchronizer used to update reference lines
|
||||
// Destroy the synchronizer used to update reference lines
|
||||
OHIF.viewer.updateImageSynchronizer.destroy();
|
||||
});
|
||||
@ -7,11 +7,22 @@
|
||||
#layoutManagerTarget
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
transition(all 0.3s ease)
|
||||
|
||||
#imageViewerViewports
|
||||
.viewportContainer:not(:last-child)
|
||||
.viewportContainer
|
||||
float: left
|
||||
border: $viewportBorderThickness solid $viewportBorderColor
|
||||
|
||||
&:hover
|
||||
border: $viewportBorderThickness solid $viewportBorderColorHover
|
||||
|
||||
&.active, &:hover.active
|
||||
border: $viewportBorderThickness solid $viewportBorderColorActive
|
||||
|
||||
.removable
|
||||
.imageViewerViewport
|
||||
border-right: $uiBorderThickness solid #436270
|
||||
width: 100%
|
||||
height: 100%
|
||||
position: relative // Necessary so that the viewportOverlay is on top of the viewports
|
||||
|
||||
|
||||
|
||||
@ -11,13 +11,13 @@
|
||||
<div>{{formatDA studyDate}} {{formatTM studyTime}}</div>
|
||||
</div>
|
||||
<div class="bottomright dicomTag">
|
||||
<div>Zoom: {{formatNumberPrecision zoom 2}}%</div>
|
||||
<div>{{#if zoom}}Zoom: {{formatNumberPrecision zoom 2}}%{{/if}}</div>
|
||||
<div>{{compression}}</div>
|
||||
<div>{{wwwc}}</div>
|
||||
</div>
|
||||
<div class="bottomleft dicomTag">
|
||||
<div>Ser: {{seriesNumber}}</div>
|
||||
<div>Img: {{imageNumber}} ({{imageIndex}}/{{numImages}})</div>
|
||||
<div>{{#if seriesNumber}}Ser: {{seriesNumber}}{{/if}}</div>
|
||||
<div>{{#if numImages}}Img: {{imageNumber}} ({{imageIndex}}/{{numImages}}){{/if}}</div>
|
||||
<div>{{#if frameRate}}{{frameRate}} FPS{{/if}}</div>
|
||||
<div>{{imageDimensions}}</div>
|
||||
<div>{{seriesDescription}}</div>
|
||||
@ -33,12 +33,12 @@
|
||||
<div>{{formatDA studyDate}} {{formatTM studyTime}}</div>
|
||||
</div>
|
||||
<div class="bottomright dicomTag">
|
||||
<div>Ser: {{seriesNumber}}</div>
|
||||
<div>Img: {{imageNumber}} ({{imageIndex}}/{{numImages}})</div>
|
||||
<div>{{#if seriesNumber}}Ser: {{seriesNumber}}{{/if}}</div>
|
||||
<div>{{#if numImages}}Img: {{imageNumber}} ({{imageIndex}}/{{numImages}}){{/if}}</div>
|
||||
<div>{{#if frameRate}}{{frameRate}} FPS{{/if}}</div>
|
||||
<div>{{imageDimensions}}</div>
|
||||
<div>{{seriesDescription}}</div>
|
||||
<div>Zoom: {{formatNumberPrecision zoom 2}}%</div>
|
||||
<div>{{#if zoom}}Zoom: {{formatNumberPrecision zoom 2}}%{{/if}}</div>
|
||||
<div>{{compression}}</div>
|
||||
<div>{{wwwc}}</div>
|
||||
</div>
|
||||
@ -53,12 +53,12 @@
|
||||
<div>{{formatDA studyDate}} {{formatTM studyTime}}</div>
|
||||
</div>
|
||||
<div class="bottomleft dicomTag">
|
||||
<div>Ser: {{seriesNumber}}</div>
|
||||
<div>Img: {{imageNumber}} ({{imageIndex}}/{{numImages}})</div>
|
||||
<div>{{#if seriesNumber}}Ser: {{seriesNumber}}{{/if}}</div>
|
||||
<div>{{#if numImages}}Img: {{imageNumber}} ({{imageIndex}}/{{numImages}}){{/if}}</div>
|
||||
<div>{{#if frameRate}}{{frameRate}} FPS{{/if}}</div>
|
||||
<div>{{imageDimensions}}</div>
|
||||
<div>{{seriesDescription}}</div>
|
||||
<div>Zoom: {{formatNumberPrecision zoom 2}}%</div>
|
||||
<div>{{#if zoom}}Zoom: {{formatNumberPrecision zoom 2}}%{{/if}}</div>
|
||||
<div>{{compression}}</div>
|
||||
<div>{{wwwc}}</div>
|
||||
</div>
|
||||
|
||||
@ -133,12 +133,12 @@ Template.viewportOverlay.helpers({
|
||||
Session.get('CornerstoneImageRendered' + this.viewportIndex);
|
||||
var element = getElementIfNotEmpty(this.viewportIndex);
|
||||
if (!element) {
|
||||
return '';
|
||||
return;
|
||||
}
|
||||
|
||||
var viewport = cornerstone.getViewport(element);
|
||||
if (!viewport) {
|
||||
return '';
|
||||
return;
|
||||
}
|
||||
|
||||
return (viewport.scale * 100.0);
|
||||
|
||||
@ -44,7 +44,7 @@ importStudies = function(filesToImport, importCallback) {
|
||||
|
||||
if (fileUploadStatus.numberOfFilesFailed > 0) {
|
||||
//TODO: Some files failed to upload, so let user know
|
||||
console.log("Failed to upload " + fileUploadStatus.numberOfFilesFailed + " of " + numberOfFilesToUpload + " files");
|
||||
log.info("Failed to upload " + fileUploadStatus.numberOfFilesFailed + " of " + numberOfFilesToUpload + " files");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -34,6 +34,7 @@ Package.onUse(function(api) {
|
||||
// ---------- Components ----------
|
||||
|
||||
// Basic components
|
||||
api.addFiles('client/components/basic/layout/layout.html', 'client');
|
||||
api.addFiles('client/components/basic/loadingText/loadingText.html', 'client');
|
||||
api.addFiles('client/components/basic/loadingText/loadingText.styl', 'client');
|
||||
|
||||
@ -44,15 +45,15 @@ Package.onUse(function(api) {
|
||||
api.addFiles('client/components/basic/confirmDeleteDialog/confirmDeleteDialog.styl', 'client');
|
||||
api.addFiles('client/components/basic/confirmDeleteDialog/confirmDeleteDialog.js', 'client');
|
||||
|
||||
api.addFiles('client/components/basic/emailVerification/emailVerification.html', 'client');
|
||||
api.addFiles('client/components/basic/emailVerification/emailVerification.styl', 'client');
|
||||
api.addFiles('client/components/basic/emailVerification/emailVerification.js', 'client');
|
||||
|
||||
// Study Browser components
|
||||
api.addFiles('client/components/studyBrowser/studyBrowser/studyBrowser.html', 'client');
|
||||
api.addFiles('client/components/studyBrowser/studyBrowser/studyBrowser.js', 'client');
|
||||
api.addFiles('client/components/studyBrowser/studyBrowser/studyBrowser.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/studyBrowser/relatedStudySelect/relatedStudySelect.html', 'client');
|
||||
api.addFiles('client/components/studyBrowser/relatedStudySelect/relatedStudySelect.js', 'client');
|
||||
api.addFiles('client/components/studyBrowser/relatedStudySelect/relatedStudySelect.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/studyBrowser/thumbnailEntry/thumbnailEntry.html', 'client');
|
||||
api.addFiles('client/components/studyBrowser/thumbnailEntry/thumbnailEntry.js', 'client');
|
||||
api.addFiles('client/components/studyBrowser/thumbnailEntry/thumbnailEntry.styl', 'client');
|
||||
@ -139,6 +140,7 @@ Package.onUse(function(api) {
|
||||
api.addFiles('lib/setMammogramViewportAlignment.js', 'client');
|
||||
api.addFiles('lib/isImage.js', 'client');
|
||||
api.addFiles('lib/sopClassDictionary.js', 'client');
|
||||
api.addFiles('lib/debugReactivity.js', 'client');
|
||||
|
||||
api.export('resizeViewportElements', 'client');
|
||||
api.export('handleResize', 'client');
|
||||
|
||||
@ -5,8 +5,10 @@
|
||||
</div>
|
||||
<div class="dialogContent">
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped active" role="progressbar" style="width:{{progressStatus}}">
|
||||
{{progressStatus}}
|
||||
<div class="progress-bar progress-bar-striped active"
|
||||
role="progressbar"
|
||||
style="width:{{progressStatus}}">
|
||||
{{formatNumberPrecision progressStatus 0}}%
|
||||
</div>
|
||||
</div>
|
||||
<div id="message">
|
||||
|
||||
@ -1,56 +1,69 @@
|
||||
progressDialog = {
|
||||
'show': function(title, numberOfTotal) {
|
||||
Session.set("progressDialogSettings", { title: title, numberOfCompleted: 0, numberOfTotal: numberOfTotal });
|
||||
show: function(title, numberOfTotal) {
|
||||
Session.set('progressDialogSettings', {
|
||||
title: title,
|
||||
numberOfCompleted: 0,
|
||||
numberOfTotal: numberOfTotal
|
||||
});
|
||||
|
||||
$('#progressDialog').css('display', 'block');
|
||||
},
|
||||
'update': function(numberOfCompleted) {
|
||||
var progressDialogSettings = Session.get("progressDialogSettings");
|
||||
update: function(numberOfCompleted) {
|
||||
var progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.numberOfCompleted = numberOfCompleted;
|
||||
|
||||
Session.set("progressDialogSettings", progressDialogSettings);
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
|
||||
if (progressDialogSettings.numberOfCompleted === progressDialogSettings.numberOfTotal) {
|
||||
progressDialog.close();
|
||||
}
|
||||
},
|
||||
'close': function() {
|
||||
Session.set("progressDialogSettings", { title: "", numberOfCompleted: 0, numberOfTotal: 1 });
|
||||
close: function() {
|
||||
Session.set('progressDialogSettings', {
|
||||
title: '',
|
||||
numberOfCompleted: 0,
|
||||
numberOfTotal: 1
|
||||
});
|
||||
|
||||
$('#progressDialog').css('display', 'none');
|
||||
},
|
||||
'setMessage': function(message) {
|
||||
var progressDialogSettings = Session.get("progressDialogSettings");
|
||||
setMessage: function(message) {
|
||||
let progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.message = message;
|
||||
Session.set("progressDialogSettings", progressDialogSettings);
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
}
|
||||
};
|
||||
|
||||
Template.progressDialog.helpers({
|
||||
'progressDialogTitle': function () {
|
||||
if (Session.get("progressDialogSettings") && Session.get("progressDialogSettings").title) {
|
||||
return Session.get("progressDialogSettings").title;
|
||||
progressDialogTitle() {
|
||||
var settings = Session.get('progressDialogSettings');
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
|
||||
return "";
|
||||
return settings.title;
|
||||
},
|
||||
'progressStatus': function() {
|
||||
var numberOfCompleted = 0;
|
||||
if (Session.get("progressDialogSettings") && Session.get("progressDialogSettings").numberOfCompleted) {
|
||||
numberOfCompleted = Session.get("progressDialogSettings").numberOfCompleted;
|
||||
|
||||
progressStatus() {
|
||||
const settings = Session.get('progressDialogSettings');
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
|
||||
var numberofTotal = 1;
|
||||
if (Session.get("progressDialogSettings") && Session.get("progressDialogSettings").numberOfTotal) {
|
||||
numberofTotal = Session.get("progressDialogSettings").numberOfTotal;
|
||||
if (settings.numberOfCompleted === undefined ||
|
||||
settings.numberOfTotal === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
return parseInt((numberOfCompleted / numberofTotal) * 100) + "%";
|
||||
return settings.numberOfCompleted / settings.numberOfTotal;
|
||||
},
|
||||
'progressMessage': function() {
|
||||
var progressDialogSettings = Session.get("progressDialogSettings");
|
||||
if (progressDialogSettings && progressDialogSettings.message) {
|
||||
return progressDialogSettings.message;
|
||||
|
||||
progressMessage() {
|
||||
var settings = Session.get('progressDialogSettings');
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
|
||||
return settings.message;
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,12 +1,4 @@
|
||||
<template name="worklist">
|
||||
<ul class="nav noselect" role="tablist" id="tablist">
|
||||
<li role="presentation" class="tabTitle active">
|
||||
<a data-target="#worklistTab" role="tab" data-toggle="tab">Study List</a>
|
||||
</li>
|
||||
{{#each worklistTabs }}
|
||||
{{>tabTitle }}
|
||||
{{/each }}
|
||||
</ul>
|
||||
<div id="worklistTabs" class="tab-content">
|
||||
<div role="tabpanel" class="tab-pane active" id="worklistTab">
|
||||
<div class="worklistContainer">
|
||||
|
||||
@ -12,59 +12,6 @@ body
|
||||
background-color: black
|
||||
margin: 0 auto
|
||||
color: white
|
||||
|
||||
#tabs
|
||||
width: 100%
|
||||
|
||||
#tablist
|
||||
border-bottom: 1px solid #424242
|
||||
background-color: #202020
|
||||
height: 41px
|
||||
|
||||
a:hover
|
||||
background-color: transparent
|
||||
|
||||
.tabTitle
|
||||
background-color: #202020
|
||||
border-color: #424242
|
||||
float: left
|
||||
line-height: 30px
|
||||
|
||||
&:hover
|
||||
color: black
|
||||
background-color: white
|
||||
|
||||
button.close
|
||||
color: black
|
||||
|
||||
&.active
|
||||
background-color: #424242
|
||||
border-color: #424242
|
||||
|
||||
&:hover
|
||||
background-color: #424242
|
||||
cursor: none
|
||||
|
||||
a
|
||||
color: white
|
||||
|
||||
button.close
|
||||
color: white
|
||||
|
||||
a
|
||||
padding: 5px 15px
|
||||
cursor: pointer
|
||||
color: #424242
|
||||
text-decoration: none
|
||||
|
||||
button.close
|
||||
margin: 4px 0 4px 8px
|
||||
text-shadow: none
|
||||
color: white
|
||||
text-decoration: none
|
||||
|
||||
&:hover
|
||||
color: red
|
||||
|
||||
.tab-content
|
||||
width: 100%
|
||||
|
||||
@ -8,8 +8,8 @@ Template.worklistResult.helpers({
|
||||
* Returns a sorted instance of the WorklistStudies Collection
|
||||
* by Patient name and Study Date in Ascending order.
|
||||
*/
|
||||
studies: function() {
|
||||
var sortOption = Session.get('sortOption');
|
||||
studies() {
|
||||
const sortOption = Session.get('sortOption');
|
||||
if (sortOption) {
|
||||
return WorklistStudies.find({}, {
|
||||
sort: sortOption
|
||||
@ -24,22 +24,24 @@ Template.worklistResult.helpers({
|
||||
});
|
||||
},
|
||||
|
||||
numberOfStudies: function() {
|
||||
numberOfStudies() {
|
||||
return WorklistStudies.find().count();
|
||||
},
|
||||
|
||||
showLoadingText: function() {
|
||||
showLoadingText() {
|
||||
return Session.get('searchResults').showLoadingText;
|
||||
},
|
||||
|
||||
showNotFoundMessage: function() {
|
||||
showNotFoundMessage() {
|
||||
return Session.get('searchResults').showNotFoundMessage;
|
||||
},
|
||||
|
||||
sortingColumnsIcons: function() {
|
||||
var sortingColumnsIcons = {};
|
||||
Object.keys(Template.instance().sortingColumns.keys).forEach(function(key) {
|
||||
var value = Template.instance().sortingColumns.get(key);
|
||||
sortingColumnsIcons() {
|
||||
const instance = Template.instance();
|
||||
|
||||
let sortingColumnsIcons = {};
|
||||
Object.keys(instance.sortingColumns.keys).forEach(key => {
|
||||
const value = instance.sortingColumns.get(key);
|
||||
|
||||
if (value === 1) {
|
||||
sortingColumnsIcons[key] = 'fa fa-fw fa-sort-up';
|
||||
@ -102,10 +104,10 @@ function replaceUndefinedColumnValue(text) {
|
||||
* Convert string to study date
|
||||
*/
|
||||
function convertStringToStudyDate(dateStr) {
|
||||
var y = dateStr.substring(0, 4);
|
||||
var m = dateStr.substring(4, 6);
|
||||
var d = dateStr.substring(6, 8);
|
||||
var newDateStr = m + '/' + d + '/' + y;
|
||||
const y = dateStr.substring(0, 4);
|
||||
const m = dateStr.substring(4, 6);
|
||||
const d = dateStr.substring(6, 8);
|
||||
const newDateStr = m + '/' + d + '/' + y;
|
||||
return new Date(newDateStr);
|
||||
}
|
||||
|
||||
@ -115,7 +117,7 @@ function convertStringToStudyDate(dateStr) {
|
||||
*/
|
||||
function search() {
|
||||
// Show loading message
|
||||
var searchResults = Session.get('searchResults');
|
||||
let searchResults = Session.get('searchResults');
|
||||
searchResults.showLoadingText = true;
|
||||
searchResults.showNotFoundMessage = false;
|
||||
Session.set('searchResults', searchResults);
|
||||
@ -130,12 +132,12 @@ function search() {
|
||||
|
||||
// Make sure that modality has a reasonable value, since it is occasionally
|
||||
// returned as 'undefined'
|
||||
var modality = replaceUndefinedColumnValue($('input#modality').val());
|
||||
const modality = replaceUndefinedColumnValue($('input#modality').val());
|
||||
|
||||
// Clear all current studies
|
||||
WorklistStudies.remove({});
|
||||
|
||||
Meteor.call('WorklistSearch', filter, function(error, studies) {
|
||||
Meteor.call('WorklistSearch', filter, (error, studies) => {
|
||||
if (error) {
|
||||
log.warn(error);
|
||||
return;
|
||||
@ -150,7 +152,7 @@ function search() {
|
||||
}
|
||||
|
||||
// Loop through all identified studies
|
||||
studies.forEach(function(study) {
|
||||
studies.forEach(study => {
|
||||
// Search the rest of the parameters that aren't done via the server call
|
||||
if (isIndexOf(study.modalities, modality) &&
|
||||
(new Date(studyDateFrom).setHours(0, 0, 0, 0) <= convertStringToStudyDate(study.studyDate) || !studyDateFrom || studyDateFrom === '') &&
|
||||
@ -173,36 +175,38 @@ function search() {
|
||||
});
|
||||
}
|
||||
|
||||
Template.worklistResult.onCreated(function() {
|
||||
this.sortOption = new ReactiveVar();
|
||||
this.sortingColumns = new ReactiveDict();
|
||||
Template.worklistResult.onCreated(() => {
|
||||
let instance = Template.instance();
|
||||
instance.sortOption = new ReactiveVar();
|
||||
instance.sortingColumns = new ReactiveDict();
|
||||
|
||||
// Retrieve all studies
|
||||
search();
|
||||
|
||||
// Set sortOption
|
||||
var sortOptionSession = Session.get('sortOption');
|
||||
const sortOptionSession = Session.get('sortOption');
|
||||
if (sortOptionSession) {
|
||||
this.sortingColumns.set(sortOptionSession);
|
||||
instance.sortingColumns.set(sortOptionSession);
|
||||
} else {
|
||||
this.sortingColumns.set('patientName', 1);
|
||||
this.sortingColumns.set('studyDate', 1);
|
||||
this.sortingColumns.set('patientId', 0);
|
||||
this.sortingColumns.set('accessionNumber', 0);
|
||||
this.sortingColumns.set('studyDescription', 0);
|
||||
this.sortingColumns.set('modality', 0);
|
||||
this.sortingColumns.set('numberOfStudyRelatedInstances', 0);
|
||||
instance.sortingColumns.set({
|
||||
patientName: 1,
|
||||
studyDate: 1,
|
||||
patientId: 0,
|
||||
accessionNumber: 0,
|
||||
studyDescription: 0,
|
||||
modality: 0,
|
||||
numberOfStudyRelatedInstances: 0
|
||||
});
|
||||
}
|
||||
|
||||
var self = this;
|
||||
if (Worklist.subscriptions) {
|
||||
Worklist.subscriptions.forEach(function(collectionName) {
|
||||
self.subscribe(collectionName);
|
||||
Worklist.subscriptions.forEach(collectionName => {
|
||||
instance.subscribe(collectionName);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
Template.worklistResult.onRendered(function() {
|
||||
Template.worklistResult.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
// Initialize daterangepicker
|
||||
@ -215,29 +219,33 @@ Template.worklistResult.onRendered(function() {
|
||||
});
|
||||
});
|
||||
|
||||
function resetSortingColumns(template, sortingColumn) {
|
||||
Object.keys(template.sortingColumns.keys).forEach(function(key) {
|
||||
function resetSortingColumns(instance, sortingColumn) {
|
||||
Object.keys(instance.sortingColumns.keys).forEach(key => {
|
||||
if (key !== sortingColumn) {
|
||||
template.sortingColumns.set(key, null);
|
||||
instance.sortingColumns.set(key, null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Template.worklistResult.events({
|
||||
'keydown input': function(e) {
|
||||
if (e.which === 13) { // Enter
|
||||
'keydown input'(event) {
|
||||
if (event.which === 13) { // Enter
|
||||
search();
|
||||
}
|
||||
},
|
||||
'onsearch input': function() {
|
||||
|
||||
'onsearch input'() {
|
||||
search();
|
||||
},
|
||||
'change #studyDate': function(e, template) {
|
||||
var dateRange = $(e.currentTarget).val();
|
||||
|
||||
'change #studyDate'(event) {
|
||||
let dateRange = $(event.currentTarget).val();
|
||||
|
||||
// Remove all space chars
|
||||
dateRange = dateRange.replace(/ /g, '');
|
||||
|
||||
// Split dateRange into subdates
|
||||
var dates = dateRange.split('-');
|
||||
const dates = dateRange.split('-');
|
||||
studyDateFrom = dates[0];
|
||||
studyDateTo = dates[1];
|
||||
|
||||
@ -245,23 +253,26 @@ Template.worklistResult.events({
|
||||
search();
|
||||
}
|
||||
},
|
||||
'click div.sortingCell': function(e, template) {
|
||||
var elementId = e.currentTarget.id;
|
||||
// Remove _ from id
|
||||
var columnName = elementId.replace('_', '');
|
||||
|
||||
var sortOption = {};
|
||||
resetSortingColumns(template, columnName);
|
||||
var columnObject = template.sortingColumns.get(columnName);
|
||||
'click div.sortingCell'(event, instance) {
|
||||
const elementId = event.currentTarget.id;
|
||||
|
||||
// Remove _ from id
|
||||
const columnName = elementId.replace('_', '');
|
||||
|
||||
let sortOption = {};
|
||||
resetSortingColumns(instance, columnName);
|
||||
|
||||
const columnObject = instance.sortingColumns.get(columnName);
|
||||
if (columnObject) {
|
||||
template.sortingColumns.set(columnName, columnObject * -1);
|
||||
instance.sortingColumns.set(columnName, columnObject * -1);
|
||||
sortOption[columnName] = columnObject * -1;
|
||||
} else {
|
||||
template.sortingColumns.set(columnName, 1);
|
||||
instance.sortingColumns.set(columnName, 1);
|
||||
sortOption[columnName] = 1;
|
||||
}
|
||||
|
||||
template.sortOption.set(sortOption);
|
||||
instance.sortOption.set(sortOption);
|
||||
Session.set('sortOption', sortOption);
|
||||
}
|
||||
});
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
Template.worklistToolbar.onCreated(() => {
|
||||
Meteor.call('importSupported', function(error, result) {
|
||||
Meteor.call('importSupported', (error, result) => {
|
||||
if (error || !result) {
|
||||
Session.set('importSupported', false);
|
||||
} else {
|
||||
|
||||
@ -50,7 +50,6 @@ switchToTab = function(contentId) {
|
||||
}
|
||||
|
||||
var studies = ViewerData[contentId].studies;
|
||||
|
||||
if (studies) {
|
||||
// ViewerData already has the meta data (in cases when worklist is launched externally)
|
||||
viewStudiesInTab(contentId, studies);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user