LT-67: Migrating the main form and its inputs to components

This commit is contained in:
Bruno Alves de Faria 2016-08-29 16:51:02 -03:00
parent eb63e88581
commit 6cbfc1c180
16 changed files with 145 additions and 39 deletions

View File

@ -8,13 +8,13 @@ npm-bcrypt@0.8.7
meteor-base@1.0.4 # Packages every Meteor app needs to have meteor-base@1.0.4 # Packages every Meteor app needs to have
mobile-experience@1.0.4 # Packages for a great mobile UX mobile-experience@1.0.4 # Packages for a great mobile UX
mongo@1.1.10 # The database Meteor supports right now mongo@1.1.10 # The database Meteor supports right now
blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views blaze-html-templates@1.0.4 # Compile .html files into Meteor Blaze views
session@1.1.6 # Client-side reactive dictionary for your app session@1.1.6 # Client-side reactive dictionary for your app
jquery@1.11.9 # Helpful client-side library jquery@1.11.9 # Helpful client-side library
tracker@1.1.0 # Meteor's client-side reactive programming library tracker@1.1.0 # Meteor's client-side reactive programming library
es5-shim@4.6.13 # ECMAScript 5 compatibility for older browsers. es5-shim@4.6.13 # ECMAScript 5 compatibility for older browsers.
ecmascript@0.5.7 # Enable ECMAScript2015+ syntax in app code ecmascript@0.5.7 # Enable ECMAScript2015+ syntax in app code
clinical:router clinical:router
@ -26,6 +26,8 @@ clinical:fonts
clinical:hipaa-audit-log clinical:hipaa-audit-log
clinical:hipaa-logger clinical:hipaa-logger
aldeed:simple-schema # Third party package to deal with schemas
design design
ohif:core ohif:core

View File

@ -26,6 +26,7 @@ spacebars@1.0.12
check@1.2.3 check@1.2.3
cornerstone cornerstone
dicomweb dicomweb
aldeed:simple-schema # Third party package to deal with schemas
design design
ohif:core ohif:core
ecmascript@0.5.7 ecmascript@0.5.7

View File

@ -4,10 +4,27 @@ html body
font-family: 'Roboto', 'OpenSans', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif font-family: 'Roboto', 'OpenSans', 'HelveticaNeue-Light', 'Helvetica Neue Light', 'Helvetica Neue', Helvetica, Arial, 'Lucida Grande', sans-serif
// Try to fix LT-273, need a monitor to test on though. // Try to fix LT-273, need a monitor to test on though.
//text-rendering: optimizeLegibility //text-rendering: optimizeLegibility
html hr html hr
border-top: 1px solid $uiBorderColor border-top: 1px solid $uiBorderColor
label.form-group
width: 100%
&>span.select2
display: block
width: 100% !important
span.select2-selection
min-height: 34px
span.select2-selection__rendered
height: 34px
line-height: 34px
span.select2-selection__arrow
height: 34px
.center-table .center-table
display: table display: table
margin-left: auto margin-left: auto
@ -38,4 +55,3 @@ html hr
.modal-header, .modal-footer .modal-header, .modal-footer
border-color: $uiBorderColor border-color: $uiBorderColor

View File

@ -1,33 +1,19 @@
<template name="serverInformationForm"> <template name="serverInformationForm">
<form class="server-information-form"> {{#form class='server-information-form' schema=instance.currentSchema}}
<input type="hidden" name="_id"> {{>inputHidden key='_id'}}
<div class="row"> <div class="row">
<div class="col-lg-6"> <div class="col-lg-6">
<div class="form-group"> {{>inputText labelClass='form-group' key='name'}}
<label class="wrapper">
<strong>Server Name</strong>
<input type="text" name="name" class="form-control">
</label>
</div>
</div> </div>
<div class="col-lg-6"> <div class="col-lg-6">
<div class="form-group"> {{>inputSelect labelClass='form-group' key='type' hideSearch=true}}
<label class="wrapper">
<strong>Server Type</strong>
<select name="type" class="form-control js-server-type">
<option>Select</option>
<option value="dicomWeb">DICOM Web</option>
<option value="dimse">DIMSE</option>
</select>
</label>
</div>
</div> </div>
</div> </div>
<hr> <hr>
{{#if eq this.serverType.get "dicomWeb"}} {{#if eq this.serverType.get 'dicomWeb'}}
{{>serverInformationDicomWeb this}} {{>serverInformationDicomWeb this}}
{{/if}} {{/if}}
{{#if eq this.serverType.get "dimse"}} {{#if eq this.serverType.get 'dimse'}}
{{>serverInformationDimse this}} {{>serverInformationDimse this}}
{{/if}} {{/if}}
{{#if this.serverType.get}} {{#if this.serverType.get}}
@ -35,5 +21,5 @@
<input type="submit" class="btn btn-primary" value="Save"> <input type="submit" class="btn btn-primary" value="Save">
</div> </div>
{{/if}} {{/if}}
</form> {{/form}}
</template> </template>

View File

@ -1,9 +1,27 @@
Template.serverInformationForm.onRendered(function() { import { Template } from 'meteor/templating';
var instance = Template.instance(); import { ReactiveVar } from 'meteor/reactive-var';
import { DICOMWebServer as dicomSchema } from 'meteor/worklist/both/schema';
import { DIMSEServer as dimseSchema } from 'meteor/worklist/both/schema';
Template.serverInformationForm.onCreated(() => {
const instance = Template.instance();
instance.currentSchema = new ReactiveVar(dicomSchema);
});
Template.serverInformationForm.onRendered(() => {
const instance = Template.instance();
instance.data.$form = instance.$('form'); instance.data.$form = instance.$('form');
instance.autorun(function() {
var mode = instance.data.mode.get(); instance.autorun(() => {
const typeComponent = instance.$('[data-key=type]').data('component');
typeComponent.changeObserver.depend();
instance.data.serverType.set(typeComponent.value());
});
instance.autorun(() => {
const mode = instance.data.mode.get();
if (mode === 'edit') { if (mode === 'edit') {
var data = instance.data.currentItem.get(); var data = instance.data.currentItem.get();
FormUtils.setFormData(instance.data.$form, data); FormUtils.setFormData(instance.data.$form, data);
@ -12,11 +30,7 @@ Template.serverInformationForm.onRendered(function() {
}); });
Template.serverInformationForm.events({ Template.serverInformationForm.events({
'change .js-server-type': function(event, instance) { submit(event, instance) {
var value = $(event.currentTarget).val();
instance.data.serverType.set(value);
},
submit: function(event, instance) {
event.preventDefault(); event.preventDefault();
var formData = FormUtils.getFormData(instance.data.$form); var formData = FormUtils.getFormData(instance.data.$form);
Meteor.call('serverSave', formData, function(error) { Meteor.call('serverSave', formData, function(error) {

View File

@ -0,0 +1 @@
import './schema.js';

View File

@ -0,0 +1,6 @@
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
SimpleSchema.extendOptions({
valuesLabels: Match.Optional([String]),
emptyOption: Match.Optional(Boolean)
});

View File

@ -1,5 +1,6 @@
import { OHIF } from 'meteor/ohif:core'; import { OHIF } from 'meteor/ohif:core';
import { Template } from 'meteor/templating'; import { Template } from 'meteor/templating';
import { ReactiveVar } from 'meteor/reactive-var';
/* /*
* form: controls a form and its registered inputs * form: controls a form and its registered inputs
@ -11,9 +12,19 @@ OHIF.mixins.form = new OHIF.Mixin({
const instance = Template.instance(); const instance = Template.instance();
const component = instance.component; const component = instance.component;
// Define the form's data schema // Run this computation every time the schema property is changed
const schema = instance.data.schema; instance.autorun(() => {
component.schema = schema && schema.newContext(); let schema;
// Check if the schema is reactive
if (instance.data.schema instanceof ReactiveVar) {
// Register a dependency on schema property
schema = instance.data.schema.get();
}
// Set the form's data schema
component.schema = schema && schema.newContext();
});
// Check if the form data is valid in its schema // Check if the form data is valid in its schema
component.validate = () => { component.validate = () => {

View File

@ -17,6 +17,11 @@ const getCurrentSchema = (parentComponent, key) => {
// Get the current schema data using component's key // Get the current schema data using component's key
const currentSchema = _.clone(schema._schema[key]); const currentSchema = _.clone(schema._schema[key]);
// Stop here if no schema was found for the given key
if (!currentSchema) {
return;
}
// Merge the sub-schema properties if it's an array // Merge the sub-schema properties if it's an array
if (Array.isArray(currentSchema.type())) { if (Array.isArray(currentSchema.type())) {
_.extend(currentSchema, schema._schema[key + '.$']); _.extend(currentSchema, schema._schema[key + '.$']);
@ -53,6 +58,11 @@ OHIF.mixins.schemaData = new OHIF.Mixin({
data.label = new ReactiveVar(currentSchema.label); data.label = new ReactiveVar(currentSchema.label);
} }
// Set the emptyOption data attribute if given on schema
if (currentSchema.emptyOption) {
data.emptyOption = currentSchema.emptyOption;
}
// Fill the items if it's an array schema // Fill the items if it's an array schema
if (!data.items && Array.isArray(currentSchema.allowedValues)) { if (!data.items && Array.isArray(currentSchema.allowedValues)) {
// Initialize the items array // Initialize the items array

View File

@ -7,6 +7,43 @@ import { Template } from 'meteor/templating';
OHIF.mixins.select = new OHIF.Mixin({ OHIF.mixins.select = new OHIF.Mixin({
dependencies: 'formItem', dependencies: 'formItem',
composition: { composition: {
onCreated() {
const instance = Template.instance();
// Check if this select will include an empty option
if (instance.data.emptyOption) {
// Get the option items
let items = instance.data.items;
// Check if the items are reactive and get them if true
const isReactive = items instanceof ReactiveVar;
if (isReactive) {
items = items.get();
}
// Check if there is already an empty option on items list
const query = {
value: ''
};
if (!_.findWhere(items, query)) {
// Clone the current items
const newItems = _.clone(items);
newItems.unshift({
label: 'Select',
value: ''
});
// Set the new items list including the empty option
if (isReactive) {
instance.data.items.set(newItems);
} else {
instance.data.items = newItems;
}
}
}
},
onRendered() { onRendered() {
const instance = Template.instance(); const instance = Template.instance();
const component = instance.component; const component = instance.component;
@ -14,5 +51,6 @@ OHIF.mixins.select = new OHIF.Mixin({
// Set the element to be controlled // Set the element to be controlled
component.$element = instance.$('select:first'); component.$element = instance.$('select:first');
} }
} }
}); });

View File

@ -6,6 +6,7 @@
name="{{this.name}}" name="{{this.name}}"
value="{{reactive this.value}}" value="{{reactive this.value}}"
placeholder="{{this.placeholder}}" placeholder="{{this.placeholder}}"
data-key="{{this.key}}"
{{this.tagAttributes}} {{this.tagAttributes}}
> >
{{>UI.contentBlock}} {{>UI.contentBlock}}

View File

@ -4,6 +4,7 @@
class="{{this.class}}" class="{{this.class}}"
name="{{this.name}}" name="{{this.name}}"
multiple="{{#if this.multiple}}multiple{{/if}}" multiple="{{#if this.multiple}}multiple{{/if}}"
data-key="{{this.key}}"
{{this.tagAttributes}} {{this.tagAttributes}}
> >
{{>UI.contentBlock}} {{>UI.contentBlock}}

View File

@ -1,6 +1,7 @@
import './form/form.html'; import './form/form.html';
import './form/group.html'; import './form/group.html';
import './input/hidden.html';
import './input/groupRadio.html'; import './input/groupRadio.html';
import './input/radio.html'; import './input/radio.html';
import './input/select.html'; import './input/select.html';

View File

@ -0,0 +1,7 @@
<template name="inputHidden">
{{>baseComponent (extend this
base='baseInput'
type='hidden'
mixins=(concat 'input ' this.mixins)
)}}
</template>

View File

@ -34,4 +34,7 @@ Package.onUse(function(api) {
// Server imports and methods // Server imports and methods
api.addFiles('server/index.js', 'server'); api.addFiles('server/index.js', 'server');
// Client and server imports
api.addFiles('both/index.js', ['client', 'server']);
}); });

View File

@ -26,9 +26,17 @@ export const DICOMWebRequestOptions = new SimpleSchema({
export const DICOMWebServer = new SimpleSchema({ export const DICOMWebServer = new SimpleSchema({
name: { name: {
type: String, type: String,
label: 'Name', label: 'Server Name',
max: 100 max: 100
}, },
type: {
type: String,
label: 'Server Type',
allowedValues: ['dicomWeb', 'dimse'],
valuesLabels: ['DICOM Web', 'DIMSE'],
optional: true,
emptyOption: true
},
wadoUriRoot: { wadoUriRoot: {
type: String, type: String,
label: 'WADO URI root', label: 'WADO URI root',