/*
- *
+ *
* Copyright 2016 RIFT.IO Inc
*
* Licensed under the Apache License, Version 2.0 (the "License");
import DeletionManager from '../libraries/DeletionManager'
import DescriptorModelIconFactory from '../libraries/model/IconFactory'
import getEventPath from '../libraries/getEventPath'
+import CatalogDataStore from '../stores/CatalogDataStore'
import imgAdd from '../../../node_modules/open-iconic/svg/plus.svg'
import imgRemove from '../../../node_modules/open-iconic/svg/trash.svg'
import '../styles/EditDescriptorModelProperties.scss'
function getDescriptorMetaBasicForType(type) {
- const basicPropertiesFilter = d => _.contains(DESCRIPTOR_MODEL_FIELDS[type], d.name);
+ const basicPropertiesFilter = d => _.includes(DESCRIPTOR_MODEL_FIELDS[type], d.name);
return DescriptorModelMetaFactory.getModelMetaForType(type, basicPropertiesFilter) || {properties: []};
}
function getDescriptorMetaAdvancedForType(type) {
- const advPropertiesFilter = d => !_.contains(DESCRIPTOR_MODEL_FIELDS[type], d.name);
+ const advPropertiesFilter = d => !_.includes(DESCRIPTOR_MODEL_FIELDS[type], d.name);
return DescriptorModelMetaFactory.getModelMetaForType(type, advPropertiesFilter) || {properties: []};
}
export default function EditDescriptorModelProperties(props) {
const container = props.container;
+ const readonly = props.readonly;
+ const isEditable = !readonly; //true
if (!(DescriptorModelFactory.isContainer(container))) {
return
}
CatalogItemsActions.catalogItemDescriptorChanged(this.getRoot());
}
+ if(readonly) {
+ return null;
+ }
return (
<Button className="inline-hint" onClick={onClickAddProperty.bind(container, property, path)} label="Add" src={imgAdd} />
);
}
CatalogItemsActions.catalogItemDescriptorChanged(this.getRoot());
}
+ if(readonly) {
+ return null;
+ }
return (
<Button className="remove-property-action inline-hint" title="Remove" onClick={onClickRemoveProperty.bind(container, property, path)} label="Remove" src={imgRemove}/>
);
}
function buildField(container, property, path, value, fieldKey) {
+ let cds = CatalogDataStore;
+ let catalogs = cds.getTransientCatalogs();
const name = path.join('.');
- const isEditable = true;
const isGuid = Property.isGuid(property);
+ const isBoolean = Property.isBoolean(property);
const onChange = onFormFieldValueChanged.bind(container);
const isEnumeration = Property.isEnumeration(property);
+ const isLeafRef = Property.isLeafRef(property);
const onFocus = onFocusPropertyFormInputElement.bind(container, property, path, value);
const placeholder = changeCase.title(property.name);
const className = ClassNames(property.name + '-input', {'-is-guid': isGuid});
+ const fieldValue = value ? (value.constructor.name != "Object") ? value : '' : undefined;
if (isEnumeration) {
const enumeration = Property.getEnumeration(property, value);
const options = enumeration.map((d, i) => {
const noValueDisplayText = changeCase.title(property.name);
options.unshift(<option key={'(value-not-in-enum)' + fieldKey.toString()} value="" placeholder={placeholder}>{noValueDisplayText}</option>);
}
- return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={value} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} readOnly={!isEditable}>{options}</select>;
+ return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={value} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} disabled={!isEditable}>{options}</select>;
+ }
+
+ if (isLeafRef) {
+ let fullFieldKey = _.isArray(fieldKey) ? fieldKey.join(':') : fieldKey;
+ let containerRef = container;
+ while (containerRef.parent) {
+ fullFieldKey = containerRef.parent.key + ':' + fullFieldKey;
+ containerRef = containerRef.parent;
+ }
+ const leafRefPathValues = Property.getLeafRef(property, path, value, fullFieldKey, catalogs, container);
+
+ const options = leafRefPathValues && leafRefPathValues.map((d, i) => {
+ return <option key={fieldKey.toString() + ':' + i} value={d.value}>{d.value}</option>;
+ });
+ const isValueSet = leafRefPathValues.filter(d => d.isSelected).length > 0;
+ if (!isValueSet || property.cardinality === '0..1') {
+ const noValueDisplayText = changeCase.title(property.name);
+ options.unshift(<option key={'(value-not-in-leafref)' + fieldKey.toString()} value="" placeholder={placeholder}>{noValueDisplayText}</option>);
+ }
+ return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={value} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} disabled={!isEditable}>{options}</select>;
+ }
+
+ if (isBoolean) {
+ let fullFieldKey = _.isArray(fieldKey) ? fieldKey.join(':') : fieldKey;
+ let containerRef = container;
+ while (containerRef.parent) {
+ fullFieldKey = containerRef.parent.key + ':' + fullFieldKey;
+ containerRef = containerRef.parent;
+ }
+
+ const options = [
+ <option key={fieldKey.toString() + '-true'} value="TRUE">TRUE</option>,
+ <option key={fieldKey.toString() + '-false'} value="FALSE">FALSE</option>
+ ]
+
+ // if (!isValueSet) {
+ const noValueDisplayText = changeCase.title(property.name);
+ options.unshift(<option key={'(value-not-in-leafref)' + fieldKey.toString()} value="" placeholder={placeholder}></option>);
+ // }
+ let val = value;
+ if(typeof(val) == 'number') {
+ val = value ? "TRUE" : "FALSE"
+ }
+ const isValueSet = (val != '' && val)
+ return <select key={fieldKey.toString()} id={fieldKey.toString()} className={ClassNames({'-value-not-set': !isValueSet})} name={name} value={val && val.toUpperCase()} title={name} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} disabled={!isEditable}>{options}</select>;
}
if (property['preserve-line-breaks']) {
- return <textarea key={fieldKey.toString()} cols="5" id={fieldKey.toString()} name={name} value={value} placeholder={placeholder} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing} readOnly={!isEditable} />;
+ return <textarea key={fieldKey.toString()} cols="5" id={fieldKey.toString()} name={name} value={value} placeholder={placeholder} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing} readOnly={!!isEditable} />;
}
- return <input key={fieldKey.toString()}
- id={fieldKey.toString()}
- type="text"
- name={name}
- value={value}
- className={className}
- placeholder={placeholder}
- onChange={onChange}
- onFocus={onFocus}
- onBlur={endEditing}
- onMouseDown={startEditing}
- onMouseOver={startEditing}
- onMouseOut={endEditing}
- onMouseLeave={endEditing}
- readOnly={!isEditable}
+ return <input
+ key={fieldKey.toString()}
+ id={fieldKey.toString()}
+ type="text"
+ name={name}
+ value={fieldValue}
+ className={className}
+ placeholder={placeholder}
+ onChange={onChange}
+ onFocus={onFocus}
+ onBlur={endEditing}
+ onMouseDown={startEditing}
+ onMouseOver={startEditing}
+ onMouseOut={endEditing}
+ onMouseLeave={endEditing}
+ readOnly={!isEditable}
/>;
}
if (typeof value === 'object') {
childValue = value[property.name];
}
- childPath.push(property.name);
-
+ if(property.type != 'choice'){
+ childPath.push(property.name);
+ }
return build(container, property, childPath, childValue);
});
event.preventDefault();
- const name = event.target.name;
+ let name = event.target.name;
const value = event.target.value;
+
/*
Transient State is stored for convenience in the uiState field.
The choice yang type uses case elements to describe the "options".
the system to determine which type is selected by the name of
the element contained within the field.
*/
-
- //const stateExample = {
- // uiState: {
- // choice: {
- // 'conf-config': {
- // selected: 'rest',
- // 'case': {
- // rest: {},
- // netconf: {},
- // script: {}
- // }
- // }
- // }
- // }
- //};
-
+ /*
+ const stateExample = {
+ uiState: {
+ choice: {
+ 'conf-config': {
+ selected: 'rest',
+ 'case': {
+ rest: {},
+ netconf: {},
+ script: {}
+ }
+ }
+ }
+ }
+ };
+ */
const statePath = ['uiState.choice'].concat(name);
const stateObject = utils.resolvePath(this.model, statePath.join('.')) || {};
+ const selected = stateObject.selected ? stateObject.selected.split('.')[1] : undefined;
// write state back to the model so the new state objects are captured
utils.assignPathValue(this.model, statePath.join('.'), stateObject);
// write the current choice value into the state
- const choiceObject = utils.resolvePath(this.model, [name, stateObject.selected].join('.'));
+ let choiceObject = utils.resolvePath(this.model, [name, selected].join('.'));
+ let isTopCase = false;
if (choiceObject) {
- utils.assignPathValue(stateObject, ['case', stateObject.selected].join('.'), _.cloneDeep(choiceObject));
+ isTopCase = true;
+ choiceObject = utils.resolvePath(this.model, [selected].join('.'));
+ }
+ utils.assignPathValue(stateObject, [selected].join('.'), _.cloneDeep(choiceObject));
+
+ if(selected) {
+ if(this.model.uiState.choice.hasOwnProperty(name)) {
+ delete this.model[selected];
+ utils.removePathValue(this.model, [name, selected].join('.'), isTopCase);
+ } else {
+ // remove the current choice value from the model
+ utils.removePathValue(this.model, [name, selected].join('.'), isTopCase);
+ }
}
-
- // remove the current choice value from the model
- utils.removePathValue(this.model, [name, stateObject.selected].join('.'));
// get any state for the new selected choice
- const newChoiceObject = utils.resolvePath(stateObject, ['case', value].join('.')) || {};
+ const newChoiceObject = utils.resolvePath(stateObject, [value].join('.')) || {};
// assign new choice value to the model
- utils.assignPathValue(this.model, [name, value].join('.'), newChoiceObject);
+ if (isTopCase) {
+ utils.assignPathValue(this.model, [name, value].join('.'), newChoiceObject);
+ } else {
+ utils.assignPathValue(this.model, [value].join('.'), newChoiceObject)
+ }
+
// update the selected name
utils.assignPathValue(this.model, statePath.concat('selected').join('.'), value);
const cases = property.properties.map(d => {
if (d.type === 'case') {
caseByNameMap[d.name] = d.properties[0];
- return {optionName: d.name, optionTitle: d.description};
+ return {
+ optionName: d.name,
+ optionTitle: d.description,
+ //represents case name and case element name
+ optionValue: [d.name, d.properties[0].name].join('.')
+ };
}
caseByNameMap[d.name] = d;
return {optionName: d.name};
});
- const options = [{optionName: ''}].concat(cases).map((d, i) => {
+ const options = [{optionName: '', optionValue: false}].concat(cases).map((d, i) => {
return (
- <option key={i} value={d.optionName} title={d.optionTitle}>
+ <option key={i} value={d.optionValue} title={d.optionTitle}>
{d.optionName}
{i ? null : changeCase.title(property.name)}
</option>
});
const selectName = path.join('.');
- const selectedOptionPath = ['uiState.choice', selectName, 'selected'].join('.');
- const selectedOptionValue = utils.resolvePath(container.model, selectedOptionPath);
- const valueProperty = caseByNameMap[selectedOptionValue] || {properties: []};
-
- const valueResponse = valueProperty.properties.map((d, i) => {
+ let selectedOptionPath = ['uiState.choice', selectName, 'selected'].join('.');
+ //Currently selected choice/case statement on UI model
+ let selectedOptionValue = utils.resolvePath(container.model, selectedOptionPath);
+ //If first time loaded, and none is selected, check if there is a value corresponding to a case statement in the container model
+ if(!selectedOptionValue) {
+ //get field properties for choice on container model
+ let fieldProperties = utils.resolvePath(container.model, selectName);
+ if(fieldProperties) {
+ //Check each case statement in model and see if it is present in container model.
+ cases.map(function(c){
+ if(fieldProperties.hasOwnProperty(c.optionValue.split('.')[1])) {
+ utils.assignPathValue(container.model, ['uiState.choice', selectName, 'selected'].join('.'), c.optionValue);
+ }
+ });
+ selectedOptionValue = utils.resolvePath(container.model, ['uiState.choice', selectName, 'selected'].join('.'));
+ } else {
+ property.properties.map(function(p) {
+ let pname = p.properties[0].name;
+ if(container.model.hasOwnProperty(pname)) {
+ utils.assignPathValue(container.model, ['uiState.choice', selectName, 'selected'].join('.'), [p.name, pname].join('.'));
+ }
+ })
+ selectedOptionValue = utils.resolvePath(container.model, ['uiState.choice', selectName, 'selected'].join('.'));
+ }
+ }
+ //If selectedOptionValue is present, take first item in string which represents the case name.
+ const valueProperty = caseByNameMap[selectedOptionValue ? selectedOptionValue.split('.')[0] : undefined] || {properties: []};
+ const isLeaf = Property.isLeaf(valueProperty);
+ const hasProperties = _.isArray(valueProperty.properties) && valueProperty.properties.length;
+ const isMissingDescriptorMeta = !hasProperties && !Property.isLeaf(valueProperty);
+ //Some magic that prevents errors for arising
+ const valueResponse = valueProperty.properties.length ? valueProperty.properties.map((d, i) => {
const childPath = path.concat(valueProperty.name, d.name);
const childValue = utils.resolvePath(container.model, childPath.join('.'));
return (
{build(container, d, childPath, childValue, props)}
</div>
);
- });
-
+ }) : (!isMissingDescriptorMeta) ? build(container, valueProperty, path.concat(valueProperty.name), utils.resolvePath(container.model, path.concat(valueProperty.name).join('.')) || container.model[valueProperty.name]) : null
+ // end magic
const onFocus = onFocusPropertyFormInputElement.bind(container, property, path, value);
return (
<div key={key} className="choice">
- <select key={Date.now()} className={ClassNames({'-value-not-set': !selectedOptionValue})} name={selectName} value={selectedOptionValue} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing}>
+ <select key={Date.now()} className={ClassNames({'-value-not-set': !selectedOptionValue})} name={selectName} value={selectedOptionValue} onChange={onChange} onFocus={onFocus} onBlur={endEditing} onMouseDown={startEditing} onMouseOver={startEditing} onMouseOut={endEditing} onMouseLeave={endEditing} readOnly={!isEditable}>
{options}
</select>
{valueResponse}
if (property.type === 'choice') {
value = utils.resolvePath(container.model, ['uiState.choice'].concat(path, 'selected').join('.'));
+ if(!value) {
+ property.properties.map(function(p) {
+ let pname = p.properties[0].name;
+ if(container.model.hasOwnProperty(pname)) {
+ value = container.model[pname];
+ }
+ })
+ }
}
let displayValue = typeof value === 'object' ? '' : value;