LT-253: Creating dynamic form components
This commit is contained in:
parent
88f737644f
commit
cb875b1913
@ -15,6 +15,8 @@ tracker # Meteor's client-side reactive programming library
|
|||||||
es5-shim # ECMAScript 5 compatibility for older browsers.
|
es5-shim # ECMAScript 5 compatibility for older browsers.
|
||||||
ecmascript # Enable ECMAScript2015+ syntax in app code
|
ecmascript # Enable ECMAScript2015+ syntax in app code
|
||||||
|
|
||||||
|
ohif:core
|
||||||
|
|
||||||
insecure # Allow all DB writes from clients (for prototyping)
|
insecure # Allow all DB writes from clients (for prototyping)
|
||||||
cornerstone
|
cornerstone
|
||||||
worklist
|
worklist
|
||||||
|
|||||||
@ -90,6 +90,7 @@ natestrauser:select2@4.0.2
|
|||||||
npm-bcrypt@0.8.6_3
|
npm-bcrypt@0.8.6_3
|
||||||
npm-mongo@1.4.45
|
npm-mongo@1.4.45
|
||||||
observe-sequence@1.0.12
|
observe-sequence@1.0.12
|
||||||
|
ohif:core@0.0.1
|
||||||
ordered-dict@1.0.8
|
ordered-dict@1.0.8
|
||||||
orthanc-remote@0.0.1
|
orthanc-remote@0.0.1
|
||||||
peppelg:bootstrap-3-modal@1.0.4
|
peppelg:bootstrap-3-modal@1.0.4
|
||||||
|
|||||||
@ -1,3 +1,6 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
OHIF.viewer = OHIF.viewer || {};
|
||||||
|
|
||||||
Template.viewer.onCreated(function() {
|
Template.viewer.onCreated(function() {
|
||||||
// Attach the Window resize listener
|
// Attach the Window resize listener
|
||||||
$(window).on('resize', handleResize);
|
$(window).on('resize', handleResize);
|
||||||
@ -7,10 +10,6 @@ Template.viewer.onCreated(function() {
|
|||||||
|
|
||||||
log.info('viewer onCreated');
|
log.info('viewer onCreated');
|
||||||
|
|
||||||
OHIF = window.OHIF || {
|
|
||||||
viewer: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
OHIF.viewer.loadIndicatorDelay = 500;
|
OHIF.viewer.loadIndicatorDelay = 500;
|
||||||
OHIF.viewer.defaultTool = 'wwwc';
|
OHIF.viewer.defaultTool = 'wwwc';
|
||||||
OHIF.viewer.refLinesEnabled = true;
|
OHIF.viewer.refLinesEnabled = true;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ label.radio-option
|
|||||||
height: 0
|
height: 0
|
||||||
width: 0
|
width: 0
|
||||||
span
|
span
|
||||||
padding-left: 20px
|
padding-left: 23px
|
||||||
position: relative
|
position: relative
|
||||||
&:before
|
&:before
|
||||||
background: white
|
background: white
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Template.matchedProtocols.onRendered(function() {
|
Template.matchedProtocols.onRendered(function() {
|
||||||
$('#matchedProtocols button').tooltip(OHIF.viewer.tooltipConfig);
|
$('#matchedProtocols button').tooltip(OHIF.viewer.tooltipConfig);
|
||||||
});
|
});
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
// Define a global variable that will be used to refer to the Protocol Engine
|
// Define a global variable that will be used to refer to the Protocol Engine
|
||||||
// It must be populated by HP.setEngine when the Viewer is initialized and a ProtocolEngine
|
// It must be populated by HP.setEngine when the Viewer is initialized and a ProtocolEngine
|
||||||
// is instantiated on top of the LayoutManager. If the global ProtocolEngine variable remains
|
// is instantiated on top of the LayoutManager. If the global ProtocolEngine variable remains
|
||||||
|
|||||||
@ -4,10 +4,10 @@ SimpleSchema.extendOptions({
|
|||||||
allowedSelect2Values: Match.Optional(Array),
|
allowedSelect2Values: Match.Optional(Array),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const AdditionalFinding = new SimpleSchema({
|
export const schema = new SimpleSchema({
|
||||||
measurableDisease: {
|
measurableDisease: {
|
||||||
type: String,
|
type: String,
|
||||||
label: 'Measurable Disease',
|
label: 'Measurable disease',
|
||||||
allowedValues: ['Present', 'Absent'],
|
allowedValues: ['Present', 'Absent'],
|
||||||
defaultValue: 'Absent',
|
defaultValue: 'Absent',
|
||||||
optional: true
|
optional: true
|
||||||
@ -7,6 +7,13 @@
|
|||||||
</div>
|
</div>
|
||||||
{{>radioOptionGroup (stateDataWithKey "measurableDisease")}}
|
{{>radioOptionGroup (stateDataWithKey "measurableDisease")}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- <h4>Testing dynamic components</h4>
|
||||||
|
{{#form id="testForm" schema=currentSchema}}
|
||||||
|
{{>inputText key='test' label='testing'}}
|
||||||
|
{{>groupRadio mixins='schemaData' key='acceptableImageQuality'}}
|
||||||
|
{{/form}} -->
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
Supplementary Measurements
|
Supplementary Measurements
|
||||||
|
|||||||
@ -1,14 +1,12 @@
|
|||||||
import { Template } from 'meteor/templating';
|
import { Template } from 'meteor/templating';
|
||||||
import { ReactiveDict } from 'meteor/reactive-dict';
|
import { ReactiveDict } from 'meteor/reactive-dict';
|
||||||
|
import { schema as AdditionalFindingsSchema } from 'meteor/lesiontracker/both/schema/additionalFindings';
|
||||||
// TODO: Check why I can't use absolute paths for this? Keeps saying module not found
|
|
||||||
import { AdditionalFinding } from '../../../both/schema/additionalFinding';
|
|
||||||
|
|
||||||
Template.additionalFindings.onCreated(function additionalFindingsOnCreated() {
|
Template.additionalFindings.onCreated(function additionalFindingsOnCreated() {
|
||||||
console.log('additionalFindingsOnCreated');
|
console.log('additionalFindingsOnCreated');
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
|
|
||||||
instance.currentSchema = AdditionalFinding;
|
instance.currentSchema = AdditionalFindingsSchema;
|
||||||
instance.state = new ReactiveDict();
|
instance.state = new ReactiveDict();
|
||||||
|
|
||||||
if (!instance.data.currentTimepointId) {
|
if (!instance.data.currentTimepointId) {
|
||||||
|
|||||||
@ -25,21 +25,22 @@
|
|||||||
.header
|
.header
|
||||||
height: 33px
|
height: 33px
|
||||||
line-height: 33px
|
line-height: 33px
|
||||||
font-weight: 400
|
font-weight: bold
|
||||||
font-size: 14px
|
font-size: 14px
|
||||||
padding: 0 10px
|
padding: 1px 13px 0
|
||||||
color: $textPrimaryColor
|
color: $textPrimaryColor
|
||||||
background-color: $uiGrayDark
|
background-color: $uiGray
|
||||||
|
|
||||||
.form-group
|
.form-group
|
||||||
padding: 10px
|
padding: 7px 11px
|
||||||
color: $textPrimaryColor
|
color: $textPrimaryColor
|
||||||
|
|
||||||
&:not(:last-child)
|
&:not(:last-child)
|
||||||
border-bottom: $uiBorderThickness solid $uiBorderColorDark
|
border-bottom: $uiBorderThickness solid $uiBorderColorDark
|
||||||
|
|
||||||
h5
|
h5
|
||||||
font-weight: 300
|
font-weight: bold
|
||||||
|
margin-bottom: 8px
|
||||||
|
|
||||||
.control-label
|
.control-label
|
||||||
font-size: 14px
|
font-size: 14px
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Template.toolbarSection.helpers({
|
Template.toolbarSection.helpers({
|
||||||
// Returns true if the view shall be split in two viewports
|
// Returns true if the view shall be split in two viewports
|
||||||
splitView() {
|
splitView() {
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Template.toolbarSectionButton.helpers({
|
Template.toolbarSectionButton.helpers({
|
||||||
activeClass() {
|
activeClass() {
|
||||||
const instance = Template.instance();
|
const instance = Template.instance();
|
||||||
|
|||||||
@ -1,5 +1,8 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
import { TimepointApi } from 'meteor/lesiontracker/lib/api/timepoint';
|
import { TimepointApi } from 'meteor/lesiontracker/lib/api/timepoint';
|
||||||
|
|
||||||
|
OHIF.viewer = OHIF.viewer || {};
|
||||||
|
|
||||||
Session.setDefault('activeViewport', false);
|
Session.setDefault('activeViewport', false);
|
||||||
Session.setDefault('leftSidebar', null);
|
Session.setDefault('leftSidebar', null);
|
||||||
Session.setDefault('rightSidebar', null);
|
Session.setDefault('rightSidebar', null);
|
||||||
@ -22,10 +25,6 @@ Template.viewer.onCreated(() => {
|
|||||||
|
|
||||||
var contentId = instance.data.contentId;
|
var contentId = instance.data.contentId;
|
||||||
|
|
||||||
OHIF = OHIF || window.OHIF || {
|
|
||||||
viewer: {}
|
|
||||||
};
|
|
||||||
|
|
||||||
OHIF.viewer.loadIndicatorDelay = 3000;
|
OHIF.viewer.loadIndicatorDelay = 3000;
|
||||||
OHIF.viewer.defaultTool = 'wwwc';
|
OHIF.viewer.defaultTool = 'wwwc';
|
||||||
OHIF.viewer.refLinesEnabled = true;
|
OHIF.viewer.refLinesEnabled = true;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates a set of lesions when lesion table row is clicked
|
* Activates a set of lesions when lesion table row is clicked
|
||||||
*
|
*
|
||||||
|
|||||||
@ -35,7 +35,7 @@ Package.onUse(function(api) {
|
|||||||
api.addFiles('log.js', [ 'client', 'server' ]);
|
api.addFiles('log.js', [ 'client', 'server' ]);
|
||||||
|
|
||||||
// Schema
|
// Schema
|
||||||
api.addFiles('both/schema/additionalFinding.js', [ 'client', 'server' ]);
|
api.addFiles('both/schema/additionalFindings.js', [ 'client', 'server' ]);
|
||||||
|
|
||||||
// Client-side collections
|
// Client-side collections
|
||||||
api.addFiles('client/collections/LesionLocations.js', 'client');
|
api.addFiles('client/collections/LesionLocations.js', 'client');
|
||||||
|
|||||||
49
Packages/ohif-core/components/base/component.js
Normal file
49
Packages/ohif-core/components/base/component.js
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Base component to template instances of all dynamic components
|
||||||
|
*/
|
||||||
|
class Component {
|
||||||
|
|
||||||
|
// Set up the component
|
||||||
|
constructor(templateInstance) {
|
||||||
|
// Store the component in the current view
|
||||||
|
templateInstance.view._component = this;
|
||||||
|
|
||||||
|
// Create an object to register section's content
|
||||||
|
templateInstance.sections = {};
|
||||||
|
|
||||||
|
// Store the template instance in the component
|
||||||
|
this.templateInstance = templateInstance;
|
||||||
|
|
||||||
|
// Store the component's registered sub-components
|
||||||
|
this.registeredItems = new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Self register the component in its first parent component
|
||||||
|
registerSelf() {
|
||||||
|
const parent = OHIF.blaze.getParentComponent(this.templateInstance.view);
|
||||||
|
if (parent) {
|
||||||
|
// Store this component's parent in a property
|
||||||
|
this.parent = parent;
|
||||||
|
|
||||||
|
// Add this component in its parent's registered items list
|
||||||
|
parent.registeredItems.add(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Self unregister the component in its first parent component
|
||||||
|
unregisterSelf() {
|
||||||
|
const parent = OHIF.blaze.getParentComponent(this.templateInstance.view);
|
||||||
|
if (parent) {
|
||||||
|
// Remove the parent property from this component
|
||||||
|
delete this.parent;
|
||||||
|
|
||||||
|
// Remove this component from its parent's registered items list
|
||||||
|
parent.registeredItems.delete(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
OHIF.Component = Component;
|
||||||
26
Packages/ohif-core/components/base/index.js
Normal file
26
Packages/ohif-core/components/base/index.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Core files
|
||||||
|
import './component.js';
|
||||||
|
import './mixin.js';
|
||||||
|
import './template.js';
|
||||||
|
|
||||||
|
// Mixins
|
||||||
|
import './mixins/component.js';
|
||||||
|
import './mixins/form.js';
|
||||||
|
import './mixins/formItem.js';
|
||||||
|
import './mixins/group.js';
|
||||||
|
import './mixins/groupRadio.js';
|
||||||
|
import './mixins/input.js';
|
||||||
|
import './mixins/schemaData.js';
|
||||||
|
import './mixins/select.js';
|
||||||
|
import './mixins/select2.js';
|
||||||
|
|
||||||
|
// Templates
|
||||||
|
import './templates/custom.html';
|
||||||
|
import './templates/div.html';
|
||||||
|
import './templates/form.html';
|
||||||
|
import './templates/input.html';
|
||||||
|
import './templates/select.html';
|
||||||
|
|
||||||
|
// wrappers
|
||||||
|
import './wrappers/label.html';
|
||||||
|
import './wrappers/title.html';
|
||||||
126
Packages/ohif-core/components/base/mixin.js
Normal file
126
Packages/ohif-core/components/base/mixin.js
Normal file
@ -0,0 +1,126 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
|
||||||
|
// Create an object to store all the application mixins
|
||||||
|
OHIF.mixins = {};
|
||||||
|
|
||||||
|
// Class to manage new mixins and its dependencies
|
||||||
|
class Mixin {
|
||||||
|
|
||||||
|
// Create the mixin instance
|
||||||
|
constructor({ dependencies, composition }) {
|
||||||
|
// Store the mixin dependencies
|
||||||
|
this.dependencies = dependencies || '';
|
||||||
|
|
||||||
|
// Store the mixin composition
|
||||||
|
this.composition = composition;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize the mixin applying all its composition functions
|
||||||
|
init(template, data, applied, behaviors) {
|
||||||
|
const dependenciesArray = this.dependencies.split(' ');
|
||||||
|
_.each(dependenciesArray, dependency => {
|
||||||
|
// Go to next dependency if the current dependency string is blank
|
||||||
|
if (!dependency) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the dependent mixin to be initizalized
|
||||||
|
const mixin = Mixin.getMixin(dependency);
|
||||||
|
|
||||||
|
// Initizalize the mixin dependencies recursively
|
||||||
|
mixin.init(template, data, applied, behaviors);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Apply the mixin's composition behaviors to the template
|
||||||
|
this.apply(template, data, applied, behaviors);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the mixin's composition behaviors to the template
|
||||||
|
apply(template, data, applied, behaviors) {
|
||||||
|
// Ignore if the mixin was already applied to the template
|
||||||
|
if (_.contains(applied, this)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the mixin's composition
|
||||||
|
const composition = this.composition;
|
||||||
|
|
||||||
|
// Iterate over each behavior
|
||||||
|
_.each(behaviors, behavior => {
|
||||||
|
// Execute something only after all the mixins are done
|
||||||
|
let functionName = behavior;
|
||||||
|
if (functionName === 'onMixins') {
|
||||||
|
functionName = 'onRendered';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (behavior === 'onData' && composition[behavior]) {
|
||||||
|
// If it's just data manipulation, call it immediately
|
||||||
|
composition[behavior](data);
|
||||||
|
} else if (composition[behavior]) {
|
||||||
|
// Register the behavior in the template
|
||||||
|
template[functionName](composition[behavior]);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Set the current mixin's state as applied
|
||||||
|
applied.push(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize all data manipulation mixins
|
||||||
|
static initData(data) {
|
||||||
|
// Split the mixins by space
|
||||||
|
const mixinsArray = data.mixins.split(' ');
|
||||||
|
_.each(mixinsArray, mixinName => {
|
||||||
|
// Ignore blank strings
|
||||||
|
if (!mixinName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current mixin
|
||||||
|
const mixin = Mixin.getMixin(mixinName);
|
||||||
|
|
||||||
|
// Initialize the data manipulation composition
|
||||||
|
mixin.init(null, data, [], ['onData']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialize all the template's mixins
|
||||||
|
static initAll(template, data) {
|
||||||
|
// Split the mixins by space
|
||||||
|
const mixinsArray = data.mixins.split(' ');
|
||||||
|
_.each(mixinsArray, mixinName => {
|
||||||
|
// Ignore blank strings
|
||||||
|
if (!mixinName) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the current mixin
|
||||||
|
const mixin = Mixin.getMixin(mixinName);
|
||||||
|
|
||||||
|
// Initialize blaze default compositions
|
||||||
|
mixin.init(template, data, [], ['onCreated', 'onRendered', 'onDestroyed', 'events', 'helpers']);
|
||||||
|
|
||||||
|
// Execute some behaviors after all mixins are applied
|
||||||
|
mixin.init(template, data, [], ['onMixins']);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get a mixin by name
|
||||||
|
static getMixin(mixinName) {
|
||||||
|
// Get the mixin from mixins object
|
||||||
|
const mixin = OHIF.mixins[mixinName];
|
||||||
|
|
||||||
|
// Throw an error if the mixin does not exists
|
||||||
|
if (!mixin) {
|
||||||
|
throw new Error(`Mixin ${mixinName} not found.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the found mixin
|
||||||
|
return mixin;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store the Mixin class inside the shared OHIF object
|
||||||
|
OHIF.Mixin = Mixin;
|
||||||
16
Packages/ohif-core/components/base/mixins/component.js
Normal file
16
Packages/ohif-core/components/base/mixins/component.js
Normal file
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
50
Packages/ohif-core/components/base/mixins/form.js
Normal file
50
Packages/ohif-core/components/base/mixins/form.js
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
154
Packages/ohif-core/components/base/mixins/formItem.js
Normal file
154
Packages/ohif-core/components/base/mixins/formItem.js
Normal file
@ -0,0 +1,154 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
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: 'component',
|
||||||
|
composition: {
|
||||||
|
|
||||||
|
onCreated() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
const component = instance.component;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
onRendered() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
const component = instance.component;
|
||||||
|
|
||||||
|
// Set the element to be controlled
|
||||||
|
component.$element = instance.$(':input:first');
|
||||||
|
|
||||||
|
// Set the element to be styled
|
||||||
|
component.$style = component.$element;
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
|
||||||
|
// Set the component in jQuery data after all mixins are rendered
|
||||||
|
component.$element.data('component', component);
|
||||||
|
},
|
||||||
|
|
||||||
|
events: {
|
||||||
|
|
||||||
|
// 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) {
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
50
Packages/ohif-core/components/base/mixins/group.js
Normal file
50
Packages/ohif-core/components/base/mixins/group.js
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
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));
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
30
Packages/ohif-core/components/base/mixins/groupRadio.js
Normal file
30
Packages/ohif-core/components/base/mixins/groupRadio.js
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.add(child.$element));
|
||||||
|
if (isGet) {
|
||||||
|
return $elements.filter(':checked').val();
|
||||||
|
}
|
||||||
|
|
||||||
|
$elements.filter(`[value='${value}']`).prop('checked', true).trigger('change');
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
18
Packages/ohif-core/components/base/mixins/input.js
Normal file
18
Packages/ohif-core/components/base/mixins/input.js
Normal file
@ -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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
46
Packages/ohif-core/components/base/mixins/schemaData.js
Normal file
46
Packages/ohif-core/components/base/mixins/schemaData.js
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { Blaze } from 'meteor/blaze';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* schemaData: change the component data based on its form's schema data
|
||||||
|
*/
|
||||||
|
OHIF.mixins.schemaData = new OHIF.Mixin({
|
||||||
|
dependencies: 'formItem',
|
||||||
|
composition: {
|
||||||
|
|
||||||
|
onData() {
|
||||||
|
const data = Template.currentData();
|
||||||
|
|
||||||
|
const parent = OHIF.blaze.getParentComponent(Blaze.currentView);
|
||||||
|
|
||||||
|
// Get the parent component schema
|
||||||
|
const schema = parent && parent.schema;
|
||||||
|
|
||||||
|
// Get the current component's key
|
||||||
|
const key = data.key;
|
||||||
|
|
||||||
|
// 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 = schema._schema[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);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: [design] convert allowedValues to items and find a way to get key/value pairs
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
18
Packages/ohif-core/components/base/mixins/select.js
Normal file
18
Packages/ohif-core/components/base/mixins/select.js
Normal file
@ -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');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
18
Packages/ohif-core/components/base/mixins/select2.js
Normal file
18
Packages/ohif-core/components/base/mixins/select2.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
/*
|
||||||
|
* input: controls a select2 component
|
||||||
|
*/
|
||||||
|
OHIF.mixins.select2 = new OHIF.Mixin({
|
||||||
|
dependencies: 'select',
|
||||||
|
composition: {
|
||||||
|
onRendered() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
const component = instance.component;
|
||||||
|
|
||||||
|
// Set the element to be controlled
|
||||||
|
component.$element = instance.$('select:first');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
106
Packages/ohif-core/components/base/template.js
Normal file
106
Packages/ohif-core/components/base/template.js
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
|
||||||
|
// Create a new custom template for the base component
|
||||||
|
Template.baseComponent = new Template('baseComponent', () => {});
|
||||||
|
|
||||||
|
// Inject some custom behaviors in the view's construction function
|
||||||
|
Template.baseComponent.constructView = function(contentFunc, elseFunc) {
|
||||||
|
// Get the data passed to the template
|
||||||
|
const data = Template.currentData();
|
||||||
|
|
||||||
|
// Check the base template. If it's not informed set as the custom base
|
||||||
|
data.base || (data.base = 'baseCustom');
|
||||||
|
|
||||||
|
// Get the base template object
|
||||||
|
const baseTemplate = Template[data.base];
|
||||||
|
|
||||||
|
// Throw an error if the base template does not exists
|
||||||
|
if (!baseTemplate) {
|
||||||
|
throw new Error(`Template ${data.base} not found.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare the template object and name it as base name + 'Component'
|
||||||
|
const template = OHIF.blaze.cloneTemplate(baseTemplate, data.base + 'Component');
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
// Create and fill a list of wrappers that will enclose the component
|
||||||
|
const wrappers = [];
|
||||||
|
if (data.wrappers) {
|
||||||
|
const wrappersList = data.wrappers.split(' ');
|
||||||
|
_.each(wrappersList, wrapper => wrapper && wrappers.push(wrapper));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare a variable to store the wrapper instances that will be rendered
|
||||||
|
const wrapperInstances = [];
|
||||||
|
|
||||||
|
// Declare the content function to render the component
|
||||||
|
let contentFunction = () => {
|
||||||
|
// Create the most inner content function
|
||||||
|
const innerContentFunction = () => {
|
||||||
|
// Assign properties to all wrappers after template's creation
|
||||||
|
template.onCreated(() => {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
// Assign the template most outer wrapper
|
||||||
|
instance.wrapper = wrapperInstances[0] || instance;
|
||||||
|
|
||||||
|
// Iterate over all wrappers and assign the component to them
|
||||||
|
wrapperInstances.forEach(wrappeInstance => {
|
||||||
|
wrappeInstance.component = instance.component;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the view instance
|
||||||
|
return template.constructView(contentFunc, elseFunc);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Apply the mixins to the component
|
||||||
|
OHIF.Mixin.initAll(template, data);
|
||||||
|
|
||||||
|
// Return the recursive function for wrappers
|
||||||
|
return Blaze.With(data, innerContentFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
let wrapper;
|
||||||
|
while (wrapper = wrappers.shift()) {
|
||||||
|
// Get the wrapper template
|
||||||
|
const wrapperTemplate = Template[wrapper];
|
||||||
|
|
||||||
|
// Throw an error if the wrapper template does not exists
|
||||||
|
if (!wrapperTemplate) {
|
||||||
|
throw new Error(`Template ${data.base} not found.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clone the wrapper template to avoid assigning duplicated handlers
|
||||||
|
const currentTemplate = OHIF.blaze.cloneTemplate(wrapperTemplate);
|
||||||
|
|
||||||
|
// Store the child content function to render it inside the wrapper
|
||||||
|
const childContentFunction = contentFunction;
|
||||||
|
|
||||||
|
// Create a function that will enable the recursion for wrappers
|
||||||
|
const enclosingContentFunction = () => {
|
||||||
|
// Add the current wrapper's instance to the wrapper instances list
|
||||||
|
currentTemplate.onCreated(() => wrapperInstances.push(Template.instance()));
|
||||||
|
|
||||||
|
// Return the wrapper view instance with its child as content
|
||||||
|
return currentTemplate.constructView(childContentFunction, elseFunc);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Replace the content function enclosing it recursively
|
||||||
|
contentFunction = () => {
|
||||||
|
return Blaze.With(data, enclosingContentFunction);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return contentFunction(contentFunc, elseFunc);
|
||||||
|
};
|
||||||
3
Packages/ohif-core/components/base/templates/custom.html
Normal file
3
Packages/ohif-core/components/base/templates/custom.html
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
<template name="baseCustom">
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
</template>
|
||||||
9
Packages/ohif-core/components/base/templates/div.html
Normal file
9
Packages/ohif-core/components/base/templates/div.html
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
<template name="baseDiv">
|
||||||
|
<div
|
||||||
|
id="{{this.id}}"
|
||||||
|
class="{{this.class}}"
|
||||||
|
{{this.tagAttributes}}
|
||||||
|
>
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
16
Packages/ohif-core/components/base/templates/form.html
Normal file
16
Packages/ohif-core/components/base/templates/form.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<template name="baseForm">
|
||||||
|
<form
|
||||||
|
id="{{this.id}}"
|
||||||
|
class="{{this.class}}"
|
||||||
|
name="{{this.name}}"
|
||||||
|
action="{{this.action}}"
|
||||||
|
method="{{this.method}}"
|
||||||
|
autocomplete="{{this.autocomplete}}"
|
||||||
|
enctype="{{this.enctype}}"
|
||||||
|
novalidate="{{this.novalidate}}"
|
||||||
|
target="{{this.target}}"
|
||||||
|
{{this.tagAttributes}}
|
||||||
|
>
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
11
Packages/ohif-core/components/base/templates/input.html
Normal file
11
Packages/ohif-core/components/base/templates/input.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<template name="baseInput">
|
||||||
|
<input
|
||||||
|
type="{{choose this.type 'text'}}"
|
||||||
|
id="{{this.id}}"
|
||||||
|
class="{{this.class}}"
|
||||||
|
name="{{this.name}}"
|
||||||
|
value="{{reactive this.value}}"
|
||||||
|
{{this.tagAttributes}}
|
||||||
|
>
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
</template>
|
||||||
16
Packages/ohif-core/components/base/templates/select.html
Normal file
16
Packages/ohif-core/components/base/templates/select.html
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<template name="baseSelect">
|
||||||
|
<select
|
||||||
|
id="{{this.id}}"
|
||||||
|
class="{{this.class}}"
|
||||||
|
name="{{this.name}}"
|
||||||
|
{{this.tagAttributes}}
|
||||||
|
>
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{#each item in (reactive this.items)}}
|
||||||
|
<option
|
||||||
|
value="{{item.value}}"
|
||||||
|
selected="{{#if eq item.value (reactive this.value)}}selected{{/if}}"
|
||||||
|
>{{item.label}}</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
</template>
|
||||||
11
Packages/ohif-core/components/base/wrappers/label.html
Normal file
11
Packages/ohif-core/components/base/wrappers/label.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<template name="wrapperLabel">
|
||||||
|
<label class="wrapperLabel {{this.labelClass}}">
|
||||||
|
{{#if this.labelAfter}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/if}}
|
||||||
|
<span class="wrapperLabelText">{{reactive this.label}}</span>
|
||||||
|
{{#unless this.labelAfter}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/unless}}
|
||||||
|
</label>
|
||||||
|
</template>
|
||||||
11
Packages/ohif-core/components/base/wrappers/title.html
Normal file
11
Packages/ohif-core/components/base/wrappers/title.html
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<template name="wrapperTitle">
|
||||||
|
<div class="wrapperTitle {{this.labelClass}}">
|
||||||
|
{{#if this.labelAfter}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/if}}
|
||||||
|
<span class="wrapperTitleText">{{reactive this.label}}</span>
|
||||||
|
{{#unless this.labelAfter}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/unless}}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
8
Packages/ohif-core/components/bootstrap/form/form.html
Normal file
8
Packages/ohif-core/components/bootstrap/form/form.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<template name="form">
|
||||||
|
{{#baseComponent (extend this
|
||||||
|
base="baseForm"
|
||||||
|
mixins=(concat "form " this.mixins)
|
||||||
|
)}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/baseComponent}}
|
||||||
|
</template>
|
||||||
8
Packages/ohif-core/components/bootstrap/form/group.html
Normal file
8
Packages/ohif-core/components/bootstrap/form/group.html
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
<template name="group">
|
||||||
|
{{#baseComponent (extend this
|
||||||
|
base="baseDiv"
|
||||||
|
mixins=(concat "group " this.mixins)
|
||||||
|
)}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/baseComponent}}
|
||||||
|
</template>
|
||||||
7
Packages/ohif-core/components/bootstrap/index.js
Normal file
7
Packages/ohif-core/components/bootstrap/index.js
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
import './form/form.html';
|
||||||
|
import './form/group.html';
|
||||||
|
|
||||||
|
import './input/groupRadio.html';
|
||||||
|
import './input/radio.html';
|
||||||
|
import './input/select.html';
|
||||||
|
import './input/text.html';
|
||||||
@ -0,0 +1,20 @@
|
|||||||
|
<template name="groupRadio">
|
||||||
|
{{#group (extend this
|
||||||
|
class=(concat 'form-group ' this.class)
|
||||||
|
wrappers=(concat ''
|
||||||
|
this.wrappers
|
||||||
|
(valueIf reactive this.label 'wrapperTitle ' '')
|
||||||
|
)
|
||||||
|
)}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{#each item in (reactive this.items)}}
|
||||||
|
{{>inputRadio
|
||||||
|
class=this.radioClass
|
||||||
|
name=this.key
|
||||||
|
value=item.value
|
||||||
|
label=item.label
|
||||||
|
checked=(eq item.value (reactive this.value))
|
||||||
|
}}
|
||||||
|
{{/each}}
|
||||||
|
{{/group}}
|
||||||
|
</template>
|
||||||
14
Packages/ohif-core/components/bootstrap/input/radio.html
Normal file
14
Packages/ohif-core/components/bootstrap/input/radio.html
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<template name="inputRadio">
|
||||||
|
{{#baseComponent (extend this
|
||||||
|
base='baseInput'
|
||||||
|
mixins=(concat 'input ' this.mixins)
|
||||||
|
labelAfter=(valueIf (isDefined this.labelAfter) this.labelAfter true)
|
||||||
|
labelClass=(concat 'checkboxLabel' this.labelClass)
|
||||||
|
wrappers=(concat ''
|
||||||
|
this.wrappers
|
||||||
|
(valueIf reactive this.label 'wrapperLabel ' '')
|
||||||
|
)
|
||||||
|
)}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/baseComponent}}
|
||||||
|
</template>
|
||||||
13
Packages/ohif-core/components/bootstrap/input/select.html
Normal file
13
Packages/ohif-core/components/bootstrap/input/select.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template name="inputSelect">
|
||||||
|
{{#baseComponent (extend this
|
||||||
|
base='baseSelect'
|
||||||
|
class=(concat 'form-control ' this.class)
|
||||||
|
mixins=(concat 'select ' this.mixins)
|
||||||
|
wrappers=(concat ''
|
||||||
|
this.wrappers
|
||||||
|
(valueIf reactive this.label 'wrapperLabel ' '')
|
||||||
|
)
|
||||||
|
)}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/baseComponent}}
|
||||||
|
</template>
|
||||||
13
Packages/ohif-core/components/bootstrap/input/text.html
Normal file
13
Packages/ohif-core/components/bootstrap/input/text.html
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<template name="inputText">
|
||||||
|
{{#baseComponent (extend this
|
||||||
|
base='baseInput'
|
||||||
|
class=(concat 'form-control ' this.class)
|
||||||
|
mixins=(concat 'input ' this.mixins)
|
||||||
|
wrappers=(concat ''
|
||||||
|
this.wrappers
|
||||||
|
(valueIf reactive this.label 'wrapperLabel ' '')
|
||||||
|
)
|
||||||
|
)}}
|
||||||
|
{{>UI.contentBlock}}
|
||||||
|
{{/baseComponent}}
|
||||||
|
</template>
|
||||||
2
Packages/ohif-core/components/index.js
Normal file
2
Packages/ohif-core/components/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import './base';
|
||||||
|
import './bootstrap';
|
||||||
26
Packages/ohif-core/helpers/blaze.js
Normal file
26
Packages/ohif-core/helpers/blaze.js
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { Session } from 'meteor/session';
|
||||||
|
import { ReactiveVar } from 'meteor/reactive-var';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global Blaze UI helpers to work with Blaze
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Return the current template instance
|
||||||
|
Template.registerHelper('instance', () => {
|
||||||
|
return Template.instance();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the session value for the given key
|
||||||
|
Template.registerHelper('session', key => {
|
||||||
|
return Session.get(key);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the value for given parameter regardless if it's reactive or not
|
||||||
|
Template.registerHelper('reactive', parameter => {
|
||||||
|
if (parameter instanceof ReactiveVar) {
|
||||||
|
return parameter.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
return parameter;
|
||||||
|
});
|
||||||
59
Packages/ohif-core/helpers/data.js
Normal file
59
Packages/ohif-core/helpers/data.js
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global Blaze UI helpers to manipulate data
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Base extend function to be used by extend and clone helpers
|
||||||
|
const extend = (...argsArray) => {
|
||||||
|
// Create the resulting object
|
||||||
|
const result = argsArray[0] || {};
|
||||||
|
|
||||||
|
// Extract the Spacebars kw hash
|
||||||
|
const kwHash = _.last(argsArray).hash;
|
||||||
|
|
||||||
|
// Extract the given objects
|
||||||
|
const objects = _.initial(argsArray);
|
||||||
|
|
||||||
|
// Iterate over the given objects
|
||||||
|
_.each(objects, current => {
|
||||||
|
// Stop here if the current argument is not an object
|
||||||
|
if (typeof current !== 'object') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extend the resulting object with the current argument object
|
||||||
|
_.extend(result, current);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Extend the resulting object with the Spacebars kw hash
|
||||||
|
_.extend(result, kwHash);
|
||||||
|
|
||||||
|
// Return the resulting object
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Extend the first argument object it with the other argument objects
|
||||||
|
Template.registerHelper('extend', (...argsArray) => {
|
||||||
|
return extend(...argsArray);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Create a new object and extends it with the argument objects
|
||||||
|
Template.registerHelper('clone', (...argsArray) => {
|
||||||
|
const newArgs = argsArray.slice();
|
||||||
|
newArgs.unshift({});
|
||||||
|
return extend(...newArgs);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Return the first thrut value in the given arguments
|
||||||
|
Template.registerHelper('choose', (...argsArray) => {
|
||||||
|
// Iterate over the given objects
|
||||||
|
for (let i = 0; i < argsArray.length; i++) {
|
||||||
|
// Check if the current value is truth
|
||||||
|
if (!!argsArray[i]) {
|
||||||
|
// Return the current value
|
||||||
|
return argsArray[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
4
Packages/ohif-core/helpers/index.js
Normal file
4
Packages/ohif-core/helpers/index.js
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import './blaze';
|
||||||
|
import './data';
|
||||||
|
import './logical';
|
||||||
|
import './string';
|
||||||
@ -1,3 +1,6 @@
|
|||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Global Blaze UI helpers to work with logical operations
|
* Global Blaze UI helpers to work with logical operations
|
||||||
*/
|
*/
|
||||||
@ -63,6 +66,15 @@ Template.registerHelper('choose', (...values) => {
|
|||||||
return result;
|
return result;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Return the second parameter if the first is true or the third if it's false
|
||||||
|
Template.registerHelper('valueIf', (condition, valueIfTrue, valueIfFalse) => {
|
||||||
|
if (condition) {
|
||||||
|
return valueIfTrue;
|
||||||
|
}
|
||||||
|
|
||||||
|
return valueIfFalse;
|
||||||
|
});
|
||||||
|
|
||||||
// Check if the value is different from undefined
|
// Check if the value is different from undefined
|
||||||
Template.registerHelper('isDefined', value => {
|
Template.registerHelper('isDefined', value => {
|
||||||
return typeof value !== 'undefined';
|
return typeof value !== 'undefined';
|
||||||
16
Packages/ohif-core/helpers/string.js
Normal file
16
Packages/ohif-core/helpers/string.js
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
import { _ } from 'meteor/underscore';
|
||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Global Blaze UI helpers to work with Strings
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Concatenate the give strings
|
||||||
|
Template.registerHelper('concat', (...args) => {
|
||||||
|
const values = _.initial(args, 1);
|
||||||
|
let result = '';
|
||||||
|
_.each(values, value => {
|
||||||
|
result += value || '';
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
});
|
||||||
42
Packages/ohif-core/lib/blaze.js
Normal file
42
Packages/ohif-core/lib/blaze.js
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
|
OHIF.blaze = {};
|
||||||
|
|
||||||
|
// Clone a template and return the clone
|
||||||
|
OHIF.blaze.cloneTemplate = (template, newName) => {
|
||||||
|
if (!template){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = newName || template.viewName;
|
||||||
|
const clone = new Template(name, template.renderFunction);
|
||||||
|
clone.inheritsEventsFrom(template);
|
||||||
|
clone.inheritsHelpersFrom(template);
|
||||||
|
clone.inheritsHooksFrom(template);
|
||||||
|
return clone;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Navigate upwards the component and get the parent with the given view name
|
||||||
|
OHIF.blaze.getParentView = (view, parentViewName) => {
|
||||||
|
let currentView = view;
|
||||||
|
while (currentView) {
|
||||||
|
if (currentView.name === parentViewName) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
currentView = currentView.originalParentView || currentView.parentView;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentView;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Search for the parent component of the given view
|
||||||
|
OHIF.blaze.getParentComponent = (view) => {
|
||||||
|
let currentView = view;
|
||||||
|
while (currentView) {
|
||||||
|
currentView = currentView.originalParentView || currentView.parentView;
|
||||||
|
if (currentView && currentView._component) {
|
||||||
|
return currentView._component;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
1
Packages/ohif-core/lib/index.js
Normal file
1
Packages/ohif-core/lib/index.js
Normal file
@ -0,0 +1 @@
|
|||||||
|
import './blaze.js';
|
||||||
6
Packages/ohif-core/main.js
Normal file
6
Packages/ohif-core/main.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
export { OHIF } from './ohif.js';
|
||||||
|
|
||||||
|
import './lib';
|
||||||
|
import './components';
|
||||||
|
import './helpers';
|
||||||
|
import './ui';
|
||||||
11
Packages/ohif-core/ohif.js
Normal file
11
Packages/ohif-core/ohif.js
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
/*
|
||||||
|
* Defines the base OHIF object
|
||||||
|
*/
|
||||||
|
|
||||||
|
const OHIF = {};
|
||||||
|
|
||||||
|
if (Meteor.isDevelopment) {
|
||||||
|
window.OHIF = OHIF;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { OHIF };
|
||||||
15
Packages/ohif-core/package.js
Normal file
15
Packages/ohif-core/package.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
Package.describe({
|
||||||
|
name: 'ohif:core',
|
||||||
|
summary: 'OHIF core components, helpers and UI functions',
|
||||||
|
version: '0.0.1'
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.onUse(function(api) {
|
||||||
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
|
api.use('ecmascript');
|
||||||
|
api.use('standard-app-packages');
|
||||||
|
api.use('jquery');
|
||||||
|
|
||||||
|
api.mainModule('main.js', 'client');
|
||||||
|
});
|
||||||
2
Packages/ohif-core/ui/index.js
Normal file
2
Packages/ohif-core/ui/index.js
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
import './draggable/draggable.js';
|
||||||
|
import './resizable/resizable.js';
|
||||||
@ -11,7 +11,7 @@
|
|||||||
class="form-control js-form-update">
|
class="form-control js-form-update">
|
||||||
{{#each option in allowedValues}}
|
{{#each option in allowedValues}}
|
||||||
<option value="{{option}}"
|
<option value="{{option}}"
|
||||||
selected="{{#if equals selectedOptionValue option}}selected{{/if}}">
|
selected="{{#if eq selectedOptionValue option}}selected{{/if}}">
|
||||||
{{option}}
|
{{option}}
|
||||||
</option>
|
</option>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
|
|||||||
@ -1,10 +0,0 @@
|
|||||||
import { Template } from 'meteor/templating';
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Compares two variables are equal in value
|
|
||||||
*
|
|
||||||
* @returns {boolean}
|
|
||||||
*/
|
|
||||||
Template.registerHelper('equals', function(a, b) {
|
|
||||||
return a === b;
|
|
||||||
});
|
|
||||||
@ -18,7 +18,6 @@ Package.onUse(function(api) {
|
|||||||
api.addFiles('client/helpers/getSchema.js', ['client']);
|
api.addFiles('client/helpers/getSchema.js', ['client']);
|
||||||
api.addFiles('client/helpers/isInvalidKey.js', ['client']);
|
api.addFiles('client/helpers/isInvalidKey.js', ['client']);
|
||||||
api.addFiles('client/helpers/stateDataWithKey.js', ['client']);
|
api.addFiles('client/helpers/stateDataWithKey.js', ['client']);
|
||||||
api.addFiles('client/helpers/equals.js', ['client']);
|
|
||||||
|
|
||||||
api.addFiles('client/components/helpBlock/helpBlock.html', ['client']);
|
api.addFiles('client/components/helpBlock/helpBlock.html', ['client']);
|
||||||
api.addFiles('client/components/helpBlock/helpBlock.js', ['client']);
|
api.addFiles('client/components/helpBlock/helpBlock.js', ['client']);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
toggleCinePlay = function() {
|
toggleCinePlay = function() {
|
||||||
var element = getActiveViewportElement();
|
var element = getActiveViewportElement();
|
||||||
var playClipToolData = cornerstoneTools.getToolState(element, 'playClip');
|
var playClipToolData = cornerstoneTools.getToolState(element, 'playClip');
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Template.gridLayout.helpers({
|
Template.gridLayout.helpers({
|
||||||
height: function() {
|
height: function() {
|
||||||
var rows = this.rows || 1;
|
var rows = this.rows || 1;
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
var allCornerstoneEvents = 'CornerstoneToolsMouseDown CornerstoneToolsMouseDownActivate ' +
|
var allCornerstoneEvents = 'CornerstoneToolsMouseDown CornerstoneToolsMouseDownActivate ' +
|
||||||
'CornerstoneToolsMouseClick CornerstoneToolsMouseDrag CornerstoneToolsMouseUp ' +
|
'CornerstoneToolsMouseClick CornerstoneToolsMouseDrag CornerstoneToolsMouseUp ' +
|
||||||
'CornerstoneToolsMouseWheel CornerstoneToolsTap CornerstoneToolsTouchPress ' +
|
'CornerstoneToolsMouseWheel CornerstoneToolsTap CornerstoneToolsTouchPress ' +
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Meteor.startup(function() {
|
Meteor.startup(function() {
|
||||||
cornerstoneTools.loadHandlerManager.setStartLoadHandler(startLoadingHandler);
|
cornerstoneTools.loadHandlerManager.setStartLoadHandler(startLoadingHandler);
|
||||||
cornerstoneTools.loadHandlerManager.setEndLoadHandler(doneLoadingHandler);
|
cornerstoneTools.loadHandlerManager.setEndLoadHandler(doneLoadingHandler);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
toggleCinePlay = function(element) {
|
toggleCinePlay = function(element) {
|
||||||
var viewports = $('.imageViewerViewport');
|
var viewports = $('.imageViewerViewport');
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
function getDefaultButtonData() {
|
function getDefaultButtonData() {
|
||||||
var buttonData = [];
|
var buttonData = [];
|
||||||
|
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
applyWLPreset = function(presetName, element) {
|
applyWLPreset = function(presetName, element) {
|
||||||
log.info("Applying WL Preset: " + presetName);
|
log.info("Applying WL Preset: " + presetName);
|
||||||
var viewport = cornerstone.getViewport(element);
|
var viewport = cornerstone.getViewport(element);
|
||||||
|
|||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This function disables reference lines for a specific viewport element.
|
* This function disables reference lines for a specific viewport element.
|
||||||
* It also enables reference lines for all other viewports with the
|
* It also enables reference lines for all other viewports with the
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
OHIF = window.OHIF || {};
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
Meteor.startup(function() {
|
Meteor.startup(function() {
|
||||||
|
|
||||||
|
|||||||
@ -1,38 +0,0 @@
|
|||||||
// Return the current template instance
|
|
||||||
Template.registerHelper('instance', () => {
|
|
||||||
return Template.instance();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Return the session value for the given key
|
|
||||||
Template.registerHelper('session', key => {
|
|
||||||
return Session.get(key);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Create a new object and extends it with the argument objects
|
|
||||||
Template.registerHelper('extend', (...argsArray) => {
|
|
||||||
// Create the resulting object
|
|
||||||
const result = {};
|
|
||||||
|
|
||||||
// Extract the Spacebars kw hash
|
|
||||||
const kwHash = _.last(argsArray).hash;
|
|
||||||
|
|
||||||
// Extract the given objects
|
|
||||||
const objects = _.initial(argsArray);
|
|
||||||
|
|
||||||
// Iterate over the given objects
|
|
||||||
_.each(objects, current => {
|
|
||||||
// Stop here if the current argument is not an object
|
|
||||||
if (typeof current !== 'object') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extend the resulting object with the current argument object
|
|
||||||
_.extend(result, current);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Extend the resulting object with the Spacebars kw hash
|
|
||||||
_.extend(result, kwHash);
|
|
||||||
|
|
||||||
// Return the resulting object
|
|
||||||
return result;
|
|
||||||
});
|
|
||||||
@ -1,3 +1,5 @@
|
|||||||
|
import { OHIF } from 'meteor/ohif:core';
|
||||||
|
|
||||||
var activeTool = 'wwwc';
|
var activeTool = 'wwwc';
|
||||||
var defaultTool = 'wwwc';
|
var defaultTool = 'wwwc';
|
||||||
|
|
||||||
|
|||||||
@ -117,9 +117,6 @@ Package.onUse(function(api) {
|
|||||||
api.addFiles('lib/toolManager.js', 'client');
|
api.addFiles('lib/toolManager.js', 'client');
|
||||||
api.addFiles('lib/enablePrefetchOnElement.js', 'client');
|
api.addFiles('lib/enablePrefetchOnElement.js', 'client');
|
||||||
api.addFiles('lib/displayReferenceLines.js', 'client');
|
api.addFiles('lib/displayReferenceLines.js', 'client');
|
||||||
api.addFiles('lib/ui/draggable/draggable.js', 'client');
|
|
||||||
api.addFiles('lib/ui/resizable/resizable.js', 'client');
|
|
||||||
api.addFiles('lib/ui/resizable/resizable.styl', 'client');
|
|
||||||
api.addFiles('lib/toggleDialog.js', 'client');
|
api.addFiles('lib/toggleDialog.js', 'client');
|
||||||
api.addFiles('lib/setActiveViewport.js', 'client');
|
api.addFiles('lib/setActiveViewport.js', 'client');
|
||||||
api.addFiles('lib/switchToImageByIndex.js', 'client');
|
api.addFiles('lib/switchToImageByIndex.js', 'client');
|
||||||
@ -168,7 +165,6 @@ Package.onUse(function(api) {
|
|||||||
api.export('LayoutManager', 'client');
|
api.export('LayoutManager', 'client');
|
||||||
|
|
||||||
// Global objects
|
// Global objects
|
||||||
api.export('OHIF', 'client');
|
|
||||||
api.export('ClientId', 'client');
|
api.export('ClientId', 'client');
|
||||||
|
|
||||||
// Collections
|
// Collections
|
||||||
@ -177,8 +173,6 @@ Package.onUse(function(api) {
|
|||||||
// UI Helpers
|
// UI Helpers
|
||||||
api.addFiles([
|
api.addFiles([
|
||||||
'lib/helpers/formatDA.js',
|
'lib/helpers/formatDA.js',
|
||||||
'lib/helpers/blaze.js',
|
|
||||||
'lib/helpers/logical.js',
|
|
||||||
'lib/helpers/formatJSDate.js',
|
'lib/helpers/formatJSDate.js',
|
||||||
'lib/helpers/jsDateFromNow.js',
|
'lib/helpers/jsDateFromNow.js',
|
||||||
'lib/helpers/formatNumberPrecision.js',
|
'lib/helpers/formatNumberPrecision.js',
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user