LT-275: Creating measure flow component common section
This commit is contained in:
1 parent
9a8eaff560
commit
bbb7dad905
60 files changed
+391
-156
No files matched your search
@@ -0,0 +1,16 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
|
||||
/*
|
||||
* component: create the base structure to aplly specific component mixins
|
||||
*/
|
||||
OHIF.mixins.component = new OHIF.Mixin({
|
||||
composition: {
|
||||
onCreated() {
|
||||
const instance = Template.instance();
|
||||
|
||||
// Declare a property that will be shared among all dependent mixins
|
||||
instance.component = new OHIF.Component(this);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,50 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
|
||||
/*
|
||||
* form: controls a form and its registered inputs
|
||||
*/
|
||||
OHIF.mixins.form = new OHIF.Mixin({
|
||||
dependencies: 'group',
|
||||
composition: {
|
||||
onCreated() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Define the form's data schema
|
||||
const schema = instance.data.schema;
|
||||
component.schema = schema && schema.newContext();
|
||||
|
||||
// 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() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Set the component main and style elements
|
||||
component.$style = component.$element = instance.$('form:first');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,169 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { Tracker } from "meteor/tracker";
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { $ } from 'meteor/jquery';
|
||||
|
||||
/*
|
||||
* formItem: create a generic controller for form items
|
||||
* It may be used to manage all components that belong to forms
|
||||
*/
|
||||
OHIF.mixins.formItem = new OHIF.Mixin({
|
||||
dependencies: 'schemaData',
|
||||
composition: {
|
||||
|
||||
onCreated() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Create a observer to monitor changed values
|
||||
component.changeObserver = new Tracker.Dependency();
|
||||
|
||||
// Register the component in the parent component
|
||||
component.registerSelf();
|
||||
|
||||
// Declare the component elements that will be manipulated
|
||||
component.$element = $();
|
||||
component.$style = $();
|
||||
component.$wrapper = $();
|
||||
|
||||
// Get or set the component's value using jQuery's val method
|
||||
component.value = value => {
|
||||
const isGet = _.isUndefined(value);
|
||||
if (isGet) {
|
||||
return component.$element.val();
|
||||
}
|
||||
|
||||
component.$element.val(value).trigger('change');
|
||||
};
|
||||
|
||||
// Disable or enable the component
|
||||
component.disable = isDisable => {
|
||||
component.$element.prop('disabled', !!isDisable);
|
||||
};
|
||||
|
||||
// Set or unset component's readonly property
|
||||
component.readonly = isReadonly => {
|
||||
component.$element.prop('readonly', !!isReadonly);
|
||||
};
|
||||
|
||||
// Show or hide the component
|
||||
component.show = isShow => {
|
||||
const method = isShow ? 'show' : 'hide';
|
||||
component.$wrapper[method]();
|
||||
};
|
||||
|
||||
// Add or remove a state from the component
|
||||
component.state = (state, flag) => {
|
||||
component.$wrapper.toggleClass(`state-${state}`, !!flag);
|
||||
};
|
||||
|
||||
// Set the component in error state and display the error message
|
||||
component.error = errorMessage => {
|
||||
// Set the component error state
|
||||
component.state('error', errorMessage);
|
||||
|
||||
// Set or remove the error message
|
||||
if (errorMessage) {
|
||||
component.$element.trigger('errorin');
|
||||
component.$wrapper.attr('data-error', errorMessage);
|
||||
} else {
|
||||
component.$element.trigger('errorout');
|
||||
component.$wrapper.removeAttr('data-error', errorMessage);
|
||||
}
|
||||
};
|
||||
|
||||
// Check if the component value is valid in its form's schema
|
||||
component.validate = () => {
|
||||
// Get the component's form
|
||||
const form = component.parent;
|
||||
|
||||
// Get the form's data schema
|
||||
const schema = form && form.schema;
|
||||
|
||||
// Get the current component's key
|
||||
const key = instance.data.key;
|
||||
|
||||
// Return true if validation is not needed
|
||||
if (!key || !schema || !component.$wrapper.is(':visible')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create the data document for validation
|
||||
const document = {
|
||||
[key]: component.value()
|
||||
};
|
||||
|
||||
// Check if the document validation failed
|
||||
if (!schema.validateOne(document, key)) {
|
||||
// Set the component in error state and display the message
|
||||
component.error(schema.keyErrorMessage(key));
|
||||
|
||||
// Return false for validation
|
||||
return false;
|
||||
}
|
||||
|
||||
// Remove the component error state and message
|
||||
component.error(false);
|
||||
|
||||
// Return true for validation
|
||||
return true;
|
||||
};
|
||||
|
||||
component.depend = () => {
|
||||
return component.changeObserver.depend();
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$(':input').first();
|
||||
|
||||
// Set the most outer wrapper element
|
||||
component.$wrapper = instance.wrapper.$('*').first();
|
||||
},
|
||||
|
||||
onDestroyed() {
|
||||
const instance = Template.instance();
|
||||
|
||||
// Register the component in the parent component
|
||||
instance.component.unregisterSelf();
|
||||
},
|
||||
|
||||
onMixins() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// If no style element was defined, set it as the element itself
|
||||
if (!component.$style.length) {
|
||||
component.$style = component.$element;
|
||||
}
|
||||
|
||||
// Set the component in jQuery data after all mixins are rendered
|
||||
component.$element.data('component', component);
|
||||
},
|
||||
|
||||
events: {
|
||||
|
||||
// Enable reactivity by changing a Tracker.Dependency observer
|
||||
change(event, instance) {
|
||||
instance.component.changeObserver.changed();
|
||||
},
|
||||
|
||||
// TODO: [design] remove log, show error box/hint over the wrapper
|
||||
errorin(event, instance) {
|
||||
console.log('ERROR when validating component', instance.component);
|
||||
},
|
||||
|
||||
// TODO: [design] hide error box/hint
|
||||
errorout(event, instance) {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,58 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { _ } from 'meteor/underscore';
|
||||
|
||||
/*
|
||||
* group: controls a group and its registered items
|
||||
*/
|
||||
OHIF.mixins.group = new OHIF.Mixin({
|
||||
dependencies: 'formItem',
|
||||
composition: {
|
||||
onCreated() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Get or set the child components values
|
||||
component.value = value => {
|
||||
const isGet = _.isUndefined(value);
|
||||
if (isGet) {
|
||||
const result = {};
|
||||
component.registeredItems.forEach(child => {
|
||||
const key = child.templateInstance.data.key;
|
||||
if (key) {
|
||||
result[key] = child.value();
|
||||
}
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
const groupValue = typeof value === 'object' ? value : {};
|
||||
component.registeredItems.forEach(child => {
|
||||
const key = child.templateInstance.data.key;
|
||||
const childValue = _.isUndefined(groupValue[key]) ? null : groupValue[key];
|
||||
child.value(childValue);
|
||||
});
|
||||
component.$element.trigger('change');
|
||||
};
|
||||
|
||||
// Disable or enable the component
|
||||
component.disable = isDisable => {
|
||||
component.registeredItems.forEach(child => child.disable(isDisable));
|
||||
};
|
||||
|
||||
// Set or unset component's readonly property
|
||||
component.readonly = isReadonly => {
|
||||
component.registeredItems.forEach(child => child.readonly(isReadonly));
|
||||
};
|
||||
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('.component-group:first');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,32 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { _ } from 'meteor/underscore';
|
||||
import { $ } from 'meteor/jquery';
|
||||
|
||||
/*
|
||||
* groupRadio: controls all the radio inputs inside the group
|
||||
*/
|
||||
OHIF.mixins.groupRadio = new OHIF.Mixin({
|
||||
dependencies: 'group',
|
||||
composition: {
|
||||
|
||||
onCreated() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Get the selected radio's value or select a radio based on value
|
||||
component.value = value => {
|
||||
const isGet = _.isUndefined(value);
|
||||
const elements = [];
|
||||
component.registeredItems.forEach(child => elements.push(child.$element[0]));
|
||||
const $elements = $(elements);
|
||||
if (isGet) {
|
||||
return $elements.filter(':checked').val();
|
||||
}
|
||||
|
||||
$elements.filter(`[value='${value}']`).prop('checked', true).trigger('change');
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
|
||||
/*
|
||||
* input: controls a basic input
|
||||
*/
|
||||
OHIF.mixins.input = new OHIF.Mixin({
|
||||
dependencies: 'formItem',
|
||||
composition: {
|
||||
onRendered() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('input:first');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,98 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Blaze } from 'meteor/blaze';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { _ } from 'meteor/underscore';
|
||||
|
||||
// Helper function to get the component's current schema
|
||||
const getCurrentSchema = (parentComponent, key) => {
|
||||
// Get the parent component schema
|
||||
const schema = parentComponent && parentComponent.schema;
|
||||
|
||||
// Stop here if there's no key or schema defined
|
||||
if (!key || !schema) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current schema data using component's key
|
||||
const currentSchema = _.clone(schema._schema[key]);
|
||||
|
||||
// Merge the sub-schema properties if it's an array
|
||||
if (Array.isArray(currentSchema.type())) {
|
||||
_.extend(currentSchema, schema._schema[key + '.$']);
|
||||
}
|
||||
|
||||
// Return the component's schema definitions
|
||||
return currentSchema;
|
||||
};
|
||||
|
||||
/*
|
||||
* schemaData: change the component data based on its form's schema data
|
||||
*/
|
||||
OHIF.mixins.schemaData = new OHIF.Mixin({
|
||||
dependencies: 'component',
|
||||
composition: {
|
||||
|
||||
onData() {
|
||||
// Get the current template data
|
||||
const data = Template.currentData();
|
||||
|
||||
// Get the parent component
|
||||
const parent = OHIF.blaze.getParentComponent(Blaze.currentView);
|
||||
|
||||
// Get the current schema data using component's key
|
||||
const currentSchema = getCurrentSchema(parent, data.key);
|
||||
|
||||
// Stop here if there's no schema data for current key
|
||||
if (!currentSchema) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use schema's label if it was not defined
|
||||
if (!data.label) {
|
||||
data.label = new ReactiveVar(currentSchema.label);
|
||||
}
|
||||
|
||||
// Fill the items if it's an array schema
|
||||
if (!data.items && Array.isArray(currentSchema.allowedValues)) {
|
||||
// Initialize the items array
|
||||
const items = [];
|
||||
|
||||
// Get the values and labels arrays from schema
|
||||
const values = currentSchema.allowedValues;
|
||||
const labels = currentSchema.valuesLabels || [];
|
||||
|
||||
// Iterate the allowed values array
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
// Push the current item to the items array
|
||||
items.push({
|
||||
value: values[i],
|
||||
label: labels[i] || values[i]
|
||||
});
|
||||
}
|
||||
|
||||
// Add the items to a reactive instance
|
||||
data.items = new ReactiveVar(items);
|
||||
}
|
||||
},
|
||||
|
||||
onMixins() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Get the current schema data using component's key
|
||||
const currentSchema = getCurrentSchema(component.parent, instance.data.key);
|
||||
|
||||
// Stop here if there's no schema data for current key
|
||||
if (!currentSchema) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Fill the component with its default value after rendering
|
||||
if (currentSchema.defaultValue) {
|
||||
component.value(currentSchema.defaultValue);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,18 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
|
||||
/*
|
||||
* input: controls a basic select
|
||||
*/
|
||||
OHIF.mixins.select = new OHIF.Mixin({
|
||||
dependencies: 'formItem',
|
||||
composition: {
|
||||
onRendered() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Set the element to be controlled
|
||||
component.$element = instance.$('select:first');
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,38 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { $ } from 'meteor/jquery';
|
||||
|
||||
/*
|
||||
* input: controls a select2 component
|
||||
*/
|
||||
OHIF.mixins.select2 = new OHIF.Mixin({
|
||||
dependencies: 'select',
|
||||
composition: {
|
||||
onRendered() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Apply the select2 to the component
|
||||
component.$element.select2(instance.data.options);
|
||||
|
||||
// Store the select2 instance to allow its further destruction
|
||||
component.select2Instance = component.$element.data('select2');
|
||||
},
|
||||
|
||||
onDestroyed() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
|
||||
// Destroy the select2 instance to remove unwanted DOM elements
|
||||
component.select2Instance.destroy();
|
||||
},
|
||||
|
||||
events: {
|
||||
'focus .select2-hidden-accessible'(event, instance) {
|
||||
// Redirect the focus to select2 focus control in case of hidden
|
||||
// accessible being focused (e.g. clicking on outer label)
|
||||
$(event.currentTarget).nextAll('.select2:first').find('.select2-selection').focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -0,0 +1,47 @@
|
||||
import { OHIF } from 'meteor/ohif:core';
|
||||
import { Template } from 'meteor/templating';
|
||||
import { ReactiveVar } from 'meteor/reactive-var';
|
||||
import { _ } from 'meteor/underscore';
|
||||
|
||||
/*
|
||||
* input: controls a tree selection component
|
||||
*/
|
||||
OHIF.mixins.selectTree = new OHIF.Mixin({
|
||||
dependencies: 'group',
|
||||
composition: {
|
||||
onCreated() {
|
||||
const instance = Template.instance();
|
||||
const component = instance.component;
|
||||
const rootComponent = instance.data.root || component;
|
||||
const rootInstance = rootComponent.templateInstance;
|
||||
|
||||
// Create the component's value storage property
|
||||
instance.data.currentNode = new ReactiveVar(null);
|
||||
|
||||
// Share the component in data property
|
||||
instance.data.component = component;
|
||||
|
||||
// Override the default value method
|
||||
component.value = value => {
|
||||
const isGet = _.isUndefined(value);
|
||||
|
||||
// Return the current node value
|
||||
if (isGet) {
|
||||
const currentNode = instance.data.currentNode.get();
|
||||
return currentNode ? currentNode.value : null;
|
||||
}
|
||||
|
||||
// get the items array
|
||||
const items = component.templateInstance.data.items;
|
||||
|
||||
// Get the node for the selected value
|
||||
const node = _.findWhere(items, {
|
||||
value: value
|
||||
});
|
||||
|
||||
// Change the current node
|
||||
instance.data.currentNode.set(node);
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
Reference in new issue
Block a user