LT-275: Storing the selected label and description on measurements collection
This commit is contained in:
parent
20a2a8e453
commit
cd5a1277aa
@ -1,3 +1,5 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { Session } from 'meteor/session';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Session.set('TimepointsReady', false);
|
Session.set('TimepointsReady', false);
|
||||||
@ -102,5 +104,36 @@ Template.viewer.events({
|
|||||||
},
|
},
|
||||||
'CornerstoneToolsMeasurementRemoved .imageViewerViewport'(event, instance, eventData) {
|
'CornerstoneToolsMeasurementRemoved .imageViewerViewport'(event, instance, eventData) {
|
||||||
OHIF.measurements.MeasurementHandlers.onRemoved(event, instance, eventData);
|
OHIF.measurements.MeasurementHandlers.onRemoved(event, instance, eventData);
|
||||||
|
},
|
||||||
|
CornerstoneToolsMouseClick(event, instance, data) {
|
||||||
|
const element = instance.$('.imageViewerViewport')[0];
|
||||||
|
|
||||||
|
const toolState = cornerstoneTools.getToolState(element, 'bidirectional');
|
||||||
|
|
||||||
|
// Stop here if no tool state was found
|
||||||
|
if (!toolState) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const selectLabelCallback = (options, value, description) => {
|
||||||
|
console.warn('>>>>options, value, description', options, value, description);
|
||||||
|
};
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
for (let i = 0; i < toolState.data.length; i++) {
|
||||||
|
const toolData = toolState.data[i];
|
||||||
|
if (toolData.active) {
|
||||||
|
OHIF.measurements.toggleLabelButton({
|
||||||
|
instance,
|
||||||
|
toolData,
|
||||||
|
element,
|
||||||
|
measurementApi: instance.data.measurementApi,
|
||||||
|
position: data.currentPoints.page,
|
||||||
|
callback: selectLabelCallback
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,12 +1,12 @@
|
|||||||
<template name="wrapperLabel">
|
<template name="wrapperLabel">
|
||||||
{{#unless this.labelAsDiv}}
|
{{#unless this.labelAsDiv}}
|
||||||
<label class="wrapperLabel {{this.labelClass}}">
|
<label class="wrapperLabel {{this.labelClass}}" {{clone this.labelTagAttributes}}>
|
||||||
{{#wrapperLabelContent}}
|
{{#wrapperLabelContent}}
|
||||||
{{>UI.contentBlock}}
|
{{>UI.contentBlock}}
|
||||||
{{/wrapperLabelContent}}
|
{{/wrapperLabelContent}}
|
||||||
</label>
|
</label>
|
||||||
{{else}}
|
{{else}}
|
||||||
<div class="wrapperLabel {{this.labelClass}}">
|
<div class="wrapperLabel {{this.labelClass}}" {{clone this.labelTagAttributes}}>
|
||||||
{{#wrapperLabelContent}}
|
{{#wrapperLabelContent}}
|
||||||
{{>UI.contentBlock}}
|
{{>UI.contentBlock}}
|
||||||
{{/wrapperLabelContent}}
|
{{/wrapperLabelContent}}
|
||||||
|
|||||||
@ -4,26 +4,26 @@ import { MeasurementSchemaTypes } from 'meteor/ohif:measurements/both/schema/mea
|
|||||||
const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema;
|
const CornerstoneHandleSchema = MeasurementSchemaTypes.CornerstoneHandleSchema;
|
||||||
|
|
||||||
const BidirectionalHandlesSchema = new SimpleSchema({
|
const BidirectionalHandlesSchema = new SimpleSchema({
|
||||||
start: {
|
start: {
|
||||||
type: CornerstoneHandleSchema,
|
type: CornerstoneHandleSchema,
|
||||||
label: 'Start'
|
label: 'Start'
|
||||||
},
|
},
|
||||||
end: {
|
end: {
|
||||||
type: CornerstoneHandleSchema,
|
type: CornerstoneHandleSchema,
|
||||||
label: 'End'
|
label: 'End'
|
||||||
},
|
},
|
||||||
perpendicularStart: {
|
perpendicularStart: {
|
||||||
type: CornerstoneHandleSchema,
|
type: CornerstoneHandleSchema,
|
||||||
label: 'Perpendicular Start'
|
label: 'Perpendicular Start'
|
||||||
},
|
},
|
||||||
perpendicularEnd: {
|
perpendicularEnd: {
|
||||||
type: CornerstoneHandleSchema,
|
type: CornerstoneHandleSchema,
|
||||||
label: 'Perpendicular End'
|
label: 'Perpendicular End'
|
||||||
},
|
},
|
||||||
textBox: {
|
textBox: {
|
||||||
type: CornerstoneHandleSchema,
|
type: CornerstoneHandleSchema,
|
||||||
label: 'Text Box'
|
label: 'Text Box'
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const BidirectionalSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, {
|
const BidirectionalSchema = new SimpleSchema([MeasurementSchemaTypes.CornerstoneToolMeasurement, {
|
||||||
@ -31,36 +31,46 @@ const BidirectionalSchema = new SimpleSchema([MeasurementSchemaTypes.Cornerstone
|
|||||||
type: BidirectionalHandlesSchema,
|
type: BidirectionalHandlesSchema,
|
||||||
label: 'Handles'
|
label: 'Handles'
|
||||||
},
|
},
|
||||||
|
location: {
|
||||||
|
type: String,
|
||||||
|
label: 'Location',
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
description: {
|
||||||
|
type: String,
|
||||||
|
label: 'Description',
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
longestDiameter: {
|
longestDiameter: {
|
||||||
type: Number,
|
type: Number,
|
||||||
label: 'Longest Diameter',
|
label: 'Longest Diameter',
|
||||||
decimal: true
|
decimal: true
|
||||||
},
|
},
|
||||||
shortestDiameter: {
|
shortestDiameter: {
|
||||||
type: Number,
|
type: Number,
|
||||||
label: 'Shortest Diameter',
|
label: 'Shortest Diameter',
|
||||||
decimal: true
|
decimal: true
|
||||||
},
|
},
|
||||||
locationUid: {
|
locationUid: {
|
||||||
type: String,
|
type: String,
|
||||||
label: 'Location UID',
|
label: 'Location UID',
|
||||||
optional: true // Optional because it is added after initial drawing, via a callback
|
optional: true // Optional because it is added after initial drawing, via a callback
|
||||||
}
|
}
|
||||||
}]);
|
}]);
|
||||||
|
|
||||||
function displayFunction(data) {
|
function displayFunction(data) {
|
||||||
// Check whether this is a Nodal or Extranodal Measurement
|
// Check whether this is a Nodal or Extranodal Measurement
|
||||||
const targetType = 'target';
|
// const targetType = 'target';
|
||||||
const nodalType = data.isNodal ? 'nodal' : 'extraNodal';
|
// const nodalType = data.isNodal ? 'nodal' : 'extraNodal';
|
||||||
|
|
||||||
// Get criteria types
|
// Get criteria types
|
||||||
const criteriaTypes = TrialCriteriaTypes.find({
|
// const criteriaTypes = TrialCriteriaTypes.find({
|
||||||
selected: true
|
// selected: true
|
||||||
}).map(criteria => {
|
// }).map(criteria => {
|
||||||
return criteria.id;
|
// return criteria.id;
|
||||||
});
|
// });
|
||||||
|
|
||||||
const currentConstraints = OHIF.lesiontracker.getTrialCriteriaConstraints(criteriaTypes, data.imageId);
|
// const currentConstraints = OHIF.lesiontracker.getTrialCriteriaConstraints(criteriaTypes, data.imageId);
|
||||||
|
|
||||||
if (data.shortestDiameter) {
|
if (data.shortestDiameter) {
|
||||||
// TODO: Make this check criteria again to see if we should display
|
// TODO: Make this check criteria again to see if we should display
|
||||||
@ -83,4 +93,4 @@ export const bidirectional = {
|
|||||||
},
|
},
|
||||||
includeInCaseProgress: true,
|
includeInCaseProgress: true,
|
||||||
},
|
},
|
||||||
}
|
};
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
<template name="measureFlow">
|
<template name="measureFlow">
|
||||||
<div class="measure-flow {{#if this.threeColumns}}tree-columns{{/if}} {{instance.state.get}}" style="top:{{choose position.y 0}}px;left:{{choose position.x 0}}px">
|
<div class="measure-flow {{#if this.threeColumns}}tree-columns{{/if}} {{instance.state.get}}" style="top:{{choose position.y 0}}px;left:{{choose position.x 0}}px" tabindex="-1">
|
||||||
<button class="btn-add">Add label</button>
|
<button class="btn-add">Add label</button>
|
||||||
{{#if eq instance.state.get 'selected'}}
|
{{#if eq instance.state.get 'selected'}}
|
||||||
<div class="tree-leaf">
|
<div class="tree-leaf">
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
import { Blaze } from 'meteor/blaze';
|
import { Blaze } from 'meteor/blaze';
|
||||||
import { ReactiveVar } from 'meteor/reactive-var';
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
@ -8,8 +9,10 @@ import { $ } from 'meteor/jquery';
|
|||||||
Template.measureFlow.onCreated(() => {
|
Template.measureFlow.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
instance.value = instance.data.currentValue || '';
|
||||||
|
|
||||||
instance.state = new ReactiveVar('closed');
|
instance.state = new ReactiveVar('closed');
|
||||||
instance.description = new ReactiveVar('');
|
instance.description = new ReactiveVar(instance.data.currentDescription || '');
|
||||||
instance.descriptionEdit = new ReactiveVar(false);
|
instance.descriptionEdit = new ReactiveVar(false);
|
||||||
|
|
||||||
const items = [
|
const items = [
|
||||||
@ -76,6 +79,8 @@ Template.measureFlow.onRendered(() => {
|
|||||||
|
|
||||||
// Make the measure flow bounded by the window borders
|
// Make the measure flow bounded by the window borders
|
||||||
instance.$('.measure-flow').bounded();
|
instance.$('.measure-flow').bounded();
|
||||||
|
|
||||||
|
instance.$('.btn-add').focus();
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.measureFlow.events({
|
Template.measureFlow.events({
|
||||||
@ -84,6 +89,8 @@ Template.measureFlow.events({
|
|||||||
},
|
},
|
||||||
|
|
||||||
'click .measure-flow .btn-add, click .measure-flow .btn-rename'(event, instance) {
|
'click .measure-flow .btn-add, click .measure-flow .btn-rename'(event, instance) {
|
||||||
|
const $measureFlow = instance.$('.measure-flow');
|
||||||
|
|
||||||
// Set the open state for the component
|
// Set the open state for the component
|
||||||
instance.state.set('open');
|
instance.state.set('open');
|
||||||
|
|
||||||
@ -109,10 +116,13 @@ Template.measureFlow.events({
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Define in which element the selectTree will be rendered in
|
// Define in which element the selectTree will be rendered in
|
||||||
const parentElement = instance.$('.measure-flow')[0];
|
const parentElement = $measureFlow[0];
|
||||||
|
|
||||||
// Render the selectTree element
|
// Render the selectTree element
|
||||||
instance.selectTreeView = Blaze.renderWithData(Template.selectTree, data, parentElement);
|
instance.selectTreeView = Blaze.renderWithData(Template.selectTree, data, parentElement);
|
||||||
|
|
||||||
|
// Focus the measure flow to handle closing
|
||||||
|
$measureFlow.focus();
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -149,6 +159,7 @@ Template.measureFlow.events({
|
|||||||
if (event.which === 13 || event.which === 27) {
|
if (event.which === 13 || event.which === 27) {
|
||||||
instance.$('.measure-flow .actions').removeClass('fadeOut');
|
instance.$('.measure-flow .actions').removeClass('fadeOut');
|
||||||
instance.descriptionEdit.set(false);
|
instance.descriptionEdit.set(false);
|
||||||
|
instance.$('.measure-flow').focus();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep the current description if ENTER was pressed
|
// Keep the current description if ENTER was pressed
|
||||||
@ -219,5 +230,31 @@ Template.measureFlow.events({
|
|||||||
|
|
||||||
// Wait the fade-out transition and remove the selectTree component
|
// Wait the fade-out transition and remove the selectTree component
|
||||||
$container.one('transitionend', event => Blaze.remove(instance.selectTreeView));
|
$container.one('transitionend', event => Blaze.remove(instance.selectTreeView));
|
||||||
|
},
|
||||||
|
|
||||||
|
'blur .measure-flow'(event, instance) {
|
||||||
|
const $measureFlow = $(event.currentTarget);
|
||||||
|
const element = $measureFlow[0];
|
||||||
|
Meteor.defer(() => {
|
||||||
|
const focused = $(':focus')[0];
|
||||||
|
if (element !== focused && !$.contains(element, focused)) {
|
||||||
|
$measureFlow.trigger('close');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
'mouseout .measure-flow'(event, instance) {
|
||||||
|
const $measureFlow = $(event.currentTarget);
|
||||||
|
const canClose = instance.state.get() === 'selected' && !instance.descriptionEdit.get();
|
||||||
|
if (canClose && !$.contains($measureFlow[0], event.toElement)) {
|
||||||
|
$measureFlow.trigger('close');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
'close .measure-flow'(event, instance) {
|
||||||
|
const $measureFlow = $(event.currentTarget);
|
||||||
|
$measureFlow.one('animationend', () => {
|
||||||
|
instance.data.doneCallback(instance.value.value, instance.description.get());
|
||||||
|
}).addClass('fadeOut');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,9 +1,13 @@
|
|||||||
@import "{design}/app"
|
@import "{design}/app"
|
||||||
|
|
||||||
.measure-flow
|
.measure-flow
|
||||||
|
outline: none
|
||||||
position: fixed
|
position: fixed
|
||||||
z-index: 1
|
z-index: 1
|
||||||
|
|
||||||
|
&.fadeOut
|
||||||
|
animateFadeOut()
|
||||||
|
|
||||||
&.open,
|
&.open,
|
||||||
&.selected
|
&.selected
|
||||||
|
|
||||||
@ -61,7 +65,7 @@
|
|||||||
display: none
|
display: none
|
||||||
|
|
||||||
.actions
|
.actions
|
||||||
margin-top: 16px
|
padding-top: 16px
|
||||||
opacity: 0
|
opacity: 0
|
||||||
|
|
||||||
&:not(.fadeOut)
|
&:not(.fadeOut)
|
||||||
@ -84,7 +88,7 @@
|
|||||||
|
|
||||||
.description
|
.description
|
||||||
margin-top: -10px
|
margin-top: -10px
|
||||||
margin-bottom: 26px
|
margin-bottom: 10px
|
||||||
|
|
||||||
textarea
|
textarea
|
||||||
background-color: white
|
background-color: white
|
||||||
@ -102,7 +106,7 @@
|
|||||||
background-color: white
|
background-color: white
|
||||||
box-shadow: 0 10px white
|
box-shadow: 0 10px white
|
||||||
line-height: 20px
|
line-height: 20px
|
||||||
margin-bottom: 26px
|
margin-bottom: 10px
|
||||||
margin-top: -10px
|
margin-top: -10px
|
||||||
padding: 0 12px
|
padding: 0 12px
|
||||||
|
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
import './viewer/imageViewerViewport.js';
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
import { Template } from 'meteor/templating';
|
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
|
||||||
|
|
||||||
Template.imageViewerViewport.events({
|
|
||||||
CornerstoneToolsMouseClick(event, instance, data) {
|
|
||||||
const toolState = cornerstoneTools.getToolState(instance.element, 'bidirectional');
|
|
||||||
|
|
||||||
// Stop here if no tool state was found
|
|
||||||
if (!toolState) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
for (let i = 0; i < toolState.data.length; i++) {
|
|
||||||
const toolData = toolState.data[i];
|
|
||||||
if (toolData.active) {
|
|
||||||
OHIF.measurements.toggleLabelButton({
|
|
||||||
instance,
|
|
||||||
toolData,
|
|
||||||
position: data.currentPoints.page
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -1,4 +1,3 @@
|
|||||||
import './lib';
|
import './lib';
|
||||||
import './helpers';
|
import './helpers';
|
||||||
import './components';
|
import './components';
|
||||||
import './hooks';
|
|
||||||
|
|||||||
@ -2,25 +2,43 @@ import { Template } from 'meteor/templating';
|
|||||||
import { Blaze } from 'meteor/blaze';
|
import { Blaze } from 'meteor/blaze';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
const toolMap = {
|
||||||
|
bidirectional: 'targets'
|
||||||
|
};
|
||||||
|
|
||||||
OHIF.measurements.toggleLabelButton = options => {
|
OHIF.measurements.toggleLabelButton = options => {
|
||||||
const removeButtonView = () => {
|
const removeButtonView = () => {
|
||||||
|
if (!options.instance.buttonView) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Blaze.remove(options.instance.buttonView);
|
Blaze.remove(options.instance.buttonView);
|
||||||
options.instance.buttonView = null;
|
options.instance.buttonView = null;
|
||||||
};
|
};
|
||||||
|
|
||||||
if (options.instance.buttonView) {
|
if (options.instance.buttonView) {
|
||||||
removeButtonView();
|
removeButtonView();
|
||||||
} else {
|
|
||||||
const data = {
|
|
||||||
position: options.position,
|
|
||||||
threeColumns: true,
|
|
||||||
hideCommon: true,
|
|
||||||
doneCallback(data) {
|
|
||||||
console.warn('>>>>DONE CALLBACK', data);
|
|
||||||
removeButtonView();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const view = Blaze.renderWithData(Template.measureFlow, data, options.instance.element);
|
|
||||||
options.instance.buttonView = view;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const data = {
|
||||||
|
position: options.position,
|
||||||
|
threeColumns: true,
|
||||||
|
hideCommon: true,
|
||||||
|
doneCallback(location, description) {
|
||||||
|
options.callback(options, location, description);
|
||||||
|
|
||||||
|
const tool = toolMap[options.toolData.toolType];
|
||||||
|
|
||||||
|
options.measurementApi[tool].update(options.toolData.id, {
|
||||||
|
$set: {
|
||||||
|
location,
|
||||||
|
description
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
removeButtonView();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
const view = Blaze.renderWithData(Template.measureFlow, data, options.element);
|
||||||
|
options.instance.buttonView = view;
|
||||||
};
|
};
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user