$scope.groupOptions = CRM.crmSearchActions.groupOptions;
// Try to create a sensible list of entities one might want to search for,
// excluding those whos primary purpose is to provide joins or option lists to other entities
- var primaryEntities = _.filter(CRM.vars.search.schema, function(entity) {
+ var primaryEntities = _.filter(CRM.crmSearchAdmin.schema, function(entity) {
return !_.includes(entity.type, 'EntityBridge') && !_.includes(entity.type, 'OptionList');
});
$scope.entities = formatForSelect2(primaryEntities, 'name', 'title_plural', ['description', 'icon']);
}
};
+ function addNum(name, num) {
+ return name + (num < 10 ? '_0' : '_') + num;
+ }
+
+ function getExistingJoins() {
+ return _.transform(ctrl.savedSearch.api_params.join || [], function(joins, join) {
+ joins[join[0].split(' AS ')[1]] = searchMeta.getJoin(join[0]);
+ }, {});
+ }
+
+ $scope.getJoin = searchMeta.getJoin;
+
$scope.getJoinEntities = function() {
- var joinEntities = _.transform(CRM.vars.search.links[ctrl.savedSearch.api_entity], function(joinEntities, link) {
- var entity = searchMeta.getEntity(link.entity);
- if (entity) {
- joinEntities.push({
- id: link.entity + ' AS ' + link.alias,
- text: entity.title_plural,
- description: '(' + link.alias + ')',
- icon: entity.icon
- });
+ var existingJoins = getExistingJoins();
+
+ function addEntityJoins(entity, stack, baseEntity) {
+ return _.transform(CRM.crmSearchAdmin.joins[entity], function(joinEntities, join) {
+ var num = 0;
+ // Add all joins that don't just point directly back to the original entity
+ if (!(baseEntity === join.entity && !join.multi)) {
+ do {
+ appendJoin(joinEntities, join, ++num, stack, entity);
+ } while (addNum((stack ? stack + '_' : '') + join.alias, num) in existingJoins);
+ }
+ }, []);
+ }
+
+ function appendJoin(collection, join, num, stack, baseEntity) {
+ var alias = addNum((stack ? stack + '_' : '') + join.alias, num),
+ opt = {
+ id: join.entity + ' AS ' + alias,
+ description: join.description,
+ text: join.label + (num > 1 ? ' ' + num : ''),
+ icon: searchMeta.getEntity(join.entity).icon,
+ disabled: alias in existingJoins
+ };
+ if (alias in existingJoins) {
+ opt.children = addEntityJoins(join.entity, (stack ? stack + '_' : '') + alias, baseEntity);
}
- }, []);
- return {results: joinEntities};
+ collection.push(opt);
+ }
+
+ return {results: addEntityJoins(ctrl.savedSearch.api_entity)};
};
$scope.addJoin = function() {
$timeout(function() {
if ($scope.controls.join) {
ctrl.savedSearch.api_params.join = ctrl.savedSearch.api_params.join || [];
- ctrl.savedSearch.api_params.join.push([$scope.controls.join, false]);
+ var join = searchMeta.getJoin($scope.controls.join),
+ params = [$scope.controls.join, false];
+ _.each(_.cloneDeep(join.conditions), function(condition) {
+ params.push(condition);
+ });
+ _.each(_.cloneDeep(join.defaults), function(condition) {
+ params.push(condition);
+ });
+ ctrl.savedSearch.api_params.join.push(params);
loadFieldOptions();
}
$scope.controls.join = '';
});
};
- $scope.changeJoin = function(idx) {
- if (ctrl.savedSearch.api_params.join[idx][0]) {
- ctrl.savedSearch.api_params.join[idx].length = 2;
- loadFieldOptions();
- } else {
- ctrl.clearParam('join', idx);
- }
- };
-
$scope.changeGroupBy = function(idx) {
if (!ctrl.savedSearch.api_params.groupBy[idx]) {
ctrl.clearParam('groupBy', idx);
if (ctrl.savedSearch.api_params.groupBy.length) {
_.each(ctrl.savedSearch.api_params.select, function(col, pos) {
if (!_.contains(col, '(') && ctrl.canAggregate(col)) {
- ctrl.savedSearch.api_params.select[pos] = ctrl.DEFAULT_AGGREGATE_FN + '(' + col + ')';
+ ctrl.savedSearch.api_params.select[pos] = ctrl.DEFAULT_AGGREGATE_FN + '(DISTINCT ' + col + ')';
}
});
}
$scope.formatResult = function(row, col) {
var info = searchMeta.parseExpr(col),
- key = info.fn ? (info.fn.name + ':' + info.path + info.suffix) : col,
- value = row[key];
+ value = row[info.alias];
if (info.fn && info.fn.name === 'COUNT') {
return value;
}
}
function getAllFields(suffix, disabledIf) {
- function formatFields(entityName, prefix) {
- return _.transform(searchMeta.getEntity(entityName).fields, function(result, field) {
- var item = {
- id: prefix + field.name + (field.options ? suffix : ''),
- text: field.label,
- description: field.description
- };
- if (disabledIf(item.id)) {
- item.disabled = true;
- }
- result.push(item);
- }, []);
+ function formatFields(entityName, join) {
+ var prefix = join ? join.alias + '.' : '',
+ result = [];
+
+ function addFields(fields) {
+ _.each(fields, function(field) {
+ var item = {
+ id: prefix + field.name + (field.options ? suffix : ''),
+ text: field.label,
+ description: field.description
+ };
+ if (disabledIf(item.id)) {
+ item.disabled = true;
+ }
+ result.push(item);
+ });
+ }
+
+ // Add extra searchable fields from bridge entity
+ if (join && join.bridge) {
+ addFields(_.filter(searchMeta.getEntity(join.bridge).fields, function(field) {
+ return (field.name !== 'id' && field.name !== 'entity_id' && field.name !== 'entity_table' && !field.fk_entity);
+ }));
+ }
+
+ addFields(searchMeta.getEntity(entityName).fields);
+ return result;
}
var mainEntity = searchMeta.getEntity(ctrl.savedSearch.api_entity),
result = [{
text: mainEntity.title_plural,
icon: mainEntity.icon,
- children: formatFields(ctrl.savedSearch.api_entity, '')
+ children: formatFields(ctrl.savedSearch.api_entity)
}];
_.each(ctrl.savedSearch.api_params.join, function(join) {
- var joinName = join[0].split(' AS '),
- joinEntity = searchMeta.getEntity(joinName[0]);
+ var joinInfo = searchMeta.getJoin(join[0]),
+ joinEntity = searchMeta.getEntity(joinInfo.entity);
result.push({
- text: joinEntity.title_plural + ' (' + joinName[1] + ')',
+ text: joinInfo.label,
+ description: joinInfo.description,
icon: joinEntity.icon,
- children: formatFields(joinEntity.name, joinName[1] + '.')
+ children: formatFields(joinEntity.name, joinInfo)
});
});
return result;
enqueue(mainEntity);
}
_.each(ctrl.savedSearch.api_params.join, function(join) {
- var joinName = join[0].split(' AS '),
- joinEntity = searchMeta.getEntity(joinName[0]);
+ var joinInfo = searchMeta.getJoin(join[0]),
+ joinEntity = searchMeta.getEntity(joinInfo.entity),
+ bridgeEntity = joinInfo.bridge ? searchMeta.getEntity(joinInfo.bridge) : null;
if (typeof joinEntity.optionsLoaded === 'undefined') {
enqueue(joinEntity);
}
+ if (bridgeEntity && typeof bridgeEntity.optionsLoaded === 'undefined') {
+ enqueue(bridgeEntity);
+ }
});
if (!_.isEmpty(entities)) {
crmApi4(entities).then(function(results) {