Fixing serverId issues
This commit is contained in:
parent
95533c785b
commit
b4bb44625c
@ -99,6 +99,7 @@ ohif:measurements@0.0.1
|
|||||||
ohif:metadata@0.0.1
|
ohif:metadata@0.0.1
|
||||||
ohif:polyfill@0.0.1
|
ohif:polyfill@0.0.1
|
||||||
ohif:select-tree@0.0.1
|
ohif:select-tree@0.0.1
|
||||||
|
ohif:servers@0.0.1
|
||||||
ohif:study-list@0.0.1
|
ohif:study-list@0.0.1
|
||||||
ohif:themes@0.0.1
|
ohif:themes@0.0.1
|
||||||
ohif:themes-common@0.0.1
|
ohif:themes-common@0.0.1
|
||||||
|
|||||||
@ -32,6 +32,7 @@ Meteor.startup(() => {
|
|||||||
|
|
||||||
Template.viewer.onCreated(() => {
|
Template.viewer.onCreated(() => {
|
||||||
Session.set('ViewerReady', false);
|
Session.set('ViewerReady', false);
|
||||||
|
console.warn('>>>>viewer.data', Template.instance().data);
|
||||||
|
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
|||||||
@ -37,9 +37,7 @@ Router.route('/studylist', {
|
|||||||
|
|
||||||
// Retrieve the timepoints data to display in studylist
|
// Retrieve the timepoints data to display in studylist
|
||||||
const promise = OHIF.studylist.timepointApi.retrieveTimepoints({});
|
const promise = OHIF.studylist.timepointApi.retrieveTimepoints({});
|
||||||
promise.then(() => {
|
promise.then(() => next());
|
||||||
next()
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
action: function() {
|
action: function() {
|
||||||
this.render('app', { data: { template: 'studylist' } });
|
this.render('app', { data: { template: 'studylist' } });
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
import loglevel from 'loglevel';
|
import loglevel from 'loglevel';
|
||||||
|
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class TimepointApi {
|
|||||||
retrieveTimepoints(filter) {
|
retrieveTimepoints(filter) {
|
||||||
const retrievalFn = configuration.dataExchange.retrieve;
|
const retrievalFn = configuration.dataExchange.retrieve;
|
||||||
if (!_.isFunction(retrievalFn)) {
|
if (!_.isFunction(retrievalFn)) {
|
||||||
OHIF.log.error('Timepoint retrieval function has not been configured.')
|
OHIF.log.error('Timepoint retrieval function has not been configured.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -156,6 +156,9 @@ class ConformanceCriteria {
|
|||||||
|
|
||||||
const promise = OHIF.studylist.retrieveStudyMetadata(studyInstanceUid);
|
const promise = OHIF.studylist.retrieveStudyMetadata(studyInstanceUid);
|
||||||
promise.then(study => {
|
promise.then(study => {
|
||||||
|
cornerstone.loadImage(imageId).then(image => {
|
||||||
|
console.warn('>>>>LOADED', image);
|
||||||
|
});
|
||||||
const metadata = OHIF.viewer.metadataProvider.getMetadata(imageId);
|
const metadata = OHIF.viewer.metadataProvider.getMetadata(imageId);
|
||||||
data[measurementType].push({
|
data[measurementType].push({
|
||||||
measurement,
|
measurement,
|
||||||
|
|||||||
5
Packages/ohif-servers/both/base.js
Normal file
5
Packages/ohif-servers/both/base.js
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
OHIF.servers = {
|
||||||
|
collections: {}
|
||||||
|
};
|
||||||
9
Packages/ohif-servers/both/collections/currentServer.js
Normal file
9
Packages/ohif-servers/both/collections/currentServer.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Mongo } from 'meteor/mongo';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
// CurrentServer is a single document collection to describe which of the Servers is being used
|
||||||
|
const CurrentServer = new Mongo.Collection('currentServer');
|
||||||
|
CurrentServer._debugName = 'CurrentServer';
|
||||||
|
OHIF.servers.collections.currentServer = CurrentServer;
|
||||||
|
|
||||||
|
export { CurrentServer };
|
||||||
4
Packages/ohif-servers/both/collections/index.js
Normal file
4
Packages/ohif-servers/both/collections/index.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import { CurrentServer } from './currentServer.js';
|
||||||
|
import { Servers } from './servers.js';
|
||||||
|
|
||||||
|
export { CurrentServer, Servers };
|
||||||
12
Packages/ohif-servers/both/collections/servers.js
Normal file
12
Packages/ohif-servers/both/collections/servers.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { Mongo } from 'meteor/mongo';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
// import { Servers as ServerSchema } from 'meteor/ohif:servers/both/schema/servers.js';
|
||||||
|
|
||||||
|
// Servers describe the DICOM servers configurations
|
||||||
|
const Servers = new Mongo.Collection('servers');
|
||||||
|
// TODO: Make the Schema match what we are currently sticking into the Collection
|
||||||
|
//Servers.attachSchema(ServerSchema);
|
||||||
|
Servers._debugName = 'Servers';
|
||||||
|
OHIF.servers.collections.servers = Servers;
|
||||||
|
|
||||||
|
export { Servers };
|
||||||
3
Packages/ohif-servers/both/index.js
Normal file
3
Packages/ohif-servers/both/index.js
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import './base.js';
|
||||||
|
import './collections';
|
||||||
|
import './lib';
|
||||||
@ -1,7 +1,10 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { Servers, CurrentServer } from 'meteor/ohif:servers/both/collections';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the current server configuration used to retrieve studies
|
* Retrieves the current server configuration used to retrieve studies
|
||||||
*/
|
*/
|
||||||
getCurrentServer = () => {
|
OHIF.servers.getCurrentServer = () => {
|
||||||
const currentServer = CurrentServer.findOne();
|
const currentServer = CurrentServer.findOne();
|
||||||
|
|
||||||
if (!currentServer) {
|
if (!currentServer) {
|
||||||
1
Packages/ohif-servers/client/collections/index.js
Normal file
1
Packages/ohif-servers/client/collections/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './subscriptions.js';
|
||||||
@ -1,2 +1,4 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
|
||||||
Meteor.subscribe('servers');
|
Meteor.subscribe('servers');
|
||||||
Meteor.subscribe('currentServer');
|
Meteor.subscribe('currentServer');
|
||||||
1
Packages/ohif-servers/client/components/index.js
Normal file
1
Packages/ohif-servers/client/components/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './serverInformation';
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
Template.serverInformationDicomWeb.onRendered(() => {
|
Template.serverInformationDicomWeb.onRendered(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
instance.autorun(function() {
|
instance.autorun(function() {
|
||||||
@ -1,3 +1,8 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
|
import { Tracker } from 'meteor/tracker';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
|
||||||
Template.serverInformationDimse.onCreated(() => {
|
Template.serverInformationDimse.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
instance.peers = new ReactiveVar([]);
|
instance.peers = new ReactiveVar([]);
|
||||||
@ -14,6 +19,7 @@ Template.serverInformationDimse.onCreated(() => {
|
|||||||
peers.push({});
|
peers.push({});
|
||||||
instance.peers.set(peers);
|
instance.peers.set(peers);
|
||||||
},
|
},
|
||||||
|
|
||||||
removePeer(peerIndex) {
|
removePeer(peerIndex) {
|
||||||
const peers = instance.peers.get();
|
const peers = instance.peers.get();
|
||||||
peers.splice(peerIndex, 1);
|
peers.splice(peerIndex, 1);
|
||||||
@ -1,8 +1,9 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
import { ReactiveVar } from 'meteor/reactive-var';
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
import { DICOMWebServer as dicomSchema } from 'meteor/ohif:study-list/both/schema/servers.js';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
import { DIMSEServer as dimseSchema } from 'meteor/ohif:study-list/both/schema/servers.js';
|
import { DICOMWebServer as dicomSchema } from 'meteor/ohif:servers/both/schema/servers.js';
|
||||||
|
import { DIMSEServer as dimseSchema } from 'meteor/ohif:servers/both/schema/servers.js';
|
||||||
|
|
||||||
Template.serverInformationForm.onCreated(() => {
|
Template.serverInformationForm.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
@ -21,6 +22,7 @@ Template.serverInformationForm.onCreated(() => {
|
|||||||
Meteor.call('serverSave', formData, function(error) {
|
Meteor.call('serverSave', formData, function(error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
// TODO: check for errors: not-authorized, data-write
|
// TODO: check for errors: not-authorized, data-write
|
||||||
|
OHIF.log.error(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.data.resetState();
|
instance.data.resetState();
|
||||||
@ -1,15 +1,21 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { Servers, CurrentServer } from 'meteor/ohif:servers/both/collections';
|
||||||
|
|
||||||
Template.serverInformationList.onCreated(() => {
|
Template.serverInformationList.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
|
|
||||||
instance.api = {
|
instance.api = {
|
||||||
add: () => instance.data.mode.set('create'),
|
add: () => instance.data.mode.set('create'),
|
||||||
|
|
||||||
edit(server) {
|
edit(server) {
|
||||||
instance.data.currentItem.set(server);
|
instance.data.currentItem.set(server);
|
||||||
instance.data.mode.set('edit');
|
instance.data.mode.set('edit');
|
||||||
},
|
},
|
||||||
|
|
||||||
delete(server) {
|
delete(server) {
|
||||||
// TODO: Replace this for confirmation dialog after LT-refactor is merged back to master
|
// TODO: Replace this for confirmation dialog after LT-refactor is merged back to master
|
||||||
if (!confirm('Are you sure you want to remove this peer?')) {
|
if (!window.confirm('Are you sure you want to remove this peer?')) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -17,6 +23,7 @@ Template.serverInformationList.onCreated(() => {
|
|||||||
// TODO: check for errors: data-write
|
// TODO: check for errors: data-write
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
use(server) {
|
use(server) {
|
||||||
Meteor.call('serverSetActive', server._id, error => {
|
Meteor.call('serverSetActive', server._id, error => {
|
||||||
// TODO: check for errors: data-write
|
// TODO: check for errors: data-write
|
||||||
1
Packages/ohif-servers/client/index.js
Normal file
1
Packages/ohif-servers/client/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './collections';
|
||||||
28
Packages/ohif-servers/package.js
Normal file
28
Packages/ohif-servers/package.js
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
Package.describe({
|
||||||
|
name: 'ohif:servers',
|
||||||
|
summary: 'OHIF collections to manage DICOM server information',
|
||||||
|
version: '0.0.1'
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.onUse(function(api) {
|
||||||
|
api.versionsFrom('1.4');
|
||||||
|
|
||||||
|
api.use('ecmascript');
|
||||||
|
api.use('jquery');
|
||||||
|
api.use('stylus');
|
||||||
|
api.use('aldeed:simple-schema');
|
||||||
|
api.use('aldeed:collection2');
|
||||||
|
|
||||||
|
// Our custom packages
|
||||||
|
api.use('ohif:core');
|
||||||
|
api.use('ohif:log');
|
||||||
|
|
||||||
|
// Client and server imports
|
||||||
|
api.addFiles('both/index.js', [ 'client', 'server' ]);
|
||||||
|
|
||||||
|
// Server imports
|
||||||
|
api.addFiles('server/index.js', 'server');
|
||||||
|
|
||||||
|
// Client imports
|
||||||
|
api.addFiles('client/index.js', 'client');
|
||||||
|
});
|
||||||
4
Packages/ohif-servers/server/index.js
Normal file
4
Packages/ohif-servers/server/index.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import './publications.js';
|
||||||
|
import './methods.js';
|
||||||
|
import './startup.js';
|
||||||
|
import './lib';
|
||||||
@ -1,33 +1,15 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { _ } from 'meteor/underscore';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { Servers, CurrentServer } from 'meteor/ohif:servers/both/collections';
|
||||||
|
|
||||||
Meteor.startup(function() {
|
OHIF.servers.control = {
|
||||||
console.log('Adding Servers from JSON Configuration');
|
writeCallback(error, affected) {
|
||||||
Servers.remove({
|
|
||||||
origin: 'json'
|
|
||||||
});
|
|
||||||
|
|
||||||
_.each(Meteor.settings.servers, function(endpoints, serverType) {
|
|
||||||
_.each(endpoints, function(endpoint) {
|
|
||||||
const server = _.clone(endpoint);
|
|
||||||
server.origin = 'json';
|
|
||||||
server.type = serverType;
|
|
||||||
Servers.insert(server);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
ServersControl.resetCurrentServer();
|
|
||||||
});
|
|
||||||
|
|
||||||
class ServersControl {
|
|
||||||
|
|
||||||
static writeCallback(error, affected) {
|
|
||||||
if (error) {
|
if (error) {
|
||||||
throw new Meteor.Error('data-write', error);
|
throw new Meteor.Error('data-write', error);
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
static resetCurrentServer() {
|
resetCurrentServer() {
|
||||||
const currentServer = CurrentServer.findOne();
|
const currentServer = CurrentServer.findOne();
|
||||||
if (currentServer && Servers.find({ _id: currentServer.serverId }).count()) {
|
if (currentServer && Servers.find({ _id: currentServer.serverId }).count()) {
|
||||||
return;
|
return;
|
||||||
@ -44,13 +26,13 @@ class ServersControl {
|
|||||||
serverId: newServer._id
|
serverId: newServer._id
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
|
||||||
static find(query) {
|
find(query) {
|
||||||
return Servers.find(query).fetch();
|
return Servers.find(query).fetch();
|
||||||
}
|
},
|
||||||
|
|
||||||
static save(serverSettings) {
|
save(serverSettings) {
|
||||||
const query = {
|
const query = {
|
||||||
_id: serverSettings._id
|
_id: serverSettings._id
|
||||||
};
|
};
|
||||||
@ -63,32 +45,24 @@ class ServersControl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Servers.update(query, serverSettings, options, this.writeCallback);
|
return Servers.update(query, serverSettings, options, this.writeCallback);
|
||||||
}
|
},
|
||||||
|
|
||||||
static setActive(serverId) {
|
setActive(serverId) {
|
||||||
CurrentServer.remove({});
|
CurrentServer.remove({});
|
||||||
CurrentServer.insert({
|
CurrentServer.insert({
|
||||||
serverId: serverId
|
serverId: serverId
|
||||||
});
|
});
|
||||||
}
|
},
|
||||||
|
|
||||||
static remove(serverId) {
|
remove(serverId) {
|
||||||
const query = {
|
const query = {
|
||||||
_id: serverId
|
_id: serverId
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeStatus = Servers.remove(query, this.writeCallback);
|
const removeStatus = Servers.remove(query, this.writeCallback);
|
||||||
|
|
||||||
ServersControl.resetCurrentServer();
|
OHIF.servers.control.resetCurrentServer();
|
||||||
|
|
||||||
return removeStatus;
|
return removeStatus;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
}
|
|
||||||
|
|
||||||
Meteor.methods({
|
|
||||||
serverFind: query => ServersControl.find(query),
|
|
||||||
serverSave: serverSettings => ServersControl.save(serverSettings),
|
|
||||||
serverSetActive: serverId => ServersControl.setActive(serverId),
|
|
||||||
serverRemove: serverId => ServersControl.remove(serverId)
|
|
||||||
});
|
|
||||||
1
Packages/ohif-servers/server/lib/index.js
Normal file
1
Packages/ohif-servers/server/lib/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './control.js';
|
||||||
9
Packages/ohif-servers/server/methods.js
Normal file
9
Packages/ohif-servers/server/methods.js
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
Meteor.methods({
|
||||||
|
serverFind: query => OHIF.servers.control.find(query),
|
||||||
|
serverSave: serverSettings => OHIF.servers.control.save(serverSettings),
|
||||||
|
serverSetActive: serverId => OHIF.servers.control.setActive(serverId),
|
||||||
|
serverRemove: serverId => OHIF.servers.control.remove(serverId)
|
||||||
|
});
|
||||||
10
Packages/ohif-servers/server/publications.js
Normal file
10
Packages/ohif-servers/server/publications.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { Servers, CurrentServer } from 'meteor/ohif:servers/both/collections';
|
||||||
|
|
||||||
|
// When publishing Servers Collection, do not publish the requestOptions.headers
|
||||||
|
// field in case any authentication information is being passed
|
||||||
|
Meteor.publish('servers', () => Servers.find({}, {
|
||||||
|
fields: { 'requestOptions.headers': 0 }
|
||||||
|
}));
|
||||||
|
|
||||||
|
Meteor.publish('currentServer', () => CurrentServer.find());
|
||||||
61
Packages/ohif-servers/server/startup.js
Normal file
61
Packages/ohif-servers/server/startup.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { Servers } from 'meteor/ohif:servers/both/collections';
|
||||||
|
import { ServerConfiguration } from 'meteor/ohif:servers/both/schema/servers.js';
|
||||||
|
|
||||||
|
// Check the servers on meteor startup
|
||||||
|
Meteor.startup(function() {
|
||||||
|
OHIF.log.info('Updating servers information from JSON configuration');
|
||||||
|
|
||||||
|
_.each(Meteor.settings.servers, function(endpoints, serverType) {
|
||||||
|
_.each(endpoints, function(endpoint) {
|
||||||
|
const server = _.clone(endpoint);
|
||||||
|
server.origin = 'json';
|
||||||
|
server.type = serverType;
|
||||||
|
|
||||||
|
// Try to find a server with the same name/type/origin combination
|
||||||
|
const existingServer = Servers.findOne({
|
||||||
|
name: server.name,
|
||||||
|
type: server.type,
|
||||||
|
origin: server.origin
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if server was already added. Update it if so and insert if not
|
||||||
|
if (existingServer) {
|
||||||
|
const newServerData = _.clone(existingServer);
|
||||||
|
delete newServerData._id;
|
||||||
|
Servers.update(existingServer._id, { $set: newServerData });
|
||||||
|
} else {
|
||||||
|
Servers.insert(server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
OHIF.servers.control.resetCurrentServer();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Validate the servers configuration
|
||||||
|
Meteor.startup(() => {
|
||||||
|
// Save custom properties (if any)...
|
||||||
|
// "Meteor.settings" and "Meteor.settings.public" are set by default...
|
||||||
|
let custom = {
|
||||||
|
private: Meteor.settings.custom,
|
||||||
|
public: Meteor.settings.public.custom
|
||||||
|
};
|
||||||
|
|
||||||
|
// ... and remove them to prevent clean up
|
||||||
|
delete Meteor.settings.custom;
|
||||||
|
delete Meteor.settings.public.custom;
|
||||||
|
|
||||||
|
ServerConfiguration.clean(Meteor.settings);
|
||||||
|
|
||||||
|
// TODO: Make the error messages more clear
|
||||||
|
// Taking this out for now to prevent confusion.
|
||||||
|
// check(Meteor.settings, ServerConfiguration);
|
||||||
|
|
||||||
|
Meteor.settings.custom = custom.private;
|
||||||
|
Meteor.settings.public.custom = custom.public;
|
||||||
|
|
||||||
|
OHIF.log.info(JSON.stringify(Meteor.settings, null, 2));
|
||||||
|
});
|
||||||
@ -1,19 +1,8 @@
|
|||||||
import { Mongo } from 'meteor/mongo';
|
import { Mongo } from 'meteor/mongo';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
import { Servers as ServerSchema } from 'meteor/ohif:study-list/both/schema/servers.js';
|
|
||||||
|
|
||||||
const StudyImportStatus = new Mongo.Collection('studyImportStatus');
|
const StudyImportStatus = new Mongo.Collection('studyImportStatus');
|
||||||
StudyImportStatus._debugName = 'StudyImportStatus';
|
StudyImportStatus._debugName = 'StudyImportStatus';
|
||||||
OHIF.studylist.collections.StudyImportStatus = StudyImportStatus;
|
OHIF.studylist.collections.StudyImportStatus = StudyImportStatus;
|
||||||
|
|
||||||
// Servers describe the DICOM servers configurations
|
export { StudyImportStatus };
|
||||||
Servers = new Mongo.Collection('servers');
|
|
||||||
// TODO: Make the Schema match what we are currently sticking into the Collection
|
|
||||||
//Servers.attachSchema(ServerSchema);
|
|
||||||
Servers._debugName = 'Servers';
|
|
||||||
|
|
||||||
// CurrentServer is a single document collection to describe which of the Servers is being used
|
|
||||||
CurrentServer = new Mongo.Collection('currentServer');
|
|
||||||
CurrentServer._debugName = 'CurrentServer';
|
|
||||||
|
|
||||||
export { StudyImportStatus, Servers, CurrentServer };
|
|
||||||
|
|||||||
@ -1,4 +1,2 @@
|
|||||||
import './base.js';
|
import './base.js';
|
||||||
import './lib';
|
|
||||||
import './schema';
|
|
||||||
import './collections.js';
|
import './collections.js';
|
||||||
|
|||||||
@ -1 +0,0 @@
|
|||||||
import './servers.js';
|
|
||||||
@ -1,2 +1 @@
|
|||||||
import './studies.js';
|
import './studies.js';
|
||||||
import './subscriptions.js';
|
|
||||||
|
|||||||
@ -1,4 +1,2 @@
|
|||||||
import './seriesDetailsModal';
|
import './seriesDetailsModal';
|
||||||
import './serverInformation';
|
|
||||||
import './studylist';
|
import './studylist';
|
||||||
import './themeSelector';
|
|
||||||
|
|||||||
@ -31,6 +31,7 @@ Package.onUse(function(api) {
|
|||||||
api.use('ohif:design');
|
api.use('ohif:design');
|
||||||
api.use('ohif:core');
|
api.use('ohif:core');
|
||||||
api.use('ohif:log');
|
api.use('ohif:log');
|
||||||
|
api.use('ohif:servers');
|
||||||
api.use('ohif:dicom-services');
|
api.use('ohif:dicom-services');
|
||||||
api.use('ohif:viewerbase');
|
api.use('ohif:viewerbase');
|
||||||
api.use('ohif:wadoproxy');
|
api.use('ohif:wadoproxy');
|
||||||
@ -44,12 +45,5 @@ Package.onUse(function(api) {
|
|||||||
// Client imports
|
// Client imports
|
||||||
api.addFiles('client/index.js', 'client');
|
api.addFiles('client/index.js', 'client');
|
||||||
|
|
||||||
// Export Servers and CurrentServer Collections
|
|
||||||
api.export('Servers', ['client', 'server']);
|
|
||||||
api.export('CurrentServer', ['client', 'server']);
|
|
||||||
|
|
||||||
// Export shared lib functions
|
|
||||||
api.export('getCurrentServer', ['client', 'server']);
|
|
||||||
|
|
||||||
api.export('Services', 'server');
|
api.export('Services', 'server');
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,6 +1,4 @@
|
|||||||
import './publications.js';
|
import './publications.js';
|
||||||
import './servers.js';
|
|
||||||
import './validateServerConfiguration.js';
|
|
||||||
|
|
||||||
import './lib';
|
import './lib';
|
||||||
import './methods';
|
import './methods';
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
@ -10,7 +11,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
// Get the server data. This is user-defined in the config.json files or through servers
|
// Get the server data. This is user-defined in the config.json files or through servers
|
||||||
// configuration modal
|
// configuration modal
|
||||||
const server = getCurrentServer();
|
const server = OHIF.servers.getCurrentServer();
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
throw 'No properly configured server was available over DICOMWeb or DIMSE.';
|
throw 'No properly configured server was available over DICOMWeb or DIMSE.';
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
var fs = Npm.require('fs');
|
const fs = Npm.require('fs');
|
||||||
var fiber = Npm.require('fibers');
|
const fiber = Npm.require('fibers');
|
||||||
|
|
||||||
WebApp.connectHandlers.use('/uploadFilesToImport', function(req, res) {
|
WebApp.connectHandlers.use('/uploadFilesToImport', function(req, res) {
|
||||||
if (!req.headers.filename) {
|
if (!req.headers.filename) {
|
||||||
@ -11,21 +12,21 @@ WebApp.connectHandlers.use('/uploadFilesToImport', function(req, res) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Store files in temp location (they will be deleted when their import operations are completed)
|
// Store files in temp location (they will be deleted when their import operations are completed)
|
||||||
var dicomDir = '/tmp/dicomDir';
|
const dicomDir = '/tmp/dicomDir';
|
||||||
createFolderIfNotExist(dicomDir);
|
createFolderIfNotExist(dicomDir);
|
||||||
|
|
||||||
var fullFileName = dicomDir + '/' + req.headers.filename;
|
const fullFileName = dicomDir + '/' + req.headers.filename;
|
||||||
var file = fs.createWriteStream(fullFileName);
|
const file = fs.createWriteStream(fullFileName);
|
||||||
|
|
||||||
file.on('error',function(error){
|
file.on('error', function(error) {
|
||||||
console.log(error);
|
OHIF.log.warn(error);
|
||||||
// Response: INTERNAL SERVER ERROR (500)
|
// Response: INTERNAL SERVER ERROR (500)
|
||||||
res.statusCode = 400;
|
res.statusCode = 400;
|
||||||
res.end();
|
res.end();
|
||||||
});
|
});
|
||||||
file.on('finish',function(){
|
file.on('finish', function() {
|
||||||
// Response: SUCCESS (200)
|
// Response: SUCCESS (200)
|
||||||
res.writeHead(200, {'Content-Type': 'text/plain'});
|
res.writeHead(200, { 'Content-Type': 'text/plain' });
|
||||||
res.end(fullFileName);
|
res.end(fullFileName);
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -39,7 +40,7 @@ Meteor.methods({
|
|||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
importSupported: function() {
|
importSupported: function() {
|
||||||
const server = getCurrentServer();
|
const server = OHIF.servers.getCurrentServer();
|
||||||
if (server && server.type === 'dimse') {
|
if (server && server.type === 'dimse') {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -54,7 +55,7 @@ Meteor.methods({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const server = getCurrentServer();
|
const server = OHIF.servers.getCurrentServer();
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
throw 'No properly configured server was available over DICOMWeb or DIMSE.';
|
throw 'No properly configured server was available over DICOMWeb or DIMSE.';
|
||||||
@ -62,7 +63,7 @@ Meteor.methods({
|
|||||||
|
|
||||||
if (server.type === 'dicomWeb') {
|
if (server.type === 'dicomWeb') {
|
||||||
//TODO: Support importing studies into dicomWeb
|
//TODO: Support importing studies into dicomWeb
|
||||||
console.log('Importing studies into dicomWeb is currently not supported.');
|
OHIF.log.warn('Importing studies into dicomWeb is currently not supported.');
|
||||||
} else if (server.type === 'dimse') {
|
} else if (server.type === 'dimse') {
|
||||||
importStudiesDIMSE(studiesToImport, studyImportStatusId);
|
importStudiesDIMSE(studiesToImport, studyImportStatusId);
|
||||||
}
|
}
|
||||||
@ -72,7 +73,10 @@ Meteor.methods({
|
|||||||
* @returns {studyImportStatusId: string}
|
* @returns {studyImportStatusId: string}
|
||||||
*/
|
*/
|
||||||
createStudyImportStatus: function() {
|
createStudyImportStatus: function() {
|
||||||
var studyImportStatus = { numberOfStudiesImported: 0, numberOfStudiesFailed: 0 };
|
const studyImportStatus = {
|
||||||
|
numberOfStudiesImported: 0,
|
||||||
|
numberOfStudiesFailed: 0
|
||||||
|
};
|
||||||
return OHIF.studylist.collections.StudyImportStatus.insert(studyImportStatus);
|
return OHIF.studylist.collections.StudyImportStatus.insert(studyImportStatus);
|
||||||
},
|
},
|
||||||
/**
|
/**
|
||||||
@ -96,17 +100,25 @@ function importStudiesDIMSE(studiesToImport, studyImportStatusId) {
|
|||||||
try {
|
try {
|
||||||
// Update the import status
|
// Update the import status
|
||||||
if (err) {
|
if (err) {
|
||||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
OHIF.studylist.collections.StudyImportStatus.update(
|
||||||
console.log("Failed to import study via DIMSE: ", file, err);
|
{ _id: studyImportStatusId },
|
||||||
|
{ $inc: { numberOfStudiesFailed: 1 } }
|
||||||
|
);
|
||||||
|
OHIF.log.warn('Failed to import study via DIMSE: ', file, err);
|
||||||
} else {
|
} else {
|
||||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesImported': 1}});
|
OHIF.studylist.collections.StudyImportStatus.update(
|
||||||
console.log("Study successfully imported via DIMSE: ", file);
|
{ _id: studyImportStatusId },
|
||||||
|
{ $inc: { numberOfStudiesImported: 1 } }
|
||||||
|
);
|
||||||
|
OHIF.log.info('Study successfully imported via DIMSE: ', file);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
|
OHIF.studylist.collections.StudyImportStatus.update(
|
||||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
{ _id: studyImportStatusId },
|
||||||
console.log("Failed to import study via DIMSE: ", file, error);
|
{ $inc: { numberOfStudiesFailed: 1 } }
|
||||||
|
);
|
||||||
|
OHIF.log.warn('Failed to import study via DIMSE: ', file, error);
|
||||||
} finally {
|
} finally {
|
||||||
// The import operation of this file is completed, so delete it if still exists
|
// The import operation of this file is completed, so delete it if still exists
|
||||||
if (fileExists(file)) {
|
if (fileExists(file)) {
|
||||||
@ -116,17 +128,20 @@ function importStudiesDIMSE(studiesToImport, studyImportStatusId) {
|
|||||||
|
|
||||||
}).run();
|
}).run();
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
OHIF.studylist.collections.StudyImportStatus.update({_id: studyImportStatusId}, {$inc: {'numberOfStudiesFailed': 1}});
|
OHIF.studylist.collections.StudyImportStatus.update(
|
||||||
console.log("Failed to import study via DIMSE: ", file, error);
|
{ _id: studyImportStatusId },
|
||||||
|
{ $inc: { numberOfStudiesFailed: 1 } }
|
||||||
|
);
|
||||||
|
OHIF.log.warn('Failed to import study via DIMSE: ', file, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
function createFolderIfNotExist(folder) {
|
function createFolderIfNotExist(folder) {
|
||||||
var folderParts = folder.split('/');
|
const folderParts = folder.split('/');
|
||||||
var folderPart = folderParts[0];
|
let folderPart = folderParts[0];
|
||||||
for (var i = 1; i < folderParts.length; i++) {
|
for (let i = 1; i < folderParts.length; i++) {
|
||||||
folderPart += '/' + folderParts[i];
|
folderPart += '/' + folderParts[i];
|
||||||
if (!folderExists(folderPart)) {
|
if (!folderExists(folderPart)) {
|
||||||
fs.mkdirSync(folderPart);
|
fs.mkdirSync(folderPart);
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Meteor.methods({
|
Meteor.methods({
|
||||||
/**
|
/**
|
||||||
* Use the specified filter to conduct a search from the DICOM server
|
* Use the specified filter to conduct a search from the DICOM server
|
||||||
@ -7,7 +10,7 @@ Meteor.methods({
|
|||||||
StudyListSearch(filter) {
|
StudyListSearch(filter) {
|
||||||
// Get the server data. This is user-defined in the config.json files or through servers
|
// Get the server data. This is user-defined in the config.json files or through servers
|
||||||
// configuration modal
|
// configuration modal
|
||||||
const server = getCurrentServer();
|
const server = OHIF.servers.getCurrentServer();
|
||||||
|
|
||||||
if (!server) {
|
if (!server) {
|
||||||
throw 'No properly configured server was available over DICOMWeb or DIMSE.';
|
throw 'No properly configured server was available over DICOMWeb or DIMSE.';
|
||||||
|
|||||||
@ -2,13 +2,3 @@ import { Meteor } from 'meteor/meteor';
|
|||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Meteor.publish('studyImportStatus', () => OHIF.studylist.collections.StudyImportStatus.find());
|
Meteor.publish('studyImportStatus', () => OHIF.studylist.collections.StudyImportStatus.find());
|
||||||
|
|
||||||
// When publishing Servers Collection, do not publish the requestOptions.headers
|
|
||||||
// field in case any authentication information is being passed
|
|
||||||
Meteor.publish('servers', () => Servers.find({}, {
|
|
||||||
fields: {
|
|
||||||
'requestOptions.headers': 0
|
|
||||||
}
|
|
||||||
}));
|
|
||||||
|
|
||||||
Meteor.publish('currentServer', () => CurrentServer.find());
|
|
||||||
|
|||||||
@ -1,66 +1,68 @@
|
|||||||
/**
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
* Parses data returned from a study search and transforms it into
|
|
||||||
* an array of series that are present in the study
|
/**
|
||||||
*
|
* Parses data returned from a study search and transforms it into
|
||||||
* @param resultData
|
* an array of series that are present in the study
|
||||||
* @returns {Array} Series List
|
*
|
||||||
*/
|
* @param resultData
|
||||||
function resultDataToStudyMetadata(resultData) {
|
* @returns {Array} Series List
|
||||||
var seriesMap = {};
|
*/
|
||||||
var seriesList = [];
|
function resultDataToStudyMetadata(resultData, studyInstanceUid) {
|
||||||
|
const seriesMap = {};
|
||||||
resultData.forEach(function(instanceRaw) {
|
const seriesList = [];
|
||||||
var instance = instanceRaw.toObject();
|
|
||||||
// Use seriesMap to cache series data
|
resultData.forEach(function(instanceRaw) {
|
||||||
// If the series instance UID has already been used to
|
const instance = instanceRaw.toObject();
|
||||||
// process series data, continue using that series
|
// Use seriesMap to cache series data
|
||||||
var seriesInstanceUid = instance[0x0020000E];
|
// If the series instance UID has already been used to
|
||||||
var series = seriesMap[seriesInstanceUid];
|
// process series data, continue using that series
|
||||||
|
const seriesInstanceUid = instance[0x0020000E];
|
||||||
// If no series data exists in the seriesMap cache variable,
|
let series = seriesMap[seriesInstanceUid];
|
||||||
// process any available series data
|
|
||||||
if (!series) {
|
// If no series data exists in the seriesMap cache variable,
|
||||||
series = {
|
// process any available series data
|
||||||
seriesInstanceUid: seriesInstanceUid,
|
if (!series) {
|
||||||
seriesNumber: instance[0x00200011],
|
series = {
|
||||||
instances: []
|
seriesInstanceUid: seriesInstanceUid,
|
||||||
};
|
seriesNumber: instance[0x00200011],
|
||||||
|
instances: []
|
||||||
// Save this data in the seriesMap cache variable
|
};
|
||||||
seriesMap[seriesInstanceUid] = series;
|
|
||||||
seriesList.push(series);
|
// Save this data in the seriesMap cache variable
|
||||||
}
|
seriesMap[seriesInstanceUid] = series;
|
||||||
|
seriesList.push(series);
|
||||||
// TODO: Check which peer it should point to
|
}
|
||||||
var server = getCurrentServer().peers[0];
|
|
||||||
|
// TODO: Check which peer it should point to
|
||||||
var serverRoot = server.host + ':' + server.port;
|
const server = OHIF.servers.getCurrentServer().peers[0];
|
||||||
|
|
||||||
var sopInstanceUid = instance[0x00080018];
|
const serverRoot = server.host + ':' + server.port;
|
||||||
var uri = serverRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1';
|
|
||||||
|
const sopInstanceUid = instance[0x00080018];
|
||||||
// Add this instance to the current series
|
const uri = serverRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1';
|
||||||
series.instances.push({
|
|
||||||
sopClassUid: instance[0x00080016],
|
// Add this instance to the current series
|
||||||
sopInstanceUid: sopInstanceUid,
|
series.instances.push({
|
||||||
uri: uri,
|
sopClassUid: instance[0x00080016],
|
||||||
instanceNumber: instance[0x00200013]
|
sopInstanceUid,
|
||||||
});
|
uri,
|
||||||
});
|
instanceNumber: instance[0x00200013]
|
||||||
return seriesList;
|
});
|
||||||
}
|
});
|
||||||
|
return seriesList;
|
||||||
/**
|
}
|
||||||
* Retrieve a set of instances using a DIMSE call
|
|
||||||
* @param studyInstanceUid
|
/**
|
||||||
* @returns {{wadoUriRoot: String, studyInstanceUid: String, seriesList: Array}}
|
* Retrieve a set of instances using a DIMSE call
|
||||||
*/
|
* @param studyInstanceUid
|
||||||
Services.DIMSE.Instances = function(studyInstanceUid) {
|
* @returns {{wadoUriRoot: String, studyInstanceUid: String, seriesList: Array}}
|
||||||
//var url = buildUrl(server, studyInstanceUid);
|
*/
|
||||||
var result = DIMSE.retrieveInstances(studyInstanceUid);
|
Services.DIMSE.Instances = function(studyInstanceUid) {
|
||||||
|
//var url = buildUrl(server, studyInstanceUid);
|
||||||
return {
|
const result = DIMSE.retrieveInstances(studyInstanceUid);
|
||||||
studyInstanceUid: studyInstanceUid,
|
|
||||||
seriesList: resultDataToStudyMetadata(result)
|
return {
|
||||||
};
|
studyInstanceUid: studyInstanceUid,
|
||||||
};
|
seriesList: resultDataToStudyMetadata(result, studyInstanceUid)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|||||||
@ -1,169 +1,169 @@
|
|||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
import { parseFloatArray } from 'meteor/ohif:study-list/server/lib/parseFloatArray';
|
import { parseFloatArray } from 'meteor/ohif:study-list/server/lib/parseFloatArray';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the value of the element (e.g. '00280009')
|
* Returns the value of the element (e.g. '00280009')
|
||||||
*
|
*
|
||||||
* @param element - The group/element of the element (e.g. '00280009')
|
* @param element - The group/element of the element (e.g. '00280009')
|
||||||
* @param defaultValue - The default value to return if the element does not exist
|
* @param defaultValue - The default value to return if the element does not exist
|
||||||
* @returns {*}
|
* @returns {*}
|
||||||
*/
|
*/
|
||||||
function getValue(element, defaultValue) {
|
function getValue(element, defaultValue) {
|
||||||
if (!element || !element.value) {
|
if (!element || !element.value) {
|
||||||
return defaultValue;
|
return defaultValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return element.value;
|
return element.value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses the SourceImageSequence, if it exists, in order
|
* Parses the SourceImageSequence, if it exists, in order
|
||||||
* to return a ReferenceSOPInstanceUID. The ReferenceSOPInstanceUID
|
* to return a ReferenceSOPInstanceUID. The ReferenceSOPInstanceUID
|
||||||
* is used to refer to this image in any accompanying DICOM-SR documents.
|
* is used to refer to this image in any accompanying DICOM-SR documents.
|
||||||
*
|
*
|
||||||
* @param instance
|
* @param instance
|
||||||
* @returns {String} The ReferenceSOPInstanceUID
|
* @returns {String} The ReferenceSOPInstanceUID
|
||||||
*/
|
*/
|
||||||
function getSourceImageInstanceUid(instance) {
|
function getSourceImageInstanceUid(instance) {
|
||||||
// TODO= Parse the whole Source Image Sequence
|
// TODO= Parse the whole Source Image Sequence
|
||||||
// This is a really poor workaround for now.
|
// This is a really poor workaround for now.
|
||||||
// Later we should probably parse the whole sequence.
|
// Later we should probably parse the whole sequence.
|
||||||
var SourceImageSequence = instance[0x00082112];
|
const SourceImageSequence = instance[0x00082112];
|
||||||
if (SourceImageSequence && SourceImageSequence.length) {
|
if (SourceImageSequence && SourceImageSequence.length) {
|
||||||
return SourceImageSequence[0][0x00081155];
|
return SourceImageSequence[0][0x00081155];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses result data from a DIMSE search into Study MetaData
|
* Parses result data from a DIMSE search into Study MetaData
|
||||||
* Returns an object populated with study metadata, including the
|
* Returns an object populated with study metadata, including the
|
||||||
* series list.
|
* series list.
|
||||||
*
|
*
|
||||||
* @param studyInstanceUid
|
* @param studyInstanceUid
|
||||||
* @param resultData
|
* @param resultData
|
||||||
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
|
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
|
||||||
*/
|
*/
|
||||||
function resultDataToStudyMetadata(studyInstanceUid, resultData) {
|
function resultDataToStudyMetadata(studyInstanceUid, resultData) {
|
||||||
OHIF.log.info('resultDataToStudyMetadata');
|
OHIF.log.info('resultDataToStudyMetadata');
|
||||||
var seriesMap = {};
|
const seriesMap = {};
|
||||||
var seriesList = [];
|
const seriesList = [];
|
||||||
|
|
||||||
if (!resultData.length) {
|
if (!resultData.length) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var anInstance = resultData[0].toObject();
|
const anInstance = resultData[0].toObject();
|
||||||
if (!anInstance) {
|
if (!anInstance) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var studyData = {
|
const studyData = {
|
||||||
seriesList: seriesList,
|
seriesList: seriesList,
|
||||||
patientName: anInstance[0x00100010],
|
patientName: anInstance[0x00100010],
|
||||||
patientId: anInstance[0x00100020],
|
patientId: anInstance[0x00100020],
|
||||||
patientBirthDate: anInstance[0x00100030],
|
patientBirthDate: anInstance[0x00100030],
|
||||||
patientSex: anInstance[0x00100040],
|
patientSex: anInstance[0x00100040],
|
||||||
accessionNumber: anInstance[0x00080050],
|
accessionNumber: anInstance[0x00080050],
|
||||||
studyDate: anInstance[0x00080020],
|
studyDate: anInstance[0x00080020],
|
||||||
modalities: anInstance[0x00080061],
|
modalities: anInstance[0x00080061],
|
||||||
studyDescription: anInstance[0x00081030],
|
studyDescription: anInstance[0x00081030],
|
||||||
imageCount: anInstance[0x00201208],
|
imageCount: anInstance[0x00201208],
|
||||||
studyInstanceUid: anInstance[0x0020000D],
|
studyInstanceUid: anInstance[0x0020000D],
|
||||||
institutionName: anInstance[0x00080080]
|
institutionName: anInstance[0x00080080]
|
||||||
};
|
};
|
||||||
|
|
||||||
resultData.forEach(function(instanceRaw) {
|
resultData.forEach(function(instanceRaw) {
|
||||||
var instance = instanceRaw.toObject();
|
const instance = instanceRaw.toObject();
|
||||||
var seriesInstanceUid = instance[0x0020000E];
|
const seriesInstanceUid = instance[0x0020000E];
|
||||||
var series = seriesMap[seriesInstanceUid];
|
let series = seriesMap[seriesInstanceUid];
|
||||||
if (!series) {
|
if (!series) {
|
||||||
series = {
|
series = {
|
||||||
seriesDescription: instance[0x0008103E],
|
seriesDescription: instance[0x0008103E],
|
||||||
modality: instance[0x00080060],
|
modality: instance[0x00080060],
|
||||||
seriesInstanceUid: seriesInstanceUid,
|
seriesInstanceUid: seriesInstanceUid,
|
||||||
seriesNumber: parseFloat(instance[0x00200011]),
|
seriesNumber: parseFloat(instance[0x00200011]),
|
||||||
instances: []
|
instances: []
|
||||||
};
|
};
|
||||||
seriesMap[seriesInstanceUid] = series;
|
seriesMap[seriesInstanceUid] = series;
|
||||||
seriesList.push(series);
|
seriesList.push(series);
|
||||||
}
|
}
|
||||||
|
|
||||||
var sopInstanceUid = instance[0x00080018];
|
const sopInstanceUid = instance[0x00080018];
|
||||||
|
|
||||||
var instanceSummary = {
|
const instanceSummary = {
|
||||||
imageType: instance[0x00080008],
|
imageType: instance[0x00080008],
|
||||||
sopClassUid: instance[0x00080016],
|
sopClassUid: instance[0x00080016],
|
||||||
modality: instance[0x00080060],
|
modality: instance[0x00080060],
|
||||||
sopInstanceUid: sopInstanceUid,
|
sopInstanceUid: sopInstanceUid,
|
||||||
instanceNumber: parseFloat(instance[0x00200013]),
|
instanceNumber: parseFloat(instance[0x00200013]),
|
||||||
imagePositionPatient: instance[0x00200032],
|
imagePositionPatient: instance[0x00200032],
|
||||||
imageOrientationPatient: instance[0x00200037],
|
imageOrientationPatient: instance[0x00200037],
|
||||||
frameOfReferenceUID: instance[0x00200052],
|
frameOfReferenceUID: instance[0x00200052],
|
||||||
sliceThickness: parseFloat(instance[0x00180050]),
|
sliceThickness: parseFloat(instance[0x00180050]),
|
||||||
sliceLocation: parseFloat(instance[0x00201041]),
|
sliceLocation: parseFloat(instance[0x00201041]),
|
||||||
tablePosition: parseFloat(instance[0x00189327]),
|
tablePosition: parseFloat(instance[0x00189327]),
|
||||||
samplesPerPixel: parseFloat(instance[0x00280002]),
|
samplesPerPixel: parseFloat(instance[0x00280002]),
|
||||||
photometricInterpretation: instance[0x00280004],
|
photometricInterpretation: instance[0x00280004],
|
||||||
planarConfiguration: parseFloat(instance[0x00280006]),
|
planarConfiguration: parseFloat(instance[0x00280006]),
|
||||||
rows: parseFloat(instance[0x00280010]),
|
rows: parseFloat(instance[0x00280010]),
|
||||||
columns: parseFloat(instance[0x00280011]),
|
columns: parseFloat(instance[0x00280011]),
|
||||||
pixelSpacing: instance[0x00280030],
|
pixelSpacing: instance[0x00280030],
|
||||||
bitsAllocated: parseFloat(instance[0x00280100]),
|
bitsAllocated: parseFloat(instance[0x00280100]),
|
||||||
bitsStored: parseFloat(instance[0x00280101]),
|
bitsStored: parseFloat(instance[0x00280101]),
|
||||||
highBit: parseFloat(instance[0x00280102]),
|
highBit: parseFloat(instance[0x00280102]),
|
||||||
pixelRepresentation: parseFloat(instance[0x00280103]),
|
pixelRepresentation: parseFloat(instance[0x00280103]),
|
||||||
windowCenter: instance[0x00281050],
|
windowCenter: instance[0x00281050],
|
||||||
windowWidth: instance[0x00281051],
|
windowWidth: instance[0x00281051],
|
||||||
rescaleIntercept: parseFloat(instance[0x00281052]),
|
rescaleIntercept: parseFloat(instance[0x00281052]),
|
||||||
rescaleSlope: parseFloat(instance[0x00281053]),
|
rescaleSlope: parseFloat(instance[0x00281053]),
|
||||||
sourceImageInstanceUid: getSourceImageInstanceUid(instance),
|
sourceImageInstanceUid: getSourceImageInstanceUid(instance),
|
||||||
laterality: instance[0x00200062],
|
laterality: instance[0x00200062],
|
||||||
viewPosition: instance[0x00185101],
|
viewPosition: instance[0x00185101],
|
||||||
acquisitionDateTime: instance[0x0008002A],
|
acquisitionDateTime: instance[0x0008002A],
|
||||||
numberOfFrames: parseFloat(instance[0x00280008]),
|
numberOfFrames: parseFloat(instance[0x00280008]),
|
||||||
frameIncrementPointer: getValue(instance[0x00280009]),
|
frameIncrementPointer: getValue(instance[0x00280009]),
|
||||||
frameTime: parseFloat(instance[0x00181063]),
|
frameTime: parseFloat(instance[0x00181063]),
|
||||||
frameTimeVector: parseFloatArray(instance[0x00181065]),
|
frameTimeVector: parseFloatArray(instance[0x00181065]),
|
||||||
lossyImageCompression: instance[0x00282110],
|
lossyImageCompression: instance[0x00282110],
|
||||||
derivationDescription: instance[0x00282111],
|
derivationDescription: instance[0x00282111],
|
||||||
lossyImageCompressionRatio: instance[0x00282112],
|
lossyImageCompressionRatio: instance[0x00282112],
|
||||||
lossyImageCompressionMethod: instance[0x00282114],
|
lossyImageCompressionMethod: instance[0x00282114],
|
||||||
spacingBetweenSlices: instance[0x00180088],
|
spacingBetweenSlices: instance[0x00180088],
|
||||||
echoNumber: instance[0x00180086],
|
echoNumber: instance[0x00180086],
|
||||||
contrastBolusAgent: instance[0x00180010]
|
contrastBolusAgent: instance[0x00180010]
|
||||||
};
|
};
|
||||||
|
|
||||||
// Retrieve the actual data over WADO-URI
|
// Retrieve the actual data over WADO-URI
|
||||||
var server = getCurrentServer();
|
const server = OHIF.servers.getCurrentServer();
|
||||||
const wadouri = `${server.wadoUriRoot}?requestType=WADO&studyUID=${studyInstanceUid}&seriesUID=${seriesInstanceUid}&objectUID=${sopInstanceUid}&contentType=application%2Fdicom`;
|
const wadouri = `${server.wadoUriRoot}?requestType=WADO&studyUID=${studyInstanceUid}&seriesUID=${seriesInstanceUid}&objectUID=${sopInstanceUid}&contentType=application%2Fdicom`;
|
||||||
instanceSummary.wadouri = WADOProxy.convertURL(wadouri, server);
|
instanceSummary.wadouri = WADOProxy.convertURL(wadouri, server);
|
||||||
|
|
||||||
series.instances.push(instanceSummary);
|
series.instances.push(instanceSummary);
|
||||||
});
|
});
|
||||||
|
|
||||||
studyData.studyInstanceUid = studyInstanceUid;
|
studyData.studyInstanceUid = studyInstanceUid;
|
||||||
|
|
||||||
return studyData;
|
return studyData;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieved Study MetaData from a DICOM server using DIMSE
|
* Retrieved Study MetaData from a DICOM server using DIMSE
|
||||||
* @param studyInstanceUid
|
* @param studyInstanceUid
|
||||||
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
|
* @returns {{seriesList: Array, patientName: *, patientId: *, accessionNumber: *, studyDate: *, modalities: *, studyDescription: *, imageCount: *, studyInstanceUid: *}}
|
||||||
*/
|
*/
|
||||||
Services.DIMSE.RetrieveMetadata = function(studyInstanceUid) {
|
Services.DIMSE.RetrieveMetadata = function(studyInstanceUid) {
|
||||||
// TODO: Check which peer it should point to
|
// TODO: Check which peer it should point to
|
||||||
const activeServer = getCurrentServer().peers[0];
|
const activeServer = OHIF.servers.getCurrentServer().peers[0];
|
||||||
const supportsInstanceRetrievalByStudyUid = activeServer.supportsInstanceRetrievalByStudyUid;
|
const supportsInstanceRetrievalByStudyUid = activeServer.supportsInstanceRetrievalByStudyUid;
|
||||||
let results;
|
let results;
|
||||||
|
|
||||||
// Check explicitly for a value of false, since this property
|
// Check explicitly for a value of false, since this property
|
||||||
// may be left undefined in config files
|
// may be left undefined in config files
|
||||||
if (supportsInstanceRetrievalByStudyUid === false) {
|
if (supportsInstanceRetrievalByStudyUid === false) {
|
||||||
results = DIMSE.retrieveInstancesByStudyOnly(studyInstanceUid);
|
results = DIMSE.retrieveInstancesByStudyOnly(studyInstanceUid);
|
||||||
} else {
|
} else {
|
||||||
results = DIMSE.retrieveInstances(studyInstanceUid);
|
results = DIMSE.retrieveInstances(studyInstanceUid);
|
||||||
}
|
}
|
||||||
|
|
||||||
return resultDataToStudyMetadata(studyInstanceUid, results);
|
return resultDataToStudyMetadata(studyInstanceUid, results);
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,11 +1,13 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { CurrentServer } from 'meteor/ohif:servers/both/collections';
|
||||||
|
|
||||||
const setupDIMSE = () => {
|
const setupDIMSE = () => {
|
||||||
// Terminate existing DIMSE servers and sockets and clean up the connection object
|
// Terminate existing DIMSE servers and sockets and clean up the connection object
|
||||||
DIMSE.connection.reset();
|
DIMSE.connection.reset();
|
||||||
|
|
||||||
// Get the new server configuration
|
// Get the new server configuration
|
||||||
const server = getCurrentServer();
|
const server = OHIF.servers.getCurrentServer();
|
||||||
|
|
||||||
// Stop here if the new server is not of DIMSE type
|
// Stop here if the new server is not of DIMSE type
|
||||||
if (server.type !== 'dimse') {
|
if (server.type !== 'dimse') {
|
||||||
@ -15,16 +17,16 @@ const setupDIMSE = () => {
|
|||||||
// Check if peers were defined in the server configuration and throw an error if not
|
// Check if peers were defined in the server configuration and throw an error if not
|
||||||
const peers = server.peers;
|
const peers = server.peers;
|
||||||
if (!peers || !peers.length) {
|
if (!peers || !peers.length) {
|
||||||
console.error('dimse-config: ' + 'No DIMSE Peers provided.');
|
OHIF.log.error('dimse-config: ' + 'No DIMSE Peers provided.');
|
||||||
throw new Meteor.Error('dimse-config', 'No DIMSE Peers provided.');
|
throw new Meteor.Error('dimse-config', 'No DIMSE Peers provided.');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add all the DIMSE peers, establishing the connections
|
// Add all the DIMSE peers, establishing the connections
|
||||||
console.log('Adding DIMSE peers');
|
OHIF.log.info('Adding DIMSE peers');
|
||||||
try {
|
try {
|
||||||
peers.forEach(peer => DIMSE.connection.addPeer(peer));
|
peers.forEach(peer => DIMSE.connection.addPeer(peer));
|
||||||
} catch(error) {
|
} catch(error) {
|
||||||
console.error('dimse-addPeers: ' + error);
|
OHIF.log.error('dimse-addPeers: ' + error);
|
||||||
throw new Meteor.Error('dimse-addPeers', error);
|
throw new Meteor.Error('dimse-addPeers', error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@ -1,28 +0,0 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
|
||||||
// import { check } from 'meteor/check';
|
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
|
||||||
import { ServerConfiguration } from 'meteor/ohif:study-list/both/schema/servers.js';
|
|
||||||
|
|
||||||
Meteor.startup(() => {
|
|
||||||
// Save custom properties (if any)...
|
|
||||||
// "Meteor.settings" and "Meteor.settings.public" are set by default...
|
|
||||||
let custom = {
|
|
||||||
private: Meteor.settings.custom,
|
|
||||||
public: Meteor.settings.public.custom
|
|
||||||
};
|
|
||||||
|
|
||||||
// ... and remove them to prevent clean up
|
|
||||||
delete Meteor.settings.custom;
|
|
||||||
delete Meteor.settings.public.custom;
|
|
||||||
|
|
||||||
ServerConfiguration.clean(Meteor.settings);
|
|
||||||
|
|
||||||
// TODO: Make the error messages more clear
|
|
||||||
// Taking this out for now to prevent confusion.
|
|
||||||
// check(Meteor.settings, ServerConfiguration);
|
|
||||||
|
|
||||||
Meteor.settings.custom = custom.private;
|
|
||||||
Meteor.settings.public.custom = custom.public;
|
|
||||||
|
|
||||||
OHIF.log.info(JSON.stringify(Meteor.settings, null, 2));
|
|
||||||
});
|
|
||||||
1
Packages/ohif-themes-common/client/index.js
Normal file
1
Packages/ohif-themes-common/client/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './components';
|
||||||
@ -7,8 +7,13 @@ Package.describe({
|
|||||||
Package.onUse(function(api) {
|
Package.onUse(function(api) {
|
||||||
api.versionsFrom('1.4.2.3');
|
api.versionsFrom('1.4.2.3');
|
||||||
|
|
||||||
|
api.use('ecmascript');
|
||||||
|
api.use('templating');
|
||||||
api.use('stylus');
|
api.use('stylus');
|
||||||
|
|
||||||
|
// Client imports
|
||||||
|
api.addFiles('client/index.js', 'client');
|
||||||
|
|
||||||
// Importable themes
|
// Importable themes
|
||||||
api.addFiles([
|
api.addFiles([
|
||||||
'themes.styl',
|
'themes.styl',
|
||||||
|
|||||||
@ -30,7 +30,7 @@ Template.studyTimepointBrowser.onCreated(() => {
|
|||||||
return timepoint.studyInstanceUids.map(studyInstanceUid => {
|
return timepoint.studyInstanceUids.map(studyInstanceUid => {
|
||||||
const query = {
|
const query = {
|
||||||
patientId: timepoint.patientId,
|
patientId: timepoint.patientId,
|
||||||
studyInstanceUid
|
studyInstanceUid: studyInstanceUid
|
||||||
};
|
};
|
||||||
|
|
||||||
const loadedStudy = OHIF.viewer.Studies.findBy(query);
|
const loadedStudy = OHIF.viewer.Studies.findBy(query);
|
||||||
@ -40,7 +40,7 @@ Template.studyTimepointBrowser.onCreated(() => {
|
|||||||
|
|
||||||
const notYetLoaded = OHIF.studylist.collections.Studies.findOne(query);
|
const notYetLoaded = OHIF.studylist.collections.Studies.findOne(query);
|
||||||
if (!notYetLoaded) {
|
if (!notYetLoaded) {
|
||||||
OHIF.log.info(`No study data available for Study: ${studyInstanceUid}`);
|
throw new OHIFError(`No study data available for Study: ${studyInstanceUid}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return notYetLoaded;
|
return notYetLoaded;
|
||||||
@ -165,8 +165,20 @@ Template.studyTimepointBrowser.helpers({
|
|||||||
timepoints = timepointApi.key();
|
timepoints = timepointApi.key();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Filter timepoints and show only the current timepoint and previous ones
|
||||||
|
let result = [];
|
||||||
|
const currentTimepoint = timepointApi.current();
|
||||||
|
if (currentTimepoint) {
|
||||||
|
timepoints.forEach(timepoint => {
|
||||||
|
if (timepoint.latestDate.getTime() <= currentTimepoint.latestDate.getTime()) {
|
||||||
|
result.push(timepoint);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Returns the timepoints
|
// Returns the timepoints
|
||||||
return timepoints;
|
return result;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Get the studies for a specific timepoint
|
// Get the studies for a specific timepoint
|
||||||
|
|||||||
@ -44,6 +44,7 @@ export const prepareViewerData = ({ studyInstanceUids, timepointId, timepointsFi
|
|||||||
// Find the timepoint by ID and load the studies from it
|
// Find the timepoint by ID and load the studies from it
|
||||||
OHIF.studylist.timepointApi.retrieveTimepoints(timepointsFilter).then(() => {
|
OHIF.studylist.timepointApi.retrieveTimepoints(timepointsFilter).then(() => {
|
||||||
const viewerData = buildViewerDataFromTimepointId(timepointId);
|
const viewerData = buildViewerDataFromTimepointId(timepointId);
|
||||||
|
console.warn('>>>>', viewerData);
|
||||||
processData(viewerData);
|
processData(viewerData);
|
||||||
}).catch(reject);
|
}).catch(reject);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,6 +16,7 @@ Package.onUse(function(api) {
|
|||||||
api.use('iron:router@1.0.13');
|
api.use('iron:router@1.0.13');
|
||||||
|
|
||||||
api.use('ohif:core');
|
api.use('ohif:core');
|
||||||
|
api.use('ohif:servers');
|
||||||
|
|
||||||
api.addFiles('server/namespace.js', 'server');
|
api.addFiles('server/namespace.js', 'server');
|
||||||
api.addFiles('server/initialize.js', 'server');
|
api.addFiles('server/initialize.js', 'server');
|
||||||
|
|||||||
@ -1,172 +1,172 @@
|
|||||||
import { Meteor } from 'meteor/meteor';
|
import { Meteor } from 'meteor/meteor';
|
||||||
import { Router } from 'meteor/iron:router';
|
import { Router } from 'meteor/iron:router';
|
||||||
import { Accounts } from 'meteor/accounts-base';
|
import { Accounts } from 'meteor/accounts-base';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { Servers } from 'meteor/ohif:servers/both/collections';
|
||||||
|
|
||||||
const url = require("url");
|
const url = require('url');
|
||||||
const http = require("http");
|
const http = require('http');
|
||||||
const https = require("https");
|
const https = require('https');
|
||||||
const now = require("performance-now")
|
const now = require('performance-now');
|
||||||
|
|
||||||
const doAuth = Meteor.users.find().count() ? true : false;
|
const doAuth = Meteor.users.find().count() ? true : false;
|
||||||
|
|
||||||
const authenticateUser = request => {
|
const authenticateUser = request => {
|
||||||
// Only allow logged-in users to access this route
|
// Only allow logged-in users to access this route
|
||||||
const userId = request.headers['x-user-id']
|
const userId = request.headers['x-user-id'];
|
||||||
const loginToken = request.headers['x-auth-token']
|
const loginToken = request.headers['x-auth-token'];
|
||||||
if (!userId || !loginToken) {
|
if (!userId || !loginToken) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const hashedToken = Accounts._hashLoginToken(loginToken);
|
const hashedToken = Accounts._hashLoginToken(loginToken);
|
||||||
|
|
||||||
return Meteor.users.findOne({
|
return Meteor.users.findOne({
|
||||||
_id: userId,
|
_id: userId,
|
||||||
'services.resume.loginTokens.hashedToken': hashedToken
|
'services.resume.loginTokens.hashedToken': hashedToken
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Setup a Route using Iron Router to avoid Cross-origin resource sharing
|
// Setup a Route using Iron Router to avoid Cross-origin resource sharing
|
||||||
// (CORS) errors. We only handle this route on the Server.
|
// (CORS) errors. We only handle this route on the Server.
|
||||||
Router.route(Settings.uri.replace(OHIF.utils.absoluteUrl(), ''), function() {
|
Router.route(Settings.uri.replace(OHIF.utils.absoluteUrl(), ''), function() {
|
||||||
const request = this.request;
|
const request = this.request;
|
||||||
const response = this.response;
|
const response = this.response;
|
||||||
const params = this.params;
|
const params = this.params;
|
||||||
|
|
||||||
let start = now();
|
let start = now();
|
||||||
let user;
|
let user;
|
||||||
if (doAuth) {
|
if (doAuth) {
|
||||||
user = authenticateUser(request);
|
user = authenticateUser(request);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
response.writeHead(401);
|
response.writeHead(401);
|
||||||
response.end('Error: You must be logged in to perform this action.\n');
|
response.end('Error: You must be logged in to perform this action.\n');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
let end = now();
|
|
||||||
const authenticationTime = end - start;
|
let end = now();
|
||||||
|
const authenticationTime = end - start;
|
||||||
start = now();
|
|
||||||
|
start = now();
|
||||||
// TODO: Merge this with ohif-study-list? There is a circular dependency now...
|
|
||||||
const server = Servers.findOne(params.query.serverId);
|
const server = Servers.findOne(params.query.serverId);
|
||||||
if (!server) {
|
if (!server) {
|
||||||
response.writeHead(500);
|
response.writeHead(500);
|
||||||
response.end('Error: No Server with the specified Server ID was found.\n');
|
response.end('Error: No Server with the specified Server ID was found.\n');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const requestOpt = server.requestOptions;
|
const requestOpt = server.requestOptions;
|
||||||
|
|
||||||
// If no Web Access to DICOM Objects (WADO) Service URL is provided
|
// If no Web Access to DICOM Objects (WADO) Service URL is provided
|
||||||
// return an error for the request.
|
// return an error for the request.
|
||||||
const wadoUrl = params.query.url;
|
const wadoUrl = params.query.url;
|
||||||
if (!wadoUrl) {
|
if (!wadoUrl) {
|
||||||
response.writeHead(500);
|
response.writeHead(500);
|
||||||
response.end('Error: No WADO URL was provided.\n');
|
response.end('Error: No WADO URL was provided.\n');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (requestOpt.logRequests) {
|
if (requestOpt.logRequests) {
|
||||||
console.log(request.url);
|
console.log(request.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
start = now();
|
start = now();
|
||||||
if (requestOpt.logTiming) {
|
if (requestOpt.logTiming) {
|
||||||
console.time(request.url);
|
console.time(request.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use Node's URL parse to decode the query URL
|
// Use Node's URL parse to decode the query URL
|
||||||
const parsed = url.parse(wadoUrl);
|
const parsed = url.parse(wadoUrl);
|
||||||
|
|
||||||
// Create an object to hold the information required
|
// Create an object to hold the information required
|
||||||
// for the request to the PACS.
|
// for the request to the PACS.
|
||||||
let options = {
|
let options = {
|
||||||
headers: {},
|
headers: {},
|
||||||
method: request.method,
|
method: request.method,
|
||||||
hostname: parsed.hostname,
|
hostname: parsed.hostname,
|
||||||
path: parsed.path
|
path: parsed.path
|
||||||
};
|
};
|
||||||
|
|
||||||
let requester;
|
let requester;
|
||||||
if (parsed.protocol === 'https:') {
|
if (parsed.protocol === 'https:') {
|
||||||
requester = https.request;
|
requester = https.request;
|
||||||
|
|
||||||
const allowUnauthorizedAgent = new https.Agent({ rejectUnauthorized: false });
|
const allowUnauthorizedAgent = new https.Agent({ rejectUnauthorized: false });
|
||||||
options.agent = allowUnauthorizedAgent
|
options.agent = allowUnauthorizedAgent;
|
||||||
} else {
|
} else {
|
||||||
requester = http.request;
|
requester = http.request;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parsed.port) {
|
if (parsed.port) {
|
||||||
options.port = parsed.port;
|
options.port = parsed.port;
|
||||||
}
|
}
|
||||||
|
|
||||||
Object.keys(request.headers).forEach(entry => {
|
Object.keys(request.headers).forEach(entry => {
|
||||||
const value = request.headers[entry];
|
const value = request.headers[entry];
|
||||||
if (entry) {
|
if (entry) {
|
||||||
options.headers[entry] = value;
|
options.headers[entry] = value;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
// Retrieve the authorization user:password string for the PACS,
|
// Retrieve the authorization user:password string for the PACS,
|
||||||
// if one is required, and include it in the request to the PACS.
|
// if one is required, and include it in the request to the PACS.
|
||||||
if (requestOpt.auth) {
|
if (requestOpt.auth) {
|
||||||
options.auth = requestOpt.auth;
|
options.auth = requestOpt.auth;
|
||||||
}
|
}
|
||||||
|
|
||||||
end = now();
|
end = now();
|
||||||
const prepRequestTime = end - start;
|
const prepRequestTime = end - start;
|
||||||
|
|
||||||
// Use Node's HTTP API to send a request to the PACS
|
// Use Node's HTTP API to send a request to the PACS
|
||||||
const proxyRequest = requester(options, proxyResponse => {
|
const proxyRequest = requester(options, proxyResponse => {
|
||||||
// When we receive data from the PACS, stream it as the
|
// When we receive data from the PACS, stream it as the
|
||||||
// response to the original request.
|
// response to the original request.
|
||||||
// console.log(`Got response: ${proxyResponse.statusCode}`);
|
// console.log(`Got response: ${proxyResponse.statusCode}`);
|
||||||
end = now();
|
end = now();
|
||||||
const proxyReqTime = end - start;
|
const proxyReqTime = end - start;
|
||||||
const totalProxyTime = authenticationTime + prepRequestTime + proxyReqTime;
|
const totalProxyTime = authenticationTime + prepRequestTime + proxyReqTime;
|
||||||
const serverTimingHeaders = `
|
const serverTimingHeaders = `
|
||||||
auth=${authenticationTime}; "Authenticate User",
|
auth=${authenticationTime}; "Authenticate User",
|
||||||
prep-req=${prepRequestTime}; "Prepare Request Headers",
|
prep-req=${prepRequestTime}; "Prepare Request Headers",
|
||||||
proxy-req=${proxyReqTime}; "Request to WADO URI",
|
proxy-req=${proxyReqTime}; "Request to WADO URI",
|
||||||
total-proxy=${totalProxyTime}; "Total",
|
total-proxy=${totalProxyTime}; "Total",
|
||||||
`.replace(/\n/g, '');
|
`.replace(/\n/g, '');
|
||||||
|
|
||||||
proxyResponse.headers['Server-Timing'] = serverTimingHeaders;
|
proxyResponse.headers['Server-Timing'] = serverTimingHeaders;
|
||||||
|
|
||||||
response.writeHead(proxyResponse.statusCode, proxyResponse.headers);
|
response.writeHead(proxyResponse.statusCode, proxyResponse.headers);
|
||||||
|
|
||||||
if (requestOpt.logTiming) {
|
if (requestOpt.logTiming) {
|
||||||
console.timeEnd(request.url);
|
console.timeEnd(request.url);
|
||||||
}
|
}
|
||||||
|
|
||||||
return proxyResponse.pipe(response, {end: true});
|
return proxyResponse.pipe(response, { end: true });
|
||||||
});
|
});
|
||||||
|
|
||||||
// If our request to the PACS fails, log the error message
|
// If our request to the PACS fails, log the error message
|
||||||
proxyRequest.on('error', error => {
|
proxyRequest.on('error', error => {
|
||||||
end = now();
|
end = now();
|
||||||
const proxyReqTime = end - start;
|
const proxyReqTime = end - start;
|
||||||
const totalProxyTime = authenticationTime + prepRequestTime + proxyReqTime;
|
const totalProxyTime = authenticationTime + prepRequestTime + proxyReqTime;
|
||||||
console.timeEnd(request.url);
|
console.timeEnd(request.url);
|
||||||
const serverTimingHeaders = {
|
const serverTimingHeaders = {
|
||||||
'Server-Timing': `
|
'Server-Timing': `
|
||||||
auth=${authenticationTime}; "Authenticate User",
|
auth=${authenticationTime}; "Authenticate User",
|
||||||
prep-req=${prepRequestTime}; "Prepare Request Headers",
|
prep-req=${prepRequestTime}; "Prepare Request Headers",
|
||||||
proxy-req=${proxyReqTime}; "Request to WADO URI",
|
proxy-req=${proxyReqTime}; "Request to WADO URI",
|
||||||
total-proxy=${totalProxyTime}; "Total",
|
total-proxy=${totalProxyTime}; "Total",
|
||||||
`.replace(/\n/g, '')
|
`.replace(/\n/g, '')
|
||||||
};
|
};
|
||||||
|
|
||||||
response.writeHead(500, serverTimingHeaders);
|
response.writeHead(500, serverTimingHeaders);
|
||||||
response.end(`Error: Problem with request to PACS: ${error.message}\n`);
|
response.end(`Error: Problem with request to PACS: ${error.message}\n`);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Stream the original request information into the request
|
// Stream the original request information into the request
|
||||||
// to the PACS
|
// to the PACS
|
||||||
request.pipe(proxyRequest);
|
request.pipe(proxyRequest);
|
||||||
}, {
|
}, {
|
||||||
where: 'server'
|
where: 'server'
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user