PWV-1: Refactoring ohif:studylist package
This commit is contained in:
1 parent
984ef94403
commit
4d79bf84a8
79 files changed
+450
-551
No files matched your search
@@ -0,0 +1,5 @@
|
||||
import './progressDialog';
|
||||
import './seriesDetailsModal';
|
||||
import './serverInformation';
|
||||
import './studyContextMenu';
|
||||
import './studylist';
|
||||
@@ -0,0 +1,3 @@
|
||||
import './progressDialog.html';
|
||||
import './progressDialog.styl';
|
||||
import './progressDialog.js';
|
||||
@@ -6,14 +6,13 @@
|
||||
<div class="dialogContent">
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped active"
|
||||
role="progressbar"
|
||||
style="width:{{progressStatus}}">
|
||||
{{formatNumberPrecision progressStatus 0}}%
|
||||
</div>
|
||||
role="progressbar"
|
||||
style="width: {{progressStatus}}%"
|
||||
>{{formatNumberPrecision progressStatus 0}}%</div>
|
||||
</div>
|
||||
<div id="message">
|
||||
{{{progressMessage}}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
@@ -1,4 +1,28 @@
|
||||
progressDialog = {
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Session } from 'meteor/session';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
const updateProgress = numberOfCompleted => {
|
||||
const progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.numberOfCompleted = numberOfCompleted;
|
||||
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
|
||||
if (progressDialogSettings.numberOfCompleted === progressDialogSettings.numberOfTotal) {
|
||||
OHIF.studylist.progressDialog.close();
|
||||
}
|
||||
};
|
||||
|
||||
const setProgressMessage = message => {
|
||||
let progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.message = message;
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
};
|
||||
|
||||
OHIF.studylist.progressDialog = {
|
||||
update: _.debounce(updateProgress, 100),
|
||||
setMessage: _.debounce(setProgressMessage, 100),
|
||||
show: function(title, numberOfTotal) {
|
||||
Session.set('progressDialogSettings', {
|
||||
title: title,
|
||||
@@ -8,16 +32,6 @@ progressDialog = {
|
||||
|
||||
$('#progressDialog').css('display', 'block');
|
||||
},
|
||||
update: function(numberOfCompleted) {
|
||||
var progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.numberOfCompleted = numberOfCompleted;
|
||||
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
|
||||
if (progressDialogSettings.numberOfCompleted === progressDialogSettings.numberOfTotal) {
|
||||
progressDialog.close();
|
||||
}
|
||||
},
|
||||
close: function() {
|
||||
Session.set('progressDialogSettings', {
|
||||
title: '',
|
||||
@@ -26,17 +40,12 @@ progressDialog = {
|
||||
});
|
||||
|
||||
$('#progressDialog').css('display', 'none');
|
||||
},
|
||||
setMessage: function(message) {
|
||||
let progressDialogSettings = Session.get('progressDialogSettings');
|
||||
progressDialogSettings.message = message;
|
||||
Session.set('progressDialogSettings', progressDialogSettings);
|
||||
}
|
||||
};
|
||||
|
||||
Template.progressDialog.helpers({
|
||||
progressDialogTitle() {
|
||||
var settings = Session.get('progressDialogSettings');
|
||||
const settings = Session.get('progressDialogSettings');
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
@@ -55,11 +64,11 @@ Template.progressDialog.helpers({
|
||||
return;
|
||||
}
|
||||
|
||||
return settings.numberOfCompleted / settings.numberOfTotal;
|
||||
return (settings.numberOfCompleted / settings.numberOfTotal) * 100;
|
||||
},
|
||||
|
||||
progressMessage() {
|
||||
var settings = Session.get('progressDialogSettings');
|
||||
const settings = Session.get('progressDialogSettings');
|
||||
if (!settings) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
import './viewSeriesDetailsModal.html';
|
||||
|
||||
import './seriesDetailsTable/seriesDetailsTable.html';
|
||||
import './seriesDetailsTable/seriesDetailsTable.styl';
|
||||
import './seriesDetailsTable/seriesDetailsTable.js';
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -0,0 +1,15 @@
|
||||
import './serverInformationDicomWeb/serverInformationDicomWeb.html';
|
||||
import './serverInformationDicomWeb/serverInformationDicomWeb.js';
|
||||
|
||||
import './serverInformationDimse/serverInformationDimse.html';
|
||||
import './serverInformationDimse/serverInformationDimse.js';
|
||||
|
||||
import './serverInformationForm/serverInformationForm.html';
|
||||
import './serverInformationForm/serverInformationForm.js';
|
||||
|
||||
import './serverInformationList/serverInformationList.html';
|
||||
import './serverInformationList/serverInformationList.js';
|
||||
|
||||
import './serverInformationModal/serverInformationModal.html';
|
||||
import './serverInformationModal/serverInformationModal.styl';
|
||||
import './serverInformationModal/serverInformationModal.js';
|
||||
-10
@@ -1,10 +0,0 @@
|
||||
<template name="serverInformationFormField">
|
||||
<div class="col-lg-6">
|
||||
<div class="form-group">
|
||||
<label class="wrapper">
|
||||
<span>{{this.label}}</span>
|
||||
<input type="text" name="{{this.name}}" class="form-control">
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@@ -0,0 +1,2 @@
|
||||
import './studyContextMenu.html';
|
||||
import './studyContextMenu.js';
|
||||
@@ -1,25 +1,12 @@
|
||||
<template name="studyContextMenu">
|
||||
{{#if uiSettings.studyListFunctionsEnabled}}
|
||||
<div id="studyContextMenu" class="studyContextMenu noselect"
|
||||
oncontextmenu='return false;'
|
||||
unselectable='on'
|
||||
onselectstart='return false;'>
|
||||
<ul>
|
||||
<li>
|
||||
<a id="viewSeriesDetails" type="button"
|
||||
title="View Series Details">
|
||||
View Series Details
|
||||
</a>
|
||||
<a class="disabled">Anonymize</a>
|
||||
<a class="disabled">Send</a>
|
||||
<hr/>
|
||||
<a class="disabled">Delete</a>
|
||||
<a id="exportSelectedStudies"
|
||||
title="Export Selected Studies">
|
||||
Export
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
{{/if}}
|
||||
{{#dropdownForm}}
|
||||
<li><a id="viewSeriesDetails" type="button"
|
||||
title="View Series Details"
|
||||
>View Series Details</a></li>
|
||||
<li class="disabled"><a class="disabled">Anonymize</a></li>
|
||||
<li class="disabled"><a class="disabled">Send</a></li>
|
||||
<li class="divider" role="separator"></li>
|
||||
<li class="disabled"><a class="disabled">Delete</a></li>
|
||||
<li><a id="exportSelectedStudies" title="Export Selected Studies">Export</a></li>
|
||||
{{/dropdownForm}}
|
||||
</template>
|
||||
@@ -1,84 +1,48 @@
|
||||
function closeHandler(dialog) {
|
||||
// Hide the dialog
|
||||
$(dialog).css('display', 'none');
|
||||
|
||||
// Remove the backdrop
|
||||
$('.removableBackdrop').remove();
|
||||
}
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
|
||||
/**
|
||||
* This function is used inside the StudyList package to define a right click callback
|
||||
*
|
||||
* @param e
|
||||
* @param event
|
||||
*/
|
||||
openStudyContextMenu = function(e) {
|
||||
StudyList.functions['exportSelectedStudies'] = exportSelectedStudies;
|
||||
StudyList.functions['viewSeriesDetails'] = viewSeriesDetails;
|
||||
|
||||
|
||||
Template.studyContextMenu.study = $(e.currentTarget);
|
||||
|
||||
var dialog = $('#studyContextMenu');
|
||||
|
||||
// Show the nonTargetLesion dialog above
|
||||
var dialogProperty = {
|
||||
display: 'block'
|
||||
};
|
||||
|
||||
var pageHeight = $(document).height();
|
||||
dialogProperty.top = Math.max(e.pageY, 0);
|
||||
dialogProperty.top = Math.min(dialogProperty.top, pageHeight - dialog.outerHeight());
|
||||
|
||||
var pageWidth = $(document).width();
|
||||
dialogProperty.left = Math.max(e.pageX, 0);
|
||||
dialogProperty.left = Math.min(dialogProperty.left, pageWidth - dialog.outerWidth());
|
||||
|
||||
// Device is touch device or not
|
||||
// If device is touch device, set position center of screen vertically and horizontally
|
||||
if (isTouchDevice()) {
|
||||
// add dialogMobile class to provide a black, transparent background
|
||||
dialog.addClass('dialogMobile');
|
||||
dialogProperty.top = 0;
|
||||
dialogProperty.left = 0;
|
||||
dialogProperty.right = 0;
|
||||
dialogProperty.bottom = 0;
|
||||
dialogProperty.margin = 'auto';
|
||||
openStudyContextMenu = event => {
|
||||
if (!OHIF.uiSettings.studyListFunctionsEnabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
dialog.css(dialogProperty);
|
||||
dialog.focus();
|
||||
StudyList.functions.exportSelectedStudies = exportSelectedStudies;
|
||||
StudyList.functions.viewSeriesDetails = viewSeriesDetails;
|
||||
|
||||
// Show the backdrop
|
||||
UI.render(Template.removableBackdrop, document.body);
|
||||
Template.studyContextMenu.$study = $(event.currentTarget);
|
||||
|
||||
// Make sure the context menu is closed when the user clicks away
|
||||
$('.removableBackdrop').one('mousedown touchstart', function() {
|
||||
closeHandler(dialog);
|
||||
});
|
||||
const dropdown = OHIF.ui.showFormDropdown('studyContextMenu');
|
||||
const $dropdown = $(dropdown);
|
||||
const $dropdownMenu = $dropdown.children('.dropdown-menu');
|
||||
|
||||
dropdown.oncontextmenu = () => false;
|
||||
|
||||
$dropdownMenu.css({
|
||||
position: 'fixed',
|
||||
left: `${event.clientX}px`,
|
||||
top: `${event.clientY}px`,
|
||||
'z-index': 10000
|
||||
}).bounded().focus();
|
||||
};
|
||||
|
||||
/**
|
||||
* Exports all selected studies on the studylist
|
||||
*/
|
||||
function exportSelectedStudies() {
|
||||
var selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch() || [];
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
exportStudies(selectedStudies);
|
||||
OHIF.studylist.exportStudies(selectedStudies);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display series details of study in modal
|
||||
*/
|
||||
function viewSeriesDetails() {
|
||||
var selectedStudies = StudyListSelectedStudies.find({}, {
|
||||
sort: {
|
||||
studyDate: 1
|
||||
}
|
||||
}).fetch();
|
||||
const selectedStudies = OHIF.studylist.getSelectedStudies();
|
||||
|
||||
if (!selectedStudies) {
|
||||
return;
|
||||
@@ -91,7 +55,7 @@ function viewSeriesDetails() {
|
||||
|
||||
Template.studyContextMenu.events({
|
||||
'click a': function(e) {
|
||||
var study = Template.studyContextMenu.study;
|
||||
var study = Template.studyContextMenu.$study;
|
||||
var id = $(e.currentTarget).attr('id');
|
||||
|
||||
var fn = StudyList.functions[id];
|
||||
@@ -100,6 +64,5 @@ Template.studyContextMenu.events({
|
||||
}
|
||||
|
||||
var dialog = $('#studyContextMenu');
|
||||
closeHandler(dialog);
|
||||
}
|
||||
});
|
||||
@@ -1,63 +0,0 @@
|
||||
@import "{design}/app"
|
||||
|
||||
.studyContextMenu
|
||||
z-index: 10000
|
||||
display: none
|
||||
position: absolute
|
||||
color: #2f2f2f
|
||||
background-color: #f2f2f2
|
||||
|
||||
width: -moz-fit-content
|
||||
width: -webkit-fit-content
|
||||
width: fit-content
|
||||
width: 207px
|
||||
|
||||
height: -moz-fit-content
|
||||
height: -webkit-fit-content
|
||||
height: fit-content
|
||||
|
||||
min-width: 100px
|
||||
font-size: 14px
|
||||
text-align: left
|
||||
-webkit-background-clip: padding-box
|
||||
background-clip: padding-box
|
||||
border: 1px solid rgba(0, 0, 0, .15)
|
||||
border-radius: 3px
|
||||
-webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, .175)
|
||||
box-shadow: 0 6px 12px rgba(0, 0, 0, .175)
|
||||
|
||||
hr
|
||||
border-top: solid 1px #d1d1d1
|
||||
margin: 2px
|
||||
|
||||
ul
|
||||
width: 100%
|
||||
margin: 5px 0
|
||||
list-style: none
|
||||
padding: 0
|
||||
|
||||
li
|
||||
clear: both
|
||||
white-space: nowrap
|
||||
|
||||
a
|
||||
padding: 3px 15px
|
||||
display: block
|
||||
text-decoration: none
|
||||
cursor: pointer
|
||||
font-size: 15px
|
||||
line-height: 1.7
|
||||
color: black
|
||||
|
||||
&:not(.disabled):hover
|
||||
theme('color', '$activeColor')
|
||||
text-decoration: none
|
||||
|
||||
&.disabled
|
||||
opacity: 0.4
|
||||
pointer-events: none
|
||||
cursor: default
|
||||
|
||||
.fa-lg
|
||||
width: 40px
|
||||
text-align: center
|
||||
@@ -0,0 +1,19 @@
|
||||
import './studylist.html';
|
||||
import './studylist.js';
|
||||
import './studylist.styl';
|
||||
|
||||
import './studylistStudy/studylistStudy.html';
|
||||
import './studylistStudy/studylistStudy.js';
|
||||
import './studylistStudy/studylistStudy.styl';
|
||||
|
||||
import './studylistResult/studylistResult.html';
|
||||
import './studylistResult/studylistResult.js';
|
||||
import './studylistResult/studylistResult.styl';
|
||||
|
||||
import './studylistToolbar/studylistToolbar.html';
|
||||
import './studylistToolbar/studylistToolbar.js';
|
||||
import './studylistToolbar/studylistToolbar.styl';
|
||||
|
||||
import './studylistPagination/studylistPagination.html';
|
||||
import './studylistPagination/studylistPagination.styl';
|
||||
import './studylistPagination/studylistPagination.js';
|
||||
+1
-2
@@ -14,6 +14,5 @@
|
||||
{{#each templateName in additionalTemplates}}
|
||||
{{> UI.dynamic template=templateName}}
|
||||
{{/each}}
|
||||
{{>studyContextMenu }}
|
||||
{{>progressDialog}}
|
||||
</template>
|
||||
</template>
|
||||
+1
-16
@@ -19,7 +19,7 @@ Session.setDefault('activeContentId', 'studylistTab');
|
||||
|
||||
Template.studylist.onCreated(() => {
|
||||
const instance = Template.instance();
|
||||
|
||||
|
||||
if (StudyList.subscriptions) {
|
||||
StudyList.subscriptions.forEach(subscriptionName => {
|
||||
instance.subscribe(subscriptionName);
|
||||
@@ -44,18 +44,3 @@ Template.studylist.onRendered(() => {
|
||||
|
||||
Meteor.subscribe('hangingprotocols');
|
||||
});
|
||||
|
||||
Template.studylist.events({
|
||||
'click #tablist a[data-toggle="tab"]': function(e) {
|
||||
// If this tab is already active, do nothing
|
||||
const tabButton = $(e.currentTarget);
|
||||
const tabTitle = tabButton.parents('.tabTitle');
|
||||
if (tabTitle.hasClass('active')) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Otherwise, switch to the tab
|
||||
const contentId = tabButton.data('target').replace('#', '');
|
||||
switchToTab(contentId);
|
||||
}
|
||||
});
|
||||
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
@@ -1,8 +0,0 @@
|
||||
<template name="tabTitle">
|
||||
<li role="presentation" class="tabTitle">
|
||||
<a data-target="#{{contentid}}" role="tab" data-toggle="tab">
|
||||
{{title}}
|
||||
<button class="close">×</button>
|
||||
</a>
|
||||
</li>
|
||||
</template>
|
||||
@@ -1,42 +0,0 @@
|
||||
Template.tabTitle.events({
|
||||
/**
|
||||
* Closes a tab when the close button is pressed in the title
|
||||
* The next tab to the left is loaded if the current tab is closed
|
||||
*
|
||||
* @param e The click event used to close the tab
|
||||
*/
|
||||
'click .close': function(e) {
|
||||
console.log('click .close');
|
||||
|
||||
// Identify the tab title DOM node
|
||||
var tab = $(e.currentTarget).parents('a[data-toggle="tab"]').eq(0);
|
||||
|
||||
// Get the relevent contentId that this tab title represents
|
||||
// Replace any hash marks (#) that were required by Bootstrap's tab switching
|
||||
var contentId = tab.data('target').replace('#', '');
|
||||
|
||||
// Check if we are closing the active tab. If we are, prepare to switch
|
||||
// to the next tab to the left.
|
||||
var activeContentId = Session.get('activeContentId');
|
||||
if (activeContentId === contentId) {
|
||||
// Find the index of the tab that is being closed
|
||||
var tabIndex = tab.parent('li').index();
|
||||
|
||||
// Find the index the tab to its left
|
||||
var newActiveTabIndex = Math.max(tabIndex - 1, 0);
|
||||
|
||||
// Find the DOM node of the tab that will be activated
|
||||
var newActiveTab = $('.tabTitle').eq(newActiveTabIndex);
|
||||
|
||||
// Find the content ID of the tab that will be switched to
|
||||
var newActiveTabLink = newActiveTab.find('a[data-toggle=tab]');
|
||||
var newContentId = newActiveTabLink.data('target').replace('#', '');
|
||||
|
||||
// Switch to this tab
|
||||
switchToTab(newContentId);
|
||||
}
|
||||
|
||||
// Remove any stored data related to this tab from the global ViewerData structure
|
||||
delete ViewerData[contentId];
|
||||
}
|
||||
});
|
||||
@@ -1,4 +0,0 @@
|
||||
.tabTitle
|
||||
button.close
|
||||
// Prevent blue glow around button in Chrome
|
||||
outline: none
|
||||
Reference in new issue
Block a user