LT-67: Refactoring schema validation
This commit is contained in:
parent
9e2ab2d21a
commit
2a119a5464
@ -29,25 +29,25 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr>
|
<hr>
|
||||||
<h4>Request options</h4>
|
<h4>Request options</h4>
|
||||||
<div class="row">
|
{{#group class='row' key='requestOptions'}}
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
{{>inputText labelClass='form-group' key='requestOptions.auth'}}
|
{{>inputText labelClass='form-group' key='auth'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-lg-6">
|
<div class="col-lg-6">
|
||||||
<strong>Logging options</strong>
|
<strong>Logging options</strong>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="form-control clearfix">
|
<div class="form-control clearfix">
|
||||||
<div class="checkbox pull-left">
|
<div class="checkbox pull-left">
|
||||||
{{>inputCheckbox key='requestOptions.logRequests'}}
|
{{>inputCheckbox key='logRequests'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox pull-left">
|
<div class="checkbox pull-left">
|
||||||
{{>inputCheckbox key='requestOptions.logResponses'}}
|
{{>inputCheckbox key='logResponses'}}
|
||||||
</div>
|
</div>
|
||||||
<div class="checkbox pull-left">
|
<div class="checkbox pull-left">
|
||||||
{{>inputCheckbox key='requestOptions.logTiming'}}
|
{{>inputCheckbox key='logTiming'}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
{{/group}}
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@ -53,7 +53,7 @@ Template.serverInformationForm.onRendered(() => {
|
|||||||
Template.serverInformationForm.events({
|
Template.serverInformationForm.events({
|
||||||
submit(event, instance) {
|
submit(event, instance) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
var formData = FormUtils.getFormData(instance.data.$form);
|
var formData = instance.data.form.value();
|
||||||
Meteor.call('serverSave', formData, function(error) {
|
Meteor.call('serverSave', formData, function(error) {
|
||||||
if (error) {
|
if (error) {
|
||||||
// TODO: check for errors: not-authorized, data-write
|
// TODO: check for errors: not-authorized, data-write
|
||||||
|
|||||||
@ -1,105 +0,0 @@
|
|||||||
class Form {
|
|
||||||
|
|
||||||
// Identify the element's type and get its value
|
|
||||||
static getElementValue($element) {
|
|
||||||
var type = $element.attr('type');
|
|
||||||
var value;
|
|
||||||
switch (type) {
|
|
||||||
case 'checkbox':
|
|
||||||
value = $element.is(':checked');
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
value = $element.val();
|
|
||||||
}
|
|
||||||
return value;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Identify the element's type and get its value
|
|
||||||
static setElementValue($element, value) {
|
|
||||||
if (!$element.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var type = $element.attr('type');
|
|
||||||
switch (type) {
|
|
||||||
case 'checkbox':
|
|
||||||
$element.prop('checked', !!value);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
$element.val(value);
|
|
||||||
}
|
|
||||||
$element.trigger('change');
|
|
||||||
};
|
|
||||||
|
|
||||||
// Transforms a shallow object with keys separated by "." into a nested object
|
|
||||||
static getNestedObject(shallowObject) {
|
|
||||||
var nestedObject = {};
|
|
||||||
for (var key in shallowObject) {
|
|
||||||
var value = shallowObject[key];
|
|
||||||
var propertyArray = key.split('.');
|
|
||||||
var currentObject = nestedObject;
|
|
||||||
while (propertyArray.length) {
|
|
||||||
var currentProperty = propertyArray.shift();
|
|
||||||
if (!propertyArray.length) {
|
|
||||||
currentObject[currentProperty] = value;
|
|
||||||
} else {
|
|
||||||
if (!currentObject[currentProperty]) {
|
|
||||||
currentObject[currentProperty] = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
currentObject = currentObject[currentProperty];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nestedObject;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Transforms a nested object into a shallowObject merging its keys with "." character
|
|
||||||
static getShallowObject(nestedObject) {
|
|
||||||
var shallowObject = {};
|
|
||||||
var putValues = function(baseKey, nestedObject, resultObject) {
|
|
||||||
for (var key in nestedObject) {
|
|
||||||
var currentKey = baseKey ? baseKey + '.' + key : key;
|
|
||||||
var currentValue = nestedObject[key];
|
|
||||||
if (typeof currentValue === 'object') {
|
|
||||||
if (currentValue instanceof Array) {
|
|
||||||
currentKey += '[]';
|
|
||||||
}
|
|
||||||
|
|
||||||
putValues(currentKey, currentValue, resultObject);
|
|
||||||
} else {
|
|
||||||
resultObject[currentKey] = currentValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
putValues('', nestedObject, shallowObject);
|
|
||||||
return shallowObject;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Gets the nested data for the given form
|
|
||||||
static getFormData($form) {
|
|
||||||
var data = {};
|
|
||||||
$form.find(':input[name]').each((index, element) => {
|
|
||||||
var $element = $(element);
|
|
||||||
var value = this.getElementValue($element);
|
|
||||||
var name = $element.attr('name');
|
|
||||||
data[name] = value;
|
|
||||||
});
|
|
||||||
return this.getNestedObject(data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sets the nested data in the given form
|
|
||||||
static setFormData($form, data) {
|
|
||||||
var shallowData = this.getShallowObject(data);
|
|
||||||
for (var key in shallowData) {
|
|
||||||
var value = shallowData[key];
|
|
||||||
var $element = $form.find(':input[name="' + key + '"]');
|
|
||||||
this.setElementValue($element, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
FormUtils = Form;
|
|
||||||
@ -58,9 +58,6 @@ Package.onUse(function(api) {
|
|||||||
|
|
||||||
api.addFiles('client/tools.js', 'client');
|
api.addFiles('client/tools.js', 'client');
|
||||||
|
|
||||||
// Utility classes
|
|
||||||
api.addFiles('client/utils/form.js', 'client');
|
|
||||||
|
|
||||||
// UI Components
|
// UI Components
|
||||||
api.addFiles('client/components/viewer/viewer.html', 'client');
|
api.addFiles('client/components/viewer/viewer.html', 'client');
|
||||||
api.addFiles('client/components/viewer/viewer.styl', 'client');
|
api.addFiles('client/components/viewer/viewer.styl', 'client');
|
||||||
|
|||||||
@ -12,62 +12,13 @@ OHIF.mixins.form = new OHIF.Mixin({
|
|||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const component = instance.component;
|
const component = instance.component;
|
||||||
|
|
||||||
// Run this computation every time the schema property is changed
|
// Set the form identifier flag
|
||||||
instance.autorun(() => {
|
component.isForm = true;
|
||||||
let schema;
|
|
||||||
|
|
||||||
// Check if the schema is reactive
|
// Reset the pathKey
|
||||||
if (instance.data.schema instanceof ReactiveVar) {
|
instance.data.pathKey = '';
|
||||||
// Register a dependency on schema property
|
|
||||||
schema = instance.data.schema.get();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the form's data schema
|
|
||||||
component.schema = schema && schema.newContext();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Get a registered item in form by its key
|
|
||||||
component.item = itemKey => {
|
|
||||||
let found;
|
|
||||||
|
|
||||||
// Iterate over each registered form item
|
|
||||||
component.registeredItems.forEach(child => {
|
|
||||||
const key = child.templateInstance.data.key;
|
|
||||||
|
|
||||||
// Change the found item if current key is the same as given
|
|
||||||
if (key === itemKey) {
|
|
||||||
found = child;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return the found item or undefined if it was not found
|
|
||||||
return found;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check if the form data is valid in its schema
|
|
||||||
component.validate = () => {
|
|
||||||
// Assume validation result as true
|
|
||||||
let result = true;
|
|
||||||
|
|
||||||
// Return true if there's no data schema defined
|
|
||||||
if (!component.schema) {
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Iterate over each registered form item and validate it
|
|
||||||
component.registeredItems.forEach(child => {
|
|
||||||
const key = child.templateInstance.data.key;
|
|
||||||
|
|
||||||
// Change result to false if any form item is invalid
|
|
||||||
if (key && !child.validate()) {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return the validation result
|
|
||||||
return result;
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
|
|
||||||
onRendered() {
|
onRendered() {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const component = instance.component;
|
const component = instance.component;
|
||||||
|
|||||||
@ -73,16 +73,27 @@ OHIF.mixins.formItem = new OHIF.Mixin({
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Search for the parent form component
|
||||||
|
component.getForm = () => {
|
||||||
|
let currentComponent = component;
|
||||||
|
while (currentComponent) {
|
||||||
|
currentComponent = currentComponent.parent;
|
||||||
|
if (currentComponent && currentComponent.isForm) {
|
||||||
|
return currentComponent;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// Check if the component value is valid in its form's schema
|
// Check if the component value is valid in its form's schema
|
||||||
component.validate = () => {
|
component.validate = () => {
|
||||||
// Get the component's form
|
// Get the component's form
|
||||||
const form = component.parent;
|
const form = component.getForm();
|
||||||
|
|
||||||
// Get the form's data schema
|
// Get the form's data schema
|
||||||
const schema = form && form.schema;
|
const schema = form && form.schema;
|
||||||
|
|
||||||
// Get the current component's key
|
// Get the current component's key
|
||||||
const key = instance.data.key;
|
const key = instance.data.pathKey;
|
||||||
|
|
||||||
// Return true if validation is not needed
|
// Return true if validation is not needed
|
||||||
if (!key || !schema || !component.$wrapper.is(':visible')) {
|
if (!key || !schema || !component.$wrapper.is(':visible')) {
|
||||||
@ -156,11 +167,13 @@ OHIF.mixins.formItem = new OHIF.Mixin({
|
|||||||
|
|
||||||
// TODO: [design] remove log, show error box/hint over the wrapper
|
// TODO: [design] remove log, show error box/hint over the wrapper
|
||||||
errorin(event, instance) {
|
errorin(event, instance) {
|
||||||
|
event.stopPropagation();
|
||||||
console.log('ERROR when validating component', instance.component);
|
console.log('ERROR when validating component', instance.component);
|
||||||
},
|
},
|
||||||
|
|
||||||
// TODO: [design] hide error box/hint
|
// TODO: [design] hide error box/hint
|
||||||
errorout(event, instance) {
|
errorout(event, instance) {
|
||||||
|
event.stopPropagation();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -12,6 +12,20 @@ OHIF.mixins.group = new OHIF.Mixin({
|
|||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
const component = instance.component;
|
const component = instance.component;
|
||||||
|
|
||||||
|
// Run this computation every time the schema property is changed
|
||||||
|
instance.autorun(() => {
|
||||||
|
let schema = instance.data.schema;
|
||||||
|
|
||||||
|
// Check if the schema is reactive
|
||||||
|
if (schema instanceof ReactiveVar) {
|
||||||
|
// Register a dependency on schema property
|
||||||
|
schema = schema.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the form's data schema
|
||||||
|
component.schema = schema && schema.newContext();
|
||||||
|
});
|
||||||
|
|
||||||
// Get or set the child components values
|
// Get or set the child components values
|
||||||
component.value = value => {
|
component.value = value => {
|
||||||
const isGet = _.isUndefined(value);
|
const isGet = _.isUndefined(value);
|
||||||
@ -35,6 +49,48 @@ OHIF.mixins.group = new OHIF.Mixin({
|
|||||||
component.$element.trigger('change');
|
component.$element.trigger('change');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Get a registered item in form by its key
|
||||||
|
component.item = itemKey => {
|
||||||
|
let found;
|
||||||
|
|
||||||
|
// Iterate over each registered form item
|
||||||
|
component.registeredItems.forEach(child => {
|
||||||
|
const key = child.templateInstance.data.key;
|
||||||
|
|
||||||
|
// Change the found item if current key is the same as given
|
||||||
|
if (key === itemKey) {
|
||||||
|
found = child;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the found item or undefined if it was not found
|
||||||
|
return found;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Check if the form data is valid in its schema
|
||||||
|
component.validate = () => {
|
||||||
|
// Assume validation result as true
|
||||||
|
let result = true;
|
||||||
|
|
||||||
|
// Return true if there's no data schema defined
|
||||||
|
if (!component.schema) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Iterate over each registered form item and validate it
|
||||||
|
component.registeredItems.forEach(child => {
|
||||||
|
const key = child.templateInstance.data.key;
|
||||||
|
|
||||||
|
// Change result to false if any form item is invalid
|
||||||
|
if (key && !child.validate()) {
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the validation result
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
// Disable or enable the component
|
// Disable or enable the component
|
||||||
component.disable = isDisable => {
|
component.disable = isDisable => {
|
||||||
component.registeredItems.forEach(child => child.disable(isDisable));
|
component.registeredItems.forEach(child => child.disable(isDisable));
|
||||||
|
|||||||
@ -7,7 +7,13 @@ import { _ } from 'meteor/underscore';
|
|||||||
// Helper function to get the component's current schema
|
// Helper function to get the component's current schema
|
||||||
const getCurrentSchema = (parentComponent, key) => {
|
const getCurrentSchema = (parentComponent, key) => {
|
||||||
// Get the parent component schema
|
// Get the parent component schema
|
||||||
const schema = parentComponent && parentComponent.schema;
|
let schema = parentComponent && parentComponent.schema;
|
||||||
|
|
||||||
|
// Try to get the form schema if it was not found
|
||||||
|
if (parentComponent && !schema) {
|
||||||
|
const form = parentComponent.getForm();
|
||||||
|
schema = form && form.schema;
|
||||||
|
}
|
||||||
|
|
||||||
// Stop here if there's no key or schema defined
|
// Stop here if there's no key or schema defined
|
||||||
if (!key || !schema) {
|
if (!key || !schema) {
|
||||||
@ -45,8 +51,18 @@ OHIF.mixins.schemaData = new OHIF.Mixin({
|
|||||||
// Get the parent component
|
// Get the parent component
|
||||||
const parent = OHIF.blaze.getParentComponent(Blaze.currentView);
|
const parent = OHIF.blaze.getParentComponent(Blaze.currentView);
|
||||||
|
|
||||||
|
// Get he parent component key
|
||||||
|
let parentKey = parent && parent.templateInstance.data.pathKey;
|
||||||
|
|
||||||
|
// Set the path key for this component
|
||||||
|
data.pathKey = data.key || '';
|
||||||
|
if (data.pathKey && typeof parentKey === 'string') {
|
||||||
|
const prefix = parentKey ? `${parentKey}.` : '';
|
||||||
|
data.pathKey = `${prefix}${data.pathKey}`;
|
||||||
|
}
|
||||||
|
|
||||||
// Get the current schema data using component's key
|
// Get the current schema data using component's key
|
||||||
const currentSchema = getCurrentSchema(parent, data.key);
|
const currentSchema = getCurrentSchema(parent, data.pathKey);
|
||||||
|
|
||||||
// Stop here if there's no schema data for current key
|
// Stop here if there's no schema data for current key
|
||||||
if (!currentSchema) {
|
if (!currentSchema) {
|
||||||
|
|||||||
@ -31,7 +31,7 @@ OHIF.blaze.getParentView = (view, parentViewName) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Search for the parent component of the given view
|
// Search for the parent component of the given view
|
||||||
OHIF.blaze.getParentComponent = (view) => {
|
OHIF.blaze.getParentComponent = view => {
|
||||||
let currentView = view;
|
let currentView = view;
|
||||||
while (currentView) {
|
while (currentView) {
|
||||||
currentView = currentView.originalParentView || currentView.parentView;
|
currentView = currentView.originalParentView || currentView.parentView;
|
||||||
|
|||||||
@ -1,3 +1,4 @@
|
|||||||
import './blaze.js';
|
import './blaze.js';
|
||||||
|
import './object.js';
|
||||||
import './string.js';
|
import './string.js';
|
||||||
import './user.js';
|
import './user.js';
|
||||||
|
|||||||
50
Packages/ohif-core/client/lib/object.js
Normal file
50
Packages/ohif-core/client/lib/object.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
OHIF.object = {};
|
||||||
|
|
||||||
|
// Transforms a shallow object with keys separated by "." into a nested object
|
||||||
|
OHIF.blaze.getNestedObject = shallowObject => {
|
||||||
|
var nestedObject = {};
|
||||||
|
for (var key in shallowObject) {
|
||||||
|
var value = shallowObject[key];
|
||||||
|
var propertyArray = key.split('.');
|
||||||
|
var currentObject = nestedObject;
|
||||||
|
while (propertyArray.length) {
|
||||||
|
var currentProperty = propertyArray.shift();
|
||||||
|
if (!propertyArray.length) {
|
||||||
|
currentObject[currentProperty] = value;
|
||||||
|
} else {
|
||||||
|
if (!currentObject[currentProperty]) {
|
||||||
|
currentObject[currentProperty] = {};
|
||||||
|
}
|
||||||
|
|
||||||
|
currentObject = currentObject[currentProperty];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nestedObject;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Transforms a nested object into a shallowObject merging its keys with "." character
|
||||||
|
OHIF.blaze.getShallowObject = nestedObject => {
|
||||||
|
var shallowObject = {};
|
||||||
|
var putValues = function(baseKey, nestedObject, resultObject) {
|
||||||
|
for (var key in nestedObject) {
|
||||||
|
var currentKey = baseKey ? baseKey + '.' + key : key;
|
||||||
|
var currentValue = nestedObject[key];
|
||||||
|
if (typeof currentValue === 'object') {
|
||||||
|
if (currentValue instanceof Array) {
|
||||||
|
currentKey += '[]';
|
||||||
|
}
|
||||||
|
|
||||||
|
putValues(currentKey, currentValue, resultObject);
|
||||||
|
} else {
|
||||||
|
resultObject[currentKey] = currentValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
putValues('', nestedObject, shallowObject);
|
||||||
|
return shallowObject;
|
||||||
|
};
|
||||||
@ -230,7 +230,8 @@ var dialogPolyfill = (function() {
|
|||||||
|
|
||||||
// TODO: Only install when any dialogs are open.
|
// TODO: Only install when any dialogs are open.
|
||||||
document.addEventListener('submit', function(ev) {
|
document.addEventListener('submit', function(ev) {
|
||||||
var method = ev.target.getAttribute('method').toLowerCase();
|
var method = ev.target.getAttribute('method');
|
||||||
|
method = method ? method.toLowerCase() : '';
|
||||||
if (method != 'dialog') { return; }
|
if (method != 'dialog') { return; }
|
||||||
ev.preventDefault();
|
ev.preventDefault();
|
||||||
|
|
||||||
@ -408,4 +409,4 @@ var dialogPolyfill = (function() {
|
|||||||
dialogPolyfill.dm.handleKey.bind(dialogPolyfill.dm));
|
dialogPolyfill.dm.handleKey.bind(dialogPolyfill.dm));
|
||||||
|
|
||||||
return dialogPolyfill;
|
return dialogPolyfill;
|
||||||
})();
|
})();
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user