Adjusting Standalone Viewer to the new structure

This commit is contained in:
Bruno Alves de Faria 2017-03-20 17:13:41 -03:00
parent 718fd30feb
commit bb9d04d569
21 changed files with 129 additions and 175 deletions

View File

@ -5,9 +5,7 @@
{{>section 'brand'}} {{>section 'brand'}}
</a> </a>
{{>section 'headerAfterBrand'}} {{>section 'headerAfterBrand'}}
<a href='#' class="header-menu pull-right"> <a href='#' class="header-menu pull-right">{{>section 'headerMenu'}}</a>
{{>section 'headerMenu'}}
</a>
</div> </div>
{{>UI.contentBlock}} {{>UI.contentBlock}}
</div> </div>

View File

@ -18,6 +18,9 @@ body>.header
text-decoration: none text-decoration: none
theme('color', '$defaultColor') theme('color', '$defaultColor')
&:empty
display: none
&.header-big &.header-big
height: $topBarExpandedHeight height: $topBarExpandedHeight
background-color: rgba(21, 25, 30, 0.7) background-color: rgba(21, 25, 30, 0.7)

View File

@ -20,6 +20,7 @@ shell-server@0.2.1 # Server-side component of the `meteor shell` comm
# OHIF Packages # OHIF Packages
ohif:core ohif:core
ohif:header
ohif:design ohif:design
ohif:cornerstone ohif:cornerstone
ohif:viewerbase ohif:viewerbase
@ -34,6 +35,7 @@ aldeed:simple-schema@1.5.3
stylus@2.513.8 stylus@2.513.8
iron:router iron:router
session@1.1.7 session@1.1.7
u2622:persistent-session@0.4.4
practicalmeteor:loglevel practicalmeteor:loglevel
reactive-dict@1.1.8 reactive-dict@1.1.8
twbs:bootstrap twbs:bootstrap

View File

@ -6,6 +6,7 @@ aldeed:schema-index@1.1.1
aldeed:simple-schema@1.5.3 aldeed:simple-schema@1.5.3
aldeed:template-extension@4.0.0 aldeed:template-extension@4.0.0
allow-deny@1.0.5 allow-deny@1.0.5
amplify@1.0.0
autoupdate@1.3.12 autoupdate@1.3.12
babel-compiler@6.13.0 babel-compiler@6.13.0
babel-runtime@1.0.1 babel-runtime@1.0.1
@ -76,9 +77,12 @@ ohif:cornerstone@0.0.1
ohif:design@0.0.1 ohif:design@0.0.1
ohif:dicom-services@0.0.1 ohif:dicom-services@0.0.1
ohif:hanging-protocols@0.0.1 ohif:hanging-protocols@0.0.1
ohif:header@0.0.1
ohif:log@0.0.1 ohif:log@0.0.1
ohif:metadata@0.0.1 ohif:metadata@0.0.1
ohif:study-list@0.0.1 ohif:study-list@0.0.1
ohif:themes@0.0.1
ohif:themes-common@0.0.1
ohif:viewerbase@0.0.1 ohif:viewerbase@0.0.1
ohif:wadoproxy@0.0.1 ohif:wadoproxy@0.0.1
ordered-dict@1.0.9 ordered-dict@1.0.9
@ -110,6 +114,7 @@ templating-runtime@1.2.15
templating-tools@1.0.5 templating-tools@1.0.5
tracker@1.1.1 tracker@1.1.1
twbs:bootstrap@3.3.6 twbs:bootstrap@3.3.6
u2622:persistent-session@0.4.4
ui@1.0.12 ui@1.0.12
underscore@1.0.10 underscore@1.0.10
url@1.0.11 url@1.0.11

View File

@ -1,10 +1,10 @@
<template name="flexboxLayout"> <template name="flexboxLayout">
<div class="viewerSection"> <div class="viewerSection">
<div class="sidebarMenu sidebar-left {{#if leftSidebarOpen}}sidebar-open{{/if}}"> <div class="sidebarMenu sidebar-left {{#if leftSidebarOpen}}sidebar-open{{/if}}">
{{> studyBrowser (clone this)}} {{>studyBrowser (clone this)}}
</div> </div>
<div class="mainContent {{#if leftSidebarOpen}}sidebar-left-open{{/if}}"> <div class="mainContent {{#if leftSidebarOpen}}sidebar-left-open{{/if}}">
{{> standaloneViewerMain (clone this)}} {{>standaloneViewerMain (clone this)}}
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,5 +1,7 @@
import { Template } from 'meteor/templating';
Template.flexboxLayout.events({ Template.flexboxLayout.events({
'transitionend .sidebarMenu'(event) { 'transitionend .sidebarMenu'(event, instance) {
if (!event.target.classList.contains('sidebarMenu')) { if (!event.target.classList.contains('sidebarMenu')) {
return; return;
} }

View File

@ -1,17 +1,11 @@
<template name="standaloneViewer"> <template name="standaloneViewer">
<div class="topBar noselect"> {{#header}}
<div class="clearfix"> {{#section 'brand'}}
<a target='_blank' <svg class="logo-image">
class="brandSection pull-left" <use xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-ohif-logo"}}></use>
href="http://ohif.org"> </svg>
<svg class="logoImage"> <div class="logo-text">Open Health Imaging Foundation</div>
<use xlink:href={{absoluteUrl "packages/ohif_viewerbase/assets/icons.svg#icon-ohif-logo"}}></use> {{/section}}
</svg> {{/header}}
<div class="logoText"> {{>viewer}}
Open Health Imaging Foundation
</div>
</a>
</div>
</div>
{{> viewer }}
</template> </template>

View File

@ -1,78 +1,24 @@
@import "{ohif:design}/app" @import "{ohif:design}/app"
$expandedHeight = 160px body>.header
.logoImage .brand
display: inline-block
height: 100%
float: left
.topBar
height: $topBarHeight
padding: 10px 10px 0
theme('color', '$textPrimaryColor')
theme('background-color', '$primaryBackgroundColor')
transition(all 0.5s ease)
&>.clearfix
position: relative
.brandSection
height: 30px height: 30px
display: inline-block display: inline-block
text-decoration: none text-decoration: none
.logoImage .logo-image
display: inline-block
fill: transparent
float: left
height: 100%
margin: 0 8px 0 0 margin: 0 8px 0 0
width: 30px width: 30px
.logoText .logo-text
display: inline-block display: inline-block
font-family: $logoFontFamily font-family: $logoFontFamily
font-size: 14px
font-weight: $logoFontWeight font-weight: $logoFontWeight
theme('color', '$textPrimaryColor') theme('color', '$textPrimaryColor')
line-height: 30px line-height: 30px
.studyListLinkSection
theme('border-left', '%s solid $uiBorderColor' % $uiBorderThickness)
margin: 3px 0 0 10px
padding: 0 0 0 10px
.btn
theme('color', '$textSecondaryColor')
cursor: pointer
font-size: 13px
font-weight: 500
line-height: 26px
&:hover
theme('color', '$hoverColor')
&:active
theme('color', '$activeColor')
&.studyList
background-color: rgba(21, 25, 30, 0.7)
height: $expandedHeight
padding-left: $studyListPadding
padding-right: $studyListPadding
.brandSection
height: 100%
width: 80%
line-height: $expandedHeight - 10px
.logoImage
width: 50px
margin: 0 20px 0 0
.logoText
font-size: 30px
.studyListLinkSection
border: none
left: 0
margin: 0
padding: 0
position: absolute
top: 0

View File

@ -1,6 +1,5 @@
<template name="standaloneViewerMain"> <template name="standaloneViewerMain">
<div class="viewerMain"> <div class="viewerMain">
<div id='layoutManagerTarget'> <div id='layoutManagerTarget'></div>
</div>
</div> </div>
</template> </template>

View File

@ -1,3 +1,5 @@
import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
import 'meteor/ohif:viewerbase'; import 'meteor/ohif:viewerbase';

View File

@ -11,7 +11,7 @@
#imageViewerViewports #imageViewerViewports
padding-right: 0 !important // Top remove odd borders from non-existant right Sidebar padding-right: 0 !important // Top remove odd borders from non-existant right Sidebar
.viewportContainer .viewportContainer
theme('border', '%s solid $uiBorderColorDark' % $viewportBorderThickness) theme('border', '%s solid $uiBorderColorDark' % $viewportBorderThickness)
float: left float: left

View File

@ -4,8 +4,7 @@
<div class="pull-left m-t-1"> <div class="pull-left m-t-1">
{{>roundedButtonGroup leftSidebarToggleButtonData}} {{>roundedButtonGroup leftSidebarToggleButtonData}}
</div> </div>
{{> toolbarSectionTools {{>toolbarSectionTools toolbarButtons=toolbarButtons}}
toolbarButtons=toolbarButtons}}
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,3 +1,4 @@
import { Template } from 'meteor/templating';
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
import 'meteor/ohif:viewerbase'; import 'meteor/ohif:viewerbase';
@ -85,7 +86,7 @@ Template.toolbarSection.helpers({
iconClasses: 'fa fa-trash' iconClasses: 'fa fa-trash'
}); });
var buttonData = []; const buttonData = [];
buttonData.push({ buttonData.push({
id: 'zoom', id: 'zoom',
@ -220,7 +221,7 @@ Template.toolbarSection.onRendered(function() {
const disabledToolButtons = states.disabledToolButtons; const disabledToolButtons = states.disabledToolButtons;
const allToolbarButtons = $('#toolbar').find('button'); const allToolbarButtons = $('#toolbar').find('button');
if (disabledToolButtons && disabledToolButtons.length > 0) { if (disabledToolButtons && disabledToolButtons.length > 0) {
for (var i = 0; i < allToolbarButtons.length; i++) { for (let i = 0; i < allToolbarButtons.length; i++) {
const toolbarButton = allToolbarButtons[i]; const toolbarButton = allToolbarButtons[i];
$(toolbarButton).prop('disabled', false); $(toolbarButton).prop('disabled', false);

View File

@ -1,15 +1,15 @@
<template name="viewer"> <template name="viewer">
{{#if Template.subscriptionsReady}} {{#if Template.subscriptionsReady}}
<div class="viewerDialogs"> <div class="viewerDialogs">
{{> cineDialog}} {{>cineDialog}}
{{> layoutChooser }} {{>layoutChooser}}
{{> annotationDialogs }} {{>annotationDialogs}}
</div> </div>
<div id="viewer"> <div id="viewer">
{{> toolbarSection (clone this)}} {{>toolbarSection (clone this)}}
{{> flexboxLayout (clone this)}} {{>flexboxLayout (clone this)}}
</div> </div>
{{else}} {{else}}
{{> loadingText}} {{>loadingText}}
{{/if}} {{/if}}
</template> </template>

View File

@ -69,6 +69,9 @@ Template.viewer.onCreated(() => {
OHIF.viewer.data.activeViewport = 0; OHIF.viewer.data.activeViewport = 0;
} }
// Store the viewer data in session for further user
Session.setPersistent('ViewerData', OHIF.viewer.data);
Session.set('activeViewport', OHIF.viewer.data.activeViewport || 0); Session.set('activeViewport', OHIF.viewer.data.activeViewport || 0);
// @TypeSafeStudies // @TypeSafeStudies

View File

@ -3,15 +3,15 @@ import { OHIF } from 'meteor/ohif:core';
import { cornerstoneWADOImageLoader } from 'meteor/ohif:cornerstone'; import { cornerstoneWADOImageLoader } from 'meteor/ohif:cornerstone';
Meteor.startup(function() { Meteor.startup(function() {
const maxWebWorkers = Math.max(navigator.hardwareConcurrency - 1, 1); const maxWebWorkers = Math.max(navigator.hardwareConcurrency - 1, 1);
const config = { const config = {
maxWebWorkers: maxWebWorkers, maxWebWorkers: maxWebWorkers,
startWebWorkersOnDemand: true, startWebWorkersOnDemand: true,
webWorkerPath : OHIF.utils.absoluteUrl('packages/ohif_cornerstone/public/js/cornerstoneWADOImageLoaderWebWorker.es5.js'), webWorkerPath: OHIF.utils.absoluteUrl('packages/ohif_cornerstone/public/js/cornerstoneWADOImageLoaderWebWorker.es5.js'),
taskConfiguration: { taskConfiguration: {
'decodeTask' : { decodeTask: {
loadCodecsOnStartup : true, loadCodecsOnStartup: true,
initializeCodecsOnStartup: false, initializeCodecsOnStartup: false,
codecsPath: OHIF.utils.absoluteUrl('packages/ohif_cornerstone/public/js/cornerstoneWADOImageLoaderCodecs.es5.js'), codecsPath: OHIF.utils.absoluteUrl('packages/ohif_cornerstone/public/js/cornerstoneWADOImageLoaderCodecs.es5.js'),
usePDFJS: false usePDFJS: false
} }
@ -19,4 +19,4 @@ Meteor.startup(function() {
}; };
cornerstoneWADOImageLoader.webWorkerManager.initialize(config); cornerstoneWADOImageLoader.webWorkerManager.initialize(config);
}); });

View File

@ -161,4 +161,4 @@ cornerstoneWebImageLoader = {};
cornerstone.registerImageLoader('https', loadImage); cornerstone.registerImageLoader('https', loadImage);
cornerstoneWebImageLoader.configure = configure; cornerstoneWebImageLoader.configure = configure;
return cornerstone; return cornerstone;
}($, cornerstone, cornerstoneWebImageLoader)); }($, cornerstone, cornerstoneWebImageLoader));

View File

@ -8,4 +8,4 @@
<meta name="MobileOptimized" content="320"> <meta name="MobileOptimized" content="320">
<meta name="HandheldFriendly" content="True"> <meta name="HandheldFriendly" content="True">
<meta name="apple-mobile-web-app-capable" content="yes"> <meta name="apple-mobile-web-app-capable" content="yes">
</head> </head>

View File

@ -1,3 +0,0 @@
// Create application logger using loglevel
// https://atmospherejs.com/spacejamio/loglevel
log = loglevel.createAppLogger('StandaloneViewer', defaultLevel = 'info');

View File

@ -1,6 +1,10 @@
import { Meteor } from 'meteor/meteor';
import { Router } from 'meteor/iron:router';
import { OHIF } from 'meteor/ohif:core';
if (Meteor.isClient) { if (Meteor.isClient) {
// Disconnect from the Meteor Server since we don't need it // Disconnect from the Meteor Server since we don't need it
console.log('Disconnecting from the Meteor server'); OHIF.log.info('Disconnecting from the Meteor server');
Meteor.disconnect(); Meteor.disconnect();
Router.configure({ Router.configure({
@ -15,31 +19,31 @@ if (Meteor.isClient) {
let id = this.params.id; let id = this.params.id;
if (!id) { if (!id) {
id = 'testId'; id = 'testId';
} }
// Define a request to the server to retrieve the study data // Define a request to the server to retrieve the study data
// as JSON, given an ID that was in the Route // as JSON, given an ID that was in the Route
var oReq = new XMLHttpRequest(); const oReq = new XMLHttpRequest();
// Add event listeners for request failure // Add event listeners for request failure
oReq.addEventListener("error", () => { oReq.addEventListener('error', () => {
console.warn("An error occurred while retrieving the JSON data"); OHIF.log.warn('An error occurred while retrieving the JSON data');
}); });
const self = this; const self = this;
// When the JSON has been returned, parse it into a JavaScript Object // When the JSON has been returned, parse it into a JavaScript Object
// and render the OHIF Viewer with this data // and render the OHIF Viewer with this data
oReq.addEventListener("load", function() { oReq.addEventListener('load', function() {
// Parse the response content // Parse the response content
// https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/responseText
if (!this.responseText) { if (!this.responseText) {
console.warn('Response was undefined'); OHIF.log.warn('Response was undefined');
return; return;
} }
console.log(JSON.stringify(this.responseText, null, 2)); OHIF.log.info(JSON.stringify(this.responseText, null, 2));
const parsed = JSON.parse(this.responseText); const parsed = JSON.parse(this.responseText);
@ -60,8 +64,8 @@ if (Meteor.isClient) {
// Open the Request to the server for the JSON data // Open the Request to the server for the JSON data
// In this case we have a server-side route called /api/ // In this case we have a server-side route called /api/
// which responds to GET requests with the study data // which responds to GET requests with the study data
console.log('Sending Request to: ' + "/api/" + id); OHIF.log.info(`Sending Request to: /api/${id}`);
oReq.open("GET", "/api/" + id); oReq.open('GET', `/api/${id}`);
// Fire the request the server // Fire the request the server
oReq.send(); oReq.send();
@ -70,7 +74,6 @@ if (Meteor.isClient) {
}); });
} }
// This is ONLY for demo purposes. // This is ONLY for demo purposes.
if (Meteor.isServer) { if (Meteor.isServer) {
// You can test this with: // You can test this with:
@ -79,19 +82,19 @@ if (Meteor.isServer) {
// Or by going to: // Or by going to:
// http://localhost:3000/api/testId // http://localhost:3000/api/testId
Router.route('/api/:id', {where: 'server'}).get(function () { Router.route('/api/:id', { where: 'server' }).get(function() {
// "this" is the RouteController instance. // "this" is the RouteController instance.
// "this.response" is the Connect response object // "this.response" is the Connect response object
// "this.request" is the Connect request object // "this.request" is the Connect request object
const id = this.params.id; const id = this.params.id;
// Find the relevant study data from the Collection given the ID // Find the relevant study data from the Collection given the ID
var data = RequestStudies.findOne({transactionId: id}); const data = RequestStudies.findOne({ transactionId: id });
// Set the response headers to return JSON to any server // Set the response headers to return JSON to any server
this.response.setHeader("Content-Type", "application/json"); this.response.setHeader('Content-Type', 'application/json');
this.response.setHeader("Access-Control-Allow-Origin", "*"); this.response.setHeader('Access-Control-Allow-Origin', '*');
this.response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); this.response.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
// Change the response text depending on the available study data // Change the response text depending on the available study data
if (!data) { if (!data) {
@ -104,4 +107,4 @@ if (Meteor.isServer) {
// Finalize the response // Finalize the response
this.response.end(); this.response.end();
}); });
} }

View File

@ -1,3 +1,5 @@
import { Meteor } from 'meteor/meteor';
// Create a Collection to store data // Create a Collection to store data
RequestStudies = new Meteor.Collection('requestStudies'); RequestStudies = new Meteor.Collection('requestStudies');
@ -6,32 +8,32 @@ RequestStudies.remove({});
// Insert our test data // Insert our test data
RequestStudies.insert({ RequestStudies.insert({
'transactionId': 'testId', transactionId: 'testId',
'studies': [{ studies: [{
'studyInstanceUid': '23.23.21.3.32', studyInstanceUid: '23.23.21.3.32',
'patientName': 'Patient Name', patientName: 'Patient Name',
'seriesList': [{ seriesList: [{
'seriesInstanceUid': '1.23.2.32.1.2.1.3.2', seriesInstanceUid: '1.23.2.32.1.2.1.3.2',
'seriesDescription': 'Wikipedia Samples', seriesDescription: 'Wikipedia Samples',
'instances': [ instances: [
{ {
'sopInstanceUid': '1.2.3.2.32.18.8', sopInstanceUid: '1.2.3.2.32.18.8',
'rows': 1, // TODO: Remove all requirement for this rows: 1, // TODO: Remove all requirement for this
'url': 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg' url: 'https://upload.wikimedia.org/wikipedia/en/a/a9/Example.jpg'
}, { }, {
'sopInstanceUid': '1.2.3.2.32.18.9', sopInstanceUid: '1.2.3.2.32.18.9',
'rows': 1, rows: 1,
'url': 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Sample_Floorplan.jpg/800px-Sample_Floorplan.jpg' url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/9/9a/Sample_Floorplan.jpg/800px-Sample_Floorplan.jpg'
} }
] ]
}, { }, {
'seriesInstanceUid': '1.33.2.32.1.2.1.3.2', seriesInstanceUid: '1.33.2.32.1.2.1.3.2',
'seriesDescription': 'JPS-sample', seriesDescription: 'JPS-sample',
'instances': [ instances: [
{ {
'sopInstanceUid': '1.2.3.2.32.18.10', sopInstanceUid: '1.2.3.2.32.18.10',
'rows': 1, rows: 1,
'url': 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/JPS-sample.jpg/800px-JPS-sample.jpg' url: 'https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/JPS-sample.jpg/800px-JPS-sample.jpg'
} }
] ]
}] }]
@ -40,36 +42,34 @@ RequestStudies.insert({
// Insert our test data // Insert our test data
RequestStudies.insert({ RequestStudies.insert({
'transactionId': 'testDICOMs', transactionId: 'testDICOMs',
'studies': [{ studies: [{
'studyInstanceUid': '23.23.21.3.32', studyInstanceUid: '23.23.21.3.32',
'patientName': 'Patient Name', patientName: 'Patient Name',
'seriesList': [{ seriesList: [{
'seriesInstanceUid': '1.23.2.32.1.2.1.3.2', seriesInstanceUid: '1.23.2.32.1.2.1.3.2',
'seriesDescription': 'T-1', seriesDescription: 'T-1',
'instances': [ instances: [
{ {
'sopInstanceUid': '1.2.3.2.32.18.8', sopInstanceUid: '1.2.3.2.32.18.8',
'rows': 1, // TODO: Remove all requirement for this rows: 1, // TODO: Remove all requirement for this
'url': 'dicomweb://cornerstonetech.org/images/ClearCanvas/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.80.dcm' url: 'dicomweb://cornerstonetech.org/images/ClearCanvas/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.80.dcm'
}, { }, {
'sopInstanceUid': '1.2.3.2.32.18.9', sopInstanceUid: '1.2.3.2.32.18.9',
'rows': 1, rows: 1,
'url': 'dicomweb://cornerstonetech.org/images/ClearCanvas/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.81.dcm' url: 'dicomweb://cornerstonetech.org/images/ClearCanvas/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.81.dcm'
} }
] ]
}, { }, {
'seriesInstanceUid': '1.33.2.32.1.2.1.3.2', seriesInstanceUid: '1.33.2.32.1.2.1.3.2',
'seriesDescription': 'COR T-1', seriesDescription: 'COR T-1',
'instances': [ instances: [
{ {
'sopInstanceUid': '1.2.3.2.32.18.10', sopInstanceUid: '1.2.3.2.32.18.10',
'rows': 1, rows: 1,
'url': 'dicomweb://cornerstonetech.org/images/ClearCanvas/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.136.dcm' url: 'dicomweb://cornerstonetech.org/images/ClearCanvas/MRStudy/1.2.840.113619.2.5.1762583153.215519.978957063.136.dcm'
} }
] ]
}] }]
}] }]
}); });