wip on react transition 8
This commit is contained in:
parent
9ae5dd25ce
commit
71b49e6766
@ -5,6 +5,13 @@ import { Router } from 'meteor/clinical:router';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
import { createStore } from 'redux';
|
||||
|
||||
const store = createStore(OHIF.viewerbase.redux.combinedReducer);
|
||||
|
||||
// TODO[react] Use a provider when the whole tree is React
|
||||
window.store = store;
|
||||
|
||||
Template.ohifViewer.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
instance.headerClasses = new ReactiveVar('');
|
||||
|
||||
@ -38,13 +38,10 @@ const initHangingProtocol = () => {
|
||||
HP.setEngine(ProtocolEngine);
|
||||
|
||||
Session.set('ViewerReady', true);
|
||||
|
||||
Session.set('activeViewport', 0);
|
||||
});
|
||||
};
|
||||
|
||||
Meteor.startup(() => {
|
||||
Session.setDefault('activeViewport', false);
|
||||
Session.setDefault('leftSidebar', false);
|
||||
Session.setDefault('rightSidebar', false);
|
||||
|
||||
@ -80,7 +77,7 @@ Meteor.startup(() => {
|
||||
cornerstone.metaData.addProvider(metadataProvider.provider.bind(metadataProvider));
|
||||
|
||||
// Instanciate viewer plugins
|
||||
OHIF.viewer.measurementTable = new MeasurementTable();
|
||||
OHIF.viewer.measurementTable = new MeasurementTable();
|
||||
});
|
||||
|
||||
Template.viewer.onCreated(() => {
|
||||
@ -112,8 +109,6 @@ Template.viewer.onCreated(() => {
|
||||
// Store the viewer data in session for further user
|
||||
Session.setPersistent('ViewerData', OHIF.viewer.data);
|
||||
|
||||
Session.set('activeViewport', OHIF.viewer.data.activeViewport || 0);
|
||||
|
||||
// @TypeSafeStudies
|
||||
// Clears OHIF.viewer.Studies collection
|
||||
OHIF.viewer.Studies.removeAll();
|
||||
@ -163,7 +158,7 @@ Template.viewer.onRendered(function() {
|
||||
}
|
||||
});
|
||||
|
||||
// Call Viewer plugins onRendered functions
|
||||
// Call Viewer plugins onRendered functions
|
||||
if(typeof OHIF.viewer.measurementTable.onRendered === 'function') {
|
||||
OHIF.viewer.measurementTable.onRendered(instance);
|
||||
}
|
||||
|
||||
@ -151,7 +151,7 @@ Template.protocolEditor.helpers({
|
||||
return ProtocolEngine.getCurrentStageModel();
|
||||
},
|
||||
activeViewportUndefined() {
|
||||
const viewportIndex = Session.get('activeViewport');
|
||||
const viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
return (viewportIndex === undefined);
|
||||
}
|
||||
});
|
||||
|
||||
@ -318,7 +318,7 @@ Template.ruleEntryDialog.events({
|
||||
rule.constraint = constraint;
|
||||
|
||||
// Instruct the Protocol Engine to update the Layout Manager with new data
|
||||
var viewportIndex = Session.get('activeViewport');
|
||||
var viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
ProtocolEngine.updateViewports(viewportIndex);
|
||||
|
||||
// Close the dialog
|
||||
|
||||
@ -6,7 +6,7 @@ Template.ruleTable.helpers({
|
||||
*/
|
||||
rulePassed: function() {
|
||||
// Retrieve the latest match details given the active viewport index
|
||||
var viewportIndex = Session.get('activeViewport');
|
||||
var viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
var details = ProtocolEngine.matchDetails[viewportIndex];
|
||||
|
||||
// If no match was found, stop here
|
||||
@ -92,7 +92,7 @@ Template.ruleTable.events({
|
||||
}
|
||||
|
||||
// Instruct the Protocol Engine to update the Layout Manager with new data
|
||||
var viewportIndex = Session.get('activeViewport');
|
||||
var viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
ProtocolEngine.updateViewports(viewportIndex);
|
||||
},
|
||||
/**
|
||||
@ -108,7 +108,7 @@ Template.ruleTable.events({
|
||||
rule.weight = $(event.currentTarget).val();
|
||||
|
||||
// Instruct the Protocol Engine to update the Layout Manager with new data
|
||||
var viewportIndex = Session.get('activeViewport');
|
||||
var viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
ProtocolEngine.updateViewports(viewportIndex);
|
||||
},
|
||||
/**
|
||||
@ -124,7 +124,7 @@ Template.ruleTable.events({
|
||||
rule.required = $(event.currentTarget).prop('checked');
|
||||
|
||||
// Instruct the Protocol Engine to update the Layout Manager with new data
|
||||
var viewportIndex = Session.get('activeViewport');
|
||||
var viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
ProtocolEngine.updateViewports(viewportIndex);
|
||||
}
|
||||
});
|
||||
|
||||
@ -165,7 +165,7 @@ Template.settingEntryDialog.events({
|
||||
viewport.viewportSettings[viewportSetting.id] = viewportSetting.value;
|
||||
|
||||
// Instruct the Protocol Engine to update the Layout Manager with new data
|
||||
var viewportIndex = Session.get('activeViewport');
|
||||
var viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
ProtocolEngine.updateViewports(viewportIndex);
|
||||
|
||||
// Close the dialog
|
||||
@ -176,7 +176,7 @@ Template.settingEntryDialog.events({
|
||||
*/
|
||||
'click #cancel': function() {
|
||||
var dialog = Template.settingEntryDialog.dialog;
|
||||
closeHandler(dialog);
|
||||
closeHandler(dialog);
|
||||
},
|
||||
/**
|
||||
* Allow Esc keydown events to close the dialog
|
||||
|
||||
@ -37,7 +37,7 @@ Template.settingsTable.events({
|
||||
delete viewport.viewportSettings[setting.key];
|
||||
|
||||
// Instruct the Protocol Engine to update the Layout Manager with new data
|
||||
var viewportIndex = Session.get('activeViewport');
|
||||
var viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
ProtocolEngine.updateViewports(viewportIndex);
|
||||
}
|
||||
});
|
||||
@ -54,4 +54,4 @@ Template.settingsTable.helpers({
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@ -11,7 +11,7 @@ getActiveViewportModel = function() {
|
||||
var stage = ProtocolEngine.getCurrentStageModel();
|
||||
|
||||
// Retrieve the index of the active viewport
|
||||
var activeViewport = Session.get('activeViewport');
|
||||
var activeViewport = window.store.getState().viewports.activeViewport;
|
||||
|
||||
// If the active viewport index is outside the bounds of the
|
||||
// number of Viewports defined for this Stage, stop here
|
||||
|
||||
@ -8,7 +8,7 @@ OHIF.lesiontracker.pixelSpacingAutorunCheck = () => {
|
||||
const $oncologyTools = $('button#lesion, button#nonTarget');
|
||||
|
||||
// TODO: Set activeViewport for empty viewport element
|
||||
const activeViewportIndex = Session.get('activeViewport');
|
||||
const activeViewportIndex = window.store.getState().viewports.activeViewport;
|
||||
if (activeViewportIndex === undefined) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -7,7 +7,7 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
* @returns {Object} - Timepoint data for the active viewport
|
||||
*/
|
||||
OHIF.measurements.getActiveTimepoint = () => {
|
||||
const activeViewportIndex = Session.get('activeViewport');
|
||||
const activeViewportIndex = window.store.getState().viewports.activeViewport;
|
||||
const { studyInstanceUid } = OHIF.viewerbase.layoutManager.viewportData[activeViewportIndex];
|
||||
return OHIF.viewer.timepointApi.study(studyInstanceUid)[0];
|
||||
};
|
||||
|
||||
@ -48,7 +48,7 @@ Template.thumbnailEntry.events({
|
||||
// Get the viewport index
|
||||
let { viewportIndex } = instance.data;
|
||||
if (_.isUndefined(viewportIndex)) {
|
||||
viewportIndex = Session.get('activeViewport') || 0;
|
||||
viewportIndex = window.store.getState().viewports.activeViewport || 0;
|
||||
}
|
||||
|
||||
// Rerender the viewport using the clicked thumbnail data
|
||||
@ -61,7 +61,7 @@ Template.thumbnailEntry.events({
|
||||
|
||||
// Get the active viewport index and total number of viewports...
|
||||
const viewportCount = OHIF.viewerbase.layoutManager.getNumberOfViewports();
|
||||
let viewportIndex = Session.get('activeViewport') || 0;
|
||||
let viewportIndex = window.store.getState().viewports.activeViewport || 0;
|
||||
if (viewportIndex >= viewportCount) {
|
||||
viewportIndex = viewportCount > 0 ? viewportCount - 1 : 0;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,10 @@
|
||||
.CornerstoneViewport
|
||||
width: 100%
|
||||
height: 100%
|
||||
|
||||
.viewport-element
|
||||
width: 100%
|
||||
height: 100%
|
||||
position: relative;
|
||||
background-color: black
|
||||
|
||||
|
||||
@ -413,7 +413,7 @@ const loadDisplaySetIntoViewport = (data, templateData) => {
|
||||
// Check if the current active viewport in the Meteor Session
|
||||
// Is the same as the viewport in which the activation event was fired.
|
||||
// If it was, no changes are necessary, so stop here.
|
||||
const activeViewportIndex = Session.get('activeViewport');
|
||||
const activeViewportIndex = window.store.getState().viewports.activeViewport;
|
||||
if (viewportIndex === activeViewportIndex) return;
|
||||
|
||||
$element.focus();
|
||||
@ -473,7 +473,7 @@ const loadDisplaySetIntoViewport = (data, templateData) => {
|
||||
// Set the active viewport based on the Session variable
|
||||
// This is done to ensure that the active element has the current
|
||||
// focus, so that keyboard events are triggered.
|
||||
if (viewportIndex === Session.get('activeViewport')) {
|
||||
if (viewportIndex === window.store.getState().viewports.activeViewport) {
|
||||
const viewportContainer = $element.parents('.viewportContainer');
|
||||
|
||||
setActiveViewport(viewportContainer);
|
||||
@ -563,7 +563,7 @@ Template.imageViewerViewport.onRendered(function() {
|
||||
|
||||
// Get the current active viewport index, if this viewport has the same index,
|
||||
// add the CSS 'active' class to highlight this viewport.
|
||||
const activeViewport = Session.get('activeViewport');
|
||||
const activeViewport = window.store.getState().viewports.activeViewport;
|
||||
|
||||
// Focus the viewport if it's the active one
|
||||
if (templateData.viewportIndex === activeViewport) {
|
||||
|
||||
@ -2,42 +2,129 @@ import { Component } from 'react';
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import './ViewportOverlay.styl';
|
||||
import { viewportOverlayUtils } from '../../../lib/viewportOverlayUtils';
|
||||
import { helpers } from '../../../lib/helpers/index.js';
|
||||
const { formatPN, formatDA, formatNumberPrecision, formatTM, isValidNumber} = helpers;
|
||||
|
||||
function getCompression(imageId) {
|
||||
const instance = cornerstone.metaData.get('instance', imageId);
|
||||
if (!instance) {
|
||||
return '';
|
||||
}
|
||||
|
||||
if (instance.lossyImageCompression === '01' &&
|
||||
instance.lossyImageCompressionRatio !== '') {
|
||||
const compressionMethod = instance.lossyImageCompressionMethod || 'Lossy: ';
|
||||
const compressionRatio = formatNumberPrecision(instance.lossyImageCompressionRatio, 2);
|
||||
return compressionMethod + compressionRatio + ' : 1';
|
||||
}
|
||||
|
||||
return 'Lossless / Uncompressed';
|
||||
}
|
||||
|
||||
function getImageDimensions(imageId) {
|
||||
const instance = cornerstone.metaData.get('instance', imageId)
|
||||
if (!instance) {
|
||||
return '';
|
||||
}
|
||||
|
||||
return `${instance.columns} x ${instance.rows}`;
|
||||
}
|
||||
|
||||
class ViewportOverlay extends Component {
|
||||
render() {
|
||||
const scale = Math.round(this.props.viewport.scale * 100) / 100;
|
||||
const zoom = this.props.viewport.scale * 100;
|
||||
const imageId = this.props.imageId;
|
||||
|
||||
/*const patientId = cornerstone.metaData.get('00100020', imageId);
|
||||
const studyDate = cornerstone.metaData.get('00080020', imageId);
|
||||
const collection = cornerstone.metaData.get('00131010', imageId);
|
||||
const studyDescription = cornerstone.metaData.get('00081030', imageId);*/
|
||||
const patientMetadata = cornerstone.metaData.get('patient', imageId);
|
||||
const studyMetadata = cornerstone.metaData.get('study', imageId);
|
||||
const seriesMetadata = cornerstone.metaData.get('series', imageId);
|
||||
const instanceMetadata = cornerstone.metaData.get('instance', imageId);
|
||||
|
||||
const windowWidth = Math.round(this.props.viewport.voi.windowWidth);
|
||||
const windowCenter = Math.round(this.props.viewport.voi.windowCenter);
|
||||
const imagesLeft =
|
||||
this.props.stack.imageIds.length - this.props.numImagesLoaded;
|
||||
const patientName = patientMetadata.name;
|
||||
const patientId = patientMetadata.id;;
|
||||
const { studyDate, studyTime, studyDescription } = studyMetadata;
|
||||
const { seriesNumber, seriesDescription } = seriesMetadata;
|
||||
const { instanceNumber, frameTime, thickness, spacingBetweenSlices, sliceLocation } = instanceMetadata;
|
||||
const frameRate = formatNumberPrecision(1000 / frameTime, 1);
|
||||
const compression = getCompression(imageId);
|
||||
const windowWidth = this.props.viewport.voi.windowWidth || 0;
|
||||
const windowCenter = this.props.viewport.voi.windowCenter || 0;
|
||||
const wwwc = `W: ${windowWidth.toFixed(0)} L: ${windowCenter.toFixed(0)}`;
|
||||
const imageIndex = this.props.stack.imageIds.indexOf(this.props.imageId) + 1;
|
||||
const numImages = this.props.stack.imageIds.length;
|
||||
const imageDimensions = getImageDimensions(imageId);
|
||||
|
||||
const normal = (<>
|
||||
<div className="top-left overlay-element">
|
||||
<div>{formatPN(patientName)}</div>
|
||||
<div>{patientId}</div>
|
||||
</div>
|
||||
<div className="top-right overlay-element">
|
||||
<div>{studyDescription}</div>
|
||||
<div>{formatDA(studyDate)} {formatTM(studyTime)}</div>
|
||||
</div>
|
||||
<div className="bottom-right overlay-element">
|
||||
<div>Zoom: {formatNumberPrecision(zoom,0)}%</div>
|
||||
<div className="compressionIndicator">{compression}</div>
|
||||
<div>{wwwc}</div>
|
||||
</div>
|
||||
<div className="bottom-left overlay-element">
|
||||
<div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
|
||||
<div>{numImages > 1 ? `Img: ${instanceNumber} ${imageIndex}/${numImages}` : ''}</div>
|
||||
<div>{frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}
|
||||
<div>{imageDimensions}</div>
|
||||
<div>
|
||||
<span>{isValidNumber(sliceLocation) ? `Loc: ${formatNumberPrecision(sliceLocation, 2)} mm` : ''}</span>
|
||||
<span>{thickness ? `Thick: ${formatNumberPrecision(thickness, 2)} mm` : ''}</span>
|
||||
<span>{spacingBetweenSlices ? `Spacing: ${formatNumberPrecision(spacingBetweenSlices, 2)} mm` : ''}</span>
|
||||
</div>
|
||||
<div>{seriesDescription}</div>
|
||||
</div>
|
||||
</div>
|
||||
</>);
|
||||
|
||||
const rightOnly = (<>
|
||||
<div className="top-right overlay-element">
|
||||
<div>{formatPN(patientName)}</div>
|
||||
<div>{patientId}</div>
|
||||
<div>{studyDescription}</div>
|
||||
<div>{formatDA(studyDate)} {formatTM(studyTime)}</div>
|
||||
</div>
|
||||
<div className="bottom-right overlay-element">
|
||||
<div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
|
||||
<div>{numImages > 1 ? `Img: ${instanceNumber} ${imageIndex}/${numImages}` : ''}</div>
|
||||
<div>{frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}</div>
|
||||
<div>{imageDimensions}</div>
|
||||
<div>{seriesDescription}</div>
|
||||
<div>Zoom: ${formatNumberPrecision(zoom, 0)}%</div>
|
||||
<div className="compressionIndicator">{compression}</div>
|
||||
<div>{wwwc}</div>
|
||||
</div>
|
||||
</>);
|
||||
|
||||
const leftOnly = (<>
|
||||
<div className="top-left overlay-element">
|
||||
<div>{formatPN(patientName)}</div>
|
||||
<div>{patientId}</div>
|
||||
<div>{studyDescription}</div>
|
||||
<div>{formatDA(studyDate)} {formatTM(studyTime)}</div>
|
||||
</div>
|
||||
<div className="bottom-left overlay-element">
|
||||
<div>{seriesNumber >= 0 ? `Ser: ${seriesNumber}` : ''}</div>
|
||||
<div>{numImages > 1 ? `Img: ${instanceNumber} ${imageIndex}/${numImages}` : ''}</div>
|
||||
<div>{frameRate >= 0 ? `${formatNumberPrecision(frameRate, 2)} FPS` : ''}</div>
|
||||
<div>{imageDimensions}</div>
|
||||
<div>{seriesDescription}</div>
|
||||
<div>Zoom: ${formatNumberPrecision(zoom, 0)}%</div>
|
||||
<div className="compressionIndicator">{compression}</div>
|
||||
<div>{wwwc}</div>
|
||||
</div>
|
||||
</>);
|
||||
|
||||
return (
|
||||
<div className="ViewportOverlay">
|
||||
<div className="top-left overlay-element">
|
||||
<span>{this.props.patientId}</span>
|
||||
<span>{this.props.studyDate}</span>
|
||||
<span>{this.props.studyDescription}</span>
|
||||
<span>
|
||||
{imagesLeft > 0 ? `${imagesLeft} images remaining...` : ''}
|
||||
</span>
|
||||
</div>
|
||||
<div className="bottom-left overlay-element">Zoom: {scale}</div>
|
||||
<div className="bottom-right overlay-element">
|
||||
<span>
|
||||
WW/WC: {windowWidth} / {windowCenter}
|
||||
</span>
|
||||
<span>
|
||||
Image: {this.props.stack.currentImageIdIndex + 1} /{' '}
|
||||
{this.props.stack.imageIds.length}
|
||||
</span>
|
||||
</div>
|
||||
<div className='ViewportOverlay'>
|
||||
{normal}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@ -2,10 +2,10 @@
|
||||
|
||||
$viewportTagPadding = 20px
|
||||
|
||||
.imageViewerViewport.empty ~ .imageViewerViewportOverlay
|
||||
.imageViewerViewport.empty ~ .ViewportOverlay
|
||||
display: none
|
||||
|
||||
.imageViewerViewportOverlay
|
||||
.ViewportOverlay
|
||||
theme('color', '$textSecondaryColor')
|
||||
|
||||
.overlay-element
|
||||
|
||||
@ -88,7 +88,7 @@ Template.cineDialog.onCreated(() => {
|
||||
|
||||
// Run this computation every time the active viewport is changed
|
||||
instance.autorun(() => {
|
||||
Session.get('activeViewport');
|
||||
window.store.getState().viewports.activeViewport;
|
||||
|
||||
Tracker.afterFlush(() => {
|
||||
// Get the active viewportElement
|
||||
|
||||
@ -100,7 +100,7 @@ Template.toolbarSectionButton.helpers({
|
||||
},
|
||||
|
||||
disableButton() {
|
||||
Session.get('activeViewport');
|
||||
window.store.getState().viewports.activeViewport;
|
||||
Session.get('LayoutManagerUpdated');
|
||||
const instance = Template.instance();
|
||||
const isCommandDisabled = OHIF.commands.isDisabled(instance.data.id);
|
||||
|
||||
@ -248,3 +248,6 @@ Viewerbase.StackImagePositionOffsetSynchronizer = StackImagePositionOffsetSynchr
|
||||
// StudyMetadataSource
|
||||
import { StudyMetadataSource } from './lib/classes/StudyMetadataSource';
|
||||
Viewerbase.StudyMetadataSource = StudyMetadataSource;
|
||||
|
||||
import redux from './lib/redux/';
|
||||
Viewerbase.redux = redux;
|
||||
|
||||
@ -416,7 +416,7 @@ export class LayoutManager {
|
||||
const isSequenced = this.isDisplaySetsSequenced(sequenceMap);
|
||||
|
||||
// Get Active Viewport Index if isMultiple is false
|
||||
const activeViewportIndex = !isMultiple ? Session.get('activeViewport') : null;
|
||||
const activeViewportIndex = !isMultiple ? window.store.getState().viewports.activeViewport : null;
|
||||
|
||||
// Check if is next and looping is blocked
|
||||
if (isNext && !allowLooping) {
|
||||
@ -649,7 +649,7 @@ export class LayoutManager {
|
||||
this.moveMultipleViewportDisplaySets(isNext);
|
||||
} else {
|
||||
// Get the selected viewport index
|
||||
const viewportIndex = Session.get('activeViewport');
|
||||
const viewportIndex = window.store.getState().viewports.activeViewport;
|
||||
|
||||
// Move display sets on a single viewport
|
||||
this.moveSingleViewportDisplaySets(viewportIndex, isNext);
|
||||
|
||||
@ -86,7 +86,7 @@ export class StackImagePositionOffsetSynchronizer {
|
||||
}
|
||||
|
||||
getActiveViewportElement() {
|
||||
const viewportIndex = Session.get('activeViewport') || 0;
|
||||
const viewportIndex = window.store.getState().viewports.activeViewport || 0;
|
||||
return $('.imageViewerViewport').get(viewportIndex);
|
||||
}
|
||||
|
||||
|
||||
@ -86,7 +86,7 @@ export class StudyPrefetcher {
|
||||
// Make sure there is a stack to fetch
|
||||
if (this.hasStack(element)) {
|
||||
// Check if this is a clip or not
|
||||
const activeViewportIndex = Session.get('activeViewport');
|
||||
const activeViewportIndex = window.store.getState().viewports.activeViewport;
|
||||
const displaySetInstanceUid = OHIF.viewer.data.loadedSeriesData[activeViewportIndex].displaySetInstanceUid;
|
||||
|
||||
const stack = StackManager.findStack(displaySetInstanceUid);
|
||||
|
||||
@ -1,10 +1,14 @@
|
||||
import { Blaze } from 'meteor/blaze';
|
||||
|
||||
function formatNumberPrecision(number, precision) {
|
||||
if (number !== null) {
|
||||
return parseFloat(number).toFixed(precision);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A global Blaze UI helper to format a float value to a specified precision
|
||||
*/
|
||||
Blaze.registerHelper('formatNumberPrecision', function(context, precision) {
|
||||
if (context != null) {
|
||||
return parseFloat(context).toFixed(precision);
|
||||
}
|
||||
});
|
||||
Blaze.registerHelper('formatNumberPrecision', formatNumberPrecision);
|
||||
|
||||
export default formatNumberPrecision;
|
||||
|
||||
@ -6,6 +6,7 @@ import { isTouchDevice } from './isTouchDevice';
|
||||
import { formatPN } from './formatPN';
|
||||
import { formatDA } from './formatDA';
|
||||
import { formatTM } from './formatTM';
|
||||
import isValidNumber from './isValidNumber';
|
||||
|
||||
/**
|
||||
* Helpers with side effects only...
|
||||
@ -13,7 +14,7 @@ import { formatTM } from './formatTM';
|
||||
|
||||
import './formatJSDate';
|
||||
import './jsDateFromNow';
|
||||
import './formatNumberPrecision';
|
||||
import formatNumberPrecision from './formatNumberPrecision';
|
||||
import './inc';
|
||||
import './isDisplaySetActive';
|
||||
import './getUsername';
|
||||
@ -33,7 +34,9 @@ const helpers = {
|
||||
isTouchDevice,
|
||||
formatPN,
|
||||
formatDA,
|
||||
formatTM
|
||||
formatTM,
|
||||
formatNumberPrecision,
|
||||
isValidNumber,
|
||||
};
|
||||
|
||||
export { helpers };
|
||||
|
||||
@ -0,0 +1,3 @@
|
||||
export default function isValidNumber(value) {
|
||||
return typeof value === 'number' && !isNaN(value);
|
||||
}
|
||||
@ -92,7 +92,7 @@ Meteor.startup(function() {
|
||||
|
||||
// Create a function that returns true if the active viewport is empty
|
||||
const isActiveViewportEmpty = () => {
|
||||
const activeViewport = Session.get('activeViewport') || 0;
|
||||
const activeViewport = window.store.getState().viewports.activeViewport || 0;
|
||||
return $('.imageViewerViewport').eq(activeViewport).hasClass('empty');
|
||||
};
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@ import { setActiveViewport } from './setActiveViewport';
|
||||
|
||||
const loadPreviousActivePanel = () => {
|
||||
OHIF.log.info('nextActivePanel');
|
||||
let currentIndex = Session.get('activeViewport');
|
||||
let currentIndex = window.store.getState().viewports.activeViewport;
|
||||
currentIndex--;
|
||||
|
||||
const $viewports = $('.viewportContainer');
|
||||
@ -24,7 +24,7 @@ const loadPreviousActivePanel = () => {
|
||||
|
||||
const loadNextActivePanel = () => {
|
||||
OHIF.log.info('nextActivePanel');
|
||||
let currentIndex = Session.get('activeViewport');
|
||||
let currentIndex = window.store.getState().viewports.activeViewport;
|
||||
currentIndex++;
|
||||
|
||||
const $viewports = $('.viewportContainer');
|
||||
|
||||
9
Packages/ohif-viewerbase/client/lib/redux/actions.js
Normal file
9
Packages/ohif-viewerbase/client/lib/redux/actions.js
Normal file
@ -0,0 +1,9 @@
|
||||
export const setToolActive = tool => ({
|
||||
type: 'SET_TOOL_ACTIVE',
|
||||
tool
|
||||
});
|
||||
|
||||
export const setViewportActive = viewportIndex => ({
|
||||
type: 'SET_VIEWPORT_ACTIVE',
|
||||
viewportIndex
|
||||
});
|
||||
8
Packages/ohif-viewerbase/client/lib/redux/index.js
Normal file
8
Packages/ohif-viewerbase/client/lib/redux/index.js
Normal file
@ -0,0 +1,8 @@
|
||||
import './actions.js';
|
||||
import combinedReducer from './reducers';
|
||||
|
||||
const redux = {
|
||||
combinedReducer
|
||||
};
|
||||
|
||||
export default redux;
|
||||
10
Packages/ohif-viewerbase/client/lib/redux/reducers/index.js
Normal file
10
Packages/ohif-viewerbase/client/lib/redux/reducers/index.js
Normal file
@ -0,0 +1,10 @@
|
||||
import { combineReducers } from 'redux';
|
||||
import tools from './tools.js';
|
||||
import viewports from './viewports.js';
|
||||
|
||||
const combinedReducer = combineReducers({
|
||||
tools,
|
||||
viewports
|
||||
});
|
||||
|
||||
export default combinedReducer;
|
||||
101
Packages/ohif-viewerbase/client/lib/redux/reducers/tools.js
Normal file
101
Packages/ohif-viewerbase/client/lib/redux/reducers/tools.js
Normal file
@ -0,0 +1,101 @@
|
||||
const defaultButtons = [
|
||||
{
|
||||
command: 'Pan',
|
||||
type: 'tool',
|
||||
text: 'Pan',
|
||||
svgUrl: '/icons.svg#icon-tools-pan',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'Zoom',
|
||||
type: 'tool',
|
||||
text: 'Zoom',
|
||||
svgUrl: '/icons.svg#icon-tools-zoom',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'Bidirectional',
|
||||
type: 'tool',
|
||||
text: 'Bidirectional',
|
||||
svgUrl: '/icons.svg#icon-tools-measure-target',
|
||||
active: true
|
||||
},
|
||||
{
|
||||
command: 'StackScroll',
|
||||
type: 'tool',
|
||||
text: 'Stack Scroll',
|
||||
svgUrl: '/icons.svg#icon-tools-stack-scroll',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'reset',
|
||||
type: 'command',
|
||||
text: 'Reset',
|
||||
svgUrl: '/icons.svg#icon-tools-reset',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'Wwwc',
|
||||
type: 'tool',
|
||||
text: 'Manual',
|
||||
svgUrl: '/icons.svg#icon-tools-levels',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'setWLPresetSoftTissue',
|
||||
type: 'command',
|
||||
text: 'Soft Tissue',
|
||||
svgUrl: '/icons.svg#icon-wl-soft-tissue',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'setWLPresetLung',
|
||||
type: 'command',
|
||||
text: 'Lung',
|
||||
svgUrl: '/icons.svg#icon-wl-lung',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'setWLPresetLiver',
|
||||
type: 'command',
|
||||
text: 'Liver',
|
||||
svgUrl: '/icons.svg#icon-wl-liver',
|
||||
active: false
|
||||
},
|
||||
{
|
||||
command: 'setWLPresetBrain',
|
||||
type: 'command',
|
||||
text: 'Brain',
|
||||
svgUrl: '/icons.svg#icon-wl-brain',
|
||||
active: false
|
||||
}
|
||||
];
|
||||
|
||||
const tools = (state = { buttons: defaultButtons }, action) => {
|
||||
switch (action.type) {
|
||||
case 'SET_TOOL_ACTIVE':
|
||||
const item = state.buttons.find(button => button.command === action.tool);
|
||||
|
||||
let buttons = [];
|
||||
|
||||
if (item.type === 'tool') {
|
||||
buttons = state.buttons.map(button => {
|
||||
if (button.command === action.tool) {
|
||||
button.active = true;
|
||||
} else if (button.type === 'tool') {
|
||||
button.active = false;
|
||||
}
|
||||
|
||||
return button;
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
buttons
|
||||
};
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default tools;
|
||||
@ -0,0 +1,15 @@
|
||||
const defaultState = {
|
||||
activeViewport: 0
|
||||
}
|
||||
|
||||
const viewports = (state = defaultState, action) => {
|
||||
console.warn(action);
|
||||
switch (action.type) {
|
||||
case 'SET_VIEWPORT_ACTIVE':
|
||||
return Object.assign({}, state, { activeViewport: action.viewportIndex });
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
};
|
||||
|
||||
export default viewports;
|
||||
@ -30,9 +30,12 @@ export function setActiveViewport(element) {
|
||||
$element.trigger('OHIFBeforeActivateViewport');
|
||||
}
|
||||
|
||||
// When an OHIFActivateViewport event is fired, update the Meteor Session
|
||||
// When an OHIFActivateViewport event is fired, update the Redux state
|
||||
// with the viewport index that it was fired from.
|
||||
Session.set('activeViewport', viewportIndex);
|
||||
window.store.dispatch({
|
||||
type: 'SET_VIEWPORT_ACTIVE',
|
||||
viewportIndex
|
||||
});
|
||||
|
||||
// Finally, enable stack prefetching and hide the reference lines from
|
||||
// the newly activated viewport that has a canvas
|
||||
|
||||
@ -12,7 +12,7 @@ const setFocusToActiveViewport = () => {
|
||||
const viewports = $('.imageViewerViewport');
|
||||
|
||||
// Get the current active viewport index from Session
|
||||
const activeViewportIndex = Session.get('activeViewport');
|
||||
const activeViewportIndex = window.store.getState().viewports.activeViewport;
|
||||
|
||||
// Find the div from the list of viewports
|
||||
const activeViewport = viewports.eq(activeViewportIndex);
|
||||
@ -21,4 +21,4 @@ const setFocusToActiveViewport = () => {
|
||||
activeViewport.focus();
|
||||
};
|
||||
|
||||
export { setFocusToActiveViewport };
|
||||
export { setFocusToActiveViewport };
|
||||
|
||||
@ -30,7 +30,7 @@ const getEnabledElement = element => {
|
||||
* @return {DOMElement} DOMElement of the current active viewport
|
||||
*/
|
||||
const getActiveViewportElement = () => {
|
||||
const viewportIndex = Session.get('activeViewport') || 0;
|
||||
const viewportIndex = window.store.getState().viewports.activeViewport || 0;
|
||||
return $('.imageViewerViewport').get(viewportIndex);
|
||||
};
|
||||
|
||||
@ -274,7 +274,7 @@ const isPlaying = () => {
|
||||
// Check if a study has multiple frames
|
||||
const hasMultipleFrames = () => {
|
||||
// Its called everytime active viewport and/or layout change
|
||||
Session.get('activeViewport');
|
||||
window.store.getState().viewports.activeViewport;
|
||||
Session.get('LayoutManagerUpdated');
|
||||
|
||||
const activeViewport = getActiveViewportElement();
|
||||
@ -326,7 +326,7 @@ const isStackScrollLinkingDisabled = () => {
|
||||
let linkableViewportsCount = 0;
|
||||
|
||||
// Its called everytime active viewport and/or layout change
|
||||
Session.get('activeViewport');
|
||||
window.store.getState().viewports.activeViewport;
|
||||
Session.get('LayoutManagerUpdated');
|
||||
|
||||
const synchronizer = OHIF.viewer.stackImagePositionOffsetSynchronizer;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user