X-Git-Url: https://vcs.fsf.org/?a=blobdiff_plain;f=ext%2Fsearch%2Fang%2FcrmSearchAdmin.module.js;h=7e737d109667ce4f1cefade078762a2680608d1e;hb=f0dcef9d944cfbfd16a286140afdcfc66e3d8202;hp=af31489c9aab42bd214682ea7f8c2f6cfe6041ca;hpb=4e93513a0be5ccbd2f2a1b2e86b34d0231d295e5;p=civicrm-core.git diff --git a/ext/search/ang/crmSearchAdmin.module.js b/ext/search/ang/crmSearchAdmin.module.js index af31489c9a..7e737d1096 100644 --- a/ext/search/ang/crmSearchAdmin.module.js +++ b/ext/search/ang/crmSearchAdmin.module.js @@ -3,6 +3,7 @@ // Shared between router and searchMeta service var searchEntity, + joinIndex, undefined; // Declare module and route/controller/services @@ -21,11 +22,11 @@ 'name', 'label', 'api_entity', - 'form_values', + 'api_params', 'GROUP_CONCAT(display.name ORDER BY display.id) AS display_name', 'GROUP_CONCAT(display.label ORDER BY display.id) AS display_label', 'GROUP_CONCAT(display.type:icon ORDER BY display.id) AS display_icon', - 'GROUP_CONCAT(group.title) AS groups' + 'GROUP_CONCAT(DISTINCT group.title) AS groups' ], join: [['SearchDisplay AS display'], ['Group AS group']], where: [['api_entity', 'IS NOT NULL']], @@ -36,6 +37,7 @@ }); $routeProvider.when('/create/:entity', { controller: 'searchCreate', + reloadOnSearch: false, template: '', }); $routeProvider.when('/edit/:id', { @@ -48,7 +50,7 @@ return crmApi4('SavedSearch', 'get', { where: [['id', '=', params.id]], chain: { - groups: ['Group', 'get', {where: [['saved_search_id', '=', '$id']]}], + groups: ['Group', 'get', {select: ['id', 'title', 'description', 'visibility', 'group_type'], where: [['saved_search_id', '=', '$id']]}], displays: ['SearchDisplay', 'get', {where: [['saved_search_id', '=', '$id']]}] } }, 0); @@ -82,13 +84,57 @@ .factory('searchMeta', function() { function getEntity(entityName) { if (entityName) { - return _.find(CRM.vars.search.schema, {name: entityName}); + return _.find(CRM.crmSearchAdmin.schema, {name: entityName}); } } - function getField(fieldName, entityName) { + // Get join metadata matching a given expression like "Email AS Contact_Email_contact_id_01" + function getJoin(fullNameOrAlias) { + var alias = _.last(fullNameOrAlias.split(' AS ')), + path = alias, + baseEntity = searchEntity, + label = [], + join, + result; + while (path.length) { + /* jshint -W083 */ + join = _.find(CRM.crmSearchAdmin.joins[baseEntity], function(join) { + return new RegExp('^' + join.alias + '_\\d\\d').test(path); + }); + if (!join) { + console.warn( 'Join ' + fullNameOrAlias + ' not found.'); + return; + } + path = path.replace(join.alias + '_', ''); + var num = parseInt(path.substr(0, 2), 10); + label.push(join.label + (num > 1 ? ' ' + num : '')); + path = path.replace(/^\d\d_?/, ''); + if (path.length) { + baseEntity = join.entity; + } + } + result = _.assign(_.cloneDeep(join), {label: label.join(' - '), alias: alias, baseEntity: baseEntity}); + // Add the numbered suffix to the join conditions + // If this is a deep join, also add the base entity prefix + var prefix = alias.replace(new RegExp('_?' + join.alias + '_?\\d?\\d?$'), ''); + _.each(result.conditions, function(condition) { + if (_.isArray(condition)) { + _.each(condition, function(ref, side) { + if (side !== 1 && _.includes(ref, '.')) { + condition[side] = ref.replace(join.alias + '.', alias + '.'); + } else if (side !== 1 && prefix.length && !_.includes(ref, '"') && !_.includes(ref, "'")) { + condition[side] = prefix + '.' + ref; + } + }); + } + }); + return result; + } + function getFieldAndJoin(fieldName, entityName) { var dotSplit = fieldName.split('.'), joinEntity = dotSplit.length > 1 ? dotSplit[0] : null, - name = _.last(dotSplit).split(':')[0]; + name = _.last(dotSplit).split(':')[0], + join, + field; // Custom fields contain a dot in their fieldname // If 3 segments, the first is the joinEntity and the last 2 are the custom field if (dotSplit.length === 3) { @@ -96,58 +142,87 @@ } // If 2 segments, it's ambiguous whether this is a custom field or joined field. Search the main entity first. if (dotSplit.length === 2) { - var field = _.find(getEntity(entityName).fields, {name: dotSplit[0] + '.' + name}); + field = _.find(getEntity(entityName).fields, {name: dotSplit[0] + '.' + name}); if (field) { - return field; + field.entity = entityName; + return {field: field}; } } if (joinEntity) { - entityName = _.find(CRM.vars.search.links[entityName], {alias: joinEntity}).entity; + join = getJoin(joinEntity); + entityName = getJoin(joinEntity).entity; + } + field = _.find(getEntity(entityName).fields, {name: name}); + if (!field && join && join.bridge) { + field = _.find(getEntity(join.bridge).fields, {name: name}); + } + if (field) { + field.entity = entityName; + return {field: field, join: join}; } - return _.find(getEntity(entityName).fields, {name: name}); + } + function parseExpr(expr) { + if (!expr) { + return; + } + var splitAs = expr.split(' AS '), + info = {fn: null, modifier: ''}, + fieldName = splitAs[0], + bracketPos = splitAs[0].indexOf('('); + if (bracketPos >= 0) { + var parsed = splitAs[0].substr(bracketPos).match(/[ ]?([A-Z]+[ ]+)?([\w.:]+)/); + fieldName = parsed[2]; + info.fn = _.find(CRM.crmSearchAdmin.functions, {name: expr.substring(0, bracketPos)}); + info.modifier = _.trim(parsed[1]); + } + var fieldAndJoin = getFieldAndJoin(fieldName, searchEntity); + if (fieldAndJoin) { + var split = fieldName.split(':'), + prefixPos = split[0].lastIndexOf(fieldAndJoin.field.name); + info.path = split[0]; + info.prefix = prefixPos > 0 ? info.path.substring(0, prefixPos) : ''; + info.suffix = !split[1] ? '' : ':' + split[1]; + info.field = fieldAndJoin.field; + info.join = fieldAndJoin.join; + info.alias = splitAs[1] || (info.fn ? info.fn.name + ':' + info.path + info.suffix : split[0]); + } + return info; } return { getEntity: getEntity, - getField: getField, - parseExpr: function(expr) { - var result = {fn: null, modifier: ''}, - fieldName = expr, - bracketPos = expr.indexOf('('); - if (bracketPos >= 0) { - var parsed = expr.substr(bracketPos).match(/[ ]?([A-Z]+[ ]+)?([\w.:]+)/); - fieldName = parsed[2]; - result.fn = _.find(CRM.crmSearchAdmin.functions, {name: expr.substring(0, bracketPos)}); - result.modifier = _.trim(parsed[1]); + getField: function(fieldName, entityName) { + return getFieldAndJoin(fieldName, entityName).field; + }, + getJoin: getJoin, + parseExpr: parseExpr, + getDefaultLabel: function(col) { + var info = parseExpr(col), + label = info.field.label; + if (info.fn) { + label = '(' + info.fn.title + ') ' + label; } - result.field = expr ? getField(fieldName, searchEntity) : undefined; - if (result.field) { - var split = fieldName.split(':'), - prefixPos = split[0].lastIndexOf(result.field.name); - result.path = split[0]; - result.prefix = prefixPos > 0 ? result.path.substring(0, prefixPos) : ''; - result.suffix = !split[1] ? '' : ':' + split[1]; + if (info.join) { + label = info.join.label + ': ' + label; } - return result; + return label; }, // Find all possible search columns that could serve as contact_id for a smart group getSmartGroupColumns: function(api_entity, api_params) { - var joins = _.pluck((api_params.join || []), 0), - entityCount = {}; + var joins = _.pluck((api_params.join || []), 0); return _.transform([api_entity].concat(joins), function(columns, joinExpr) { var joinName = joinExpr.split(' AS '), - entityName = joinName[0], - entity = getEntity(entityName), - prefix = joinName[1] ? joinName[1] + '.' : ''; + joinInfo = joinName[1] ? getJoin(joinName[1]) : {entity: joinName[0]}, + entity = getEntity(joinInfo.entity), + prefix = joinInfo.alias ? joinInfo.alias + '.' : ''; _.each(entity.fields, function(field) { - if ((entityName === 'Contact' && field.name === 'id') || field.fk_entity === 'Contact') { + if ((entity.name === 'Contact' && field.name === 'id') || (field.fk_entity === 'Contact' && joinInfo.baseEntity !== 'Contact')) { columns.push({ id: prefix + field.name, - text: entity.title_plural + (entityCount[entityName] ? ' ' + entityCount[entityName] : '') + ': ' + field.label, + text: (joinInfo.label ? joinInfo.label + ': ' : '') + field.label, icon: entity.icon }); } }); - entityCount[entityName] = 1 + (entityCount[entityName] || 1); }); } };