Fixing serverId issues

This commit is contained in:
Bruno Alves de Faria 2017-06-16 16:36:34 -03:00
parent 95533c785b
commit b4bb44625c
62 changed files with 685 additions and 556 deletions

View File

@ -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

View File

@ -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();

View File

@ -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' } });

View File

@ -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';

View File

@ -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;
} }

View File

@ -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,

View File

@ -0,0 +1,5 @@
import { OHIF } from 'meteor/ohif:core';
OHIF.servers = {
collections: {}
};

View 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 };

View File

@ -0,0 +1,4 @@
import { CurrentServer } from './currentServer.js';
import { Servers } from './servers.js';
export { CurrentServer, Servers };

View 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 };

View File

@ -0,0 +1,3 @@
import './base.js';
import './collections';
import './lib';

View File

@ -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) {

View File

@ -0,0 +1 @@
import './subscriptions.js';

View File

@ -1,2 +1,4 @@
import { Meteor } from 'meteor/meteor';
Meteor.subscribe('servers'); Meteor.subscribe('servers');
Meteor.subscribe('currentServer'); Meteor.subscribe('currentServer');

View File

@ -0,0 +1 @@
import './serverInformation';

View File

@ -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() {

View File

@ -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);

View File

@ -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();

View File

@ -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

View File

@ -0,0 +1 @@
import './collections';

View 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');
});

View File

@ -0,0 +1,4 @@
import './publications.js';
import './methods.js';
import './startup.js';
import './lib';

View File

@ -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)
});

View File

@ -0,0 +1 @@
import './control.js';

View 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)
});

View 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());

View 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));
});

View File

@ -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 };

View File

@ -1,4 +1,2 @@
import './base.js'; import './base.js';
import './lib';
import './schema';
import './collections.js'; import './collections.js';

View File

@ -1 +0,0 @@
import './servers.js';

View File

@ -1,2 +1 @@
import './studies.js'; import './studies.js';
import './subscriptions.js';

View File

@ -1,4 +1,2 @@
import './seriesDetailsModal'; import './seriesDetailsModal';
import './serverInformation';
import './studylist'; import './studylist';
import './themeSelector';

View File

@ -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');
}); });

View File

@ -1,6 +1,4 @@
import './publications.js'; import './publications.js';
import './servers.js';
import './validateServerConfiguration.js';
import './lib'; import './lib';
import './methods'; import './methods';

View File

@ -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.';

View File

@ -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,14 +12,14 @@ 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();
@ -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);

View File

@ -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.';

View File

@ -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());

View File

@ -1,3 +1,5 @@
import { OHIF } from 'meteor/ohif:core';
/** /**
* Parses data returned from a study search and transforms it into * Parses data returned from a study search and transforms it into
* an array of series that are present in the study * an array of series that are present in the study
@ -5,17 +7,17 @@
* @param resultData * @param resultData
* @returns {Array} Series List * @returns {Array} Series List
*/ */
function resultDataToStudyMetadata(resultData) { function resultDataToStudyMetadata(resultData, studyInstanceUid) {
var seriesMap = {}; const seriesMap = {};
var seriesList = []; const seriesList = [];
resultData.forEach(function(instanceRaw) { resultData.forEach(function(instanceRaw) {
var instance = instanceRaw.toObject(); const instance = instanceRaw.toObject();
// Use seriesMap to cache series data // Use seriesMap to cache series data
// If the series instance UID has already been used to // If the series instance UID has already been used to
// process series data, continue using that series // process series data, continue using that series
var seriesInstanceUid = instance[0x0020000E]; const seriesInstanceUid = instance[0x0020000E];
var series = seriesMap[seriesInstanceUid]; let series = seriesMap[seriesInstanceUid];
// If no series data exists in the seriesMap cache variable, // If no series data exists in the seriesMap cache variable,
// process any available series data // process any available series data
@ -32,18 +34,18 @@ function resultDataToStudyMetadata(resultData) {
} }
// TODO: Check which peer it should point to // TODO: Check which peer it should point to
var server = getCurrentServer().peers[0]; const server = OHIF.servers.getCurrentServer().peers[0];
var serverRoot = server.host + ':' + server.port; const serverRoot = server.host + ':' + server.port;
var sopInstanceUid = instance[0x00080018]; const sopInstanceUid = instance[0x00080018];
var uri = serverRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1'; const uri = serverRoot + '/studies/' + studyInstanceUid + '/series/' + seriesInstanceUid + '/instances/' + sopInstanceUid + '/frames/1';
// Add this instance to the current series // Add this instance to the current series
series.instances.push({ series.instances.push({
sopClassUid: instance[0x00080016], sopClassUid: instance[0x00080016],
sopInstanceUid: sopInstanceUid, sopInstanceUid,
uri: uri, uri,
instanceNumber: instance[0x00200013] instanceNumber: instance[0x00200013]
}); });
}); });
@ -57,10 +59,10 @@ function resultDataToStudyMetadata(resultData) {
*/ */
Services.DIMSE.Instances = function(studyInstanceUid) { Services.DIMSE.Instances = function(studyInstanceUid) {
//var url = buildUrl(server, studyInstanceUid); //var url = buildUrl(server, studyInstanceUid);
var result = DIMSE.retrieveInstances(studyInstanceUid); const result = DIMSE.retrieveInstances(studyInstanceUid);
return { return {
studyInstanceUid: studyInstanceUid, studyInstanceUid: studyInstanceUid,
seriesList: resultDataToStudyMetadata(result) seriesList: resultDataToStudyMetadata(result, studyInstanceUid)
}; };
}; };

View File

@ -28,7 +28,7 @@ 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];
} }
@ -45,19 +45,19 @@ function getSourceImageInstanceUid(instance) {
*/ */
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],
@ -73,9 +73,9 @@ function resultDataToStudyMetadata(studyInstanceUid, resultData) {
}; };
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],
@ -88,9 +88,9 @@ function resultDataToStudyMetadata(studyInstanceUid, resultData) {
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],
@ -134,7 +134,7 @@ function resultDataToStudyMetadata(studyInstanceUid, resultData) {
}; };
// 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);
@ -153,7 +153,7 @@ function resultDataToStudyMetadata(studyInstanceUid, resultData) {
*/ */
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;

View File

@ -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);
} }
}; };

View File

@ -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));
});

View File

@ -0,0 +1 @@
import './components';

View File

@ -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',

View File

@ -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

View File

@ -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);
} }

View File

@ -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');

View File

@ -1,20 +1,20 @@
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;
} }
@ -25,7 +25,7 @@ const authenticateUser = request => {
_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.
@ -44,12 +44,12 @@ Router.route(Settings.uri.replace(OHIF.utils.absoluteUrl(), ''), function() {
return; return;
} }
} }
let end = now(); let end = now();
const authenticationTime = end - start; 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);
@ -94,7 +94,7 @@ Router.route(Settings.uri.replace(OHIF.utils.absoluteUrl(), ''), function() {
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;
} }