PVW-2: Creating form modals mechanism

This commit is contained in:
Bruno Alves de Faria 2016-09-22 18:47:56 -03:00 committed by Erik Ziegler
parent 5c5c2afb42
commit 7bbd380983
16 changed files with 156 additions and 34 deletions

View File

@ -11,7 +11,6 @@
"disallowKeywordsOnNewLine": ["else"],
"disallowNewlineBeforeBlockStatements": true,
"requirePaddingNewLinesAfterUseStrict": true,
"requirePaddingNewLinesInObjects": true,
"requirePaddingNewLinesAfterBlocks": {
"allExcept": ["inCallExpressions", "inArrayExpressions", "inProperties"]
},

View File

@ -1,5 +1,7 @@
import { OHIF } from 'meteor/ohif:core';
import { Template } from 'meteor/templating';
import { Blaze } from 'meteor/blaze';
import { _ } from 'meteor/underscore';
import { OHIF } from 'meteor/ohif:core';
// Create a new custom template for the base component
Template.baseComponent = new Template('baseComponent', () => {});
@ -30,9 +32,6 @@ Template.baseComponent.constructView = function(contentFunc, elseFunc) {
// Extract the render function from the base template
template.renderFunction = baseTemplate.renderFunction;
// Check for the mixins. If it's not informed set the lowest level mixin
const mixins = data.mixins || 'component';
// Init the data manipulation mixins
OHIF.Mixin.initData(data);

View File

@ -11,7 +11,7 @@
target="{{this.target}}"
{{this.tagAttributes}}
>
{{#if validationErrors}}
{{#if (and validationErrors (not this.hideValidationBox))}}
<div class="validation-error-container alert alert-danger" role="alert">
{{#each error in validationErrors}}
<p><a href="#" class="text-danger" data-target="{{error.key}}">{{error.message}}</a></p>

View File

@ -0,0 +1,19 @@
<template name="dialogForm">
<div id="{{this.id}}" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog {{this.dialogClass}}" role="document">
{{#form class='modal-content' schema=this.schema hideValidationBox=true api=instance.api}}
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title">{{this.title}}</h4>
</div>
<div class="modal-body">
{{>UI.contentBlock}}
</div>
<div class="modal-footer">
{{#button class='btn-default' action='cancel'}}Cancel{{/button}}
{{#button class='btn-primary' action='confirm'}}Confirm{{/button}}
</div>
{{/form}}
</div>
</div>
</template>

View File

@ -0,0 +1,45 @@
import { Template } from 'meteor/templating';
import { _ } from 'meteor/underscore';
Template.dialogForm.onCreated(() => {
const instance = Template.instance();
instance.api = {
confirm() {
// Check if the form has valid data
const form = instance.$('form').data('component');
if (!form.validate()) {
return;
}
// Get the form value and call the confirm callback or resolve the promise
const formData = form.value();
if (_.isFunction(instance.data.confirmCallback)) {
instance.data.confirmCallback(formData, instance.data.promiseResolve);
} else {
instance.data.promiseResolve(formData);
}
},
cancel() {
// Call the cancel callback or resolve the promise
if (_.isFunction(instance.data.cancelCallback)) {
instance.data.cancelCallback(instance.data.promiseReject);
} else {
instance.data.promiseReject();
}
}
};
});
Template.dialogForm.onRendered(() => {
const instance = Template.instance();
// Create the bootstrap modal
const $modal = instance.$('.modal');
$modal.modal();
// Remove the created modal backdrop from DOM after promise is done
const $backdrop = $modal.next('.modal-backdrop');
const dismissDialogBackdrop = () => $backdrop.remove();
instance.data.promise.then(dismissDialogBackdrop).catch(dismissDialogBackdrop);
});

View File

@ -0,0 +1,6 @@
<template name="dialogLogin">
{{#dialogForm (extend this dialogClass='modal-sm' schema=(choose this.schema instance.schema))}}
{{>inputText labelClass='form-group' key='username'}}
{{>inputPassword labelClass='form-group' key='password'}}
{{/dialogForm}}
</template>

View File

@ -0,0 +1,17 @@
import { Template } from 'meteor/templating';
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
Template.dialogLogin.onCreated(() => {
const instance = Template.instance();
instance.schema = new SimpleSchema({
username: {
type: String,
label: 'Username'
},
password: {
type: String,
label: 'Password'
}
});
});

View File

@ -1,3 +1,8 @@
import './dialog/form.html';
import './dialog/form.js';
import './dialog/login.html';
import './dialog/login.js';
import './form/button.html';
import './form/form.html';
import './form/group.html';
@ -5,6 +10,7 @@ import './form/group.html';
import './input/checkbox.html';
import './input/hidden.html';
import './input/groupRadio.html';
import './input/password.html';
import './input/radio.html';
import './input/range.html';
import './input/select.html';

View File

@ -0,0 +1,7 @@
<template name="inputPassword">
{{#inputText (extend this
type='password'
)}}
{{>UI.contentBlock}}
{{/inputText}}
</template>

View File

@ -158,4 +158,4 @@ class Bounded {
}
OHIF.Bounded = Bounded;
OHIF.ui.Bounded = Bounded;

View File

@ -0,0 +1,38 @@
import { Template } from 'meteor/templating';
import { Blaze } from 'meteor/blaze';
import { _ } from 'meteor/underscore';
import { OHIF } from 'meteor/ohif:core';
OHIF.ui.showFormDialog = (templateName, dialogData) => {
// Check if the given template exists
const template = Template[templateName];
if (!template) {
throw {
name: 'TEMPLATE_NOT_FOUND',
message: `Template ${templateName} not found.`
};
}
// Create a new promise to control the modal and store its resolve and reject callbacks
let promiseResolve;
let promiseReject;
const promise = new Promise((resolve, reject) => {
promiseResolve = resolve;
promiseReject = reject;
});
// 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);
// Destroy the created dialog view when the promise is either resolved or rejected
const dismissModal = () => Blaze.remove(view);
promise.then(dismissModal).catch(dismissModal);
// Return the promise to allow callbacks stacking from outside
return promise;
};

View File

@ -1,6 +1,8 @@
import { OHIF } from 'meteor/ohif:core';
// Allow attaching to jQuery selectors
$.fn.draggable = function(options) {
makeDraggable(this, options);
$.fn.draggable = function() {
OHIF.ui.makeDraggable(this);
return this;
};
@ -11,7 +13,7 @@ $.fn.draggable = function(options) {
*
* @param element
*/
makeDraggable = function(element, options) {
OHIF.ui.makeDraggable = function(element) {
var container = $(window);
var diffX,
diffY,

View File

@ -1,3 +1,4 @@
import './bounded/bounded.js';
import './dialog/form.js';
import './draggable/draggable.js';
import './resizable/resizable.js';

View File

@ -1,3 +1,5 @@
import { OHIF } from 'meteor/ohif:core';
// Allow attaching to jQuery selectors
$.fn.resizable = function(options) {
_.each(this, element => {
@ -174,3 +176,5 @@ class Resizable {
}
}
OHIF.ui.Resizable = Resizable;

View File

@ -1,9 +1,12 @@
import { Meteor } from 'meteor/meteor';
/*
* Defines the base OHIF object
*/
const OHIF = {
log: {},
ui: {},
viewer: {},
measurements: {}
};

View File

@ -1,24 +0,0 @@
// TODO: stop exposing the libraries below and start using imports
import { cornerstone } from './client/cornerstone.js';
import { dicomParser } from './client/dicomParser.js';
import { cornerstoneMath } from './client/cornerstoneMath.js';
import { cornerstoneTools } from './client/cornerstoneTools.js';
import { cornerstoneWADOImageLoader } from './client/cornerstoneWADOImageLoader.js';
// Expose the cornerstone objects to the client if it is on development mode
if (Meteor.isDevelopment) {
window.cornerstone = cornerstone;
window.cornerstoneMath = cornerstoneMath;
window.cornerstoneTools = cornerstoneTools;
window.cornerstoneWADOImageLoader = cornerstoneWADOImageLoader;
window.dicomParser = dicomParser;
}
export {
cornerstone,
cornerstoneMath,
cornerstoneTools,
cornerstoneWADOImageLoader,
dicomParser
};