in ui-modules/blueprint-composer/app/components/spec-editor/spec-editor.directive.js [969:1071]
function getLocalConfigValueFromModelValue(key, value) {
if (!specEditor.defined(value) || value === null) {
return value;
}
if (value.hasOwnProperty(DSL_ENTITY_SPEC)) {
let wrapper = {};
wrapper[REPLACED_DSL_ENTITYSPEC] = value[DSL_ENTITY_SPEC];
return wrapper;
}
if (value instanceof Dsl) {
return value.toString();
}
let definition = scope.model.miscData.get('config').find(config => config.name === key);
if (!definition) {
definition = {};
scope.getConfigWidgetMode(definition, value)
} else {
if (!definition.widgetMode) scope.getConfigWidgetMode(definition, value);
}
// if json mode, then just stringify
if (scope.state.config.codeModeActive[key]) {
if (scope.state.config.codeModeError[key]) {
// errors don't get stringified because model value was not parsed
return value;
}
// if current local value gives same result then don't change it
// (don't interrupt user's flow, and respect their spacing, at least until
// they click away; ultimately we would like access to the parse tree,
// so we could take the text as entered exactly (maybe stripping initial whitespace),
// also supporting yaml and comments, but that is a bigger task!)
if (scope.config && typeof scope.config[key] === 'string') {
try {
if (JSON.stringify(parseYamlOrJson(scope.config[key])) === JSON.stringify(value)) {
return scope.config[key];
}
} catch (ignoredError) {
$log.debug("Couldn't handle entered JSON", scope.config[key], ignoredError);
}
}
// otherwise pretty print it, so they get decent multiline on first load and
// if they click off the entity then back on to the entity and this field
// (we'd like to respect what they actually typed but that needs the parse tree, as above)
return toCode(value, true);
}
// else treat as value, with array/map special
try {
if (definition.widgetMode === 'array' || definition.widgetMode === 'array-manual') {
if (Array.isArray(value)) {
return value.map(item => {
if (item instanceof Dsl) {
return item.toString();
} else if (item instanceof Array || item instanceof Object || typeof item === 'object') {
throw 'not simple json in array';
} else {
return item;
}
});
}
// fall through to return toString below
} else if (definition.widgetMode === 'map' || definition.widgetMode === 'map-manual') {
if (typeof value === "object") {
let object = {};
for (let keyObject in value) {
if (value[keyObject] instanceof Dsl) {
object[keyObject] = value[keyObject].toString();
} else if (value[keyObject] instanceof Array || value[keyObject] instanceof Object || typeof value[keyObject] === 'object') {
throw 'not simple json in map';
} else {
object[keyObject] = value[keyObject];
}
}
return object;
}
// fall through to return toString below
} else if ((value instanceof Object || value instanceof Array || typeof value === 'object') && !(value instanceof Dsl)) {
throw 'must use code editor for array/object';
}
} catch (hasComplexJson) {
// any map/array with complex json inside, or other value of complex json,
// will force the code editor
// (previously we did stringify on entries then tried to parse, but that was inconsistent)
console.log("Forcing code mode on ", key, "=", value, "because", hasComplexJson);
scope.state.config.codeModeActive[key] = true;
// and the widget mode updated to be 'manual'
scope.getConfigWidgetMode(definition, value);
// and rerun this method so we get it prettified if appropriate
return getLocalConfigValueFromModelValue(key, value);
}
// if boolean, return as primitive type
if (typeof value === 'boolean') {
return value;
}
// all other primitives treat as string (as they will get a string-based widget)
return "" + value;
}