X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;f=skyquake%2Fplugins%2Fcomposer%2Fsrc%2Fsrc%2Fcomponents%2FNavigateDescriptorModel.jsx;fp=skyquake%2Fplugins%2Fcomposer%2Fsrc%2Fsrc%2Fcomponents%2FNavigateDescriptorModel.jsx;h=244c4e4d2a22498f750d74d8d47c8b9e6a4edf92;hb=03156e335275de1dafbc2a816e98006afdf249bf;hp=0000000000000000000000000000000000000000;hpb=f2dc2462571800e62cba969964de621dca09299c;p=osm%2FUI.git diff --git a/skyquake/plugins/composer/src/src/components/NavigateDescriptorModel.jsx b/skyquake/plugins/composer/src/src/components/NavigateDescriptorModel.jsx new file mode 100644 index 000000000..244c4e4d2 --- /dev/null +++ b/skyquake/plugins/composer/src/src/components/NavigateDescriptorModel.jsx @@ -0,0 +1,238 @@ +/* + * + * Copyright 2016 RIFT.IO Inc + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +/** + * Created by onvelocity on 1/18/16. + * + * This class generates the form fields used to edit the CONFD JSON model. + */ + +import _uniqueId from 'lodash/uniqueId'; +import _set from 'lodash/set'; +import _get from 'lodash/get'; +import _has from 'lodash/has'; +import _keys from 'lodash/keys'; +import _isObject from 'lodash/isObject'; +import _isArray from 'lodash/isArray'; +import _isNumber from 'lodash/isNumber'; +import utils from '../libraries/utils' +import React from 'react' +import changeCase from 'change-case' +import toggle from '../libraries/ToggleElementHandler' +import Property from '../libraries/model/DescriptorModelMetaProperty' +import SelectionManager from '../libraries/SelectionManager' +import ComposerAppActions from '../actions/ComposerAppActions' +import CatalogItemsActions from '../actions/CatalogItemsActions' +import DescriptorEditorActions from '../actions/DescriptorEditorActions' +import DescriptorModelFactory from '../libraries/model/DescriptorModelFactory' +import DescriptorModelMetaFactory from '../libraries/model/DescriptorModelMetaFactory' +import PropertyNavigate from './model/PropertyNavigate' + + +import '../styles/EditDescriptorModelProperties.scss' + +function selectModel(container, model) { + const root = container.getRoot(); + if (SelectionManager.select(model)) { + CatalogItemsActions.catalogItemMetaDataChanged(root.model); + } +} + +function isDataProperty(property) { + return property.type === 'leaf' || property.type === 'leaf_list' || property.type === 'choice'; +} + +function checkIfValueEmpty(value) { + if (value === null || typeof value === 'undefined') { + return true; + } else if (_isArray(value) && !value.length) { + return true; + } else if (_isObject(value)) { + const keys = _keys(value); + if (keys.length < 2) { + return !keys.length || (keys[0] === 'uiState') + } + } + return false; +} + +function makeOption(path, value) { + let labelPath = path.map(node => _isNumber(node) ? node + 1: node); + return { + value: path, + label: labelPath.join(' . ') + (value ? ' : ' + value : '') + } +} + +export default function NavigateDescriptorModel(props) { + const { container, idMaker, style } = props; + const uiState = container.uiState; + + function buildField(property, path, value) { + return [makeOption(path, value)]; + } + + function buildLeafList(property, path, value) { + const searchValue = Array.isArray(value) ? value.join(' ') : value; + return [makeOption(path, searchValue)]; + } + + function buildChoice(property, path, value) { + const uiStatePath = path.concat(['uiState']); + const choiceStatePath = ['choice', property.name]; + const fullChoiceStatePath = uiStatePath.concat(choiceStatePath); + + function determineSelectedChoice(model) { + let choiceState = utils.resolvePath(container.model, fullChoiceStatePath.join('.')); + if (choiceState) { + return property.properties.find(c => c.name === choiceState.selected); + } + const selectedCase = property.properties.find(c => + c.properties && c.properties.find(p => _has(model, path.concat([p.name]))) + ); + return selectedCase; + } + + const selectedCase = determineSelectedChoice(container.model); + return [makeOption(path)].concat(selectedCase ? + buildComponentsForProperties( + selectedCase.properties, path, path.length ? _get(container.model, path) : container.model) : + []); + } + + function buildList(property, path, value, uniqueId) { + if (value && !Array.isArray(value)) { + value = [value]; + } + + function getListItemSummary(index, value) { + const keys = property.key.map((key) => value[key]); + const summary = keys.join(' '); + return summary.length > 1 ? summary : '' + (index + 1); + } + const children = value ? value.reduce((a, itemValue, i) => { + const itemPath = path.concat([i]); + return a.concat(buildComponentsForProperties(property.properties, itemPath, itemValue)); + }, [makeOption(path)]) + : [makeOption(path)]; + return children; + } + + function buildSimpleList(property, path, value, uniqueId) { + return [makeOption(path)]; + } + + function buildContainer(property, path, value, uniqueId, readOnly) { + return buildComponentsForProperties(property.properties, path, value); + } + + /** + * buiid and return an array of components representing an editor for each property. + * + * @param {any} container the master document being edited + * @param {[property]} properties + * @param {string} pathToProperties path within the container to the properties + * @param {Object} data source for each property + * which may be useful/necessary to a components rendering. + * @returns an array of react components + */ + function buildComponentsForProperties(properties, pathToProperties, data) { + return properties.reduce((a, property) => { + let value; + let propertyPath = pathToProperties.slice(); + if (property.type != 'choice') { + propertyPath.push(property.name); + } + if (data && typeof data === 'object') { + value = _get(data, property.name); + } + let result = []; + try { + result = buildPropertyComponent(property, propertyPath, value); + } catch (e) { + console.error(e); + } + return a.concat(result); + }, []); + } + + function buildPropertyComponent(property, path, value) { + + const fields = []; + const isObject = Property.isObject(property); + const title = changeCase.titleCase(property.name); + + // create a unique Id for use as react component keys and html element ids + // use uid (from ui info) instead of id property (which is not stable) + let uniqueId = container.uid; + let containerRef = container; + while (containerRef.parent) { + uniqueId = containerRef.parent.uid + ':' + uniqueId; + containerRef = containerRef.parent; + } + uniqueId += ':' + path.join(':') + + if (!property.properties && isObject) { + console.debug('no properties', property); + const uiState = DescriptorModelMetaFactory.getModelMetaForType(property.name) || {}; + property.properties = uiState.properties; + } + + if (property.type === 'leaf') { + return buildField(property, path, value, uniqueId); + } else if (property.type === 'leaf_list') { + return buildLeafList(property, path, value, uniqueId); + } else if (property.type === 'list') { + return Property.isSimpleList(property) ? + buildSimpleList(property, path, value, uniqueId) : + buildList(property, path, value, uniqueId); + } else if (property.type === 'container') { + return buildContainer(property, path, value, uniqueId); + } else if (property.type === 'choice') { + return buildChoice(property, path, value, uniqueId); + } else { + return ([]); + } + } + + + if (!(DescriptorModelFactory.isContainer(container))) { + return null; + } + + const containerType = container.uiState['qualified-type'] || container.uiState.type; + let properties = DescriptorModelMetaFactory.getModelMetaForType(containerType).properties; + // bubble all data properties to top of list + let twoLists = properties.reduce((o, property) => { + const value = _get(container.model, [property.name]); + if (isDataProperty(property)) { + o.listOne.push(property); + } else { + o.listTwo.push(property); + } + return o; + }, { + listOne: [], + listTwo: [] + }); + properties = twoLists.listOne.concat(twoLists.listTwo); + const options = buildComponentsForProperties(properties, [], container.model); + return options.length ? + () + :
; +}; \ No newline at end of file