PVW-2: Creating form modals mechanism
This commit is contained in:
parent
5c5c2afb42
commit
7bbd380983
1
.jscsrc
1
.jscsrc
@ -11,7 +11,6 @@
|
||||
"disallowKeywordsOnNewLine": ["else"],
|
||||
"disallowNewlineBeforeBlockStatements": true,
|
||||
"requirePaddingNewLinesAfterUseStrict": true,
|
||||
"requirePaddingNewLinesInObjects": true,
|
||||
"requirePaddingNewLinesAfterBlocks": {
|
||||
"allExcept": ["inCallExpressions", "inArrayExpressions", "inProperties"]
|
||||
},
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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">×</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>
|
||||
@ -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);
|
||||
});
|
||||
@ -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>
|
||||
@ -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'
|
||||
}
|
||||
});
|
||||
});
|
||||
@ -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';
|
||||
|
||||
@ -0,0 +1,7 @@
|
||||
<template name="inputPassword">
|
||||
{{#inputText (extend this
|
||||
type='password'
|
||||
)}}
|
||||
{{>UI.contentBlock}}
|
||||
{{/inputText}}
|
||||
</template>
|
||||
@ -158,4 +158,4 @@ class Bounded {
|
||||
|
||||
}
|
||||
|
||||
OHIF.Bounded = Bounded;
|
||||
OHIF.ui.Bounded = Bounded;
|
||||
|
||||
38
Packages/ohif-core/client/ui/dialog/form.js
Normal file
38
Packages/ohif-core/client/ui/dialog/form.js
Normal 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;
|
||||
};
|
||||
@ -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,
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
import './bounded/bounded.js';
|
||||
import './dialog/form.js';
|
||||
import './draggable/draggable.js';
|
||||
import './resizable/resizable.js';
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1,9 +1,12 @@
|
||||
import { Meteor } from 'meteor/meteor';
|
||||
|
||||
/*
|
||||
* Defines the base OHIF object
|
||||
*/
|
||||
|
||||
const OHIF = {
|
||||
log: {},
|
||||
ui: {},
|
||||
viewer: {},
|
||||
measurements: {}
|
||||
};
|
||||
|
||||
@ -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
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user