LT-259 New proactive UI (three options) for unsaved changes dialog + New API for unsaved changes module (now handlers can be attached to unsaved changes namespace) + Save measurements integration.

This commit is contained in:
Emanuel F. Oliveira committed 2016-11-21 10:22:33 -02:00
1 parent 4a3b01a4f6
commit 91bafb367c
10 files changed
+671 -173

No files matched your search

@@ -0,0 +1,35 @@
<template name="unsavedChangesDialog">
<div class="modal unsavedChangesDialog fade" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button class="close" aria-label="Close" data-choice="abort-action" data-dismiss="modal">
<span aria-hidden="true">&times;</span>
</button>
<h4 class="modal-title">You have unsaved changes!</h4>
</div>
<div class="modal-footer">
{{#let label='Stay'}}
<button class="btn btn-default" aria-label="{{label}}" data-choice="abort-action" data-dismiss="modal">
{{label}}
</button>
{{/let}}
{{#let label='Leave without saving...'}}
<button class="btn btn-danger" aria-label="{{label}}" data-choice="abandon-changes" data-dismiss="modal">
{{label}}
</button>
{{/let}}
{{#let label='Save and Exit!'}}
<button class="btn btn-primary" aria-label="{{label}}" data-choice="save-changes" data-dismiss="modal">
{{label}}
</button>
{{/let}}
</div>
</div>
</div>
</div>
</template>
@@ -0,0 +1,133 @@
import { Blaze } from 'meteor/blaze';
import { Template } from 'meteor/templating';
import { OHIF } from 'meteor/ohif:core';
import { _ } from 'meteor/underscore';
import { $ } from 'meteor/jquery';
const MARGIN_RIGHT = 15;
const MARGIN_BOTTOM = 15;
Template.unsavedChangesDialog.onRendered(function() {
const instance = Template.instance();
const $modal = instance.$('.modal.unsavedChangesDialog');
// Routine which effectivelly displays the BS modal...
instance.displayModal = () => {
// Make modal options extensible...
const modalOptions = _.extend({
backdrop: 'static',
keyboard: false
}, instance.data.modalOptions);
// Set handler for "hidden" event... Simply remove the view!
$modal.on('hidden.bs.modal', () => {
Blaze.remove(instance.view);
});
// Create the bootstrap modal
$modal.modal(modalOptions);
};
// Routine which repositions the modal before display...
instance.displayModalWithPosition = (position) => {
// Preserve original CSS rules...
const origCSS = {
display: $modal.css('display'),
visibility: $modal.css('visibility')
};
// Make sure modal is propperly rendered before proceeding with math...
if (origCSS.display === 'none') {
$modal.css({
visibility: 'hidden',
display: 'block'
});
}
// Run presentation code on next tick...
setTimeout(() => {
let dimension;
const $dialog = $modal.find('.modal-dialog');
const dialogRect = {
position: {
x: parseInt(position.x) || 0,
y: parseInt(position.y) || 0
},
size: {
width: $dialog.outerWidth(),
height: $dialog.outerHeight()
}
};
const modalSize = {
width: $modal.width(),
height: $modal.height()
};
dimension = dialogRect.position.x + dialogRect.size.width + MARGIN_RIGHT;
if (dimension > modalSize.width) {
dialogRect.position.x -= dimension - modalSize.width;
}
if (dialogRect.position.x < 0) {
dialogRect.position.x = 0;
}
dimension = dialogRect.position.y + dialogRect.size.height + MARGIN_BOTTOM;
if (dimension > modalSize.height) {
dialogRect.position.y -= dimension - modalSize.height;
}
if (dialogRect.position.y < 0) {
dialogRect.position.y = 0;
}
// Restore original CSS...
$modal.css(origCSS);
// Set new position...
$dialog.css({
position: 'fixed',
margin: 0,
left: dialogRect.position.x,
top: dialogRect.position.y
});
instance.displayModal();
}, 0);
};
// Check if modal will be presented with custom positioning...
let position = instance.data.position;
if (position && 'x' in position && 'y' in position) {
instance.displayModalWithPosition(position);
} else {
instance.displayModal();
}
});
Template.unsavedChangesDialog.events({
'click button[data-choice]'(event) {
const instance = Template.instance();
const callback = instance.data.callback;
const choice = $(event.currentTarget).attr('data-choice') || '';
// if callback is a function, call it passing user choice...
if (typeof callback === 'function') {
callback.call(instance, choice);
}
}
});
@@ -0,0 +1,7 @@
.modal.unsavedChangesDialog
.modal-dialog
width: 400px
.modal-footer
border-top: 0 none
@@ -3,6 +3,8 @@ import './dialog/form.html';
import './dialog/form.js';
import './dialog/login.html';
import './dialog/login.js';
import './dialog/unsavedChangesDialog.html';
import './dialog/unsavedChangesDialog.js';
import './dropdown/backdrop.html';
import './dropdown/form.html';