LT-253: Creating radio group component

This commit is contained in:
Bruno Alves de Faria 2016-07-14 11:25:39 -03:00 committed by Erik Ziegler
parent cb875b1913
commit 9d31b49997
19 changed files with 180 additions and 88 deletions

3
.gitignore vendored
View File

@ -2,6 +2,7 @@
docs/ docs/
.meteor/local .meteor/local
.meteor/meteorite .meteor/meteorite
.meteor/dev_bundle
node_modules node_modules
Packages/active-entry/helloworld/ Packages/active-entry/helloworld/
LesionTracker/tests/nightwatch/reports/ LesionTracker/tests/nightwatch/reports/

View File

@ -29,6 +29,11 @@ Package.onUse(function(api) {
'styles/common/spacings.styl' 'styles/common/spacings.styl'
], 'client'); ], 'client');
// Component styles
api.addFiles([
'styles/components/radio.styl'
], 'client');
// Rounded Button Group // Rounded Button Group
api.addFiles([ api.addFiles([
'components/roundedButtonGroup/roundedButtonGroup.html', 'components/roundedButtonGroup/roundedButtonGroup.html',

View File

@ -0,0 +1,36 @@
@import "{design}/app"
.group-radio
label
cursor: pointer
input
height: 0
width: 0
span
padding-left: 23px
position: relative
&:before
background: white
border-radius: 8px
content: ''
display: block
height: 16px
left: 0
position: absolute
top: 50%
transform(translateY(-50%))
width: 16px
input:focus + span:before
// TODO: [design] define a outline for the design
outline: none
box-shadow: 0 0 2px 2px $textSecondaryColor
input:checked + span:after
background: $uiBorderColorDark
border-radius: 5px
content: ''
height: 10px
left: 3px
position: absolute
top: 50%
transform(translateY(-50%))
width: 10px

View File

@ -1,70 +1,51 @@
<template name="additionalFindings"> <template name="additionalFindings">
<div class="additionalFindings"> <div class="additionalFindings">
<div class="scrollArea"> <div class="scrollArea">
<div class="row"> {{#form schema=currentSchema}}
<div class="header"> <div class="row">
Additional Findings: Baseline <div class="header">Additional Findings: Baseline</div>
{{>groupRadio labelClass='form-group' key='measurableDisease'}}
</div> </div>
{{>radioOptionGroup (stateDataWithKey "measurableDisease")}} <div class="row">
</div> <div class="header">Supplementary Measurements</div>
{{>selectInput (stateDataWithKey "numberOfBoneLesions")}}
<!-- <h4>Testing dynamic components</h4> {{>select2Input
{{#form id="testForm" schema=currentSchema}} key="regionsOfMetastaticDisease"
{{>inputText key='test' label='testing'}} select2Options=regionsOfMetastaticDiseaseSelect2Options
{{>groupRadio mixins='schemaData' key='acceptableImageQuality'}} state=state
{{/form}} --> currentSchema=currentSchema
}}
<div class="row"> {{>groupRadio labelClass='form-group' key='tracerRelatedToMetastaticDisease'}}
<div class="header">
Supplementary Measurements
</div> </div>
{{>selectInput (stateDataWithKey "numberOfBoneLesions")}} <div class="row">
{{>select2Input <div class="header">Image Quality</div>
key="regionsOfMetastaticDisease" {{>groupRadio labelClass='form-group' key='acceptableImageQuality'}}
select2Options=regionsOfMetastaticDiseaseSelect2Options {{>groupRadio labelClass='form-group' key='adequateAnatomicalCoverage'}}
state=state {{>groupRadio labelClass='form-group' key='presenceOfContrast'}}
currentSchema=currentSchema
}}
{{>radioOptionGroup (stateDataWithKey "tracerRelatedToMetastaticDisease")}}
</div>
<div class="row">
<div class="header">
Image Quality
</div> </div>
{{>radioOptionGroup (stateDataWithKey "acceptableImageQuality")}} <div class="row">
{{>radioOptionGroup (stateDataWithKey "adequateAnatomicalCoverage")}} <div class="header">Additional Screen Captures</div>
{{>radioOptionGroup (stateDataWithKey "presenceOfContrast")}} <div class="entrySection buttonSection">
</div> <div class="svgContainer">
<div class="row"> <svg>
<div class="header"> <use xlink:href="/packages/lesiontracker/assets/icons.svg#icon-create-screen-capture"></use>
Additional Screen Captures </svg>
</div> </div>
<div class="entrySection buttonSection"> <div class="buttonLabel noselect">Add new screen capture</div>
<div class="svgContainer">
<svg>
<use xlink:href="/packages/lesiontracker/assets/icons.svg#icon-create-screen-capture"></use>
</svg>
</div>
<div class="buttonLabel noselect">
Add new screen capture
</div> </div>
</div> </div>
</div> <div class="row">
<div class="row"> <div class="header">Comments</div>
<div class="header"> <div class="entrySection buttonSection">
Comments <div class="svgContainer">
</div> <svg>
<div class="entrySection buttonSection"> <use xlink:href="/packages/lesiontracker/assets/icons.svg#icon-create-comment"></use>
<div class="svgContainer"> </svg>
<svg> </div>
<use xlink:href="/packages/lesiontracker/assets/icons.svg#icon-create-comment"></use> <div class="buttonLabel noselect">Add a comment</div>
</svg>
</div>
<div class="buttonLabel noselect">
Add a comment
</div> </div>
</div> </div>
</div> {{/form}}
</div> </div>
</div> </div>
</template> </template>

View File

@ -38,6 +38,13 @@
&:not(:last-child) &:not(:last-child)
border-bottom: $uiBorderThickness solid $uiBorderColorDark border-bottom: $uiBorderThickness solid $uiBorderColorDark
& > .wrapperText
display: block
font-weight: bold
line-height: 15px
margin: 10px 0 8px
// TODO: remove
h5 h5
font-weight: bold font-weight: bold
margin-bottom: 8px margin-bottom: 8px
@ -48,10 +55,11 @@
display: inline-block display: inline-block
padding: 5px padding: 5px
.radio-group // TODO: remove radio-group
.radio-group, .group-radio
height: 30px height: 30px
.radio-option label
display: inline-block display: inline-block
float: left float: left
font-size: 14px font-size: 14px

View File

@ -44,7 +44,7 @@ OHIF.mixins.form = new OHIF.Mixin({
const component = instance.component; const component = instance.component;
// Set the component main and style elements // Set the component main and style elements
component.$style = component.$element = instance.$('form').first(); component.$style = component.$element = instance.$('form:first');
} }
} }
}); });

View File

@ -8,7 +8,7 @@ import { $ } from 'meteor/jquery';
* It may be used to manage all components that belong to forms * It may be used to manage all components that belong to forms
*/ */
OHIF.mixins.formItem = new OHIF.Mixin({ OHIF.mixins.formItem = new OHIF.Mixin({
dependencies: 'component', dependencies: 'schemaData',
composition: { composition: {
onCreated() { onCreated() {
@ -113,7 +113,7 @@ OHIF.mixins.formItem = new OHIF.Mixin({
const component = instance.component; const component = instance.component;
// Set the element to be controlled // Set the element to be controlled
component.$element = instance.$(':input:first'); component.$element = instance.$(':input').first();
// Set the element to be styled // Set the element to be styled
component.$style = component.$element; component.$style = component.$element;

View File

@ -45,6 +45,14 @@ OHIF.mixins.group = new OHIF.Mixin({
component.registeredItems.forEach(child => child.readonly(isReadonly)); component.registeredItems.forEach(child => child.readonly(isReadonly));
}; };
},
onRendered() {
const instance = Template.instance();
const component = instance.component;
// Set the element to be controlled
component.$element = instance.$('.component-group:first');
} }
} }
}); });

View File

@ -16,8 +16,9 @@ OHIF.mixins.groupRadio = new OHIF.Mixin({
// Get the selected radio's value or select a radio based on value // Get the selected radio's value or select a radio based on value
component.value = value => { component.value = value => {
const isGet = _.isUndefined(value); const isGet = _.isUndefined(value);
const $elements = $(); const elements = [];
component.registeredItems.forEach(child => $elements.add(child.$element)); component.registeredItems.forEach(child => elements.push(child.$element[0]));
const $elements = $(elements);
if (isGet) { if (isGet) {
return $elements.filter(':checked').val(); return $elements.filter(':checked').val();
} }

View File

@ -3,31 +3,39 @@ import { Blaze } from 'meteor/blaze';
import { Template } from 'meteor/templating'; import { Template } from 'meteor/templating';
import { _ } from 'meteor/underscore'; import { _ } from 'meteor/underscore';
// Helper function to get the component's current schema
const getCurrentSchema = (parentComponent, key) => {
// Get the parent component schema
const schema = parentComponent && parentComponent.schema;
// Stop here if there's no key or schema defined
if (!key || !schema) {
return;
}
// Get the current schema data using component's key
const currentSchema = schema._schema[key];
// Return the component's schema definitions
return currentSchema;
};
/* /*
* schemaData: change the component data based on its form's schema data * schemaData: change the component data based on its form's schema data
*/ */
OHIF.mixins.schemaData = new OHIF.Mixin({ OHIF.mixins.schemaData = new OHIF.Mixin({
dependencies: 'formItem', dependencies: 'component',
composition: { composition: {
onData() { onData() {
// Get the current template data
const data = Template.currentData(); const data = Template.currentData();
// Get the parent component
const parent = OHIF.blaze.getParentComponent(Blaze.currentView); 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 // Get the current schema data using component's key
const currentSchema = schema._schema[key]; const currentSchema = getCurrentSchema(parent, data.key);
// Stop here if there's no schema data for current key // Stop here if there's no schema data for current key
if (!currentSchema) { if (!currentSchema) {
@ -39,7 +47,42 @@ OHIF.mixins.schemaData = new OHIF.Mixin({
data.label = new ReactiveVar(currentSchema.label); data.label = new ReactiveVar(currentSchema.label);
} }
// TODO: [design] convert allowedValues to items and find a way to get key/value pairs // Fill the items if it's an array schema
if (!data.items && Array.isArray(currentSchema.allowedValues)) {
// Initialize the items array
data.items = [];
// Get the values and labels arrays from schema
const values = currentSchema.allowedValues;
const labels = currentSchema.valuesLabels || [];
// Iterate the allowed values array
for (let i = 0; i < values.length; i++) {
// Push the current item to the items array
data.items.push({
value: values[i],
label: labels[i] || values[i]
});
}
}
},
onMixins() {
const instance = Template.instance();
const component = instance.component;
// Get the current schema data using component's key
const currentSchema = getCurrentSchema(component.parent, instance.data.key);
// Stop here if there's no schema data for current key
if (!currentSchema) {
return;
}
// Fill the component with its default value after rendering
if (currentSchema.defaultValue) {
component.value(currentSchema.defaultValue);
}
} }
} }

View File

@ -77,7 +77,7 @@ Template.baseComponent.constructView = function(contentFunc, elseFunc) {
// Throw an error if the wrapper template does not exists // Throw an error if the wrapper template does not exists
if (!wrapperTemplate) { if (!wrapperTemplate) {
throw new Error(`Template ${data.base} not found.`); throw new Error(`Template ${wrapper} not found.`);
} }
// Clone the wrapper template to avoid assigning duplicated handlers // Clone the wrapper template to avoid assigning duplicated handlers

View File

@ -3,7 +3,7 @@
{{#if this.labelAfter}} {{#if this.labelAfter}}
{{>UI.contentBlock}} {{>UI.contentBlock}}
{{/if}} {{/if}}
<span class="wrapperLabelText">{{reactive this.label}}</span> <span class="wrapperText">{{reactive this.label}}</span>
{{#unless this.labelAfter}} {{#unless this.labelAfter}}
{{>UI.contentBlock}} {{>UI.contentBlock}}
{{/unless}} {{/unless}}

View File

@ -3,7 +3,7 @@
{{#if this.labelAfter}} {{#if this.labelAfter}}
{{>UI.contentBlock}} {{>UI.contentBlock}}
{{/if}} {{/if}}
<span class="wrapperTitleText">{{reactive this.label}}</span> <span class="wrapperText">{{reactive this.label}}</span>
{{#unless this.labelAfter}} {{#unless this.labelAfter}}
{{>UI.contentBlock}} {{>UI.contentBlock}}
{{/unless}} {{/unless}}

View File

@ -1,5 +1,6 @@
<template name="group"> <template name="group">
{{#baseComponent (extend this {{#baseComponent (extend this
class=(concat 'component-group ' this.class)
base="baseDiv" base="baseDiv"
mixins=(concat "group " this.mixins) mixins=(concat "group " this.mixins)
)}} )}}

View File

@ -1,9 +1,10 @@
<template name="groupRadio"> <template name="groupRadio">
{{#group (extend this {{#group (extend this
class=(concat 'form-group ' this.class) class=(concat 'group-radio ' this.class)
mixins=(concat "groupRadio " this.mixins)
wrappers=(concat '' wrappers=(concat ''
this.wrappers
(valueIf reactive this.label 'wrapperTitle ' '') (valueIf reactive this.label 'wrapperTitle ' '')
this.wrappers
) )
)}} )}}
{{>UI.contentBlock}} {{>UI.contentBlock}}

View File

@ -1,12 +1,13 @@
<template name="inputRadio"> <template name="inputRadio">
{{#baseComponent (extend this {{#baseComponent (extend this
base='baseInput' base='baseInput'
type='radio'
mixins=(concat 'input ' this.mixins) mixins=(concat 'input ' this.mixins)
labelAfter=(valueIf (isDefined this.labelAfter) this.labelAfter true) labelAfter=(valueIf (isDefined this.labelAfter) this.labelAfter true)
labelClass=(concat 'checkboxLabel' this.labelClass) labelClass=(concat 'checkboxLabel' this.labelClass)
wrappers=(concat '' wrappers=(concat ''
this.wrappers
(valueIf reactive this.label 'wrapperLabel ' '') (valueIf reactive this.label 'wrapperLabel ' '')
this.wrappers
) )
)}} )}}
{{>UI.contentBlock}} {{>UI.contentBlock}}

View File

@ -4,8 +4,8 @@
class=(concat 'form-control ' this.class) class=(concat 'form-control ' this.class)
mixins=(concat 'select ' this.mixins) mixins=(concat 'select ' this.mixins)
wrappers=(concat '' wrappers=(concat ''
this.wrappers
(valueIf reactive this.label 'wrapperLabel ' '') (valueIf reactive this.label 'wrapperLabel ' '')
this.wrappers
) )
)}} )}}
{{>UI.contentBlock}} {{>UI.contentBlock}}

View File

@ -4,8 +4,8 @@
class=(concat 'form-control ' this.class) class=(concat 'form-control ' this.class)
mixins=(concat 'input ' this.mixins) mixins=(concat 'input ' this.mixins)
wrappers=(concat '' wrappers=(concat ''
this.wrappers
(valueIf reactive this.label 'wrapperLabel ' '') (valueIf reactive this.label 'wrapperLabel ' '')
this.wrappers
) )
)}} )}}
{{>UI.contentBlock}} {{>UI.contentBlock}}

View File

@ -62,7 +62,13 @@ Template.registerHelper('or', (...values) => {
// Choose the first truthy value in the given values // Choose the first truthy value in the given values
Template.registerHelper('choose', (...values) => { Template.registerHelper('choose', (...values) => {
let result; let result;
_.each(_.initial(values, 1), value => value && (result = value)); _.each(_.initial(values, 1), value => {
if (result) {
return;
} else if (value) {
result = value;
}
});
return result; return result;
}); });