ohif-viewer/Packages/ohif-hanging-protocols/client/components/protocolEditor/protocolEditor.js
Evren Ozkan 2e06b652b3 OHIF-152 Fix hanging protocol issues
- Replace “OHIF.viewerbase.showConfirmDialog” with “Viewerbase.dialogUtils.showConfirmDialog”
- Check the length of the filtered images (instead of checking whether it is undefined, because the filtered images is returned as an empty array if not found) to find the display set in protocolEngine
2017-02-01 19:14:41 -05:00

388 lines
13 KiB
JavaScript

import { Meteor } from 'meteor/meteor';
import { Template } from 'meteor/templating';
import { Session } from 'meteor/session';
import { Random } from 'meteor/random';
import { $ } from 'meteor/jquery';
import { OHIF } from 'meteor/ohif:core';
import { Viewerbase } from 'meteor/ohif:viewerbase';
import 'meteor/ohif:viewerbase';
/**
* Updates the Hanging Protocol Select2 Input
*/
function updateProtocolSelect() {
if (!ProtocolEngine) {
return;
}
// Loop through the available hanging protocols
// to create an array with the protocols that includes
// a property labelled 'text', so that Select2 has something
// to display
var protocolsSelect2Data = HP.ProtocolStore.getProtocol().map(function(protocol) {
return {
id: protocol.id,
text: protocol.name
};
});
// Select the Protocol select DOM element
var protocolSelect = $('#protocolSelect');
// Empty the element using Select2 for rerendering
protocolSelect.select2().empty();
// Initialize the select element with Select2 using the
// array of protocols
protocolSelect.select2({
data: protocolsSelect2Data
});
// Update the ProtocolSelector to display the current active Protocol
protocolSelect.select2().val(ProtocolEngine.protocol.id).trigger('change');
}
Template.protocolEditor.onRendered(() => {
const instance = Template.instance();
instance.timeAgoInterval = Meteor.setInterval(() => {
// Run this every minute
Session.set('timeAgoVariable', new Date());
}, 60000);
// Update the Protocol select box when the hanging protocol store is ready
HP.ProtocolStore.onReady(() => {
updateProtocolSelect();
});
});
Template.protocolEditor.onDestroyed(() => {
const instance = Template.instance();
Meteor.clearInterval(instance.timeAgoInterval);
});
Template.protocolEditor.helpers({
/**
* Reactively updates the active Protocol
*
* @returns {*} The currently active Protocol Model
*/
activeProtocol() {
// Whenever the Layout Manager is updated, trigger this helper
Session.get('LayoutManagerUpdated');
// If no ProtocolEngine, protocol, or stage is defined, stop here
if (!ProtocolEngine ||
!ProtocolEngine.protocol ||
!ProtocolEngine.LayoutManager ||
ProtocolEngine.stage === undefined) {
return;
}
// Update the Protocol Select box
updateProtocolSelect();
// Make sure that the number of referenced priors is correct
ProtocolEngine.protocol.updateNumberOfPriorsReferenced();
// Otherwise, return the active Hanging Protocol
return ProtocolEngine.protocol;
},
/**
* Reactively updates the active Protocol Stage
*
* @returns {*} The current Protocol's active Stage model
*/
activeStage() {
// Whenever the Layout Manager is updated, trigger this helper
Session.get('LayoutManagerUpdated');
// If no ProtocolEngine, protocol, or stage is defined, stop here
if (!ProtocolEngine ||
!ProtocolEngine.protocol ||
!ProtocolEngine.LayoutManager ||
ProtocolEngine.stage === undefined) {
return;
}
// Retrieve the Stage Model for the current Protocol's active Stage
var stage = ProtocolEngine.getCurrentStageModel();
if (!stage) {
return;
}
// Update active Stage's layout template and properties based on the displayed
// layout properties. This is used to update the Stage Model when the user modifies
// the layout in the viewer
stage.viewportStructure.layoutTemplateName = ProtocolEngine.LayoutManager.layoutTemplateName;
stage.viewportStructure.properties = ProtocolEngine.LayoutManager.layoutProps;
// If there is a discrepancy between the Stage's number of viewports and the
// the number of required viewports given the properties above, rectify it
// by removing or adding Viewports to the stage
//
// First, calculate the difference, if any exists
var difference = stage.viewportStructure.getNumViewports() - stage.viewports.length;
if (difference < 0) {
// Make the viewport difference into a positive value
var absDifference = Math.abs(difference);
// If there are more Viewports defined than necessary, remove the extraneous Viewports
var position = stage.viewports.length - absDifference;
// Splice extra viewports from the Stage's viewports array
stage.viewports.splice(position, absDifference);
} else if (difference > 0) {
// If there are less Viewports defined than necessary, add viewports until we reach the
// required amount
// Count up until the difference in number of Viewports
for (var i = 0; i < difference; i++) {
// Instantiate a new Viewport Model
var viewport = new HP.Viewport();
// Add new Viewports to the Stage's viewports array
stage.viewports.push(viewport);
}
}
// Return the current Stage model for the active Protocol
return ProtocolEngine.getCurrentStageModel();
},
activeViewportUndefined() {
const viewportIndex = Session.get('activeViewport');
return (viewportIndex === undefined);
}
});
Template.protocolEditor.events({
/**
* Creates a new Hanging Protocol and displays it in the Viewer
*/
'click #newProtocol'() {
// Clone the default Protocol
var protocol = HP.defaultProtocol.createClone();
// Change the Protocol name to state that it is New, and give it a timestamp
protocol.name = 'New (created ' + moment().format('h:mm:ss a') + ')';
// Change the Protocol ID from the default value
protocol.id = Random.id();
// Insert the protocol
HP.ProtocolStore.addProtocol(protocol);
// Activate the new Protocol using the ProtocolEngine
ProtocolEngine.setHangingProtocol(protocol);
// Update the protocol selector to display the new Protocols
updateProtocolSelect();
},
/**
* Rename the current Protocol
*/
'click #renameProtocol'() {
var selectedProtocol = this;
if (selectedProtocol.locked) {
return;
}
// Define some details for the text entry dialog
var title = 'Rename Protocol';
var instructions = 'Enter a new name';
var currentValue = selectedProtocol.name;
// Open the text entry dialog with the details above
// and fire the callback function when finished.
openTextEntryDialog(title, instructions, currentValue, function(value) {
// Update the name with the entered text
selectedProtocol.name = value;
// Update the protocol
HP.ProtocolStore.updateProtocol(selectedProtocol.id, selectedProtocol);
// Update the protocol selector
updateProtocolSelect();
});
},
/**
* Import a Protocol
*/
'click #importProtocol'() {
// Hide the protocol dropdown manually, because it is not hidden automatically
// when it has input as a child
$("#protocolDropdown").dropdown('toggle');
},
/**
* Triggers a custom event when for the HTML5 File input when files are selected
*
* @param event The Change event for the input
*/
'change .btn-file :file': function(event) {
// http://www.abeautifulsite.net/whipping-file-inputs-into-shape-with-bootstrap-3/
// Find the Input in the DOM
var input = $(event.currentTarget);
// Get the number of selected files
var numFiles = input.get(0).files ? input.get(0).files.length : 1;
// Get the label of the file
var label = input.val().replace(/\\/g, '/').replace(/.*\//, '');
// Trigger our custom event with the number of files and label
input.trigger('fileselect', [numFiles, label]);
},
/**
* Imports files selected by the user into the Hanging Protocols Collection
*
* @param event The custom fileselect event
*/
'fileselect .btn-file :file': function(event) {
// Retreieve the FileList
var files = event.target.files;
// Create an HTML5 File Reader
var reader = new FileReader();
reader.onload = () => {
var protocolToImport = JSON.parse(reader.result);
// Insert the protocol
HP.ProtocolStore.addProtocol(protocolToImport);
// Update the protocol selector to display the imported Protocol
updateProtocolSelect();
};
// Instruct the FileReader to read the (first) selected file
// TODO: Update to allow batch uploads?
reader.readAsText(files[0], 'utf-8');
},
/**
* Set the Hanging Protocol when the select box is changed
*
* @param event The select2:select event
*/
'select2:select #protocolSelect': function(event) {
// Retrieve the protocolId
var protocolId = event.params.data.id;
// Retrieve the protocol from the protocol store
var selectedProtocol = HP.ProtocolStore.getProtocol(protocolId);
// If it doesn't exist, stop here
if (!selectedProtocol) {
return;
}
// Set the current Hanging Protocol to the user-specified Protocol
ProtocolEngine.setHangingProtocol(selectedProtocol);
},
/**
* Allow the Protocols / Stage navigation tabs to toggle the
* 'active' class when clicked
*/
'click .navigationButtons a'() {
$(this).addClass('active').siblings().removeClass('active');
},
/**
* Update the protocol with the latest changes to the current Protocol
*/
'click #saveProtocol'() {
var selectedProtocol = this;
if (selectedProtocol.locked) {
return;
}
// Update the Protocol's modifiedDate and modifiedBy User details
selectedProtocol.protocolWasModified();
// Update the current Protocol in the database with the latest changes
HP.ProtocolStore.updateProtocol(selectedProtocol.id, selectedProtocol);
},
/**
* Save the current Protocol as a new document
*/
'click #saveAsProtocol'() {
var selectedProtocol = this;
// Clone the selected Protocol
var protocol = selectedProtocol.createClone();
// Define some details for the text entry dialog
var title = 'Save Protocol As';
var instructions = 'Enter a new name';
var currentValue = protocol.name;
// Open the text entry dialog with the details above
// and fire the callback function when finished.
openTextEntryDialog(title, instructions, currentValue, function(value) {
// Create a new ID for the protocol
protocol.id = Random.id();
// Update the name with the entered text
protocol.name = value;
// Unlock the protocol
protocol.locked = false;
// Update the Protocol's modifiedDate and modifiedBy User details
protocol.protocolWasModified();
// Insert the new Protocol
HP.ProtocolStore.addProtocol(protocol);
// Activate the new Protocol using the ProtocolEngine
ProtocolEngine.setHangingProtocol(protocol);
// Update the protocol selector to display the new Protocols
updateProtocolSelect();
});
},
/**
* Export the currently selected Protocol as a JSON file
*/
'click #exportJSON'() {
var selectedProtocol = this;
var protocolJSON = JSON.stringify(selectedProtocol, null, 2),
currentDate = new Date(),
filename = selectedProtocol.name + '-' + (currentDate.getTime().toString()) + '.json',
protocolBlob = new Blob([protocolJSON], { type: 'application/json' });
var downloadElement = document.getElementById('downloadElement');
downloadElement.href = URL.createObjectURL(protocolBlob);
downloadElement.download = filename;
downloadElement.click();
},
/**
* Delete the currently selected Protocol
*/
'click #deleteProtocol'() {
var selectedProtocol = this;
if (selectedProtocol.locked) {
return;
}
var options = {
title: 'Delete Protocol',
text: 'Are you sure you would like to remove this Protocol? This cannot be reversed.'
};
Viewerbase.dialogUtils.showConfirmDialog(() => {
// Remove the Protocol
HP.ProtocolStore.removeProtocol(selectedProtocol.id);
// Reset the ProtocolEngine to the next best match
ProtocolEngine.reset();
// Update the protocol selector
updateProtocolSelect();
}, options);
}
});