PWV-1: Refactoring ohif:studylist package
This commit is contained in:
1 parent
984ef94403
commit
4d79bf84a8
79 files changed
+450
-551
No files matched your search
@@ -12,7 +12,7 @@ OHIF.mixins.button = new OHIF.Mixin({
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('button:first');
|
||||
component.$element = instance.$('button').first();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -54,7 +54,7 @@ OHIF.mixins.form = new OHIF.Mixin({
|
||||
const component = instance.component;
|
||||
|
||||
// Set the component main and style elements
|
||||
component.$style = component.$element = instance.$('form:first');
|
||||
component.$style = component.$element = instance.$('form').first();
|
||||
|
||||
// Block page redirecting on submit
|
||||
component.$element[0].onsubmit = () => false;
|
||||
@@ -66,7 +66,7 @@ OHIF.mixins.form = new OHIF.Mixin({
|
||||
const targetKey = $(event.currentTarget).attr('data-target');
|
||||
|
||||
// Focus the first input inside the element with error state
|
||||
instance.$(`.state-error[data-key="${targetKey}"] :input:first`).focus();
|
||||
instance.$(`.state-error[data-key="${targetKey}"]`).find(':input:first').focus();
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ OHIF.mixins.group = new OHIF.Mixin({
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('.component-group:first');
|
||||
component.$element = instance.$('.component-group').first();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -12,7 +12,7 @@ OHIF.mixins.input = new OHIF.Mixin({
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('input:first');
|
||||
component.$element = instance.$('input').first();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -12,7 +12,7 @@ OHIF.mixins.link = new OHIF.Mixin({
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('a:first');
|
||||
component.$element = instance.$('a').first();
|
||||
},
|
||||
|
||||
events: {
|
||||
|
||||
@@ -12,7 +12,7 @@ OHIF.mixins.select = new OHIF.Mixin({
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('select:first');
|
||||
component.$element = instance.$('select').first();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,3 @@
|
||||
<template name="dropdownBackdrop">
|
||||
<div class="dropdown-backdrop"></div>
|
||||
</template>
|
||||
@@ -0,0 +1,8 @@
|
||||
<template name="dropdownForm">
|
||||
{{#form class='dropdown' api=this.api hideValidationBox=true}}
|
||||
{{>dropdownBackdrop}}
|
||||
<ul class="dropdown-menu">
|
||||
{{>UI.contentBlock}}
|
||||
</ul>
|
||||
{{/form}}
|
||||
</template>
|
||||
@@ -0,0 +1,25 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Blaze } from 'meteor/blaze';
|
||||
import { _ } from 'meteor/underscore';
|
||||
|
||||
Template.dropdownForm.onRendered(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
// Show the dropdown
|
||||
instance.$('.dropdown').addClass('open');
|
||||
|
||||
// Destroy the Blaze created view (either created with template calls or with renderWithData)
|
||||
instance.destroyView = () => {
|
||||
if (_.isFunction(instance.data.destroyView)) {
|
||||
instance.data.destroyView();
|
||||
} else {
|
||||
Blaze.remove(instance.view);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
Template.dropdownForm.events({
|
||||
'click .dropdown'(event, instance) {
|
||||
instance.destroyView();
|
||||
}
|
||||
});
|
||||
@@ -3,6 +3,10 @@ import './dialog/form.js';
|
||||
import './dialog/login.html';
|
||||
import './dialog/login.js';
|
||||
|
||||
import './dropdown/backdrop.html';
|
||||
import './dropdown/form.html';
|
||||
import './dropdown/form.js';
|
||||
|
||||
import './form/button.html';
|
||||
import './form/form.html';
|
||||
import './form/group.html';
|
||||
|
||||
@@ -36,10 +36,15 @@ class Bounded {
|
||||
options(options={}) {
|
||||
// Process the given options and store it in the instance
|
||||
const { boundingElement, allowResizing } = options;
|
||||
this.boundingElement = boundingElement || window;
|
||||
this.boundingElement = boundingElement;
|
||||
this.$boundingElement = $(this.boundingElement);
|
||||
this.allowResizing = allowResizing;
|
||||
|
||||
// Check for fixed positioning
|
||||
if (this.$element.css('position') === 'fixed') {
|
||||
this.boundingElement = window;
|
||||
}
|
||||
|
||||
// Destroy and initialize again the instance
|
||||
this.destroy();
|
||||
this.init();
|
||||
@@ -55,6 +60,9 @@ class Bounded {
|
||||
|
||||
// Add the bounded class to the element
|
||||
this.$element.addClass('bounded');
|
||||
|
||||
// Trigger the bounding check for the first timepoint
|
||||
setTimeout(() => this.$element.trigger('spatialChanged'));
|
||||
}
|
||||
|
||||
// Destroy this instance, returning the element to its previous state
|
||||
@@ -70,12 +78,26 @@ class Bounded {
|
||||
// Create the result object
|
||||
const result = {};
|
||||
|
||||
// Check if the element is the window
|
||||
if (element === window) {
|
||||
const $window = $(window);
|
||||
const width = $window.outerWidth();
|
||||
const height = $window.outerHeight();
|
||||
return {
|
||||
width,
|
||||
height,
|
||||
x0: 0,
|
||||
y0: 0,
|
||||
x1: width,
|
||||
y1: height
|
||||
};
|
||||
}
|
||||
|
||||
// Get the jQuery object for the element
|
||||
const el = element === window ? window.document.body : element;
|
||||
const $element = $(el);
|
||||
const $element = $(element);
|
||||
|
||||
// Get the element style
|
||||
const style = el.style;
|
||||
const style = element.style;
|
||||
|
||||
// Get the integer numbers for element's width
|
||||
if (style.width && style.width.indexOf('px') > -1) {
|
||||
@@ -91,10 +113,13 @@ class Bounded {
|
||||
result.height = $element.outerHeight();
|
||||
}
|
||||
|
||||
// Get the position property based on the element position CSS attribute
|
||||
const positionProperty = $element.css('position') === 'fixed' ? 'position' : 'offset';
|
||||
|
||||
// Get the element's start position
|
||||
const offset = $element.offset();
|
||||
result.x0 = offset.left;
|
||||
result.y0 = offset.top;
|
||||
const position = $element[positionProperty]();
|
||||
result.x0 = position.left;
|
||||
result.y0 = position.top;
|
||||
|
||||
// Get the element's end position
|
||||
result.x1 = result.x0 + result.width;
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Blaze } from 'meteor/blaze';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
OHIF.ui.showFormDropdown = (templateName, dropdownData) => {
|
||||
// Check if the given template exists
|
||||
const template = Template[templateName];
|
||||
if (!template) {
|
||||
throw {
|
||||
name: 'TEMPLATE_NOT_FOUND',
|
||||
message: `Template ${templateName} not found.`
|
||||
};
|
||||
}
|
||||
|
||||
// Prepare the method to destroy the view
|
||||
let view;
|
||||
const destroyView = () => Blaze.remove(view);
|
||||
const templateData = _.extend({}, dropdownData, {
|
||||
destroyView
|
||||
});
|
||||
|
||||
// Render the dialog with the given template and data
|
||||
view = Blaze.renderWithData(template, templateData, document.body);
|
||||
|
||||
// Return the dropdown element to enable position manipulation
|
||||
const dropdown = view.firstNode();
|
||||
return dropdown;
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import './bounded/bounded.js';
|
||||
import './dialog/form.js';
|
||||
import './draggable/draggable.js';
|
||||
import './dropdown/form.js';
|
||||
import './resizable/resizable.js';
|
||||
@@ -7,8 +7,7 @@ import { Meteor } from 'meteor/meteor';
|
||||
const OHIF = {
|
||||
log: {},
|
||||
ui: {},
|
||||
viewer: {},
|
||||
measurements: {}
|
||||
viewer: {}
|
||||
};
|
||||
|
||||
// Expose the OHIF object to the client if it is on development mode
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
OHIF.measurements = {};
|
||||
@@ -1,2 +1,3 @@
|
||||
import './base.js';
|
||||
import './configuration';
|
||||
import './schema';
|
||||
+25
-35
@@ -1,3 +1,7 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { moment } from 'meteor/momentjs:moment';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Finds related studies within defined time window of =/- 14 days of selected studies
|
||||
* @param selectedStudies
|
||||
@@ -14,13 +18,13 @@ function getDateRange(selectedStudies, range) {
|
||||
return;
|
||||
}
|
||||
|
||||
var earliestStudy = selectedStudies[0];
|
||||
var latestStudy = selectedStudies[selectedStudies.length - 1];
|
||||
const earliestStudy = selectedStudies[0];
|
||||
const latestStudy = selectedStudies[selectedStudies.length - 1];
|
||||
|
||||
var earliestDate = moment(earliestStudy.studyDate, 'YYYYMMDD');
|
||||
const earliestDate = moment(earliestStudy.studyDate, 'YYYYMMDD');
|
||||
earliestDate.subtract(range);
|
||||
|
||||
var latestDate = moment(latestStudy.studyDate, 'YYYYMMDD');
|
||||
const latestDate = moment(latestStudy.studyDate, 'YYYYMMDD');
|
||||
latestDate.add(range);
|
||||
|
||||
return {
|
||||
@@ -43,12 +47,12 @@ function autoSelectStudies(selectedStudies) {
|
||||
return;
|
||||
}
|
||||
|
||||
var range = getDateRange(selectedStudies);
|
||||
const range = getDateRange(selectedStudies);
|
||||
|
||||
// Fetch autoselected studies based on the date range
|
||||
// Note that we used MongoDB's fetch here so we have a mutable array,
|
||||
// rather than a Cursor
|
||||
var autoselected = StudyListStudies.find({
|
||||
const autoselected = StudyListStudies.find({
|
||||
studyDate: {
|
||||
$gte: range.earliestDate.format('YYYYMMDD'),
|
||||
$lte: range.latestDate.format('YYYYMMDD')
|
||||
@@ -60,12 +64,10 @@ function autoSelectStudies(selectedStudies) {
|
||||
}).fetch();
|
||||
|
||||
// Make an array of studyInstanceUids in selectedStudies
|
||||
var studyInstanceUids = selectedStudies.map(function(selectedStudy) {
|
||||
return selectedStudy.studyInstanceUid;
|
||||
});
|
||||
const studyInstanceUids = selectedStudies.map(selectedStudy => selectedStudy.studyInstanceUid);
|
||||
|
||||
autoselected.forEach(function(study) {
|
||||
var exists = studyInstanceUids.indexOf(study.studyInstanceUid);
|
||||
autoselected.forEach(study => {
|
||||
const exists = studyInstanceUids.indexOf(study.studyInstanceUid);
|
||||
if (exists > -1) {
|
||||
study.autoselected = false;
|
||||
return;
|
||||
@@ -84,12 +86,8 @@ Template.studyAssociationTable.helpers({
|
||||
*
|
||||
* @returns {Array.<T>}
|
||||
*/
|
||||
relevantStudies: function() {
|
||||
var selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch() || [];
|
||||
relevantStudies() {
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
return autoSelectStudies(selectedStudies);
|
||||
},
|
||||
@@ -98,7 +96,7 @@ Template.studyAssociationTable.helpers({
|
||||
*
|
||||
* @returns {Array.<T>}
|
||||
*/
|
||||
timepointOptions: function() {
|
||||
timepointOptions() {
|
||||
return [{
|
||||
value: 'baseline',
|
||||
name: 'Baseline',
|
||||
@@ -109,26 +107,18 @@ Template.studyAssociationTable.helpers({
|
||||
checked: false
|
||||
}];
|
||||
},
|
||||
earliestDate: function() {
|
||||
var selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch();
|
||||
earliestDate() {
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
var range = getDateRange(selectedStudies);
|
||||
const range = getDateRange(selectedStudies);
|
||||
if (range) {
|
||||
return range.earliestDate;
|
||||
}
|
||||
},
|
||||
latestDate: function() {
|
||||
var selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch();
|
||||
latestDate() {
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
var range = getDateRange(selectedStudies);
|
||||
const range = getDateRange(selectedStudies);
|
||||
if (range) {
|
||||
return range.latestDate;
|
||||
}
|
||||
@@ -136,9 +126,9 @@ Template.studyAssociationTable.helpers({
|
||||
});
|
||||
|
||||
Template.studyAssociationTable.events({
|
||||
'change input.includeStudy': function(e) {
|
||||
var checkbox = e.currentTarget;
|
||||
var studyDataCells = $(checkbox).parents('tr').find('td.studyDataCell');
|
||||
'change input.includeStudy'(event, instance) {
|
||||
const checkbox = event.currentTarget;
|
||||
const studyDataCells = $(checkbox).parents('tr').find('td.studyDataCell');
|
||||
if (checkbox.checked === true) {
|
||||
studyDataCells.removeClass('disabled');
|
||||
studyDataCells.find('input').attr('disabled', false);
|
||||
|
||||
+18
-28
@@ -1,30 +1,20 @@
|
||||
<template name="longitudinalStudyListContextMenu">
|
||||
{{#if uiSettings.studyListFunctionsEnabled}}
|
||||
<div id="studyContextMenu" class="studyContextMenu noselect"
|
||||
oncontextmenu='return false;'
|
||||
unselectable='on'
|
||||
onselectstart='return false;'>
|
||||
<ul>
|
||||
<li>
|
||||
<a id="viewStudies" type="button" title="View Studies">View</a>
|
||||
<hr/>
|
||||
<!-- {{#link action='associate'}}Associate{{/link}} -->
|
||||
<a id="launchStudyAssociation" title="Launch Study Association">Associate</a>
|
||||
<a id="launchRemoveAssociation" type="button"
|
||||
data-toggle="modal"
|
||||
data-target="#confirmRemoveTimepointAssociation"
|
||||
title="Remove Timepoint Association">Remove Association</a>
|
||||
<hr/>
|
||||
<a id="viewSeriesDetails" type="button"
|
||||
title="View Series Details">View Series Details</a>
|
||||
<a class="disabled">Anonymize</a>
|
||||
<a class="disabled">Send</a>
|
||||
<hr/>
|
||||
<a id="exportSelectedStudies"
|
||||
title="Export Selected Studies">Export</a>
|
||||
<a class="disabled">Delete</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#dropdownForm}}
|
||||
<li><a id="viewStudies" type="button" title="View Studies">View</a></li>
|
||||
<li class="divider" role="separator"></li>
|
||||
<!-- {{#link action='associate'}}Associate{{/link}} -->
|
||||
<li><a id="launchStudyAssociation" title="Launch Study Association">Associate</a></li>
|
||||
<li><a id="launchRemoveAssociation" type="button" data-toggle="modal"
|
||||
data-target="#confirmRemoveTimepointAssociation" title="Remove Timepoint Association"
|
||||
>Remove Association</a></li>
|
||||
<li class="divider" role="separator"></li>
|
||||
<li><a id="viewSeriesDetails" type="button"
|
||||
title="View Series Details"
|
||||
>View Series Details</a></li>
|
||||
<li class="disabled"><a class="disabled">Anonymize</a></li>
|
||||
<li class="disabled"><a class="disabled">Send</a></li>
|
||||
<li class="divider" role="separator"></li>
|
||||
<li><a id="exportSelectedStudies" title="Export Selected Studies">Export</a></li>
|
||||
<li class="disabled"><a class="disabled">Delete</a></li>
|
||||
{{/dropdownForm}}
|
||||
</template>
|
||||
+26
-38
@@ -1,3 +1,6 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Random } from 'meteor/random';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Use Aldeed's meteor-template-extension package to replace the
|
||||
@@ -7,21 +10,17 @@ const defaultTemplate = 'studyContextMenu';
|
||||
|
||||
Template.longitudinalStudyListContextMenu.replaces(defaultTemplate);
|
||||
|
||||
StudyList.functions['launchStudyAssociation'] = () => OHIF.ui.showFormDialog('dialogStudyAssociation');
|
||||
StudyList.functions['removeTimepointAssociations'] = removeTimepointAssociations;
|
||||
StudyList.functions['exportSelectedStudies'] = exportSelectedStudies;
|
||||
StudyList.functions['viewStudies'] = viewStudies;
|
||||
StudyList.functions.launchStudyAssociation = () => OHIF.ui.showFormDialog('dialogStudyAssociation');
|
||||
StudyList.functions.removeTimepointAssociations = removeTimepointAssociations;
|
||||
StudyList.functions.exportSelectedStudies = exportSelectedStudies;
|
||||
StudyList.functions.viewStudies = viewStudies;
|
||||
|
||||
/**
|
||||
* Removes all present study / timepoint associations from the Clinical Trial
|
||||
*/
|
||||
function removeTimepointAssociations() {
|
||||
// Get a Cursor pointing to the selected Studies from the StudyList
|
||||
const selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
});
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
// Loop through the Cursor of Selected Studies
|
||||
selectedStudies.forEach(function(selectedStudy) {
|
||||
@@ -31,14 +30,14 @@ function removeTimepointAssociations() {
|
||||
return;
|
||||
}
|
||||
|
||||
let timepoint = timepointApi.study(data.study.studyInstanceUid)[0];
|
||||
let timepoint = timepointApi.study(selectedStudy.studyInstanceUid)[0];
|
||||
if (!timepoint) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Find the index of the current studyInstanceUid in the array
|
||||
// of reference studyInstanceUids
|
||||
var index = timepoint.studyInstanceUids.indexOf(study.studyInstanceUid);
|
||||
const index = timepoint.studyInstanceUids.indexOf(selectedStudy.studyInstanceUid);
|
||||
if (index < 0) {
|
||||
return;
|
||||
}
|
||||
@@ -57,14 +56,14 @@ function removeTimepointAssociations() {
|
||||
});
|
||||
|
||||
// Log
|
||||
var hipaaEvent = {
|
||||
const hipaaEvent = {
|
||||
eventType: 'modify',
|
||||
userId: Meteor.userId(),
|
||||
userName: Meteor.user().profile.fullName,
|
||||
collectionName: "Timepoints",
|
||||
recordId: study.timepointId,
|
||||
patientId: study.patientId,
|
||||
patientName: study.patientName
|
||||
collectionName: 'Timepoints',
|
||||
recordId: selectedStudy.timepointId,
|
||||
patientId: selectedStudy.patientId,
|
||||
patientName: selectedStudy.patientName
|
||||
};
|
||||
HipaaLogger.logEvent(hipaaEvent);
|
||||
} else {
|
||||
@@ -77,14 +76,14 @@ function removeTimepointAssociations() {
|
||||
}
|
||||
|
||||
// Log
|
||||
var hipaaEvent = {
|
||||
const hipaaEvent = {
|
||||
eventType: 'delete',
|
||||
userId: Meteor.userId(),
|
||||
userName: Meteor.user().profile.fullName,
|
||||
collectionName: "Timepoints",
|
||||
recordId: study.timepointId,
|
||||
patientId: study.patientId,
|
||||
patientName: study.patientName
|
||||
collectionName: 'Timepoints',
|
||||
recordId: selectedStudy.timepointId,
|
||||
patientId: selectedStudy.patientId,
|
||||
patientName: selectedStudy.patientName
|
||||
};
|
||||
HipaaLogger.logEvent(hipaaEvent);
|
||||
});
|
||||
@@ -94,43 +93,32 @@ function removeTimepointAssociations() {
|
||||
|
||||
// ---------- TODO: Remove these duplicated functions below -------------
|
||||
|
||||
|
||||
/**
|
||||
* Exports all selected studies on the studylist
|
||||
*/
|
||||
function exportSelectedStudies() {
|
||||
const selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch();
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
if (!selectedStudies || !selectedStudies.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
exportStudies(selectedStudies);
|
||||
OHIF.studylist.exportStudies(selectedStudies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads multiple unassociated studies in the Viewer
|
||||
*/
|
||||
function viewStudies() {
|
||||
console.log('viewStudies');
|
||||
const selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch();
|
||||
OHIF.log.info('viewStudies');
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
if (!selectedStudies || !selectedStudies.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
var title = selectedStudies[0].patientName;
|
||||
var studyInstanceUids = selectedStudies.map(function(study) {
|
||||
return study.studyInstanceUid;
|
||||
});
|
||||
const title = selectedStudies[0].patientName;
|
||||
const studyInstanceUids = selectedStudies.map(study => study.studyInstanceUid);
|
||||
|
||||
// Generate a unique ID to represent this tab
|
||||
// We can't just use the Mongo entry ID because
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import './components';
|
||||
import './lib';
|
||||
import './helpers';
|
||||
import './components';
|
||||
@@ -0,0 +1,6 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
OHIF.studylist = {
|
||||
collections: {},
|
||||
actions: {}
|
||||
};
|
||||
@@ -1,8 +1,10 @@
|
||||
import { Mongo } from 'meteor/mongo';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Servers as ServerSchema } from 'meteor/ohif:study-list/both/schema/servers.js';
|
||||
|
||||
StudyImportStatus = new Mongo.Collection('studyImportStatus');
|
||||
const StudyImportStatus = new Mongo.Collection('studyImportStatus');
|
||||
StudyImportStatus._debugName = 'StudyImportStatus';
|
||||
OHIF.studylist.collections.StudyImportStatus = StudyImportStatus;
|
||||
|
||||
// Servers describe the DICOM servers configurations
|
||||
Servers = new Mongo.Collection('servers');
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
import './lib';
|
||||
import './schema';
|
||||
import './base.js';
|
||||
import './collections.js';
|
||||
@@ -0,0 +1 @@
|
||||
import './getCurrentServer.js';
|
||||
@@ -0,0 +1 @@
|
||||
import './servers.js';
|
||||
@@ -0,0 +1 @@
|
||||
import './subscriptions.js';
|
||||
@@ -0,0 +1,5 @@
|
||||
import './progressDialog';
|
||||
import './seriesDetailsModal';
|
||||
import './serverInformation';
|
||||
import './studyContextMenu';
|
||||
import './studylist';
|
||||
@@ -0,0 +1,3 @@
|
||||
import './progressDialog.html';
|
||||
import './progressDialog.styl';
|
||||
import './progressDialog.js';
|
||||
@@ -6,14 +6,13 @@
|
||||
<div class="dialogContent">
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped active"
|
||||
role="progressbar"
|
||||
style="width:{{progressStatus}}">
|
||||
{{formatNumberPrecision progressStatus 0}}%
|
||||
</div>
|
||||
role="progressbar"
|
||||
style="width: {{progressStatus}}%"
|
||||
>{{formatNumberPrecision progressStatus 0}}%</div>
|
||||
</div>
|
||||
<div id="message">
|
||||
{{{progressMessage}}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
@@ -1,4 +1,28 @@
|
||||
progressDialog = {
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Session } from 'meteor/session';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
const updateProgress = numberOfCompleted => {
|
||||
const progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.numberOfCompleted = numberOfCompleted;
|
||||
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
|
||||
if (progressDialogSettings.numberOfCompleted === progressDialogSettings.numberOfTotal) {
|
||||
OHIF.studylist.progressDialog.close();
|
||||
}
|
||||
};
|
||||
|
||||
const setProgressMessage = message => {
|
||||
let progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.message = message;
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
};
|
||||
|
||||
OHIF.studylist.progressDialog = {
|
||||
update: _.debounce(updateProgress, 100),
|
||||
setMessage: _.debounce(setProgressMessage, 100),
|
||||
show: function(title, numberOfTotal) {
|
||||
Session.set('progressDialogSettings', {
|
||||
title: title,
|
||||
@@ -8,16 +32,6 @@ progressDialog = {
|
||||
|
||||
$('#progressDialog').css('display', 'block');
|
||||
},
|
||||
update: function(numberOfCompleted) {
|
||||
var progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.numberOfCompleted = numberOfCompleted;
|
||||
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
|
||||
if (progressDialogSettings.numberOfCompleted === progressDialogSettings.numberOfTotal) {
|
||||
progressDialog.close();
|
||||
}
|
||||
},
|
||||
close: function() {
|
||||
Session.set('progressDialogSettings', {
|
||||
title: '',
|
||||
@@ -26,17 +40,12 @@ progressDialog = {
|
||||
});
|
||||
|
||||
$('#progressDialog').css('display', 'none');
|
||||
},
|
||||
setMessage: function(message) {
|
||||
let progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.message = message;
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
}
|
||||
};
|
||||
|
||||
Template.progressDialog.helpers({
|
||||
progressDialogTitle() {
|
||||
var settings = Session.get('progressDialogSettings');
|
||||
const settings = Session.get('progressDialogSettings');
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
@@ -55,11 +64,11 @@ Template.progressDialog.helpers({
|
||||
return;
|
||||
}
|
||||
|
||||
return settings.numberOfCompleted / settings.numberOfTotal;
|
||||
return (settings.numberOfCompleted / settings.numberOfTotal) * 100;
|
||||
},
|
||||
|
||||
progressMessage() {
|
||||
var settings = Session.get('progressDialogSettings');
|
||||
const settings = Session.get('progressDialogSettings');
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import './viewSeriesDetailsModal.html';
|
||||
|
||||
import './seriesDetailsTable/seriesDetailsTable.html';
|
||||
import './seriesDetailsTable/seriesDetailsTable.styl';
|
||||
import './seriesDetailsTable/seriesDetailsTable.js';
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,15 @@
|
||||
import './serverInformationDicomWeb/serverInformationDicomWeb.html';
|
||||
import './serverInformationDicomWeb/serverInformationDicomWeb.js';
|
||||
|
||||
import './serverInformationDimse/serverInformationDimse.html';
|
||||
import './serverInformationDimse/serverInformationDimse.js';
|
||||
|
||||
import './serverInformationForm/serverInformationForm.html';
|
||||
import './serverInformationForm/serverInformationForm.js';
|
||||
|
||||
import './serverInformationList/serverInformationList.html';
|
||||
import './serverInformationList/serverInformationList.js';
|
||||
|
||||
import './serverInformationModal/serverInformationModal.html';
|
||||
import './serverInformationModal/serverInformationModal.styl';
|
||||
import './serverInformationModal/serverInformationModal.js';
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
<template name="serverInformationFormField">
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label class="wrapper">
|
||||
<span>{{this.label}}</span>
|
||||
<input type="text" name="{{this.name}}" class="form-control">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,2 @@
|
||||
import './studyContextMenu.html';
|
||||
import './studyContextMenu.js';
|
||||
@@ -1,25 +1,12 @@
|
||||
<template name="studyContextMenu">
|
||||
{{#if uiSettings.studyListFunctionsEnabled}}
|
||||
<div id="studyContextMenu" class="studyContextMenu noselect"
|
||||
oncontextmenu='return false;'
|
||||
unselectable='on'
|
||||
onselectstart='return false;'>
|
||||
<ul>
|
||||
<li>
|
||||
<a id="viewSeriesDetails" type="button"
|
||||
title="View Series Details">
|
||||
View Series Details
|
||||
</a>
|
||||
<a class="disabled">Anonymize</a>
|
||||
<a class="disabled">Send</a>
|
||||
<hr/>
|
||||
<a class="disabled">Delete</a>
|
||||
<a id="exportSelectedStudies"
|
||||
title="Export Selected Studies">
|
||||
Export
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#dropdownForm}}
|
||||
<li><a id="viewSeriesDetails" type="button"
|
||||
title="View Series Details"
|
||||
>View Series Details</a></li>
|
||||
<li class="disabled"><a class="disabled">Anonymize</a></li>
|
||||
<li class="disabled"><a class="disabled">Send</a></li>
|
||||
<li class="divider" role="separator"></li>
|
||||
<li class="disabled"><a class="disabled">Delete</a></li>
|
||||
<li><a id="exportSelectedStudies" title="Export Selected Studies">Export</a></li>
|
||||
{{/dropdownForm}}
|
||||
</template>
|
||||
@@ -1,84 +1,48 @@
|
||||
function closeHandler(dialog) {
|
||||
// Hide the dialog
|
||||
$(dialog).css('display', 'none');
|
||||
|
||||
// Remove the backdrop
|
||||
$('.removableBackdrop').remove();
|
||||
}
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* This function is used inside the StudyList package to define a right click callback
|
||||
*
|
||||
* @param e
|
||||
* @param event
|
||||
*/
|
||||
openStudyContextMenu = function(e) {
|
||||
StudyList.functions['exportSelectedStudies'] = exportSelectedStudies;
|
||||
StudyList.functions['viewSeriesDetails'] = viewSeriesDetails;
|
||||
|
||||
|
||||
Template.studyContextMenu.study = $(e.currentTarget);
|
||||
|
||||
var dialog = $('#studyContextMenu');
|
||||
|
||||
// Show the nonTargetLesion dialog above
|
||||
var dialogProperty = {
|
||||
display: 'block'
|
||||
};
|
||||
|
||||
var pageHeight = $(document).height();
|
||||
dialogProperty.top = Math.max(e.pageY, 0);
|
||||
dialogProperty.top = Math.min(dialogProperty.top, pageHeight - dialog.outerHeight());
|
||||
|
||||
var pageWidth = $(document).width();
|
||||
dialogProperty.left = Math.max(e.pageX, 0);
|
||||
dialogProperty.left = Math.min(dialogProperty.left, pageWidth - dialog.outerWidth());
|
||||
|
||||
// Device is touch device or not
|
||||
// If device is touch device, set position center of screen vertically and horizontally
|
||||
if (isTouchDevice()) {
|
||||
// add dialogMobile class to provide a black, transparent background
|
||||
dialog.addClass('dialogMobile');
|
||||
dialogProperty.top = 0;
|
||||
dialogProperty.left = 0;
|
||||
dialogProperty.right = 0;
|
||||
dialogProperty.bottom = 0;
|
||||
dialogProperty.margin = 'auto';
|
||||
openStudyContextMenu = event => {
|
||||
if (!OHIF.uiSettings.studyListFunctionsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.css(dialogProperty);
|
||||
dialog.focus();
|
||||
StudyList.functions.exportSelectedStudies = exportSelectedStudies;
|
||||
StudyList.functions.viewSeriesDetails = viewSeriesDetails;
|
||||
|
||||
// Show the backdrop
|
||||
UI.render(Template.removableBackdrop, document.body);
|
||||
Template.studyContextMenu.$study = $(event.currentTarget);
|
||||
|
||||
// Make sure the context menu is closed when the user clicks away
|
||||
$('.removableBackdrop').one('mousedown touchstart', function() {
|
||||
closeHandler(dialog);
|
||||
});
|
||||
const dropdown = OHIF.ui.showFormDropdown('studyContextMenu');
|
||||
const $dropdown = $(dropdown);
|
||||
const $dropdownMenu = $dropdown.children('.dropdown-menu');
|
||||
|
||||
dropdown.oncontextmenu = () => false;
|
||||
|
||||
$dropdownMenu.css({
|
||||
position: 'fixed',
|
||||
left: `${event.clientX}px`,
|
||||
top: `${event.clientY}px`,
|
||||
'z-index': 10000
|
||||
}).bounded().focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Exports all selected studies on the studylist
|
||||
*/
|
||||
function exportSelectedStudies() {
|
||||
var selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch() || [];
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
exportStudies(selectedStudies);
|
||||
OHIF.studylist.exportStudies(selectedStudies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display series details of study in modal
|
||||
*/
|
||||
function viewSeriesDetails() {
|
||||
var selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch();
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
if (!selectedStudies) {
|
||||
return;
|
||||
@@ -91,7 +55,7 @@ function viewSeriesDetails() {
|
||||
|
||||
Template.studyContextMenu.events({
|
||||
'click a': function(e) {
|
||||
var study = Template.studyContextMenu.study;
|
||||
var study = Template.studyContextMenu.$study;
|
||||
var id = $(e.currentTarget).attr('id');
|
||||
|
||||
var fn = StudyList.functions[id];
|
||||
@@ -100,6 +64,5 @@ Template.studyContextMenu.events({
|
||||
}
|
||||
|
||||
var dialog = $('#studyContextMenu');
|
||||
closeHandler(dialog);
|
||||
}
|
||||
});
|
||||
@@ -1,63 +0,0 @@
|
||||
@import "{design}/app"
|
||||
|
||||
.studyContextMenu
|
||||
z-index: 10000
|
||||
display: none
|
||||
position: absolute
|
||||
color: #2f2f2f
|
||||
background-color: #f2f2f2
|
||||
|
||||
width: -moz-fit-content
|
||||
width: -webkit-fit-content
|
||||
width: fit-content
|
||||
width: 207px
|
||||
|
||||
height: -moz-fit-content
|
||||
height: -webkit-fit-content
|
||||
height: fit-content
|
||||
|
||||
min-width: 100px
|
||||
font-size: 14px
|
||||
text-align: left
|
||||
-webkit-background-clip: padding-box
|
||||
background-clip: padding-box
|
||||
border: 1px solid rgba(0, 0, 0, .15)
|
||||
border-radius: 3px
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175)
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, .175)
|
||||
|
||||
hr
|
||||
border-top: solid 1px #d1d1d1
|
||||
margin: 2px
|
||||
|
||||
ul
|
||||
width: 100%
|
||||
margin: 5px 0
|
||||
list-style: none
|
||||
padding: 0
|
||||
|
||||
li
|
||||
clear: both
|
||||
white-space: nowrap
|
||||
|
||||
a
|
||||
padding: 3px 15px
|
||||
display: block
|
||||
text-decoration: none
|
||||
cursor: pointer
|
||||
font-size: 15px
|
||||
line-height: 1.7
|
||||
color: black
|
||||
|
||||
&:not(.disabled):hover
|
||||
theme('color', '$activeColor')
|
||||
text-decoration: none
|
||||
|
||||
&.disabled
|
||||
opacity: 0.4
|
||||
pointer-events: none
|
||||
cursor: default
|
||||
|
||||
.fa-lg
|
||||
width: 40px
|
||||
text-align: center
|
||||
@@ -0,0 +1,19 @@
|
||||
import './studylist.html';
|
||||
import './studylist.js';
|
||||
import './studylist.styl';
|
||||
|
||||
import './studylistStudy/studylistStudy.html';
|
||||
import './studylistStudy/studylistStudy.js';
|
||||
import './studylistStudy/studylistStudy.styl';
|
||||
|
||||
import './studylistResult/studylistResult.html';
|
||||
import './studylistResult/studylistResult.js';
|
||||
import './studylistResult/studylistResult.styl';
|
||||
|
||||
import './studylistToolbar/studylistToolbar.html';
|
||||
import './studylistToolbar/studylistToolbar.js';
|
||||
import './studylistToolbar/studylistToolbar.styl';
|
||||
|
||||
import './studylistPagination/studylistPagination.html';
|
||||
import './studylistPagination/studylistPagination.styl';
|
||||
import './studylistPagination/studylistPagination.js';
|
||||
+1
-2
@@ -14,6 +14,5 @@
|
||||
{{#each templateName in additionalTemplates}}
|
||||
{{> UI.dynamic template=templateName}}
|
||||
{{/each}}
|
||||
{{>studyContextMenu }}
|
||||
{{>progressDialog}}
|
||||
</template>
|
||||
</template>
|
||||
+1
-16
@@ -19,7 +19,7 @@ Session.setDefault('activeContentId', 'studylistTab');
|
||||
|
||||
Template.studylist.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
|
||||
if (StudyList.subscriptions) {
|
||||
StudyList.subscriptions.forEach(subscriptionName => {
|
||||
instance.subscribe(subscriptionName);
|
||||
@@ -44,18 +44,3 @@ Template.studylist.onRendered(() => {
|
||||
|
||||
Meteor.subscribe('hangingprotocols');
|
||||
});
|
||||
|
||||
Template.studylist.events({
|
||||
'click #tablist a[data-toggle="tab"]': function(e) {
|
||||
// If this tab is already active, do nothing
|
||||
const tabButton = $(e.currentTarget);
|
||||
const tabTitle = tabButton.parents('.tabTitle');
|
||||
if (tabTitle.hasClass('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, switch to the tab
|
||||
const contentId = tabButton.data('target').replace('#', '');
|
||||
switchToTab(contentId);
|
||||
}
|
||||
});
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,8 +0,0 @@
|
||||
<template name="tabTitle">
|
||||
<li role="presentation" class="tabTitle">
|
||||
<a data-target="#{{contentid}}" role="tab" data-toggle="tab">
|
||||
{{title}}
|
||||
<button class="close">×</button>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
@@ -1,42 +0,0 @@
|
||||
Template.tabTitle.events({
|
||||
/**
|
||||
* Closes a tab when the close button is pressed in the title
|
||||
* The next tab to the left is loaded if the current tab is closed
|
||||
*
|
||||
* @param e The click event used to close the tab
|
||||
*/
|
||||
'click .close': function(e) {
|
||||
console.log('click .close');
|
||||
|
||||
// Identify the tab title DOM node
|
||||
var tab = $(e.currentTarget).parents('a[data-toggle="tab"]').eq(0);
|
||||
|
||||
// Get the relevent contentId that this tab title represents
|
||||
// Replace any hash marks (#) that were required by Bootstrap's tab switching
|
||||
var contentId = tab.data('target').replace('#', '');
|
||||
|
||||
// Check if we are closing the active tab. If we are, prepare to switch
|
||||
// to the next tab to the left.
|
||||
var activeContentId = Session.get('activeContentId');
|
||||
if (activeContentId === contentId) {
|
||||
// Find the index of the tab that is being closed
|
||||
var tabIndex = tab.parent('li').index();
|
||||
|
||||
// Find the index the tab to its left
|
||||
var newActiveTabIndex = Math.max(tabIndex - 1, 0);
|
||||
|
||||
// Find the DOM node of the tab that will be activated
|
||||
var newActiveTab = $('.tabTitle').eq(newActiveTabIndex);
|
||||
|
||||
// Find the content ID of the tab that will be switched to
|
||||
var newActiveTabLink = newActiveTab.find('a[data-toggle=tab]');
|
||||
var newContentId = newActiveTabLink.data('target').replace('#', '');
|
||||
|
||||
// Switch to this tab
|
||||
switchToTab(newContentId);
|
||||
}
|
||||
|
||||
// Remove any stored data related to this tab from the global ViewerData structure
|
||||
delete ViewerData[contentId];
|
||||
}
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
.tabTitle
|
||||
button.close
|
||||
// Prevent blue glow around button in Chrome
|
||||
outline: none
|
||||
@@ -0,0 +1,3 @@
|
||||
import './collections';
|
||||
import './lib';
|
||||
import './components';
|
||||
@@ -1,10 +1,13 @@
|
||||
var exportFailed;
|
||||
import { JSZip } from 'meteor/silentcicero:jszip';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
let exportFailed;
|
||||
|
||||
/**
|
||||
* Exports requested studies
|
||||
* @param studiesToExport Studies to export
|
||||
*/
|
||||
exportStudies = function(studiesToExport) {
|
||||
OHIF.studylist.exportStudies = studiesToExport => {
|
||||
if (studiesToExport.length < 1) {
|
||||
return;
|
||||
}
|
||||
@@ -12,37 +15,45 @@ exportStudies = function(studiesToExport) {
|
||||
queryStudies(studiesToExport, exportQueriedStudies);
|
||||
};
|
||||
|
||||
function exportQueriedStudies(studiesToExport) {
|
||||
var numberOfFilesToExport = 0;
|
||||
studiesToExport.forEach(function(study) {
|
||||
const exportQueriedStudies = studiesToExport => {
|
||||
let numberOfFilesToExport = 0;
|
||||
studiesToExport.forEach(study => {
|
||||
numberOfFilesToExport += getNumberOfFilesInStudy(study);
|
||||
});
|
||||
|
||||
progressDialog.show("Exporting Studies...", numberOfFilesToExport);
|
||||
OHIF.studylist.progressDialog.show('Exporting Studies...', numberOfFilesToExport);
|
||||
|
||||
try {
|
||||
exportQueriedStudiesInternal(studiesToExport, numberOfFilesToExport);
|
||||
} catch (err) {
|
||||
progressDialog.close();
|
||||
console.error("Failed to export studies: " + err.message);
|
||||
OHIF.studylist.progressDialog.close();
|
||||
OHIF.log.error(`Failed to export studies: ${err.message}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
function exportQueriedStudiesInternal(studiesToExport, numberOfFilesToExport) {
|
||||
var zip = new JSZip();
|
||||
const exportQueriedStudiesInternal = (studiesToExport, numberOfFilesToExport) => {
|
||||
const zip = new JSZip();
|
||||
|
||||
exportFailed = false;
|
||||
var numberOfFilesExported = 0;
|
||||
let numberOfFilesExported = 0;
|
||||
|
||||
studiesToExport.forEach(function(study) {
|
||||
const onExportFailed = err => {
|
||||
exportFailed = true;
|
||||
OHIF.studylist.progressDialog.close();
|
||||
|
||||
//TODO: Export failed and dialog closed, so let user know
|
||||
OHIF.log.error('Failed to export studies!', err);
|
||||
};
|
||||
|
||||
studiesToExport.forEach(study => {
|
||||
sortStudy(study);
|
||||
|
||||
var studyFolder = zip.folder(study.studyInstanceUid);
|
||||
const studyFolder = zip.folder(study.studyInstanceUid);
|
||||
|
||||
study.seriesList.forEach(function(series) {
|
||||
var seriesFolder = studyFolder.folder(series.seriesInstanceUid);
|
||||
study.seriesList.forEach(series => {
|
||||
const seriesFolder = studyFolder.folder(series.seriesInstanceUid);
|
||||
|
||||
series.instances.forEach(function(instance) {
|
||||
series.instances.forEach(instance => {
|
||||
if (!instance.wadouri) {
|
||||
return;
|
||||
}
|
||||
@@ -53,12 +64,12 @@ function exportQueriedStudiesInternal(studiesToExport, numberOfFilesToExport) {
|
||||
}
|
||||
|
||||
// Download and Zip the dicom file
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("GET", instance.wadouri, true);
|
||||
xhr.responseType = "blob";
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('GET', instance.wadouri, true);
|
||||
xhr.responseType = 'blob';
|
||||
|
||||
// Downloaded the dicom file completely
|
||||
xhr.onload = function(e) {
|
||||
xhr.onload = () => {
|
||||
// If failed to download a dicom file, skip others
|
||||
if (exportFailed) {
|
||||
return;
|
||||
@@ -66,17 +77,17 @@ function exportQueriedStudiesInternal(studiesToExport, numberOfFilesToExport) {
|
||||
|
||||
// Failed to export a file
|
||||
if (xhr.readyState === 4 && xhr.status !== 200) {
|
||||
onExportFailed("File not downloaded: " + instance.wadouri);
|
||||
onExportFailed(`File not downloaded: ${instance.wadouri}`);
|
||||
return;
|
||||
}
|
||||
|
||||
var blobFile = new Blob([xhr.response], {type: 'application/dicom'});
|
||||
const blobFile = new Blob([xhr.response], { type: 'application/dicom' });
|
||||
|
||||
var fileReader = new FileReader();
|
||||
const fileReader = new FileReader();
|
||||
|
||||
fileReader.onload = function() {
|
||||
fileReader.onload = () => {
|
||||
try {
|
||||
seriesFolder.file(instance.sopInstanceUid + ".dcm", fileReader.result, { binary: true });
|
||||
seriesFolder.file(`${instance.sopInstanceUid}.dcm`, fileReader.result, { binary: true });
|
||||
} catch(err) {
|
||||
onExportFailed(err.message);
|
||||
return;
|
||||
@@ -85,31 +96,21 @@ function exportQueriedStudiesInternal(studiesToExport, numberOfFilesToExport) {
|
||||
numberOfFilesExported++;
|
||||
|
||||
if (numberOfFilesExported === numberOfFilesToExport) {
|
||||
var zipContent = zip.generate({ type: "blob" });
|
||||
saveAs(zipContent, "studies.zip");
|
||||
const zipContent = zip.generate({ type: 'blob' });
|
||||
saveAs(zipContent, 'studies.zip');
|
||||
}
|
||||
|
||||
progressDialog.update(numberOfFilesExported);
|
||||
OHIF.studylist.progressDialog.update(numberOfFilesExported);
|
||||
};
|
||||
|
||||
fileReader.readAsArrayBuffer(blobFile);
|
||||
};
|
||||
|
||||
// Failed to download the dicom file
|
||||
xhr.onerror = function() {
|
||||
onExportFailed("File not downloaded: " + instance.wadouri);
|
||||
};
|
||||
xhr.onerror = () => onExportFailed(`File not downloaded: ${instance.wadouri}`);
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function onExportFailed(err) {
|
||||
exportFailed = true;
|
||||
progressDialog.close();
|
||||
|
||||
//TODO: Export failed and dialog closed, so let user know
|
||||
console.error("Failed to export studies!", err);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,9 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
OHIF.studylist.getSelectedStudies = () => {
|
||||
return StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch() || [];
|
||||
};
|
||||
@@ -1,3 +1,4 @@
|
||||
import { $ } from 'meteor/jquery';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
@@ -10,7 +11,7 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
* @param doneCallback The callback function to be executed when the study retrieval has finished
|
||||
* @param failCallback The callback function to be executed when the study retrieval has failed
|
||||
*/
|
||||
getStudiesMetadata = function(studyInstanceUids, doneCallback, failCallback) {
|
||||
OHIF.studylist.getStudiesMetadata = (studyInstanceUids, doneCallback, failCallback) => {
|
||||
// Check to make sure studyInstanceUids were actually input
|
||||
if (!studyInstanceUids || !studyInstanceUids.length) {
|
||||
if (failCallback && typeof failCallback === 'function') {
|
||||
@@ -22,13 +23,13 @@ getStudiesMetadata = function(studyInstanceUids, doneCallback, failCallback) {
|
||||
|
||||
// Create an empty array to store the Promises for each metaData
|
||||
// retrieval call
|
||||
var promises = [];
|
||||
const promises = [];
|
||||
|
||||
// Loop through the array of studyInstanceUids
|
||||
studyInstanceUids.forEach(function(studyInstanceUid) {
|
||||
// Create a new Deferred to monitor the progress of the asynchronous
|
||||
// metaData retrieval
|
||||
var deferred = new $.Deferred();
|
||||
const deferred = new $.Deferred();
|
||||
|
||||
// Send the call, and attach doneCallbacks and failCallbacks
|
||||
// which can resolve or reject the related promise based on its outcome
|
||||
@@ -45,7 +46,7 @@ getStudiesMetadata = function(studyInstanceUids, doneCallback, failCallback) {
|
||||
// When all of the promises are complete, this callback runs
|
||||
$.when.apply($, promises).done(function() {
|
||||
// Convert the Arguments Array-like Object to an actual array
|
||||
var studies = $.makeArray(arguments);
|
||||
const studies = $.makeArray(arguments);
|
||||
|
||||
// Pass the studies array to the doneCallback, if one exists
|
||||
if (doneCallback && typeof doneCallback === 'function') {
|
||||
|
||||
@@ -14,7 +14,7 @@ importStudies = function(filesToImport, importCallback) {
|
||||
};
|
||||
var numberOfFilesToUpload = filesToImport.length;
|
||||
var studiesToImport = [];
|
||||
progressDialog.show({
|
||||
OHIF.studylist.progressDialog.show({
|
||||
title: "Uploading Files...",
|
||||
numberOfCompleted: 0,
|
||||
numberOfTotal: numberOfFilesToUpload
|
||||
@@ -38,7 +38,7 @@ importStudies = function(filesToImport, importCallback) {
|
||||
updateFileUploadStatus(fileUploadStatus, true);
|
||||
|
||||
var numberOfFilesProcessedToUpload = fileUploadStatus.numberOfFilesUploaded + fileUploadStatus.numberOfFilesFailed;
|
||||
progressDialog.update(numberOfFilesProcessedToUpload);
|
||||
OHIF.studylist.progressDialog.update(numberOfFilesProcessedToUpload);
|
||||
|
||||
if (numberOfFilesToUpload === numberOfFilesProcessedToUpload) {
|
||||
// The upload is completed, so import files
|
||||
@@ -74,7 +74,7 @@ function importStudiesInternal(studiesToImport, importCallback) {
|
||||
|
||||
var numberOfStudiesToImport = studiesToImport.length;
|
||||
|
||||
progressDialog.show({
|
||||
OHIF.studylist.progressDialog.show({
|
||||
title: "Importing Studies...",
|
||||
numberOfCompleted: 0,
|
||||
numberOfTotal: numberOfStudiesToImport
|
||||
@@ -84,13 +84,13 @@ function importStudiesInternal(studiesToImport, importCallback) {
|
||||
Meteor.call("createStudyImportStatus", function(err, studyImportStatusId) {
|
||||
if (err) {
|
||||
// Hide dialog
|
||||
progressDialog.close();
|
||||
OHIF.studylist.progressDialog.close();
|
||||
console.log(err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
// Handle when StudyImportStatus collection is updated
|
||||
StudyImportStatus.find(studyImportStatusId).observe({
|
||||
OHIF.studylist.collections.StudyImportStatus.find(studyImportStatusId).observe({
|
||||
changed: function(studyImportStatus) {
|
||||
if (!studyImportStatus) {
|
||||
return;
|
||||
@@ -100,16 +100,16 @@ function importStudiesInternal(studiesToImport, importCallback) {
|
||||
|
||||
// Show number of imported files
|
||||
var successMessage = 'Imported '+studyImportStatus.numberOfStudiesImported+' of '+numberOfStudiesToImport;
|
||||
progressDialog.setMessage({
|
||||
OHIF.studylist.progressDialog.setMessage({
|
||||
message: successMessage,
|
||||
messageType: 'success'
|
||||
});
|
||||
progressDialog.update(numberOfStudiesProcessedToImport);
|
||||
OHIF.studylist.progressDialog.update(numberOfStudiesProcessedToImport);
|
||||
|
||||
// Show number of failed files if there is at least one failed file
|
||||
if (studyImportStatus.numberOfStudiesFailed > 0) {
|
||||
var successMessage = 'Failed '+studyImportStatus.numberOfStudiesFailed+' of '+numberOfStudiesToImport;
|
||||
progressDialog.setMessage({
|
||||
OHIF.studylist.progressDialog.setMessage({
|
||||
message: successMessage,
|
||||
messageType: 'warning'
|
||||
});
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
import './third-party/jquery.twbsPagination.min.js';
|
||||
|
||||
import './exportStudies.js';
|
||||
import './getSelectedStudies.js';
|
||||
import './getStudyMetadata.js';
|
||||
import './getStudiesMetadata.js';
|
||||
import './importStudies.js';
|
||||
import './openNewTab.js';
|
||||
import './queryStudies.js';
|
||||
import './studylist.js';
|
||||
import './switchToTab.js';
|
||||
@@ -1,3 +1,5 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Queries requested studies to get their metadata from PACS
|
||||
* @param studiesToQuery Studies to query
|
||||
@@ -11,7 +13,7 @@ queryStudies = function(studiesToQuery, doneCallback) {
|
||||
var studiesQueried = [];
|
||||
var numberOfStudiesToQuery = studiesToQuery.length;
|
||||
|
||||
progressDialog.show("Querying Studies...", numberOfStudiesToQuery);
|
||||
OHIF.studylist.progressDialog.show("Querying Studies...", numberOfStudiesToQuery);
|
||||
|
||||
studiesToQuery.forEach(function(studyToQuery) {
|
||||
getStudyMetadata(studyToQuery.studyInstanceUid, function(study) {
|
||||
@@ -19,7 +21,7 @@ queryStudies = function(studiesToQuery, doneCallback) {
|
||||
|
||||
var numberOfStudiesQueried = studiesQueried.length;
|
||||
|
||||
progressDialog.update(numberOfStudiesQueried);
|
||||
OHIF.studylist.progressDialog.update(numberOfStudiesQueried);
|
||||
|
||||
if (numberOfStudiesQueried === numberOfStudiesToQuery) {
|
||||
doneCallback(studiesQueried);
|
||||
@@ -45,4 +47,4 @@ getNumberOfFilesInStudy = function(study) {
|
||||
});
|
||||
|
||||
return numberOFFilesToExport;
|
||||
};
|
||||
};
|
||||
@@ -13,9 +13,6 @@ switchToTab = function(contentId) {
|
||||
|
||||
OHIF.log.info('Switching to tab: ' + contentId);
|
||||
|
||||
$('.tabTitle').removeClass('active');
|
||||
$('.tabTitle a[data-target="#' + contentId + '"]').addClass('active');
|
||||
|
||||
$('.tab-content .tab-pane').removeClass('active');
|
||||
if (contentId !== 'studylistTab') {
|
||||
$('.tab-content .tab-pane#viewerTab').addClass('active');
|
||||
@@ -71,7 +68,7 @@ switchToTab = function(contentId) {
|
||||
var studyInstanceUids = ViewerData[contentId].studyInstanceUids;
|
||||
|
||||
// Attempt to retrieve the meta data (it might be cached)
|
||||
getStudiesMetadata(studyInstanceUids, function(studies) {
|
||||
OHIF.studylist.getStudiesMetadata(studyInstanceUids, function(studies) {
|
||||
viewStudiesInTab(contentId, studies);
|
||||
});
|
||||
}
|
||||
|
||||
File renamed without changes.
@@ -1,10 +1,10 @@
|
||||
Package.describe({
|
||||
name: "ohif:study-list",
|
||||
summary: "Basic study list for web-based DICOM viewers",
|
||||
version: '0.0.1'
|
||||
name: 'ohif:study-list',
|
||||
summary: 'Basic study list for web-based DICOM viewers',
|
||||
version: '0.0.1'
|
||||
});
|
||||
|
||||
Package.onUse(function (api) {
|
||||
Package.onUse(function(api) {
|
||||
api.versionsFrom('1.4');
|
||||
|
||||
api.use('ecmascript');
|
||||
@@ -34,109 +34,14 @@ Package.onUse(function (api) {
|
||||
// TODO: Replace with NPM dependency
|
||||
api.use('ohif:cornerstone'); // Only for HammerJS
|
||||
|
||||
api.addFiles('both/collections.js', ['client', 'server']);
|
||||
api.addFiles('both/schema/servers.js', ['client', 'server']);
|
||||
api.addFiles('both/lib/getCurrentServer.js', ['client', 'server']);
|
||||
// Client and server imports
|
||||
api.addFiles('both/index.js', [ 'client', 'server' ]);
|
||||
|
||||
// Client collections and subscriptions
|
||||
api.addFiles('client/collections/subscriptions.js', 'client');
|
||||
// Server imports
|
||||
api.addFiles('server/index.js', 'server');
|
||||
|
||||
// Components
|
||||
api.addFiles('client/components/studylist.html', 'client');
|
||||
api.addFiles('client/components/studylist.js', 'client');
|
||||
api.addFiles('client/components/studylist.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/tabTitle/tabTitle.html', 'client');
|
||||
api.addFiles('client/components/tabTitle/tabTitle.js', 'client');
|
||||
api.addFiles('client/components/tabTitle/tabTitle.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/studylistStudy/studylistStudy.html', 'client');
|
||||
api.addFiles('client/components/studylistStudy/studylistStudy.js', 'client');
|
||||
api.addFiles('client/components/studylistStudy/studylistStudy.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/studylistResult/studylistResult.html', 'client');
|
||||
api.addFiles('client/components/studylistResult/studylistResult.js', 'client');
|
||||
api.addFiles('client/components/studylistResult/studylistResult.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/studyContextMenu/studyContextMenu.html', 'client');
|
||||
api.addFiles('client/components/studyContextMenu/studyContextMenu.js', 'client');
|
||||
api.addFiles('client/components/studyContextMenu/studyContextMenu.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/studylistToolbar/studylistToolbar.html', 'client');
|
||||
api.addFiles('client/components/studylistToolbar/studylistToolbar.js', 'client');
|
||||
api.addFiles('client/components/studylistToolbar/studylistToolbar.styl', 'client');
|
||||
|
||||
api.addFiles('client/components/progressDialog/progressDialog.html', 'client');
|
||||
api.addFiles('client/components/progressDialog/progressDialog.styl', 'client');
|
||||
api.addFiles('client/components/progressDialog/progressDialog.js', 'client');
|
||||
|
||||
api.addFiles('client/components/studylistPagination/studylistPagination.html', 'client');
|
||||
api.addFiles('client/components/studylistPagination/studylistPagination.styl', 'client');
|
||||
api.addFiles('client/components/studylistPagination/studylistPagination.js', 'client');
|
||||
|
||||
api.addFiles('client/components/viewSeriesDetailsModal/viewSeriesDetailsModal.html', 'client');
|
||||
|
||||
api.addFiles('client/components/seriesDetailsTable/seriesDetailsTable.html', 'client');
|
||||
api.addFiles('client/components/seriesDetailsTable/seriesDetailsTable.styl', 'client');
|
||||
api.addFiles('client/components/seriesDetailsTable/seriesDetailsTable.js', 'client');
|
||||
|
||||
api.addFiles('client/components/serverInformation/serverInformationDicomWeb/serverInformationDicomWeb.html', 'client');
|
||||
api.addFiles('client/components/serverInformation/serverInformationDicomWeb/serverInformationDicomWeb.js', 'client');
|
||||
|
||||
api.addFiles('client/components/serverInformation/serverInformationDimse/serverInformationDimse.html', 'client');
|
||||
api.addFiles('client/components/serverInformation/serverInformationDimse/serverInformationDimse.js', 'client');
|
||||
|
||||
api.addFiles('client/components/serverInformation/serverInformationForm/serverInformationForm.html', 'client');
|
||||
api.addFiles('client/components/serverInformation/serverInformationForm/serverInformationForm.js', 'client');
|
||||
api.addFiles('client/components/serverInformation/serverInformationForm/serverInformationFormField.html', 'client');
|
||||
|
||||
api.addFiles('client/components/serverInformation/serverInformationList/serverInformationList.html', 'client');
|
||||
api.addFiles('client/components/serverInformation/serverInformationList/serverInformationList.js', 'client');
|
||||
|
||||
api.addFiles('client/components/serverInformation/serverInformationModal/serverInformationModal.html', 'client');
|
||||
api.addFiles('client/components/serverInformation/serverInformationModal/serverInformationModal.styl', 'client');
|
||||
api.addFiles('client/components/serverInformation/serverInformationModal/serverInformationModal.js', 'client');
|
||||
|
||||
// Client-side library functions
|
||||
api.addFiles('client/lib/getStudyMetadata.js', 'client');
|
||||
api.addFiles('client/lib/getStudiesMetadata.js', 'client');
|
||||
api.addFiles('client/lib/openNewTab.js', 'client');
|
||||
api.addFiles('client/lib/switchToTab.js', 'client');
|
||||
api.addFiles('client/lib/exportStudies.js', 'client');
|
||||
api.addFiles('client/lib/studylist.js', 'client');
|
||||
api.addFiles('client/lib/queryStudies.js', 'client');
|
||||
api.addFiles('client/lib/importStudies.js', 'client');
|
||||
api.addFiles('client/lib/jquery.twbsPagination/jquery.twbsPagination.min.js', 'client');
|
||||
|
||||
// Server-side functions
|
||||
api.addFiles('server/publications.js', 'server');
|
||||
api.addFiles('server/validateServerConfiguration.js', 'server');
|
||||
api.addFiles('server/servers.js', 'server');
|
||||
api.addFiles('server/lib/remoteGetValue.js', 'server');
|
||||
api.addFiles('server/lib/encodeQueryData.js', 'server');
|
||||
api.addFiles('server/lib/parseFloatArray.js', 'server');
|
||||
|
||||
api.addFiles('server/methods/getStudyMetadata.js', 'server');
|
||||
api.addFiles('server/methods/importStudies.js', 'server');
|
||||
api.addFiles('server/methods/studylistSearch.js', 'server');
|
||||
|
||||
api.addFiles('server/services/namespace.js', 'server');
|
||||
|
||||
// DICOMWeb instance, study, and metadata retrieval
|
||||
api.addFiles('server/services/qido/instances.js', 'server');
|
||||
api.addFiles('server/services/qido/studies.js', 'server');
|
||||
api.addFiles('server/services/wado/retrieveMetadata.js', 'server');
|
||||
|
||||
// DIMSE instance, study, and metadata retrieval
|
||||
api.addFiles('server/services/dimse/instances.js', 'server');
|
||||
api.addFiles('server/services/dimse/studies.js', 'server');
|
||||
api.addFiles('server/services/dimse/retrieveMetadata.js', 'server');
|
||||
api.addFiles('server/services/dimse/setup.js', 'server');
|
||||
|
||||
// Study, instance, and metadata retrieval from remote PACS via Orthanc as a proxy
|
||||
api.addFiles('server/services/remote/instances.js', 'server');
|
||||
api.addFiles('server/services/remote/studies.js', 'server');
|
||||
api.addFiles('server/services/remote/retrieveMetadata.js', 'server');
|
||||
// Client imports
|
||||
api.addFiles('client/index.js', 'client');
|
||||
|
||||
// Export Servers and CurrentServer Collections
|
||||
api.export('Servers', ['client', 'server']);
|
||||
@@ -149,10 +54,8 @@ Package.onUse(function (api) {
|
||||
|
||||
// Export StudyList helper functions for usage in Routes
|
||||
api.export('getStudyMetadata', 'client');
|
||||
api.export('getStudiesMetadata', 'client');
|
||||
api.export('openNewTab', 'client');
|
||||
api.export('switchToTab', 'client');
|
||||
api.export('progressDialog', 'client');
|
||||
api.export('StudyList');
|
||||
|
||||
// Export the global ViewerData object
|
||||
@@ -160,5 +63,5 @@ Package.onUse(function (api) {
|
||||
|
||||
// Export the Collections
|
||||
api.export('StudyListStudies', 'client');
|
||||
api.export('StudyListSelectedStudies', 'client')
|
||||
api.export('StudyListSelectedStudies', 'client');
|
||||
});
|
||||
@@ -0,0 +1,6 @@
|
||||
import './publications.js';
|
||||
import './validateServerConfiguration.js';
|
||||
|
||||
import './lib';
|
||||
import './methods';
|
||||
import './services';
|
||||
@@ -0,0 +1,2 @@
|
||||
import './remoteGetValue.js';
|
||||
import './encodeQueryData.js';
|
||||
@@ -1,4 +1,4 @@
|
||||
import { StudyImportStatus } from '../../both/collections';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
var fs = Npm.require('fs');
|
||||
var fiber = Npm.require('fibers');
|
||||
@@ -73,14 +73,14 @@ Meteor.methods({
|
||||
*/
|
||||
createStudyImportStatus: function() {
|
||||
var studyImportStatus = { numberOfStudiesImported: 0, numberOfStudiesFailed: 0 };
|
||||
return StudyImportStatus.insert(studyImportStatus);
|
||||
return OHIF.studylist.collections.StudyImportStatus.insert(studyImportStatus);
|
||||
},
|
||||
/**
|
||||
* Remove the study import status item from the collection
|
||||
* @param id Collection id of the study import status in the collection
|
||||
*/
|
||||
removeStudyImportStatus: function(id) {
|
||||
StudyImportStatus.remove(id);
|
||||
OHIF.studylist.collections.StudyImportStatus.remove(id);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -96,16 +96,16 @@ function importStudiesDIMSE(studiesToImport, studyImportStatusId) {
|
||||
try {
|
||||
// Update the import status
|
||||
if (err) {
|
||||
StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
||||
console.log("Failed to import study via DIMSE: ", file, err);
|
||||
} else {
|
||||
StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesImported': 1}});
|
||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesImported': 1}});
|
||||
console.log("Study successfully imported via DIMSE: ", file);
|
||||
}
|
||||
|
||||
} catch(error) {
|
||||
|
||||
StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
||||
console.log("Failed to import study via DIMSE: ", file, error);
|
||||
} finally {
|
||||
// The import operation of this file is completed, so delete it if still exists
|
||||
@@ -116,7 +116,7 @@ function importStudiesDIMSE(studiesToImport, studyImportStatusId) {
|
||||
|
||||
}).run();
|
||||
} catch(error) {
|
||||
StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
||||
console.log("Failed to import study via DIMSE: ", file, error);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
import './getStudyMetadata.js';
|
||||
import './importStudies.js';
|
||||
import './studylistSearch.js';
|
||||
@@ -1,5 +1,8 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Meteor.publish('studyImportStatus', () => {
|
||||
return StudyImportStatus.find();
|
||||
return OHIF.studylist.collections.StudyImportStatus.find();
|
||||
});
|
||||
|
||||
Meteor.publish('servers', () => {
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import './namespace.js';
|
||||
|
||||
// DICOMWeb instance, study, and metadata retrieval
|
||||
import './qido/instances.js';
|
||||
import './qido/studies.js';
|
||||
import './wado/retrieveMetadata.js';
|
||||
|
||||
// DIMSE instance, study, and metadata retrieval
|
||||
import './dimse/instances.js';
|
||||
import './dimse/studies.js';
|
||||
import './dimse/retrieveMetadata.js';
|
||||
|
||||
// Study, instance, and metadata retrieval from remote PACS via Orthanc as a proxy
|
||||
import './remote/instances.js';
|
||||
import './remote/studies.js';
|
||||
import './remote/retrieveMetadata.js';
|
||||
@@ -183,7 +183,6 @@ Package.onUse(function(api) {
|
||||
api.export('updateAllViewports', 'client');
|
||||
api.export('queryStudies', 'client');
|
||||
api.export('getNumberOfFilesInStudy', 'client');
|
||||
api.export('exportStudies', 'client');
|
||||
api.export('importStudies', 'client');
|
||||
api.export('getActiveViewportElement', 'client');
|
||||
api.export('getInstanceClassDefaultViewport', 'client');
|
||||
|
||||
Reference in new issue
Block a user