Merge pull request #18915 from colemanw/entityPaths2
[civicrm-core.git] / ext / search / ang / crmSearchAdmin.module.js
CommitLineData
25523059
CW
1(function(angular, $, _) {
2 "use strict";
3
4 // Shared between router and searchMeta service
2c7e2f4b 5 var searchEntity,
2c7e2f4b 6 undefined;
25523059
CW
7
8 // Declare module and route/controller/services
493f83d4 9 angular.module('crmSearchAdmin', CRM.angRequires('crmSearchAdmin'))
25523059
CW
10
11 .config(function($routeProvider) {
475029f6
CW
12 $routeProvider.when('/list', {
13 controller: 'searchList',
493f83d4 14 templateUrl: '~/crmSearchAdmin/searchList.html',
475029f6
CW
15 resolve: {
16 // Load data for lists
17 savedSearches: function(crmApi4) {
18 return crmApi4('SavedSearch', 'get', {
7620b30a
CW
19 select: [
20 'id',
21 'name',
22 'label',
23 'api_entity',
24 'form_values',
25 'GROUP_CONCAT(display.name ORDER BY display.id) AS display_name',
26 'GROUP_CONCAT(display.label ORDER BY display.id) AS display_label',
27 'GROUP_CONCAT(display.type:icon ORDER BY display.id) AS display_icon',
28 'GROUP_CONCAT(group.title) AS groups'
29 ],
30 join: [['SearchDisplay AS display'], ['Group AS group']],
475029f6
CW
31 where: [['api_entity', 'IS NOT NULL']],
32 groupBy: ['id']
33 });
34 }
35 }
36 });
2894db84
CW
37 $routeProvider.when('/create/:entity', {
38 controller: 'searchCreate',
964ecb17 39 template: '<crm-search-admin saved-search="$ctrl.savedSearch"></crm-search-admin>',
2894db84
CW
40 });
41 $routeProvider.when('/edit/:id', {
42 controller: 'searchEdit',
964ecb17 43 template: '<crm-search-admin saved-search="$ctrl.savedSearch"></crm-search-admin>',
2c7e2f4b 44 resolve: {
2894db84
CW
45 // Load saved search
46 savedSearch: function($route, crmApi4) {
47 var params = $route.current.params;
48 return crmApi4('SavedSearch', 'get', {
49 where: [['id', '=', params.id]],
50 chain: {
44402a2e 51 groups: ['Group', 'get', {where: [['saved_search_id', '=', '$id']]}],
2894db84
CW
52 displays: ['SearchDisplay', 'get', {where: [['saved_search_id', '=', '$id']]}]
53 }
54 }, 0);
2c7e2f4b
CW
55 }
56 }
25523059
CW
57 });
58 })
59
2894db84
CW
60 // Controller for creating a new search
61 .controller('searchCreate', function($scope, $routeParams, $location) {
62 searchEntity = $routeParams.entity;
2c7e2f4b 63 $scope.$ctrl = this;
2894db84
CW
64 this.savedSearch = {
65 api_entity: searchEntity,
66 };
25523059 67 // Changing entity will refresh the angular page
2894db84 68 $scope.$watch('$ctrl.savedSearch.api_entity', function(newEntity, oldEntity) {
25523059 69 if (newEntity && oldEntity && newEntity !== oldEntity) {
2c7e2f4b 70 $location.url('/create/' + newEntity);
25523059
CW
71 }
72 });
73 })
74
2894db84
CW
75 // Controller for editing a SavedSearch
76 .controller('searchEdit', function($scope, savedSearch) {
77 searchEntity = savedSearch.api_entity;
78 this.savedSearch = savedSearch;
79 $scope.$ctrl = this;
80 })
81
25523059
CW
82 .factory('searchMeta', function() {
83 function getEntity(entityName) {
84 if (entityName) {
25523059
CW
85 return _.find(CRM.vars.search.schema, {name: entityName});
86 }
87 }
c419e6ed
CW
88 function getField(fieldName, entityName) {
89 var dotSplit = fieldName.split('.'),
25523059 90 joinEntity = dotSplit.length > 1 ? dotSplit[0] : null,
f9cf8797
CW
91 name = _.last(dotSplit).split(':')[0],
92 field;
27bed3cb
CW
93 // Custom fields contain a dot in their fieldname
94 // If 3 segments, the first is the joinEntity and the last 2 are the custom field
95 if (dotSplit.length === 3) {
c419e6ed 96 name = dotSplit[1] + '.' + name;
27bed3cb
CW
97 }
98 // If 2 segments, it's ambiguous whether this is a custom field or joined field. Search the main entity first.
99 if (dotSplit.length === 2) {
f9cf8797 100 field = _.find(getEntity(entityName).fields, {name: dotSplit[0] + '.' + name});
27bed3cb 101 if (field) {
f9cf8797 102 field.entity = entityName;
27bed3cb
CW
103 return field;
104 }
105 }
25523059
CW
106 if (joinEntity) {
107 entityName = _.find(CRM.vars.search.links[entityName], {alias: joinEntity}).entity;
108 }
f9cf8797
CW
109 field = _.find(getEntity(entityName).fields, {name: name});
110 if (field) {
111 field.entity = entityName;
112 return field;
113 }
25523059
CW
114 }
115 return {
116 getEntity: getEntity,
117 getField: getField,
118 parseExpr: function(expr) {
f99d41d2 119 var result = {fn: null, modifier: ''},
25523059
CW
120 fieldName = expr,
121 bracketPos = expr.indexOf('(');
122 if (bracketPos >= 0) {
f99d41d2
CW
123 var parsed = expr.substr(bracketPos).match(/[ ]?([A-Z]+[ ]+)?([\w.:]+)/);
124 fieldName = parsed[2];
493f83d4 125 result.fn = _.find(CRM.crmSearchAdmin.functions, {name: expr.substring(0, bracketPos)});
f99d41d2 126 result.modifier = _.trim(parsed[1]);
25523059 127 }
c419e6ed
CW
128 result.field = expr ? getField(fieldName, searchEntity) : undefined;
129 if (result.field) {
130 var split = fieldName.split(':'),
131 prefixPos = split[0].lastIndexOf(result.field.name);
132 result.path = split[0];
133 result.prefix = prefixPos > 0 ? result.path.substring(0, prefixPos) : '';
134 result.suffix = !split[1] ? '' : ':' + split[1];
135 }
25523059 136 return result;
4b01551f
CW
137 },
138 // Find all possible search columns that could serve as contact_id for a smart group
139 getSmartGroupColumns: function(api_entity, api_params) {
140 var joins = _.pluck((api_params.join || []), 0),
141 entityCount = {};
142 return _.transform([api_entity].concat(joins), function(columns, joinExpr) {
143 var joinName = joinExpr.split(' AS '),
144 entityName = joinName[0],
145 entity = getEntity(entityName),
146 prefix = joinName[1] ? joinName[1] + '.' : '';
147 _.each(entity.fields, function(field) {
148 if ((entityName === 'Contact' && field.name === 'id') || field.fk_entity === 'Contact') {
149 columns.push({
150 id: prefix + field.name,
493f83d4 151 text: entity.title_plural + (entityCount[entityName] ? ' ' + entityCount[entityName] : '') + ': ' + field.label,
4b01551f
CW
152 icon: entity.icon
153 });
154 }
155 });
156 entityCount[entityName] = 1 + (entityCount[entityName] || 1);
157 });
25523059
CW
158 }
159 };
25523059
CW
160 });
161
162})(angular, CRM.$, CRM._);