Adding loading state and error message when saving measurements
This commit is contained in:
parent
5d8c608e70
commit
6b17deabcb
@ -1,5 +1,6 @@
|
|||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
import { _ } from 'meteor/underscore';
|
import { _ } from 'meteor/underscore';
|
||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Template.dialogForm.onCreated(() => {
|
Template.dialogForm.onCreated(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
@ -14,7 +15,7 @@ Template.dialogForm.onCreated(() => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Hide the modal, removing the backdrop
|
// Hide the modal, removing the backdrop
|
||||||
instance.$('.modal').on('hidden.bs.modal', event => {
|
instance.$('.modal').one('hidden.bs.modal', event => {
|
||||||
// Get the form value and call the confirm callback or resolve the promise
|
// Get the form value and call the confirm callback or resolve the promise
|
||||||
const formData = form.value();
|
const formData = form.value();
|
||||||
if (_.isFunction(instance.data.confirmCallback)) {
|
if (_.isFunction(instance.data.confirmCallback)) {
|
||||||
@ -27,7 +28,7 @@ Template.dialogForm.onCreated(() => {
|
|||||||
|
|
||||||
cancel() {
|
cancel() {
|
||||||
// Hide the modal, removing the backdrop
|
// Hide the modal, removing the backdrop
|
||||||
instance.$('.modal').on('hidden.bs.modal', event => {
|
instance.$('.modal').one('hidden.bs.modal', event => {
|
||||||
// Call the cancel callback or resolve the promise
|
// Call the cancel callback or resolve the promise
|
||||||
if (_.isFunction(instance.data.cancelCallback)) {
|
if (_.isFunction(instance.data.cancelCallback)) {
|
||||||
instance.data.cancelCallback(instance.data.promiseReject);
|
instance.data.cancelCallback(instance.data.promiseReject);
|
||||||
@ -61,21 +62,21 @@ Template.dialogForm.onRendered(() => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
Template.dialogForm.events({
|
Template.dialogForm.events({
|
||||||
'keydown'(event) {
|
keydown(event) {
|
||||||
const instance = Template.instance(),
|
const instance = Template.instance(),
|
||||||
keyCode = event.keyCode || event.which;
|
keyCode = event.keyCode || event.which;
|
||||||
|
|
||||||
let handled = false;
|
let handled = false;
|
||||||
|
|
||||||
if(keyCode === 27) {
|
if (keyCode === 27) {
|
||||||
instance.$('.btn.btn-cancel').click();
|
instance.$('.btn.btn-cancel').click();
|
||||||
handled = true;
|
handled = true;
|
||||||
} else if(keyCode === 13) {
|
} else if (keyCode === 13) {
|
||||||
instance.$('.btn.btn-confirm').click();
|
instance.$('.btn.btn-confirm').click();
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(handled) {
|
if (handled) {
|
||||||
event.stopPropagation();
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,13 @@
|
|||||||
|
<template name="dialogInfo">
|
||||||
|
{{#dialogSimple (extend this
|
||||||
|
title=(choose this.title 'Error')
|
||||||
|
)}}
|
||||||
|
<div class="messages">
|
||||||
|
{{#each message in this.messages}}
|
||||||
|
<div class="message">{{{message}}}</div>
|
||||||
|
{{else}}
|
||||||
|
<div class="message">An error has ocurred.</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{/dialogSimple}}
|
||||||
|
</template>
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
Template.dialogInfo.onRendered(() => {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
const $modal = instance.$('.modal');
|
||||||
|
|
||||||
|
$modal.one('hidden.bs.modal', () => instance.data.promiseResolve());
|
||||||
|
});
|
||||||
@ -0,0 +1,7 @@
|
|||||||
|
<template name="dialogLoading">
|
||||||
|
<div id="{{this.id}}" class="modal fade" tabindex="-1" role="dialog">
|
||||||
|
<div class="loading-text noselect">
|
||||||
|
{{choose this.text 'Loading...'}} <i class="fa fa-spin fa-circle-o-notch fa-fw"></i>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,14 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
Template.dialogLoading.onRendered(() => {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
const $modal = instance.$('.modal');
|
||||||
|
|
||||||
|
// Create the bootstrap modal
|
||||||
|
$modal.modal({
|
||||||
|
backdrop: 'static',
|
||||||
|
keyboard: false,
|
||||||
|
modal: true
|
||||||
|
});
|
||||||
|
});
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
@import "{ohif:design}/app"
|
||||||
|
|
||||||
|
.modal .loading-text
|
||||||
|
theme('color', '$textSecondaryColor')
|
||||||
|
font-size: 30px
|
||||||
|
height: 100vh
|
||||||
|
line-height: 100vh
|
||||||
|
text-align: center
|
||||||
|
text-shadow: 1px 1px 0 #000, -1px -1px 0 #000, -1px 1px 0 #000, 1px -1px 0 #000, -1px 0 0 #000, 0 -1px 0 #000, 1px 0 0 #000, 0 1px 0 #000
|
||||||
@ -1,10 +1,14 @@
|
|||||||
import './dialog/confirm.html';
|
import './dialog/confirm.html';
|
||||||
import './dialog/progress.html';
|
|
||||||
import './dialog/progress.js';
|
|
||||||
import './dialog/form.html';
|
import './dialog/form.html';
|
||||||
import './dialog/form.js';
|
import './dialog/form.js';
|
||||||
|
import './dialog/info.html';
|
||||||
|
import './dialog/info.js';
|
||||||
|
import './dialog/loading.html';
|
||||||
|
import './dialog/loading.js';
|
||||||
import './dialog/login.html';
|
import './dialog/login.html';
|
||||||
import './dialog/login.js';
|
import './dialog/login.js';
|
||||||
|
import './dialog/progress.html';
|
||||||
|
import './dialog/progress.js';
|
||||||
import './dialog/simple.html';
|
import './dialog/simple.html';
|
||||||
import './dialog/simple.js';
|
import './dialog/simple.js';
|
||||||
import './dialog/unsavedChangesDialog.html';
|
import './dialog/unsavedChangesDialog.html';
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
import { Blaze } from 'meteor/blaze';
|
import { Blaze } from 'meteor/blaze';
|
||||||
import { _ } from 'meteor/underscore';
|
import { _ } from 'meteor/underscore';
|
||||||
|
import { $ } from 'meteor/jquery';
|
||||||
import { OHIF } from 'meteor/ohif:core';
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
OHIF.ui.showDialog = (templateName, dialogData) => {
|
OHIF.ui.showDialog = (templateName, dialogData) => {
|
||||||
@ -13,25 +14,51 @@ OHIF.ui.showDialog = (templateName, dialogData) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create a new promise to control the modal and store its resolve and reject callbacks
|
let promise;
|
||||||
let promiseResolve;
|
let templateData;
|
||||||
let promiseReject;
|
if (dialogData && dialogData.promise instanceof Promise) {
|
||||||
const promise = new Promise((resolve, reject) => {
|
// Use the given promise to control the modal
|
||||||
promiseResolve = resolve;
|
promise = dialogData.promise;
|
||||||
promiseReject = reject;
|
templateData = dialogData;
|
||||||
});
|
} else {
|
||||||
|
// Create a new promise to control the modal and store its resolve and reject callbacks
|
||||||
|
let promiseResolve;
|
||||||
|
let promiseReject;
|
||||||
|
promise = new Promise((resolve, reject) => {
|
||||||
|
promiseResolve = resolve;
|
||||||
|
promiseReject = reject;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Render the dialog with the given template passing the promise object and callbacks
|
||||||
|
templateData = _.extend({}, dialogData, {
|
||||||
|
promise,
|
||||||
|
promiseResolve,
|
||||||
|
promiseReject
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Render the dialog with the given template passing the promise object and callbacks
|
|
||||||
const templateData = _.extend({}, dialogData, {
|
|
||||||
promise,
|
|
||||||
promiseResolve,
|
|
||||||
promiseReject
|
|
||||||
});
|
|
||||||
const view = Blaze.renderWithData(template, templateData, document.body);
|
const view = Blaze.renderWithData(template, templateData, document.body);
|
||||||
|
|
||||||
|
const node = view.firstNode();
|
||||||
|
const $node = node && $(node);
|
||||||
|
|
||||||
|
let $modal;
|
||||||
|
if ($node && $node.hasClass('modal')) {
|
||||||
|
$modal = $node;
|
||||||
|
} else if ($node && $node.has('.modal')) {
|
||||||
|
$modal = $node.find('.modal:first');
|
||||||
|
}
|
||||||
|
|
||||||
// Destroy the created dialog view when the promise is either resolved or rejected
|
// Destroy the created dialog view when the promise is either resolved or rejected
|
||||||
const dismissModal = () => Blaze.remove(view);
|
const dismissModal = () => {
|
||||||
promise.then(dismissModal, dismissModal);
|
if (dialogData.promise && $modal) {
|
||||||
|
$modal.one('hidden.bs.modal', () => Blaze.remove(view)).modal('hide');
|
||||||
|
} else {
|
||||||
|
Blaze.remove(view);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
promise.then(dismissModal).catch(dismissModal);
|
||||||
|
|
||||||
// Return the promise to allow callbacks stacking from outside
|
// Return the promise to allow callbacks stacking from outside
|
||||||
return promise;
|
return promise;
|
||||||
|
|||||||
@ -26,6 +26,7 @@ Package.onUse(function(api) {
|
|||||||
api.addFiles([
|
api.addFiles([
|
||||||
'client/ui/dimensional/dimensional.styl',
|
'client/ui/dimensional/dimensional.styl',
|
||||||
'client/ui/resizable/resizable.styl',
|
'client/ui/resizable/resizable.styl',
|
||||||
|
'client/components/bootstrap/dialog/loading.styl',
|
||||||
'client/components/bootstrap/dialog/progress.styl',
|
'client/components/bootstrap/dialog/progress.styl',
|
||||||
'client/components/bootstrap/dialog/unsavedChangesDialog.styl',
|
'client/components/bootstrap/dialog/unsavedChangesDialog.styl',
|
||||||
'client/components/bootstrap/dropdown/dropdown.styl'
|
'client/components/bootstrap/dropdown/dropdown.styl'
|
||||||
|
|||||||
@ -250,7 +250,7 @@ class MeasurementApi {
|
|||||||
};
|
};
|
||||||
|
|
||||||
OHIF.log.info('Saving Measurements for timepoints:', timepoints);
|
OHIF.log.info('Saving Measurements for timepoints:', timepoints);
|
||||||
storeFn(measurementData, filter).then(() => {
|
return storeFn(measurementData, filter).then(() => {
|
||||||
OHIF.log.info('Measurement storage completed');
|
OHIF.log.info('Measurement storage completed');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@ -9,12 +9,27 @@ Template.caseProgress.onCreated(() => {
|
|||||||
instance.progressPercent = new ReactiveVar();
|
instance.progressPercent = new ReactiveVar();
|
||||||
instance.progressText = new ReactiveVar();
|
instance.progressText = new ReactiveVar();
|
||||||
instance.isLocked = new ReactiveVar();
|
instance.isLocked = new ReactiveVar();
|
||||||
|
instance.path = 'viewer.studyViewer.measurements';
|
||||||
|
|
||||||
instance.saveData = () => {
|
instance.saveData = () => {
|
||||||
instance.data.measurementApi.storeMeasurements();
|
const api = instance.data.measurementApi;
|
||||||
|
|
||||||
// Clear signaled unsaved changes...
|
// Clear signaled unsaved changes...
|
||||||
OHIF.ui.unsavedChanges.clear('viewer.studyViewer.measurements.*');
|
const successHandler = () => {
|
||||||
|
OHIF.ui.unsavedChanges.clear(`${instance.path}.*`);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Display the error messages
|
||||||
|
const errorHandler = data => OHIF.ui.showDialog('dialogInfo', data);
|
||||||
|
|
||||||
|
const promise = api.storeMeasurements();
|
||||||
|
promise.then(successHandler).catch(errorHandler);
|
||||||
|
OHIF.ui.showDialog('dialogLoading', {
|
||||||
|
promise,
|
||||||
|
text: 'Saving measurements data'
|
||||||
|
});
|
||||||
|
|
||||||
|
return promise;
|
||||||
};
|
};
|
||||||
|
|
||||||
instance.unsavedChangesHandler = () => {
|
instance.unsavedChangesHandler = () => {
|
||||||
@ -25,14 +40,13 @@ Template.caseProgress.onCreated(() => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Attach handler for unsaved changes dialog...
|
// Attach handler for unsaved changes dialog...
|
||||||
OHIF.ui.unsavedChanges.attachHandler('viewer.studyViewer.measurements', 'save', instance.unsavedChangesHandler);
|
OHIF.ui.unsavedChanges.attachHandler(instance.path, 'save', instance.unsavedChangesHandler);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.caseProgress.onDestroyed(() => {
|
Template.caseProgress.onDestroyed(() => {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
// Remove unsaved changes handler after this view has been destroyed...
|
// Remove unsaved changes handler after this view has been destroyed...
|
||||||
OHIF.ui.unsavedChanges.removeHandler('viewer.studyViewer.measurements', 'save', instance.unsavedChangesHandler);
|
OHIF.ui.unsavedChanges.removeHandler(instance.path, 'save', instance.unsavedChangesHandler);
|
||||||
});
|
});
|
||||||
|
|
||||||
Template.caseProgress.onRendered(() => {
|
Template.caseProgress.onRendered(() => {
|
||||||
@ -169,8 +183,6 @@ Template.caseProgress.events({
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance.saveData();
|
instance.saveData().then(() => switchToTab('studylistTab'));
|
||||||
switchToTab('studylistTab');
|
|
||||||
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user