LT-253: Added Collection to store Additional Findings in the database. Set up some form components that store temporary UI state
This commit is contained in:
parent
022c534895
commit
40062e2e9d
@ -1,5 +1,6 @@
|
|||||||
accounts-base@1.2.8
|
accounts-base@1.2.8
|
||||||
accounts-password@1.1.13
|
accounts-password@1.1.13
|
||||||
|
aldeed:simple-schema@1.5.3
|
||||||
aldeed:template-extension@4.0.0
|
aldeed:template-extension@4.0.0
|
||||||
allow-deny@1.0.5
|
allow-deny@1.0.5
|
||||||
anti:gagarin@0.4.11
|
anti:gagarin@0.4.11
|
||||||
@ -70,6 +71,7 @@ lesiontracker@0.0.1
|
|||||||
livedata@1.0.18
|
livedata@1.0.18
|
||||||
localstorage@1.0.11
|
localstorage@1.0.11
|
||||||
logging@1.0.14
|
logging@1.0.14
|
||||||
|
mdg:validation-error@0.5.1
|
||||||
meteor@1.1.16
|
meteor@1.1.16
|
||||||
meteor-base@1.0.4
|
meteor-base@1.0.4
|
||||||
meteor-platform@1.2.6
|
meteor-platform@1.2.6
|
||||||
@ -97,6 +99,7 @@ promise@0.7.3
|
|||||||
random@1.0.10
|
random@1.0.10
|
||||||
rate-limit@1.0.5
|
rate-limit@1.0.5
|
||||||
reactive-dict@1.1.8
|
reactive-dict@1.1.8
|
||||||
|
reactive-form-controls@0.0.1
|
||||||
reactive-var@1.0.10
|
reactive-var@1.0.10
|
||||||
reload@1.1.10
|
reload@1.1.10
|
||||||
retry@1.0.8
|
retry@1.0.8
|
||||||
|
|||||||
@ -5,7 +5,7 @@ Package.describe({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Package.onUse(function(api) {
|
Package.onUse(function(api) {
|
||||||
api.versionsFrom('1.2.0.2');
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
api.use('jquery');
|
api.use('jquery');
|
||||||
api.use('dicomweb');
|
api.use('dicomweb');
|
||||||
|
|||||||
@ -5,7 +5,7 @@ Package.describe({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Package.onUse(function(api) {
|
Package.onUse(function(api) {
|
||||||
api.versionsFrom('1.2.1');
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
api.use('ecmascript');
|
api.use('ecmascript');
|
||||||
api.use('standard-app-packages');
|
api.use('standard-app-packages');
|
||||||
|
|||||||
@ -5,7 +5,7 @@ Package.describe({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Package.onUse(function(api) {
|
Package.onUse(function(api) {
|
||||||
api.versionsFrom('1.2.1');
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
api.use('standard-app-packages');
|
api.use('standard-app-packages');
|
||||||
api.use('ecmascript');
|
api.use('ecmascript');
|
||||||
|
|||||||
@ -1,7 +1,14 @@
|
|||||||
Timepoints = new Meteor.Collection('timepoints');
|
Timepoints = new Meteor.Collection('timepoints');
|
||||||
Studies = new Meteor.Collection('studies');
|
Studies = new Meteor.Collection('studies');
|
||||||
Measurements = new Meteor.Collection('measurements');
|
Measurements = new Meteor.Collection('measurements');
|
||||||
|
|
||||||
|
// ImageMeasurements describe temporary measurements that aren't
|
||||||
|
// specifically listed in the Lesion Table
|
||||||
ImageMeasurements = new Meteor.Collection('imageMeasurements');
|
ImageMeasurements = new Meteor.Collection('imageMeasurements');
|
||||||
|
|
||||||
|
// Additional Findings stores details from the Additional Findings
|
||||||
|
// panel, and represents items such as data quality,
|
||||||
|
AdditionalFindings = new Meteor.Collection('additionalFindings');
|
||||||
|
|
||||||
WorklistSubscriptions = ['studies', 'timepoints'];
|
WorklistSubscriptions = ['studies', 'timepoints'];
|
||||||
Reviewers = new Meteor.Collection('reviewers');
|
Reviewers = new Meteor.Collection('reviewers');
|
||||||
|
|||||||
58
Packages/lesiontracker/both/schema/additionalFinding.js
Normal file
58
Packages/lesiontracker/both/schema/additionalFinding.js
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
import { SimpleSchema } from 'meteor/aldeed:simple-schema';
|
||||||
|
|
||||||
|
SimpleSchema.extendOptions({
|
||||||
|
allowedSelect2Values: Match.Optional(Array),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const AdditionalFinding = new SimpleSchema({
|
||||||
|
measurableDisease: {
|
||||||
|
type: String,
|
||||||
|
label: 'Measurable Disease',
|
||||||
|
allowedValues: ['Present', 'Absent'],
|
||||||
|
defaultValue: 'Absent',
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
// TODO: Add check so that the value cannot be None & something other region
|
||||||
|
regionsOfMetastaticDisease: {
|
||||||
|
type: [String],
|
||||||
|
label: 'Regions of Metastatic Disease',
|
||||||
|
allowedSelect2Values: ['None', 'Lymph Node'], // allowedValues doesn't seem show up in the Schema since this is an Array. There may be a better way to do this
|
||||||
|
defaultValue: ['None'],
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
tracerRelatedToMetastaticDisease: {
|
||||||
|
type: String,
|
||||||
|
label: 'Tracer Related to Metastatic Disease?',
|
||||||
|
allowedValues: ['Yes', 'No'],
|
||||||
|
defaultValue: 'Yes',
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
numberOfBoneLesions: {
|
||||||
|
type: String,
|
||||||
|
label: 'Number of Bone Lesions',
|
||||||
|
allowedValues: ['0', '1-2', '2-4', '>5'],
|
||||||
|
defaultValue: '0',
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
acceptableImageQuality: {
|
||||||
|
type: String,
|
||||||
|
label: 'Acceptable Image Quality',
|
||||||
|
allowedValues: ['Yes', 'No'],
|
||||||
|
defaultValue: 'Yes',
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
adequateAnatomicalCoverage: {
|
||||||
|
type: String,
|
||||||
|
label: 'Adequate Anatomical Coverage',
|
||||||
|
allowedValues: ['Yes', 'No'],
|
||||||
|
defaultValue: 'Yes',
|
||||||
|
optional: true
|
||||||
|
},
|
||||||
|
presenceOfContrast: {
|
||||||
|
type: String,
|
||||||
|
label: 'Presence of Contrast',
|
||||||
|
allowedValues: ['Yes', 'No'],
|
||||||
|
defaultValue: 'Yes',
|
||||||
|
optional: true
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -1,48 +1,34 @@
|
|||||||
<template name="additionalMeasurements">
|
<template name="additionalFindings">
|
||||||
<div id="additionalMeasurements">
|
<div class="additionalFindings">
|
||||||
<div class="scrollArea">
|
<div class="scrollArea">
|
||||||
<div class="section">
|
<div class="row">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
Additional Findings: Baseline
|
Additional Findings: Baseline
|
||||||
</div>
|
</div>
|
||||||
<div>
|
{{> radioOptionGroup (stateDataWithKey "measurableDisease")}}
|
||||||
{{ >radioOptionGroup measurableDiseaseButtonData}}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="row">
|
||||||
<div class="section">
|
|
||||||
<div class="header">
|
<div class="header">
|
||||||
Supplementary Measurements
|
Supplementary Measurements
|
||||||
</div>
|
</div>
|
||||||
<div class="entrySection">
|
{{> selectInput (stateDataWithKey "numberOfBoneLesions")}}
|
||||||
<label>Number of bone lesions</label>
|
{{> select2Input
|
||||||
<div>
|
key="regionsOfMetastaticDisease"
|
||||||
<select>
|
select2Options=regionsOfMetastaticDiseaseSelect2Options
|
||||||
<option>0</option>
|
state=state
|
||||||
<option>1-2</option>
|
currentSchema=currentSchema
|
||||||
<option selected>2-4</option>
|
}}
|
||||||
<option>>5</option>
|
{{> radioOptionGroup (stateDataWithKey "tracerRelatedToMetastaticDisease")}}
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="entrySection">
|
|
||||||
<label>Regions of metastatic disease</label>
|
|
||||||
<select id="regionsOfMetastaticDisease">
|
|
||||||
<option>None</option>
|
|
||||||
<option>Lymph node</option>
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
{{ >radioOptionGroup metastaticDiseaseButtonData}}
|
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="row">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
Image Quality
|
Image Quality
|
||||||
</div>
|
</div>
|
||||||
{{ >radioOptionGroup imageQualityButtonData}}
|
{{> radioOptionGroup (stateDataWithKey "acceptableImageQuality")}}
|
||||||
{{ >radioOptionGroup anatomicalCoverageButtonData}}
|
{{> radioOptionGroup (stateDataWithKey "adequateAnatomicalCoverage")}}
|
||||||
{{ >radioOptionGroup presenceOfContrastButtonData}}
|
{{> radioOptionGroup (stateDataWithKey "presenceOfContrast")}}
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="row">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
Additional Screen Captures
|
Additional Screen Captures
|
||||||
</div>
|
</div>
|
||||||
@ -57,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="section">
|
<div class="row">
|
||||||
<div class="header">
|
<div class="header">
|
||||||
Comments
|
Comments
|
||||||
</div>
|
</div>
|
||||||
@ -0,0 +1,82 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
import { ReactiveDict } from 'meteor/reactive-dict';
|
||||||
|
|
||||||
|
// 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() {
|
||||||
|
console.log('additionalFindingsOnCreated');
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
instance.currentSchema = AdditionalFinding;
|
||||||
|
instance.state = new ReactiveDict();
|
||||||
|
|
||||||
|
if (!instance.data.currentTimepointId) {
|
||||||
|
console.warn('Case has no timepointId');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const currentTimepointId = instance.data.currentTimepointId;
|
||||||
|
if (!currentTimepointId) {
|
||||||
|
console.warn('No currentTimepointId');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log(AdditionalFindings.find().fetch());
|
||||||
|
const additionalFindings = AdditionalFindings.findOne({
|
||||||
|
timepointId: currentTimepointId
|
||||||
|
});
|
||||||
|
|
||||||
|
if (additionalFindings) {
|
||||||
|
instance.id = additionalFindings._id;
|
||||||
|
|
||||||
|
// Don't store the MongoDB Id in the ReactiveDict
|
||||||
|
delete additionalFindings._id;
|
||||||
|
|
||||||
|
instance.state.set(additionalFindings);
|
||||||
|
} else {
|
||||||
|
const defaultData = instance.currentSchema.clean({});
|
||||||
|
instance.state.set(defaultData);
|
||||||
|
|
||||||
|
// Include patientId and timepointId
|
||||||
|
defaultData.patientId = Session.get('patientId');
|
||||||
|
defaultData.timepointId = currentTimepointId;
|
||||||
|
|
||||||
|
// TODO: Turn this into a Meteor Call to insert it on the server
|
||||||
|
instance.id = AdditionalFindings.insert(defaultData);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.additionalFindings.onRendered(function additionalFindingsOnRendered() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
instance.autorun(() => {
|
||||||
|
console.log('Updating AdditionalFindings Collection');
|
||||||
|
console.log(instance.state.all());
|
||||||
|
|
||||||
|
// TODO: Turn this into a Meteor Call to update it on the server
|
||||||
|
let update = instance.state.all();
|
||||||
|
AdditionalFindings.update(instance.id, {
|
||||||
|
$set: update
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.additionalFindings.helpers({
|
||||||
|
// We need these helper methods
|
||||||
|
// since we assign them into instance object instead of instance.data
|
||||||
|
currentSchema() {
|
||||||
|
return Template.instance().currentSchema;
|
||||||
|
},
|
||||||
|
|
||||||
|
state() {
|
||||||
|
return Template.instance().state;
|
||||||
|
},
|
||||||
|
|
||||||
|
regionsOfMetastaticDiseaseSelect2Options() {
|
||||||
|
return {
|
||||||
|
placeholder: 'Search Regions',
|
||||||
|
allowClear: true,
|
||||||
|
multiple: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -1,6 +1,6 @@
|
|||||||
@import "{design}/app"
|
@import "{design}/app"
|
||||||
|
|
||||||
#additionalMeasurements
|
.additionalFindings
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
background-color: #000000
|
background-color: #000000
|
||||||
@ -15,6 +15,10 @@
|
|||||||
|
|
||||||
-webkit-overflow-scrolling: touch
|
-webkit-overflow-scrolling: touch
|
||||||
|
|
||||||
|
.row
|
||||||
|
margin-right: 0
|
||||||
|
margin-left: 0
|
||||||
|
|
||||||
&::-webkit-scrollbar
|
&::-webkit-scrollbar
|
||||||
display: none
|
display: none
|
||||||
|
|
||||||
@ -27,7 +31,47 @@
|
|||||||
color: $textPrimaryColor
|
color: $textPrimaryColor
|
||||||
background-color: $uiGrayDarker
|
background-color: $uiGrayDarker
|
||||||
|
|
||||||
.entrySection
|
.form-group
|
||||||
|
padding: 10px
|
||||||
|
color: $textPrimaryColor
|
||||||
|
|
||||||
|
&:not(:last-child)
|
||||||
|
border-bottom: $uiBorderThickness solid $uiBorderColorDark
|
||||||
|
|
||||||
|
h5
|
||||||
|
font-weight: 300
|
||||||
|
|
||||||
|
label
|
||||||
|
font-size: 14px
|
||||||
|
font-weight: 100
|
||||||
|
display: inline-block
|
||||||
|
padding: 5px
|
||||||
|
|
||||||
|
.radio-group
|
||||||
|
height: 30px
|
||||||
|
|
||||||
|
.radio-option
|
||||||
|
width: 50%
|
||||||
|
text-align: center
|
||||||
|
float: left
|
||||||
|
display: inline-block
|
||||||
|
padding: 5px
|
||||||
|
height: 30px
|
||||||
|
|
||||||
|
input
|
||||||
|
float: left
|
||||||
|
height: 30px
|
||||||
|
width: 30px
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
|
label
|
||||||
|
float: left
|
||||||
|
height: 30px
|
||||||
|
line-height: 30px
|
||||||
|
font-size: 14px
|
||||||
|
font-weight: 100
|
||||||
|
display: inline-block
|
||||||
|
|
||||||
#regionsOfMetastaticDisease
|
#regionsOfMetastaticDisease
|
||||||
width: 285px
|
width: 285px
|
||||||
height: 30px
|
height: 30px
|
||||||
@ -1,87 +0,0 @@
|
|||||||
var yesNoOptions = [{
|
|
||||||
key: 'yes',
|
|
||||||
text: 'Yes'
|
|
||||||
}, {
|
|
||||||
key: 'no',
|
|
||||||
text: 'No'
|
|
||||||
}];
|
|
||||||
|
|
||||||
Template.additionalMeasurements.onCreated(function additionalMeasurementsOnCreated() {
|
|
||||||
const instance = this;
|
|
||||||
|
|
||||||
instance.measurableDisease = new ReactiveVar();
|
|
||||||
instance.numberOfBoneLesions = new ReactiveVar();
|
|
||||||
instance.regionsOfMetastaticDisease = new ReactiveVar();
|
|
||||||
instance.tracerRelatedToMetastaticDisease = new ReactiveVar();
|
|
||||||
instance.acceptableImageQuality = new ReactiveVar();
|
|
||||||
instance.adequateAnatomicalCoverage = new ReactiveVar();
|
|
||||||
instance.presenceOfContrast = new ReactiveVar();
|
|
||||||
instance.phaseOfContrast = new ReactiveVar();
|
|
||||||
|
|
||||||
instance.measurableDisease.set('absent');
|
|
||||||
instance.tracerRelatedToMetastaticDisease.set('no');
|
|
||||||
instance.acceptableImageQuality.set('yes');
|
|
||||||
instance.adequateAnatomicalCoverage.set('yes');
|
|
||||||
instance.presenceOfContrast.set('yes');
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.additionalMeasurements.onRendered(function additionalMeasurementsOnRendered() {
|
|
||||||
const instance = this;
|
|
||||||
|
|
||||||
instance.$("#regionsOfMetastaticDisease").select2({
|
|
||||||
multiple: true
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.additionalMeasurements.helpers({
|
|
||||||
measurableDiseaseButtonData() {
|
|
||||||
const instance = Template.instance();
|
|
||||||
return {
|
|
||||||
text: 'Measurable disease',
|
|
||||||
value: instance.measurableDisease,
|
|
||||||
options: [{
|
|
||||||
key: 'present',
|
|
||||||
text: 'Present'
|
|
||||||
}, {
|
|
||||||
key: 'absent',
|
|
||||||
text: 'Absent'
|
|
||||||
}]
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
metastaticDiseaseButtonData() {
|
|
||||||
const instance = Template.instance();
|
|
||||||
return {
|
|
||||||
text: 'Tracer related to metastatic disease',
|
|
||||||
value: instance.tracerRelatedToMetastaticDisease,
|
|
||||||
options: yesNoOptions
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
imageQualityButtonData() {
|
|
||||||
const instance = Template.instance();
|
|
||||||
return {
|
|
||||||
text: 'Acceptable image quality',
|
|
||||||
value: instance.acceptableImageQuality,
|
|
||||||
options: yesNoOptions
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
anatomicalCoverageButtonData() {
|
|
||||||
const instance = Template.instance();
|
|
||||||
return {
|
|
||||||
text: 'Adequate anatomical coverage',
|
|
||||||
value: instance.adequateAnatomicalCoverage,
|
|
||||||
options: yesNoOptions
|
|
||||||
};
|
|
||||||
},
|
|
||||||
|
|
||||||
presenceOfContrastButtonData() {
|
|
||||||
const instance = Template.instance();
|
|
||||||
return {
|
|
||||||
text: 'Presence of contrast',
|
|
||||||
value: instance.presenceOfContrast,
|
|
||||||
options: yesNoOptions
|
|
||||||
};
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -1,16 +0,0 @@
|
|||||||
<template name="radioOptionGroup">
|
|
||||||
<div class="{{class}} entrySection viewerRadioOptionGroup">
|
|
||||||
<h5>{{text}}</h5>
|
|
||||||
<div>
|
|
||||||
{{#each item in this.options}}
|
|
||||||
<label>
|
|
||||||
<input type="radio"
|
|
||||||
name="{{item.key}}"
|
|
||||||
data-key="{{item.key}}"
|
|
||||||
{{inlineIf value.get item.key 'selected'}}/>
|
|
||||||
{{item.text}}
|
|
||||||
</label>
|
|
||||||
{{/each}}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
@ -1,15 +0,0 @@
|
|||||||
Template.radioOptionGroup.onRendered(() => {
|
|
||||||
const instance = Template.instance();
|
|
||||||
const value = instance.data.value;
|
|
||||||
if (!value.get()) {
|
|
||||||
value.set(instance.data.options[0].key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
Template.radioOptionGroup.events({
|
|
||||||
'click [data-key]'(event, instance) {
|
|
||||||
const $element = $(event.currentTarget);
|
|
||||||
const key = $element.attr('data-key');
|
|
||||||
instance.data.value.set(key);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
@import "{design}/app"
|
|
||||||
|
|
||||||
.entrySection
|
|
||||||
padding: 10px
|
|
||||||
color: $textPrimaryColor
|
|
||||||
|
|
||||||
&:not(:last-child)
|
|
||||||
border-bottom: $uiBorderThickness solid $uiBorderColorDark
|
|
||||||
|
|
||||||
h5
|
|
||||||
font-weight: 300
|
|
||||||
|
|
||||||
label
|
|
||||||
font-size: 14px
|
|
||||||
font-weight: 100
|
|
||||||
display: inline-block
|
|
||||||
padding: 5px
|
|
||||||
|
|
||||||
input
|
|
||||||
margin: 5px
|
|
||||||
@ -6,12 +6,12 @@
|
|||||||
<div class="mainContent {{#if leftSidebarOpen}}sidebar-left-open{{/if}} {{#if rightSidebarOpen}}sidebar-right-open{{/if}}">
|
<div class="mainContent {{#if leftSidebarOpen}}sidebar-left-open{{/if}} {{#if rightSidebarOpen}}sidebar-right-open{{/if}}">
|
||||||
{{>viewerMain}}
|
{{>viewerMain}}
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebarMenu sidebar-right {{#if or lesionSidebarOpen additionalMeasurementsSidebarOpen}}sidebar-open{{/if}}">
|
<div class="sidebarMenu sidebar-right {{#if or lesionSidebarOpen additionalFindingsSidebarOpen}}sidebar-open{{/if}}">
|
||||||
<div class="sidebar-option {{#if lesionSidebarOpen}}active{{/if}}">
|
<div class="sidebar-option {{#if lesionSidebarOpen}}active{{/if}}">
|
||||||
{{>lesionTable (extend this)}}
|
{{>lesionTable (extend this)}}
|
||||||
</div>
|
</div>
|
||||||
<div class="sidebar-option {{#if additionalMeasurementsSidebarOpen}}active{{/if}}">
|
<div class="sidebar-option {{#if additionalFindingsSidebarOpen}}active{{/if}}">
|
||||||
{{>additionalMeasurements (extend this)}}
|
{{>additionalFindings (extend this)}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -17,7 +17,7 @@ Template.flexboxLayout.helpers({
|
|||||||
return Template.instance().data.state.get('rightSidebar') === 'lesions';
|
return Template.instance().data.state.get('rightSidebar') === 'lesions';
|
||||||
},
|
},
|
||||||
|
|
||||||
additionalMeasurementsSidebarOpen() {
|
additionalFindingsSidebarOpen() {
|
||||||
return Template.instance().data.state.get('rightSidebar') === 'additional';
|
return Template.instance().data.state.get('rightSidebar') === 'additional';
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
@ -4,7 +4,7 @@
|
|||||||
display: flex
|
display: flex
|
||||||
flex-flow: row nowrap
|
flex-flow: row nowrap
|
||||||
align-items: stretch
|
align-items: stretch
|
||||||
height: 100%
|
height: calc(100% - 78px);
|
||||||
width: 100%
|
width: 100%
|
||||||
|
|
||||||
.sidebarMenu
|
.sidebarMenu
|
||||||
|
|||||||
@ -34,33 +34,11 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
|
|
||||||
<div class="toolbarSectionEntry pull-right rm-l-1 p-x-1">
|
<div class="toolbarSectionEntry pull-right rm-l-1 p-x-1">
|
||||||
{{ >caseProgress }}
|
{{> caseProgress }}
|
||||||
</div>
|
</div>
|
||||||
<div class="pull-right m-t-1 rm-x-1">
|
<div class="pull-right m-t-1 rm-x-1">
|
||||||
{{>roundedButtonGroup rightSidebarToggleButtonData}}
|
{{>roundedButtonGroup rightSidebarToggleButtonData}}
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="capsule-group pull-right">
|
|
||||||
<div id="lesionSidebarToggle" class="capsule-entry">
|
|
||||||
<div class="svgContainer capsule">
|
|
||||||
<svg>
|
|
||||||
<use xlink:href="/packages/lesiontracker/assets/icons.svg#icon-measurements-lesions"></use>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="buttonLabel">
|
|
||||||
Lesions
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="additionalMeasurementsSidebarToggle" class="capsule-entry">
|
|
||||||
<div class="svgContainer capsule">
|
|
||||||
<svg>
|
|
||||||
<use xlink:href="/packages/lesiontracker/assets/icons.svg#icon-measurements-additional"></use>
|
|
||||||
</svg>
|
|
||||||
</div>
|
|
||||||
<div class="buttonLabel">
|
|
||||||
Additional
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div> -->
|
|
||||||
<div id="toggleHUD" class="toolbarSectionButton pull-right rp-x-1 m-t-1 rm-r-3">
|
<div id="toggleHUD" class="toolbarSectionButton pull-right rp-x-1 m-t-1 rm-r-3">
|
||||||
<div class="svgContainer">
|
<div class="svgContainer">
|
||||||
<svg>
|
<svg>
|
||||||
|
|||||||
@ -127,6 +127,7 @@ Template.viewer.onCreated(function() {
|
|||||||
instance.subscribe('singlePatientTimepoints', dataContext.studies[0].patientId);
|
instance.subscribe('singlePatientTimepoints', dataContext.studies[0].patientId);
|
||||||
instance.subscribe('singlePatientMeasurements', dataContext.studies[0].patientId);
|
instance.subscribe('singlePatientMeasurements', dataContext.studies[0].patientId);
|
||||||
instance.subscribe('singlePatientImageMeasurements', dataContext.studies[0].patientId);
|
instance.subscribe('singlePatientImageMeasurements', dataContext.studies[0].patientId);
|
||||||
|
instance.subscribe('singlePatientAdditionalFindings', dataContext.studies[0].patientId);
|
||||||
|
|
||||||
var subscriptionsReady = instance.subscriptionsReady();
|
var subscriptionsReady = instance.subscriptionsReady();
|
||||||
log.info('autorun viewer.js. Ready: ' + subscriptionsReady);
|
log.info('autorun viewer.js. Ready: ' + subscriptionsReady);
|
||||||
|
|||||||
@ -5,7 +5,7 @@ Package.describe({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Package.onUse(function(api) {
|
Package.onUse(function(api) {
|
||||||
api.versionsFrom('1.2.0.2');
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
api.use('ecmascript');
|
api.use('ecmascript');
|
||||||
api.use('standard-app-packages');
|
api.use('standard-app-packages');
|
||||||
@ -15,6 +15,9 @@ Package.onUse(function(api) {
|
|||||||
|
|
||||||
api.use('validatejs');
|
api.use('validatejs');
|
||||||
|
|
||||||
|
// Schema for Data Models
|
||||||
|
api.use('aldeed:simple-schema');
|
||||||
|
|
||||||
// Control over logging
|
// Control over logging
|
||||||
api.use('practicalmeteor:loglevel');
|
api.use('practicalmeteor:loglevel');
|
||||||
|
|
||||||
@ -24,12 +27,16 @@ Package.onUse(function(api) {
|
|||||||
// Template overriding
|
// Template overriding
|
||||||
api.use('aldeed:template-extension@4.0.0');
|
api.use('aldeed:template-extension@4.0.0');
|
||||||
|
|
||||||
// Our custom package
|
// Our custom packages
|
||||||
api.use('worklist');
|
api.use('worklist');
|
||||||
api.use('cornerstone');
|
api.use('cornerstone');
|
||||||
|
api.use('reactive-form-controls');
|
||||||
|
|
||||||
api.addFiles('log.js', [ 'client', 'server' ]);
|
api.addFiles('log.js', [ 'client', 'server' ]);
|
||||||
|
|
||||||
|
// Schema
|
||||||
|
api.addFiles('both/schema/additionalFinding.js', [ 'client', 'server' ]);
|
||||||
|
|
||||||
// Client-side collections
|
// Client-side collections
|
||||||
api.addFiles('client/collections/LesionLocations.js', 'client');
|
api.addFiles('client/collections/LesionLocations.js', 'client');
|
||||||
api.addFiles('client/collections/LocationResponses.js', 'client');
|
api.addFiles('client/collections/LocationResponses.js', 'client');
|
||||||
@ -86,13 +93,9 @@ Package.onUse(function(api) {
|
|||||||
|
|
||||||
api.addFiles('client/components/lesionTrackerLayout/lesionTrackerLayout.html', 'client');
|
api.addFiles('client/components/lesionTrackerLayout/lesionTrackerLayout.html', 'client');
|
||||||
|
|
||||||
api.addFiles('client/components/additionalMeasurements/additionalMeasurements.html', 'client');
|
api.addFiles('client/components/additionalFindings/additionalFindings.html', 'client');
|
||||||
api.addFiles('client/components/additionalMeasurements/additionalMeasurements.styl', 'client');
|
api.addFiles('client/components/additionalFindings/additionalFindings.styl', 'client');
|
||||||
api.addFiles('client/components/additionalMeasurements/additionalMeasurements.js', 'client');
|
api.addFiles('client/components/additionalFindings/additionalFindings.js', 'client');
|
||||||
|
|
||||||
api.addFiles('client/components/additionalMeasurements/radioOptionGroup/radioOptionGroup.html', 'client');
|
|
||||||
api.addFiles('client/components/additionalMeasurements/radioOptionGroup/radioOptionGroup.styl', 'client');
|
|
||||||
api.addFiles('client/components/additionalMeasurements/radioOptionGroup/radioOptionGroup.js', 'client');
|
|
||||||
|
|
||||||
api.addFiles('client/components/studySeriesQuickSwitch/studySeriesQuickSwitch.html', 'client');
|
api.addFiles('client/components/studySeriesQuickSwitch/studySeriesQuickSwitch.html', 'client');
|
||||||
api.addFiles('client/components/studySeriesQuickSwitch/studySeriesQuickSwitch.styl', 'client');
|
api.addFiles('client/components/studySeriesQuickSwitch/studySeriesQuickSwitch.styl', 'client');
|
||||||
@ -279,6 +282,7 @@ Package.onUse(function(api) {
|
|||||||
api.export('TrialCriteriaTypes', 'client');
|
api.export('TrialCriteriaTypes', 'client');
|
||||||
|
|
||||||
// Export collections spanning both client and server
|
// Export collections spanning both client and server
|
||||||
|
api.export('AdditionalFindings', [ 'client', 'server' ]);
|
||||||
api.export('ImageMeasurements', [ 'client', 'server' ]);
|
api.export('ImageMeasurements', [ 'client', 'server' ]);
|
||||||
api.export('Measurements', [ 'client', 'server' ]);
|
api.export('Measurements', [ 'client', 'server' ]);
|
||||||
api.export('Studies', [ 'client', 'server' ]);
|
api.export('Studies', [ 'client', 'server' ]);
|
||||||
|
|||||||
@ -30,11 +30,20 @@ Meteor.publish('singlePatientImageMeasurements', function(patientId) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Meteor.publish('additionalFindings', function() {
|
||||||
|
return AdditionalFindings.find();
|
||||||
|
});
|
||||||
|
|
||||||
|
Meteor.publish('singlePatientAdditionalFindings', function(patientId) {
|
||||||
|
return AdditionalFindings.find({
|
||||||
|
patientId: patientId
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
Meteor.publish('reviewers', function() {
|
Meteor.publish('reviewers', function() {
|
||||||
return Reviewers.find();
|
return Reviewers.find();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Temporary fix to drop all Collections on server restart
|
// Temporary fix to drop all Collections on server restart
|
||||||
// http://stackoverflow.com/questions/23891631/meteor-how-can-i-drop-all-mongo-collections-and-clear-all-data-on-startup
|
// http://stackoverflow.com/questions/23891631/meteor-how-can-i-drop-all-mongo-collections-and-clear-all-data-on-startup
|
||||||
Meteor.startup(function() {
|
Meteor.startup(function() {
|
||||||
|
|||||||
@ -0,0 +1,7 @@
|
|||||||
|
<template name="helpBlock">
|
||||||
|
{{#if isInvalidKey key}}
|
||||||
|
<span class="help-block m-b-none">
|
||||||
|
{{invalidKeyMessage key}}
|
||||||
|
</span>
|
||||||
|
{{/if}}
|
||||||
|
</template>
|
||||||
@ -0,0 +1,10 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
import './helpBlock.html';
|
||||||
|
|
||||||
|
Template.helpBlock.onCreated(function helpBlockOnCreated() {
|
||||||
|
var instance = this;
|
||||||
|
|
||||||
|
// Invalid keys comes from Trials schema
|
||||||
|
instance.invalidKeys = this.data.invalidKeys;
|
||||||
|
});
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<template name="radioOptionGroup">
|
||||||
|
<div class="{{class}} form-group">
|
||||||
|
{{ #with getSchema key }}
|
||||||
|
<h5>{{label}}</h5>
|
||||||
|
<div class="radio-group">
|
||||||
|
{{#each option in allowedValues}}
|
||||||
|
<div class="radio-option">
|
||||||
|
<input type="radio"
|
||||||
|
id="{{../key}}_{{option}}"
|
||||||
|
name="{{../key}}"
|
||||||
|
value="{{option}}"
|
||||||
|
class="form-control js-form-update"
|
||||||
|
{{inlineIf value option 'checked'}}/>
|
||||||
|
<label for="{{../key}}_{{option}}">
|
||||||
|
{{option}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
{{ /with }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,40 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
import './radioOptionGroup.html';
|
||||||
|
|
||||||
|
Template.radioOptionGroup.onCreated(function radioOptionGroupOnCreated() {
|
||||||
|
let instance = this;
|
||||||
|
|
||||||
|
instance.currentSchema = this.data.currentSchema;
|
||||||
|
|
||||||
|
// Here we set this Template instance's state property to equal the input state data
|
||||||
|
// The purpose of this is to make our helpers and events more consistent across templates.
|
||||||
|
instance.state = this.data.state;
|
||||||
|
|
||||||
|
// Invalid keys comes from Trials schema
|
||||||
|
instance.invalidKeys = this.data.invalidKeys;
|
||||||
|
|
||||||
|
// Validation Context of registrationWorkflow
|
||||||
|
instance.validationContext = this.data.validationContext;
|
||||||
|
|
||||||
|
// isModified records whether or not the user has unsaved changes
|
||||||
|
instance.isModified = this.data.isModified;
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.radioOptionGroup.events({
|
||||||
|
'change .js-form-update'(event, instance) {
|
||||||
|
const value = event.currentTarget.value;
|
||||||
|
const key = instance.data.key;
|
||||||
|
if (event.currentTarget.checked) {
|
||||||
|
instance.state.set(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.radioOptionGroup.helpers({
|
||||||
|
value() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
const key = instance.data.key;
|
||||||
|
return instance.state.get(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,22 @@
|
|||||||
|
<template name="select2Input">
|
||||||
|
<div class="form-group {{#if isInvalidKey key}}has-error{{/if}}">
|
||||||
|
<label class="control-label">
|
||||||
|
{{#with getSchema key }}
|
||||||
|
{{label}}
|
||||||
|
{{/with }}
|
||||||
|
</label>
|
||||||
|
<div>
|
||||||
|
<select id="{{key}}"
|
||||||
|
name="{{key}}"
|
||||||
|
required="{{isRequired}}"
|
||||||
|
class="form-control js-form-update">
|
||||||
|
{{#each option in options}}
|
||||||
|
<option value="{{option.id}}">
|
||||||
|
{{option.text}}
|
||||||
|
</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
{{> helpBlock}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,80 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
import './select2Input.html';
|
||||||
|
|
||||||
|
Template.select2Input.onCreated(function selectInputOnCreated() {
|
||||||
|
let instance = this;
|
||||||
|
|
||||||
|
instance.currentSchema = this.data.currentSchema;
|
||||||
|
|
||||||
|
// Here we set this Template instance's state property to equal the input state data
|
||||||
|
// The purpose of this is to make our helpers and events more consistent across templates.
|
||||||
|
instance.state = this.data.state;
|
||||||
|
|
||||||
|
// Invalid keys comes from Trials schema
|
||||||
|
instance.invalidKeys = this.data.invalidKeys;
|
||||||
|
|
||||||
|
// Validation Context of registrationWorkflow
|
||||||
|
instance.validationContext = this.data.validationContext;
|
||||||
|
|
||||||
|
// isModified records whether or not the user has unsaved changes
|
||||||
|
instance.isModified = this.data.isModified;
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.select2Input.onRendered(function select2InputOnRendered() {
|
||||||
|
const instance = this;
|
||||||
|
|
||||||
|
Meteor.defer(function() {
|
||||||
|
// Initialize select2 box
|
||||||
|
const selectBox = instance.$('select');
|
||||||
|
selectBox.select2(instance.data.select2Options);
|
||||||
|
|
||||||
|
// Set selected value(s) from current state;
|
||||||
|
const key = instance.data.key;
|
||||||
|
const value = instance.state.get(key);
|
||||||
|
if (value) {
|
||||||
|
selectBox.val(value).trigger('change');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.select2Input.helpers({
|
||||||
|
options() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
if (instance.data.options) {
|
||||||
|
return instance.data.options;
|
||||||
|
}
|
||||||
|
|
||||||
|
const key = instance.data.key;
|
||||||
|
const schema = instance.currentSchema.schema(key);
|
||||||
|
const allowedValues = schema.allowedSelect2Values;
|
||||||
|
return allowedValues.map((value) => {
|
||||||
|
return {
|
||||||
|
id: value,
|
||||||
|
text: value
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.select2Input.events({
|
||||||
|
'focus .select2'(event, instance) {
|
||||||
|
var control = event.currentTarget;
|
||||||
|
|
||||||
|
// Find select element that is assigned to select2
|
||||||
|
var hiddenSelect2Box = $(control).prev('select');
|
||||||
|
|
||||||
|
// Prevent auto open for select2 boxes that has multiple attribute
|
||||||
|
if (!hiddenSelect2Box || $(hiddenSelect2Box).prop('multiple')) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$(hiddenSelect2Box).select2('open');
|
||||||
|
},
|
||||||
|
|
||||||
|
'change .js-form-update'(event, instance) {
|
||||||
|
const value = $(event.currentTarget).val();
|
||||||
|
const key = instance.data.key;
|
||||||
|
instance.state.set(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
<template name="selectInput">
|
||||||
|
<div class="form-group {{#if isInvalidKey key}}has-error{{/if}}">
|
||||||
|
{{ #with getSchema key }}
|
||||||
|
<label class="control-label">
|
||||||
|
{{label}}
|
||||||
|
</label>
|
||||||
|
<div>
|
||||||
|
<select id="{{../key}}"
|
||||||
|
name="{{../key}}"
|
||||||
|
required="{{isRequired}}"
|
||||||
|
class="form-control js-form-update">
|
||||||
|
{{#each option in allowedValues}}
|
||||||
|
<option value="{{option}}"
|
||||||
|
selected="{{#if equals selectedOptionValue option}}selected{{/if}}">
|
||||||
|
{{option}}
|
||||||
|
</option>
|
||||||
|
{{/each}}
|
||||||
|
</select>
|
||||||
|
{{> helpBlock }}
|
||||||
|
</div>
|
||||||
|
{{ /with }}
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@ -0,0 +1,38 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
import './selectInput.html';
|
||||||
|
|
||||||
|
Template.selectInput.onCreated(function selectInputOnCreated() {
|
||||||
|
let instance = this;
|
||||||
|
|
||||||
|
instance.currentSchema = this.data.currentSchema;
|
||||||
|
|
||||||
|
// Here we set this Template instance's state property to equal the input state data
|
||||||
|
// The purpose of this is to make our helpers and events more consistent across templates.
|
||||||
|
instance.state = this.data.state;
|
||||||
|
|
||||||
|
// Invalid keys comes from Trials schema
|
||||||
|
instance.invalidKeys = this.data.invalidKeys;
|
||||||
|
|
||||||
|
// Validation Context of registrationWorkflow
|
||||||
|
instance.validationContext = this.data.validationContext;
|
||||||
|
|
||||||
|
// isModified records whether or not the user has unsaved changes
|
||||||
|
instance.isModified = this.data.isModified;
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.selectInput.helpers({
|
||||||
|
selectedOptionValue() {
|
||||||
|
const instance = Template.instance();
|
||||||
|
var key = instance.data.key;
|
||||||
|
return instance.state.get(key);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Template.selectInput.events({
|
||||||
|
'change .js-form-update'(event, instance) {
|
||||||
|
const value = $(event.currentTarget).val();
|
||||||
|
const key = instance.data.key;
|
||||||
|
instance.state.set(key, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
10
Packages/reactive-form-controls/client/helpers/equals.js
Normal file
10
Packages/reactive-form-controls/client/helpers/equals.js
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compares two variables are equal in value
|
||||||
|
*
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
Template.registerHelper('equals', function(a, b) {
|
||||||
|
return a === b;
|
||||||
|
});
|
||||||
14
Packages/reactive-form-controls/client/helpers/getSchema.js
Normal file
14
Packages/reactive-form-controls/client/helpers/getSchema.js
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
Template.registerHelper('getSchema', function(context) {
|
||||||
|
const instance = Template.instance();
|
||||||
|
if (!instance.currentSchema) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return instance.currentSchema.schema(context);
|
||||||
|
});
|
||||||
@ -0,0 +1,19 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A global Blaze UI helper function to return whether or not a key is part of the invalidKeys dictionary
|
||||||
|
*/
|
||||||
|
Template.registerHelper('isInvalidKey', function(context, format, options) {
|
||||||
|
if (!context) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const instance = Template.instance();
|
||||||
|
if (!instance.invalidKeys) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error message if key is at first index
|
||||||
|
var firstInvalidKey = instance.invalidKeys.get(0);
|
||||||
|
return (firstInvalidKey && firstInvalidKey.name === context)
|
||||||
|
});
|
||||||
@ -0,0 +1,28 @@
|
|||||||
|
import { Template } from 'meteor/templating';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A global Blaze UI helper function to return whether or not a
|
||||||
|
* field is required based on the Template's specified currentSchema
|
||||||
|
*/
|
||||||
|
Template.registerHelper('stateDataWithKey', function(context) {
|
||||||
|
const instance = Template.instance();
|
||||||
|
|
||||||
|
if (!context) {
|
||||||
|
return {
|
||||||
|
state: instance.state,
|
||||||
|
invalidKeys: instance.invalidKeys,
|
||||||
|
validationContext: instance.validationContext,
|
||||||
|
currentSchema: instance.currentSchema,
|
||||||
|
isModified: instance.isModified
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: context,
|
||||||
|
state: instance.state,
|
||||||
|
invalidKeys: instance.invalidKeys,
|
||||||
|
validationContext: instance.validationContext,
|
||||||
|
currentSchema: instance.currentSchema,
|
||||||
|
isModified: instance.isModified
|
||||||
|
};
|
||||||
|
});
|
||||||
35
Packages/reactive-form-controls/package.js
Executable file
35
Packages/reactive-form-controls/package.js
Executable file
@ -0,0 +1,35 @@
|
|||||||
|
Package.describe({
|
||||||
|
name: 'reactive-form-controls',
|
||||||
|
summary: 'A set of basic form controls that store their state in a ReactiveDict',
|
||||||
|
version: '0.0.1'
|
||||||
|
});
|
||||||
|
|
||||||
|
Package.onUse(function(api) {
|
||||||
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
|
api.use('standard-app-packages');
|
||||||
|
api.use('ecmascript');
|
||||||
|
api.use('jquery');
|
||||||
|
api.use('stylus');
|
||||||
|
api.use('reactive-dict');
|
||||||
|
api.use('templating');
|
||||||
|
api.use('natestrauser:select2@4.0.1', 'client');
|
||||||
|
|
||||||
|
api.addFiles('client/helpers/getSchema.js', ['client']);
|
||||||
|
api.addFiles('client/helpers/isInvalidKey.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.js', ['client']);
|
||||||
|
|
||||||
|
api.addFiles('client/components/radioOptionGroup/radioOptionGroup.html', ['client']);
|
||||||
|
api.addFiles('client/components/radioOptionGroup/radioOptionGroup.js', ['client']);
|
||||||
|
|
||||||
|
api.addFiles('client/components/selectInput/selectInput.html', ['client']);
|
||||||
|
api.addFiles('client/components/selectInput/selectInput.js', ['client']);
|
||||||
|
|
||||||
|
api.addFiles('client/components/select2Input/select2Input.html', ['client']);
|
||||||
|
api.addFiles('client/components/select2Input/select2Input.js', ['client']);
|
||||||
|
|
||||||
|
});
|
||||||
@ -5,7 +5,8 @@ Package.describe({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Package.onUse(function(api) {
|
Package.onUse(function(api) {
|
||||||
api.versionsFrom('1.3.2.4');
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
api.use('ecmascript');
|
api.use('ecmascript');
|
||||||
|
|
||||||
api.addFiles('lib/validate.js', 'client');
|
api.addFiles('lib/validate.js', 'client');
|
||||||
|
|||||||
@ -5,7 +5,7 @@ Package.describe({
|
|||||||
});
|
});
|
||||||
|
|
||||||
Package.onUse(function(api) {
|
Package.onUse(function(api) {
|
||||||
api.versionsFrom(['1.2.1', '1.3.2.4']);
|
api.versionsFrom('1.3.4.1');
|
||||||
|
|
||||||
api.use('standard-app-packages');
|
api.use('standard-app-packages');
|
||||||
api.use('ecmascript');
|
api.use('ecmascript');
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user