- function buildChoice(container, property, path, value, key, props={}) {
-
- function onFormFieldValueChanged(event) {
- if (DescriptorModelFactory.isContainer(this)) {
-
- event.preventDefault();
-
- 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".
- A choice can only ever have one option selected which allows
- 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 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
- let choiceObject = utils.resolvePath(this.model, [name, selected].join('.'));
- let isTopCase = false;
- if (!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);
- }
- }
-
- // get any state for the new selected choice
- const newChoiceObject = utils.resolvePath(stateObject, [value].join('.')) || {};
-
- // assign new choice value to the model
- 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);
-
- CatalogItemsActions.catalogItemDescriptorChanged(this.getRoot());
- }
- }
-
- const caseByNameMap = {};
-
- const onChange = onFormFieldValueChanged.bind(container);
-
- const cases = property.properties.map(d => {
- if (d.type === 'case') {
- caseByNameMap[d.name] = d.properties[0];
- 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: '', optionValue: false}].concat(cases).map((d, i) => {
- return (
- <option key={i} value={d.optionValue} title={d.optionTitle}>
- {d.optionName}
- {i ? null : changeCase.title(property.name)}
- </option>
- );
- });
-
- const selectName = path.join('.');
- 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 (
- <div key={childPath.concat('info', i).join(':')}>
- {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}>
- {options}
- </select>
- {valueResponse}
- </div>
- );
-
- }