in ui-modules/blueprint-composer/app/components/dsl-editor/dsl-editor.js [71:295]
function link(scope) {
const blueprint = blueprintService.get();
blueprint.isInDslEdit = true;
scope.$on('$destroy', () => {
blueprint.isInDslEdit = false;
});
scope.$on('d3.entity-selected', (event, entity) => {
scope.state.filter = scope.filters.find(filter => filter.id === entity._id);
});
scope.DSL_KINDS = DSL_KINDS;
scope.kinds = Object.values(DSL_KINDS);
scope.filters = [{
id: 'blueprint',
label: 'Anywhere on the blueprint',
scope: 'Global'
}].concat(getEntityItems(blueprintService.get()).map(item => {
let attrs = [];
if (item.entity === scope.entity) {
attrs.push('this');
}
if (!item.entity.hasParent()) {
attrs.push('root');
}
if (scope.entity.parent === item.entity) {
attrs.push('parent');
}
let { name, entity, id } = item;
name += attrs.length > 0 ? ` (${attrs.join(', ')})` : ` (${entity.id || id})`;
return {
id,
label: name,
scope: 'On specific entity'
};
}));
scope.orders = [{
label: 'name',
property: 'name'
}, {
label: 'entity',
property: 'entity.type'
}];
scope.items = [].concat(
getConfigItems(blueprintService.get(), scope.definition),
getSensorItems(blueprintService.get()),
getEntityItems(blueprintService.get(), scope.definition.type)
);
scope.state = {
kind: scope.kinds[0],
filter: scope.filters[0],
orderBy: scope.orders[0],
search: '',
sensor: false,
arguments: [],
toggles: [],
entityId: '',
};
if (scope.dsl) {
let lastMethod = scope.dsl.getLastMethod();
if (lastMethod.kind === KIND.METHOD && lastMethod.name === 'config') {
scope.state.kind = scope.kinds[1];
scope.state.search = lastMethod.params[0].name;
scope.state.item = scope.items.find(item => (item.type === DSL_KINDS.CONFIG && item.name === lastMethod.params[0].name));
}
if (lastMethod.kind === KIND.METHOD && ['attributeWhenReady', 'sensor'].includes(lastMethod.name)) {
scope.state.kind = scope.kinds[2];
scope.state.search = lastMethod.params[0].name;
scope.state.item = scope.items.find(item => (item.type === DSL_KINDS.SENSOR && item.name === lastMethod.params[0].name));
scope.state.sensor = lastMethod.name === 'sensor';
}
if (lastMethod.kind === KIND.UTILITY && lastMethod.name === 'formatString') {
scope.state.kind = scope.kinds[4];
scope.state.pattern = scope.dsl.params[0].name;
scope.state.arguments = Array.from(scope.dsl.params).splice(1).map(argument => {
return argument.kind === KIND.STRING ? argument.name : argument.toString();
});
}
try {
let relatedEntity = scope.dsl.params.length && scope.dsl.getRoot().relationships.find(entity => entity.id === scope.dsl.params[0].name);
if (relatedEntity) {
scope.state.filter = scope.filters.find(filter => filter.id === relatedEntity._id);
}
} catch (e) {
console.log("Error analysing DSL (ignore)", scope.dsl, scope.filters, e);
}
}
scope.$watch('state.pattern', (newValue, oldValue) => {
if (!newValue || angular.equals(newValue, oldValue)) {
return;
}
scope.dsl.params.splice(0, 1, new Dsl(KIND.STRING, newValue));
});
scope.$watchCollection('state.arguments', (newValue, oldValue) => {
if (!newValue || angular.equals(newValue, oldValue)) {
return;
}
newValue.forEach((argument, index) => {
let dsl;
try {
dsl = new DslParser().parseString(argument, scope.entity, blueprintService.get());
scope.dsl.params.splice(index + 1, 1, dsl);
} catch (ex) {
$log.debug(`Argument ${index} is not a DSL. Defaulting to string`, ex);
dsl = new Dsl(KIND.STRING, argument);
}
scope.dsl.params.splice(index + 1, 1, dsl);
})
});
scope.isDsl = (index) => {
return scope.dsl.params[index + 1] instanceof Dsl && scope.dsl.params[index + 1].kind !== KIND.STRING;
};
scope.predicate = (value, index, array) => {
let predicates = [];
let validTypes = scope.state.kind.id === DSL_KINDS.ALL.id ? Object.values(DSL_KINDS).filter(type => type !== DSL_KINDS.FORMAT_STRING) : [scope.state.kind];
predicates.push(validTypes.map(type => type.id).includes(value.type.id));
if (scope.state.filter.id !== 'blueprint') {
predicates.push(scope.state.filter.id === value.entity._id);
}
if (scope.state.search) {
let searchPredicate = value.name.toLowerCase().indexOf(scope.state.search.toLowerCase()) > -1;
if (value.description) {
searchPredicate |= value.description.toLowerCase().indexOf(scope.state.search.toLowerCase()) > -1;
}
if ([ DSL_KINDS.ENTITY.id, DSL_KINDS.ALL.id ].includes(scope.state.kind.id) ) {
// if searching for entity or config/sensors/entity, show everything.
// but searching just for a config or sensor doesn't show everything.
// (not sure that's the right semantics?)
searchPredicate |= value.entity.id && value.entity.id.toLowerCase().indexOf(scope.state.search.toLowerCase()) > -1;
searchPredicate |= value.entity.name && value.entity.name.toLowerCase().indexOf(scope.state.search.toLowerCase()) > -1;
}
predicates.push(searchPredicate);
}
return predicates.reduce((ret, predicate) => (ret && predicate), true);
};
scope.selectItem = (item, event) => {
scope.state.item = item;
event.preventDefault();
event.stopPropagation();
};
scope.selectDsl = () => {
scope.dsl = buildDsl();
$rootScope.$broadcast(`${MODULE_NAME}.select`, {
dsl: scope.dsl,
definition: scope.definition
});
};
scope.nestDsl = (index) => {
scope.dsl = buildDsl();
$rootScope.$broadcast(`${MODULE_NAME}.nest`, {
dsl: scope.dsl,
definition: scope.definition,
index: index
});
};
scope.isDone = () => {
if (scope.state.kind.id !== DSL_KINDS.FORMAT_STRING.id) {
return angular.isDefined(scope.state.item);
} else {
return brUtilsGeneral.isNonEmpty(scope.state.pattern) && brUtilsGeneral.isNonEmpty(scope.state.arguments);
}
};
function buildDsl() {
let dsl;
let funcDsl;
if (scope.state.kind.id !== DSL_KINDS.FORMAT_STRING.id) {
let scopedDsl = getScopedDsl(scope.entity, scope.state.item.entity, scope.state);
switch (scope.state.item.type) {
case DSL_KINDS.CONFIG:
funcDsl = new Dsl(KIND.METHOD, 'config').param(new Dsl(KIND.STRING, scope.state.item.name));
scopedDsl.chain(funcDsl);
dsl = isSelfDsl(scopedDsl) ? funcDsl : scopedDsl;
break;
case DSL_KINDS.SENSOR:
funcDsl = new Dsl(KIND.METHOD, scope.state.sensor ? 'sensor' : 'attributeWhenReady').param(new Dsl(KIND.STRING, scope.state.item.name));
scopedDsl.chain(funcDsl);
dsl = isSelfDsl(scopedDsl) ? funcDsl : scopedDsl;
break;
case DSL_KINDS.ENTITY:
dsl = scopedDsl;
break;
}
} else {
dsl = new Dsl(KIND.UTILITY, 'formatString').param(new Dsl(KIND.STRING, scope.state.pattern));
scope.state.arguments.forEach((arg, index) => {
dsl.param(scope.isDsl(index) ? scope.dsl.params[index + 1] : new Dsl(KIND.STRING, arg));
});
}
try {
dsl = new DslParser().parseString(dsl.toString(), scope.entity, blueprintService.get());
} catch (ex) {
$log.debug(`Cannot get DSL relationship for DSL "${dsl}`, ex);
}
return dsl;
}
}