reorganize packages, start converting overall app to react (very broken at the moment)
This commit is contained in:
1 parent
024fe1a448
commit
5f30f7bd35
479 files changed
+5364
-11611
No files matched your search
@@ -1,5 +1,6 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Object.assign(OHIF.studylist, {
|
||||
OHIF.studylist = {
|
||||
actions: {},
|
||||
callbacks: {}
|
||||
});
|
||||
};
|
||||
@@ -1,11 +1,9 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
// Define the Studies Collection. This is a client-side only Collection which stores the list of
|
||||
// studies in the StudyList
|
||||
Meteor.startup(() => {
|
||||
const Studies = new Meteor.Collection(null);
|
||||
Studies._debugName = 'Studies';
|
||||
const Studies = new Meteor.Collection(null);
|
||||
Studies._debugName = 'Studies';
|
||||
|
||||
OHIF.studylist.collections.Studies = Studies;
|
||||
});
|
||||
OHIF.studylist.collections = {};
|
||||
OHIF.studylist.collections.Studies = Studies;
|
||||
@@ -1,5 +1,9 @@
|
||||
import React, { Component } from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
import Blaze from 'meteor/gadicc:blaze-react-component';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import './StudyList.css';
|
||||
|
||||
class StudyList extends Component {
|
||||
constructor(props) {
|
||||
@@ -10,14 +14,14 @@ class StudyList extends Component {
|
||||
render() {
|
||||
return (
|
||||
<div className='StudyList'>
|
||||
<Blaze template="studylist" />
|
||||
<Blaze template="studylist" className='tempStudyList'/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
StudyList.propTypes = {
|
||||
studies: PropTypes.array.isRequired
|
||||
studies: PropTypes.array
|
||||
};
|
||||
|
||||
OHIF.studylist.components = {
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
import './seriesDetailsModal';
|
||||
import './studylist';
|
||||
import './studylist/index.js';
|
||||
import './StudyList.js';
|
||||
@@ -0,0 +1,24 @@
|
||||
<template name="roundedButtonGroup">
|
||||
<div class="{{class}} roundedButtonGroup clearfix center-table">
|
||||
{{#each item in this.options}}
|
||||
<a class="roundedButtonWrapper noselect {{#if eq getValue item.value}}active{{/if}}" data-value="{{item.value}}">
|
||||
<div class="roundedButton">
|
||||
{{#if item.svgLink}}
|
||||
<svg style="width: {{item.svgWidth}}px; height: {{item.svgHeight}}px">
|
||||
<use xlink:href="{{absoluteUrl item.svgLink}}"></use>
|
||||
</svg>
|
||||
{{/if}}
|
||||
{{#if item.text}}
|
||||
<span>{{item.text}}</span>
|
||||
{{/if}}
|
||||
{{#if item.iconClasses}}
|
||||
<i class="{{item.iconClasses}}"></i>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{#if item.bottomLabel}}
|
||||
<div class="bottomLabel">{{item.bottomLabel}}</div>
|
||||
{{/if}}
|
||||
</a>
|
||||
{{/each}}
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,46 @@
|
||||
Template.roundedButtonGroup.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
const reactiveValue = instance.data.value;
|
||||
|
||||
// Get the value for ReactiveVar or ReactiveDict objects
|
||||
instance.getValue = () => {
|
||||
return reactiveValue.get(instance.data.key);
|
||||
};
|
||||
|
||||
// Set the value for ReactiveVar or ReactiveDict objects
|
||||
instance.setValue = value => {
|
||||
const args = [value];
|
||||
if (reactiveValue instanceof ReactiveDict) {
|
||||
args.unshift(instance.data.key);
|
||||
}
|
||||
|
||||
reactiveValue.set(...args);
|
||||
};
|
||||
|
||||
// Initialize the value with the first option if there's no value set and options are not toggleable
|
||||
if (!instance.getValue() && !instance.data.toggleable) {
|
||||
instance.setValue(instance.data.options[0].value);
|
||||
}
|
||||
});
|
||||
|
||||
Template.roundedButtonGroup.events({
|
||||
'click [data-value]'(event, instance) {
|
||||
event.preventDefault();
|
||||
const $target = $(event.currentTarget);
|
||||
|
||||
// Stop here if the tool is disabled
|
||||
if ($target.hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const nullValue = $target.hasClass('active') && instance.data.toggleable;
|
||||
const value = nullValue ? null : $target.attr('data-value');
|
||||
instance.setValue(value);
|
||||
}
|
||||
});
|
||||
|
||||
Template.roundedButtonGroup.helpers({
|
||||
getValue() {
|
||||
return Template.instance().getValue();
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,81 @@
|
||||
@import "{ohif:viewerbase}/app"
|
||||
|
||||
$height = 25px
|
||||
|
||||
.roundedButtonGroup
|
||||
position: relative
|
||||
z-index: 0
|
||||
|
||||
.roundedButtonWrapper
|
||||
cursor: pointer
|
||||
display: inline-block
|
||||
float: left
|
||||
margin-left: -2px
|
||||
text-decoration: none
|
||||
text-align: center
|
||||
|
||||
&.disabled
|
||||
opacity: 0.5
|
||||
cursor: not-allowed
|
||||
|
||||
.roundedButton
|
||||
align-items: center
|
||||
theme('background-color', '$uiGrayDark')
|
||||
theme('border', '2px solid $uiBorderColorDark')
|
||||
theme('color', '$textSecondaryColor')
|
||||
display: flex
|
||||
font-size: 11px
|
||||
font-weight: 500
|
||||
justify-content: center
|
||||
height: $height
|
||||
line-height: $height
|
||||
padding: 0 22px
|
||||
position: relative
|
||||
text-transform: uppercase
|
||||
transition($sidebarTransition)
|
||||
z-index: 1
|
||||
|
||||
svg
|
||||
theme('fill', '$defaultColor')
|
||||
theme('stroke', '$defaultColor')
|
||||
|
||||
svg
|
||||
span
|
||||
margin: 0 2px
|
||||
|
||||
i
|
||||
line-height: 15px
|
||||
font-size: 15px
|
||||
|
||||
.bottomLabel
|
||||
theme('color', '$textSecondaryColor')
|
||||
font-size: 12px
|
||||
font-weight: 500
|
||||
line-height: 12px
|
||||
margin-top: 8px
|
||||
|
||||
&:first-child
|
||||
margin-left: 0
|
||||
.roundedButton
|
||||
border-bottom-left-radius: $height
|
||||
border-top-left-radius: $height
|
||||
|
||||
&:last-child .roundedButton
|
||||
border-bottom-right-radius: $height
|
||||
border-top-right-radius: $height
|
||||
|
||||
&:hover .roundedButton
|
||||
theme('color', '$uiGrayDark')
|
||||
theme('background-color', '$boxBackgroundColor')
|
||||
|
||||
&.active .roundedButton
|
||||
theme('background-color', '$activeColor')
|
||||
theme('border-color', '$uiBorderColorActive')
|
||||
theme('color', '$uiGrayDark')
|
||||
z-index: 2
|
||||
|
||||
&:hover .roundedButton
|
||||
&.active .roundedButton
|
||||
svg
|
||||
theme('fill', '$uiGrayDark')
|
||||
theme('stroke', '$uiGrayDark')
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveDict } from 'meteor/reactive-dict';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import _ from 'underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Template.seriesDetailsTable.onCreated(() => {
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
@import "{ohif:design}/app"
|
||||
@import "{ohif:viewerbase}/app"
|
||||
|
||||
.selectedStudyContainer
|
||||
margin-bottom: 15px;
|
||||
@@ -27,4 +27,4 @@
|
||||
|
||||
.loadingTextDiv
|
||||
font-size: 13px
|
||||
color: $textSecondaryColor
|
||||
color: $textSecondaryColor
|
||||
@@ -1,4 +1,4 @@
|
||||
@import "{ohif:design}/app"
|
||||
@import "{ohif:viewerbase}/app"
|
||||
|
||||
.study-list-wrapper
|
||||
theme('background-color', '$primaryBackgroundColor')
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ import { Template } from 'meteor/templating';
|
||||
import { Session } from 'meteor/session';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { ReactiveDict } from 'meteor/reactive-dict';
|
||||
import { moment } from 'meteor/momentjs:moment';
|
||||
import moment from 'moment';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
Session.setDefault('showLoadingText', true);
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
@import "{ohif:design}/app"
|
||||
@import "{ohif:viewerbase}/app"
|
||||
|
||||
$tableHoverColor = #2c363f
|
||||
$tableTextPrimaryColor = white
|
||||
@@ -61,8 +61,8 @@ $bodyCellHeight = 40px
|
||||
|
||||
#studyListContainer
|
||||
width: 100%
|
||||
padding: 0 $studyListPadding
|
||||
position: absolute
|
||||
//padding: 0 $studyListPadding
|
||||
//position: absolute
|
||||
z-index: 2
|
||||
|
||||
.loadingTextDiv
|
||||
|
||||
+1
-1
@@ -2,7 +2,7 @@ import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { Session } from 'meteor/session';
|
||||
import { $ } from 'meteor/jquery';
|
||||
import $ from 'jquery';
|
||||
|
||||
Template.studylistToolbar.onCreated(() => {
|
||||
Meteor.call('importSupported', (error, result) => {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
@import "{ohif:design}/app"
|
||||
@import "{ohif:viewerbase}/app"
|
||||
|
||||
.studylistToolbar
|
||||
.addNewStudy
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* Imports selected studies from local into studylist
|
||||
* @param filesToImport Files located in the client machine to import
|
||||
*/
|
||||
OHIF.studylist.importStudies = filesToImport => {
|
||||
const numberOfFiles = filesToImport && filesToImport.length;
|
||||
if (!numberOfFiles) {
|
||||
return new Promise((resolve, reject) => reject('No files to upload'));
|
||||
}
|
||||
|
||||
const uploadMessage = msg => (typeof msg === 'undefined') ? '' : `Uploaded files: ${msg.processed} / ${msg.total}`;
|
||||
|
||||
const taskRunHandler = dialog => {
|
||||
const uploadErrorHandler = fileNames => {
|
||||
const names = fileNames.join('; ');
|
||||
dialog.setMessage(`Failed to upload files: ${names}`);
|
||||
};
|
||||
|
||||
const uploadSuccessHandler = studiesToImport => {
|
||||
importStudiesInternal(studiesToImport, dialog).then(() => {
|
||||
dialog.done();
|
||||
}).catch(errorMessage => {
|
||||
dialog.setMessage(errorMessage);
|
||||
});
|
||||
};
|
||||
|
||||
uploadFiles(filesToImport, dialog).then(uploadSuccessHandler).catch(uploadErrorHandler);
|
||||
};
|
||||
|
||||
return OHIF.ui.showDialog('dialogProgress', {
|
||||
title: 'Importing Studies...',
|
||||
message: uploadMessage,
|
||||
total: numberOfFiles,
|
||||
task: { run: taskRunHandler }
|
||||
});
|
||||
};
|
||||
|
||||
const uploadFiles = (files, dialog) => {
|
||||
let processed = 0;
|
||||
|
||||
const promise = new Promise((resolve, reject) => {
|
||||
const promises = [];
|
||||
|
||||
// Upload files to the server
|
||||
files.forEach(file => {
|
||||
const filePromise = uploadFile(file, dialog);
|
||||
filePromise.then(() => dialog.update(++processed));
|
||||
promises.push(filePromise);
|
||||
});
|
||||
|
||||
Promise.all(promises).then(resolve).catch(reject);
|
||||
});
|
||||
|
||||
return promise;
|
||||
};
|
||||
|
||||
const uploadFile = file => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '/uploadFilesToImport', true);
|
||||
xhr.setRequestHeader('filename', file.name);
|
||||
|
||||
xhr.onload = () => {
|
||||
if (xhr.readyState === 4 && xhr.status !== 200) {
|
||||
// Failed to upload the file
|
||||
reject(file.name);
|
||||
} else {
|
||||
// Success uploading the file
|
||||
resolve(xhr.responseText);
|
||||
}
|
||||
};
|
||||
|
||||
// Failed to upload the file
|
||||
xhr.onerror = () => reject(file.name);
|
||||
|
||||
xhr.send(file);
|
||||
});
|
||||
};
|
||||
|
||||
const importStudiesInternal = (studiesToImport, dialog) => {
|
||||
const numberOfStudies = studiesToImport && studiesToImport.length;
|
||||
if (!numberOfStudies) {
|
||||
return new Promise((resolve, reject) => reject('No studies to import'));
|
||||
}
|
||||
|
||||
let processed = 0;
|
||||
dialog.update(processed);
|
||||
dialog.setTotal(numberOfStudies);
|
||||
dialog.setMessage(({ processed, total }) => `Imported: ${processed} / ${total}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
// Create/Insert a new study import status item
|
||||
Meteor.call('createStudyImportStatus', (error, studyImportStatusId) => {
|
||||
if (error) {
|
||||
return reject(error.message);
|
||||
}
|
||||
|
||||
// Handle when StudyImportStatus collection is updated
|
||||
OHIF.studylist.collections.StudyImportStatus.find(studyImportStatusId).observe({
|
||||
changed(studyImportStatus) {
|
||||
const { numberOfStudiesImported, numberOfStudiesFailed } = studyImportStatus;
|
||||
dialog.update(numberOfStudiesImported);
|
||||
|
||||
if ((numberOfStudiesImported + numberOfStudiesFailed) === numberOfStudies) {
|
||||
// The entire import operation is completed, so remove the study import status item
|
||||
Meteor.call('removeStudyImportStatus', studyImportStatus._id);
|
||||
|
||||
// Show number of failed files if there is at least one failed file
|
||||
if (studyImportStatus.numberOfStudiesFailed > 0) {
|
||||
const failed = numberOfStudiesFailed;
|
||||
reject(`Failed to import ${failed} of ${numberOfStudies} studies`);
|
||||
} else {
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Import studies with study import status id to get callbacks
|
||||
Meteor.call('importStudies', studiesToImport, studyImportStatusId);
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -1,7 +1,6 @@
|
||||
import './exportSelectedStudies.js';
|
||||
import './exportStudies.js';
|
||||
//import './exportSelectedStudies.js';
|
||||
//import './exportStudies.js';
|
||||
import './getSelectedStudies.js';
|
||||
import './importStudies.js';
|
||||
import './queryStudies.js';
|
||||
import './studylist.js';
|
||||
import './viewSeriesDetails.js';
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Router } from 'meteor/clinical:router';
|
||||
|
||||
// Functions
|
||||
import { getStudyPriors } from './getStudyPriors';
|
||||
@@ -11,7 +10,8 @@ OHIF.studylist.functions = {
|
||||
};
|
||||
|
||||
const dblClickOnStudy = data => {
|
||||
Router.go('viewerStudies', { studyInstanceUids: data.studyInstanceUid });
|
||||
//Router.go('viewerStudies', { studyInstanceUids: data.studyInstanceUid });
|
||||
console.log('dblClickOnStudy');
|
||||
};
|
||||
|
||||
OHIF.studylist.callbacks.dblClickOnStudy = dblClickOnStudy;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Router } from 'meteor/clinical:router';
|
||||
|
||||
/**
|
||||
* Loads multiple unassociated studies in the Viewer
|
||||
@@ -14,5 +13,6 @@ OHIF.studylist.viewStudies = () => {
|
||||
|
||||
const studyInstanceUids = selectedStudies.map(study => study.studyInstanceUid).join(';');
|
||||
|
||||
Router.go('viewerStudies', { studyInstanceUids });
|
||||
//Router.go('viewerStudies', { studyInstanceUids });
|
||||
console.log('OHIF.studylist.viewStudies');
|
||||
};
|
||||
Reference in new issue
Block a user