Commit | Line | Data |
---|---|---|
25523059 CW |
1 | (function(angular, $, _) { |
2 | "use strict"; | |
3 | ||
964ecb17 | 4 | angular.module('searchAdmin').component('crmSearchAdmin', { |
25523059 | 5 | bindings: { |
2894db84 | 6 | savedSearch: '<' |
25523059 | 7 | }, |
964ecb17 | 8 | templateUrl: '~/searchAdmin/crmSearchAdmin.html', |
25523059 CW |
9 | controller: function($scope, $element, $timeout, crmApi4, dialogService, searchMeta, formatForSelect2) { |
10 | var ts = $scope.ts = CRM.ts(), | |
11 | ctrl = this; | |
5fcd63f4 CW |
12 | |
13 | this.DEFAULT_AGGREGATE_FN = 'GROUP_CONCAT'; | |
14 | ||
25523059 CW |
15 | this.selectedRows = []; |
16 | this.limit = CRM.cache.get('searchPageSize', 30); | |
17 | this.page = 1; | |
f9197b41 | 18 | this.displayTypes = _.indexBy(CRM.searchAdmin.displayTypes, 'name'); |
25523059 | 19 | // After a search this.results is an object of result arrays keyed by page, |
c419e6ed | 20 | // Initially this.results is an empty string because 1: it's falsey (unlike an empty object) and 2: it doesn't throw an error if you try to access undefined properties (unlike null) |
25523059 CW |
21 | this.results = ''; |
22 | this.rowCount = false; | |
2894db84 | 23 | this.allRowsSelected = false; |
25523059 CW |
24 | // Have the filters (WHERE, HAVING, GROUP BY, JOIN) changed? |
25 | this.stale = true; | |
25523059 | 26 | |
f9197b41 | 27 | $scope.controls = {tab: 'compose'}; |
25523059 | 28 | $scope.joinTypes = [{k: false, v: ts('Optional')}, {k: true, v: ts('Required')}]; |
9813ae79 | 29 | $scope.entities = formatForSelect2(CRM.vars.search.schema, 'name', 'title_plural', ['description', 'icon']); |
25523059 CW |
30 | this.perm = { |
31 | editGroups: CRM.checkPerm('edit groups') | |
32 | }; | |
33 | ||
2894db84 CW |
34 | this.$onInit = function() { |
35 | this.entityTitle = searchMeta.getEntity(this.savedSearch.api_entity).title_plural; | |
36 | ||
f9197b41 CW |
37 | this.savedSearch.displays = this.savedSearch.displays || []; |
38 | ||
2894db84 CW |
39 | if (!this.savedSearch.api_params) { |
40 | this.savedSearch.api_params = { | |
41 | select: getDefaultSelect(), | |
42 | orderBy: {}, | |
43 | where: [], | |
44 | }; | |
45 | } | |
46 | ||
47 | $scope.$watchCollection('$ctrl.savedSearch.api_params.select', onChangeSelect); | |
48 | ||
49 | $scope.$watch('$ctrl.savedSearch.api_params.where', onChangeFilters, true); | |
50 | ||
51 | if (this.paramExists('groupBy')) { | |
52 | this.savedSearch.api_params.groupBy = this.savedSearch.api_params.groupBy || []; | |
53 | $scope.$watchCollection('$ctrl.savedSearch.api_params.groupBy', onChangeFilters); | |
54 | } | |
55 | ||
56 | if (this.paramExists('join')) { | |
57 | this.savedSearch.api_params.join = this.savedSearch.api_params.join || []; | |
58 | $scope.$watch('$ctrl.savedSearch.api_params.join', onChangeFilters, true); | |
59 | } | |
60 | ||
61 | if (this.paramExists('having')) { | |
62 | this.savedSearch.api_params.having = this.savedSearch.api_params.having || []; | |
63 | $scope.$watch('$ctrl.savedSearch.api_params.having', onChangeFilters, true); | |
64 | } | |
65 | ||
66 | loadFieldOptions(); | |
67 | }; | |
25523059 CW |
68 | |
69 | this.paramExists = function(param) { | |
2894db84 | 70 | return _.includes(searchMeta.getEntity(ctrl.savedSearch.api_entity).params, param); |
25523059 CW |
71 | }; |
72 | ||
f9197b41 CW |
73 | this.addDisplay = function(type) { |
74 | $scope.controls.tab = 'display_' + ctrl.savedSearch.displays.length; | |
75 | ctrl.savedSearch.displays.push({ | |
76 | type: type | |
77 | }); | |
78 | }; | |
79 | ||
25523059 | 80 | $scope.getJoinEntities = function() { |
2894db84 | 81 | var joinEntities = _.transform(CRM.vars.search.links[ctrl.savedSearch.api_entity], function(joinEntities, link) { |
25523059 CW |
82 | var entity = searchMeta.getEntity(link.entity); |
83 | if (entity) { | |
84 | joinEntities.push({ | |
85 | id: link.entity + ' AS ' + link.alias, | |
9813ae79 | 86 | text: entity.title_plural, |
25523059 CW |
87 | description: '(' + link.alias + ')', |
88 | icon: entity.icon | |
89 | }); | |
90 | } | |
91 | }, []); | |
92 | return {results: joinEntities}; | |
93 | }; | |
94 | ||
95 | $scope.addJoin = function() { | |
96 | // Debounce the onchange event using timeout | |
97 | $timeout(function() { | |
98 | if ($scope.controls.join) { | |
2894db84 CW |
99 | ctrl.savedSearch.api_params.join = ctrl.savedSearch.api_params.join || []; |
100 | ctrl.savedSearch.api_params.join.push([$scope.controls.join, false]); | |
25523059 CW |
101 | loadFieldOptions(); |
102 | } | |
103 | $scope.controls.join = ''; | |
104 | }); | |
105 | }; | |
106 | ||
107 | $scope.changeJoin = function(idx) { | |
2894db84 CW |
108 | if (ctrl.savedSearch.api_params.join[idx][0]) { |
109 | ctrl.savedSearch.api_params.join[idx].length = 2; | |
25523059 CW |
110 | loadFieldOptions(); |
111 | } else { | |
112 | ctrl.clearParam('join', idx); | |
113 | } | |
114 | }; | |
115 | ||
116 | $scope.changeGroupBy = function(idx) { | |
2894db84 | 117 | if (!ctrl.savedSearch.api_params.groupBy[idx]) { |
25523059 CW |
118 | ctrl.clearParam('groupBy', idx); |
119 | } | |
5fcd63f4 | 120 | // Remove aggregate functions when no grouping |
2894db84 CW |
121 | if (!ctrl.savedSearch.api_params.groupBy.length) { |
122 | _.each(ctrl.savedSearch.api_params.select, function(col, pos) { | |
5fcd63f4 CW |
123 | if (_.contains(col, '(')) { |
124 | var info = searchMeta.parseExpr(col); | |
125 | if (info.fn.category === 'aggregate') { | |
2894db84 | 126 | ctrl.savedSearch.api_params.select[pos] = info.path + info.suffix; |
5fcd63f4 CW |
127 | } |
128 | } | |
129 | }); | |
130 | } | |
25523059 CW |
131 | }; |
132 | ||
133 | /** | |
134 | * Called when clicking on a column header | |
135 | * @param col | |
136 | * @param $event | |
137 | */ | |
138 | $scope.setOrderBy = function(col, $event) { | |
139 | var dir = $scope.getOrderBy(col) === 'fa-sort-asc' ? 'DESC' : 'ASC'; | |
140 | if (!$event.shiftKey) { | |
2894db84 | 141 | ctrl.savedSearch.api_params.orderBy = {}; |
25523059 | 142 | } |
2894db84 | 143 | ctrl.savedSearch.api_params.orderBy[col] = dir; |
7da9d079 CW |
144 | if (ctrl.results) { |
145 | ctrl.refreshPage(); | |
146 | } | |
25523059 CW |
147 | }; |
148 | ||
149 | /** | |
150 | * Returns crm-i icon class for a sortable column | |
151 | * @param col | |
152 | * @returns {string} | |
153 | */ | |
154 | $scope.getOrderBy = function(col) { | |
2894db84 | 155 | var dir = ctrl.savedSearch.api_params.orderBy && ctrl.savedSearch.api_params.orderBy[col]; |
25523059 CW |
156 | if (dir) { |
157 | return 'fa-sort-' + dir.toLowerCase(); | |
158 | } | |
159 | return 'fa-sort disabled'; | |
160 | }; | |
161 | ||
162 | $scope.addParam = function(name) { | |
2894db84 CW |
163 | if ($scope.controls[name] && !_.contains(ctrl.savedSearch.api_params[name], $scope.controls[name])) { |
164 | ctrl.savedSearch.api_params[name].push($scope.controls[name]); | |
25523059 CW |
165 | if (name === 'groupBy') { |
166 | // Expand the aggregate block | |
167 | $timeout(function() { | |
168 | $('#crm-search-build-group-aggregate.collapsed .collapsible-title').click(); | |
169 | }, 10); | |
170 | } | |
171 | } | |
172 | $scope.controls[name] = ''; | |
173 | }; | |
174 | ||
175 | // Deletes an item from an array param | |
176 | this.clearParam = function(name, idx) { | |
2894db84 | 177 | ctrl.savedSearch.api_params[name].splice(idx, 1); |
25523059 CW |
178 | }; |
179 | ||
180 | // Prevent visual jumps in results table height during loading | |
181 | function lockTableHeight() { | |
182 | var $table = $('.crm-search-results', $element); | |
183 | $table.css('height', $table.height()); | |
184 | } | |
185 | ||
186 | function unlockTableHeight() { | |
187 | $('.crm-search-results', $element).css('height', ''); | |
188 | } | |
189 | ||
5fcd63f4 CW |
190 | // Ensure all non-grouped columns are aggregated if using GROUP BY |
191 | function aggregateGroupByColumns() { | |
2894db84 CW |
192 | if (ctrl.savedSearch.api_params.groupBy.length) { |
193 | _.each(ctrl.savedSearch.api_params.select, function(col, pos) { | |
5fcd63f4 | 194 | if (!_.contains(col, '(') && ctrl.canAggregate(col)) { |
2894db84 | 195 | ctrl.savedSearch.api_params.select[pos] = ctrl.DEFAULT_AGGREGATE_FN + '(' + col + ')'; |
5fcd63f4 CW |
196 | } |
197 | }); | |
198 | } | |
199 | } | |
200 | ||
25523059 CW |
201 | // Debounced callback for loadResults |
202 | function _loadResultsCallback() { | |
203 | // Multiply limit to read 2 pages at once & save ajax requests | |
2894db84 | 204 | var params = angular.merge({debug: true, limit: ctrl.limit * 2}, ctrl.savedSearch.api_params); |
25523059 CW |
205 | lockTableHeight(); |
206 | $scope.error = false; | |
207 | if (ctrl.stale) { | |
208 | ctrl.page = 1; | |
209 | ctrl.rowCount = false; | |
210 | } | |
211 | if (ctrl.rowCount === false) { | |
212 | params.select.push('row_count'); | |
213 | } | |
214 | params.offset = ctrl.limit * (ctrl.page - 1); | |
2894db84 | 215 | crmApi4(ctrl.savedSearch.api_entity, 'get', params).then(function(success) { |
25523059 CW |
216 | if (ctrl.stale) { |
217 | ctrl.results = {}; | |
218 | } | |
219 | if (ctrl.rowCount === false) { | |
220 | ctrl.rowCount = success.count; | |
221 | } | |
222 | ctrl.debug = success.debug; | |
223 | // populate this page & the next | |
224 | ctrl.results[ctrl.page] = success.slice(0, ctrl.limit); | |
225 | if (success.length > ctrl.limit) { | |
226 | ctrl.results[ctrl.page + 1] = success.slice(ctrl.limit); | |
227 | } | |
228 | $scope.loading = false; | |
229 | ctrl.stale = false; | |
230 | unlockTableHeight(); | |
231 | }, function(error) { | |
232 | $scope.loading = false; | |
233 | ctrl.results = {}; | |
234 | ctrl.stale = true; | |
235 | ctrl.debug = error.debug; | |
236 | $scope.error = errorMsg(error); | |
9c4a1dae CW |
237 | }) |
238 | .finally(function() { | |
239 | if (ctrl.debug) { | |
2894db84 | 240 | ctrl.debug.params = JSON.stringify(_.extend({version: 4}, ctrl.savedSearch.api_params), null, 2); |
8afb2047 CW |
241 | if (ctrl.debug.timeIndex) { |
242 | ctrl.debug.timeIndex = Number.parseFloat(ctrl.debug.timeIndex).toPrecision(2); | |
243 | } | |
9c4a1dae CW |
244 | } |
245 | }); | |
25523059 CW |
246 | } |
247 | ||
248 | var _loadResults = _.debounce(_loadResultsCallback, 250); | |
249 | ||
250 | function loadResults() { | |
251 | $scope.loading = true; | |
5fcd63f4 | 252 | aggregateGroupByColumns(); |
25523059 CW |
253 | _loadResults(); |
254 | } | |
255 | ||
256 | // What to tell the user when search returns an error from the server | |
257 | // Todo: parse error codes and give helpful feedback. | |
258 | function errorMsg(error) { | |
259 | return ts('Ensure all search critera are set correctly and try again.'); | |
260 | } | |
261 | ||
262 | this.changePage = function() { | |
263 | if (ctrl.stale || !ctrl.results[ctrl.page]) { | |
264 | lockTableHeight(); | |
265 | loadResults(); | |
266 | } | |
267 | }; | |
268 | ||
269 | this.refreshAll = function() { | |
270 | ctrl.stale = true; | |
271 | ctrl.selectedRows.length = 0; | |
272 | loadResults(); | |
273 | }; | |
274 | ||
275 | // Refresh results while staying on current page. | |
276 | this.refreshPage = function() { | |
277 | lockTableHeight(); | |
278 | ctrl.results = {}; | |
279 | loadResults(); | |
280 | }; | |
281 | ||
282 | $scope.onClickSearch = function() { | |
283 | if (ctrl.autoSearch) { | |
284 | ctrl.autoSearch = false; | |
285 | } else { | |
286 | ctrl.refreshAll(); | |
287 | } | |
288 | }; | |
289 | ||
290 | $scope.onClickAuto = function() { | |
291 | ctrl.autoSearch = !ctrl.autoSearch; | |
292 | if (ctrl.autoSearch && ctrl.stale) { | |
293 | ctrl.refreshAll(); | |
294 | } | |
0b1769c6 | 295 | $('.crm-search-auto-toggle').blur(); |
25523059 CW |
296 | }; |
297 | ||
298 | $scope.onChangeLimit = function() { | |
299 | // Refresh only if search has already been run | |
300 | if (ctrl.autoSearch || ctrl.results) { | |
301 | // Save page size in localStorage | |
302 | CRM.cache.set('searchPageSize', ctrl.limit); | |
303 | ctrl.refreshAll(); | |
304 | } | |
305 | }; | |
306 | ||
307 | function onChangeSelect(newSelect, oldSelect) { | |
7da9d079 | 308 | // When removing a column from SELECT, also remove from ORDER BY |
2894db84 CW |
309 | _.each(_.difference(_.keys(ctrl.savedSearch.api_params.orderBy), newSelect), function(col) { |
310 | delete ctrl.savedSearch.api_params.orderBy[col]; | |
7da9d079 | 311 | }); |
25523059 CW |
312 | // Re-arranging or removing columns doesn't merit a refresh, only adding columns does |
313 | if (!oldSelect || _.difference(newSelect, oldSelect).length) { | |
314 | if (ctrl.autoSearch) { | |
315 | ctrl.refreshPage(); | |
316 | } else { | |
317 | ctrl.stale = true; | |
318 | } | |
319 | } | |
2c7e2f4b | 320 | if (ctrl.load) { |
f9197b41 | 321 | ctrl.saved = false; |
2c7e2f4b | 322 | } |
25523059 CW |
323 | } |
324 | ||
25523059 CW |
325 | function onChangeFilters() { |
326 | ctrl.stale = true; | |
327 | ctrl.selectedRows.length = 0; | |
2c7e2f4b | 328 | if (ctrl.load) { |
f9197b41 | 329 | ctrl.saved = false; |
2c7e2f4b | 330 | } |
25523059 CW |
331 | if (ctrl.autoSearch) { |
332 | ctrl.refreshAll(); | |
333 | } | |
334 | } | |
335 | ||
336 | $scope.selectAllRows = function() { | |
337 | // Deselect all | |
338 | if (ctrl.allRowsSelected) { | |
339 | ctrl.allRowsSelected = false; | |
340 | ctrl.selectedRows.length = 0; | |
341 | return; | |
342 | } | |
343 | // Select all | |
344 | ctrl.allRowsSelected = true; | |
345 | if (ctrl.page === 1 && ctrl.results[1].length < ctrl.limit) { | |
346 | ctrl.selectedRows = _.pluck(ctrl.results[1], 'id'); | |
347 | return; | |
348 | } | |
349 | // If more than one page of results, use ajax to fetch all ids | |
350 | $scope.loadingAllRows = true; | |
2894db84 | 351 | var params = _.cloneDeep(ctrl.savedSearch.api_params); |
25523059 | 352 | params.select = ['id']; |
2894db84 | 353 | crmApi4(ctrl.savedSearch.api_entity, 'get', params, ['id']).then(function(ids) { |
25523059 CW |
354 | $scope.loadingAllRows = false; |
355 | ctrl.selectedRows = _.toArray(ids); | |
356 | }); | |
357 | }; | |
358 | ||
359 | $scope.selectRow = function(row) { | |
360 | var index = ctrl.selectedRows.indexOf(row.id); | |
361 | if (index < 0) { | |
362 | ctrl.selectedRows.push(row.id); | |
363 | ctrl.allRowsSelected = (ctrl.rowCount === ctrl.selectedRows.length); | |
364 | } else { | |
365 | ctrl.allRowsSelected = false; | |
366 | ctrl.selectedRows.splice(index, 1); | |
367 | } | |
368 | }; | |
369 | ||
370 | $scope.isRowSelected = function(row) { | |
371 | return ctrl.allRowsSelected || _.includes(ctrl.selectedRows, row.id); | |
372 | }; | |
373 | ||
374 | this.getFieldLabel = function(col) { | |
375 | var info = searchMeta.parseExpr(col), | |
b6b6cb2d | 376 | label = info.field.label; |
25523059 CW |
377 | if (info.fn) { |
378 | label = '(' + info.fn.title + ') ' + label; | |
379 | } | |
380 | return label; | |
381 | }; | |
382 | ||
383 | // Is a column eligible to use an aggregate function? | |
384 | this.canAggregate = function(col) { | |
4f3a95d9 | 385 | var info = searchMeta.parseExpr(col); |
25523059 | 386 | // If the column is used for a groupBy, no |
2894db84 | 387 | if (ctrl.savedSearch.api_params.groupBy.indexOf(info.path) > -1) { |
25523059 CW |
388 | return false; |
389 | } | |
390 | // If the entity this column belongs to is being grouped by id, then also no | |
2894db84 | 391 | return ctrl.savedSearch.api_params.groupBy.indexOf(info.prefix + 'id') < 0; |
25523059 CW |
392 | }; |
393 | ||
394 | $scope.formatResult = function formatResult(row, col) { | |
395 | var info = searchMeta.parseExpr(col), | |
396 | key = info.fn ? (info.fn.name + ':' + info.path + info.suffix) : col, | |
397 | value = row[key]; | |
7ce7b1cd | 398 | if (info.fn && info.fn.name === 'COUNT') { |
2d198bb4 CW |
399 | return value; |
400 | } | |
25523059 CW |
401 | return formatFieldValue(info.field, value); |
402 | }; | |
403 | ||
404 | function formatFieldValue(field, value) { | |
405 | var type = field.data_type; | |
7ce7b1cd CW |
406 | if (_.isArray(value)) { |
407 | return _.map(value, function(val) { | |
408 | return formatFieldValue(field, val); | |
409 | }).join(', '); | |
410 | } | |
25523059 CW |
411 | if (value && (type === 'Date' || type === 'Timestamp') && /^\d{4}-\d{2}-\d{2}/.test(value)) { |
412 | return CRM.utils.formatDate(value, null, type === 'Timestamp'); | |
413 | } | |
414 | else if (type === 'Boolean' && typeof value === 'boolean') { | |
415 | return value ? ts('Yes') : ts('No'); | |
416 | } | |
7ce7b1cd | 417 | else if (type === 'Money' && typeof value === 'number') { |
2d198bb4 CW |
418 | return CRM.formatMoney(value); |
419 | } | |
25523059 CW |
420 | return value; |
421 | } | |
422 | ||
25523059 CW |
423 | $scope.fieldsForGroupBy = function() { |
424 | return {results: getAllFields('', function(key) { | |
2894db84 | 425 | return _.contains(ctrl.savedSearch.api_params.groupBy, key); |
25523059 CW |
426 | }) |
427 | }; | |
428 | }; | |
429 | ||
430 | $scope.fieldsForSelect = function() { | |
431 | return {results: getAllFields(':label', function(key) { | |
2894db84 | 432 | return _.contains(ctrl.savedSearch.api_params.select, key); |
25523059 CW |
433 | }) |
434 | }; | |
435 | }; | |
436 | ||
437 | $scope.fieldsForWhere = function() { | |
438 | return {results: getAllFields(':name', _.noop)}; | |
439 | }; | |
440 | ||
441 | $scope.fieldsForHaving = function() { | |
2894db84 | 442 | return {results: _.transform(ctrl.savedSearch.api_params.select, function(fields, name) { |
25523059 CW |
443 | fields.push({id: name, text: ctrl.getFieldLabel(name)}); |
444 | })}; | |
445 | }; | |
446 | ||
447 | function getDefaultSelect() { | |
c419e6ed | 448 | return _.filter(['id', 'display_name', 'label', 'title', 'location_type_id:label'], function(field) { |
2894db84 | 449 | return !!searchMeta.getField(field, ctrl.savedSearch.api_entity); |
c419e6ed | 450 | }); |
25523059 CW |
451 | } |
452 | ||
453 | function getAllFields(suffix, disabledIf) { | |
454 | function formatFields(entityName, prefix) { | |
455 | return _.transform(searchMeta.getEntity(entityName).fields, function(result, field) { | |
456 | var item = { | |
457 | id: prefix + field.name + (field.options ? suffix : ''), | |
b6b6cb2d | 458 | text: field.label, |
25523059 CW |
459 | description: field.description |
460 | }; | |
461 | if (disabledIf(item.id)) { | |
462 | item.disabled = true; | |
463 | } | |
464 | result.push(item); | |
465 | }, []); | |
466 | } | |
467 | ||
2894db84 | 468 | var mainEntity = searchMeta.getEntity(ctrl.savedSearch.api_entity), |
25523059 | 469 | result = [{ |
9813ae79 | 470 | text: mainEntity.title_plural, |
25523059 | 471 | icon: mainEntity.icon, |
2894db84 | 472 | children: formatFields(ctrl.savedSearch.api_entity, '') |
25523059 | 473 | }]; |
2894db84 | 474 | _.each(ctrl.savedSearch.api_params.join, function(join) { |
25523059 CW |
475 | var joinName = join[0].split(' AS '), |
476 | joinEntity = searchMeta.getEntity(joinName[0]); | |
477 | result.push({ | |
9813ae79 | 478 | text: joinEntity.title_plural + ' (' + joinName[1] + ')', |
25523059 CW |
479 | icon: joinEntity.icon, |
480 | children: formatFields(joinEntity.name, joinName[1] + '.') | |
481 | }); | |
482 | }); | |
483 | return result; | |
484 | } | |
485 | ||
486 | /** | |
487 | * Fetch pseudoconstants for main entity + joined entities | |
488 | * | |
489 | * Sets an optionsLoaded property on each entity to avoid duplicate requests | |
490 | */ | |
491 | function loadFieldOptions() { | |
2894db84 | 492 | var mainEntity = searchMeta.getEntity(ctrl.savedSearch.api_entity), |
25523059 CW |
493 | entities = {}; |
494 | ||
495 | function enqueue(entity) { | |
496 | entity.optionsLoaded = false; | |
497 | entities[entity.name] = [entity.name, 'getFields', { | |
22601c92 | 498 | loadOptions: ['id', 'name', 'label', 'description', 'color', 'icon'], |
25523059 CW |
499 | where: [['options', '!=', false]], |
500 | select: ['options'] | |
501 | }, {name: 'options'}]; | |
502 | } | |
503 | ||
504 | if (typeof mainEntity.optionsLoaded === 'undefined') { | |
505 | enqueue(mainEntity); | |
506 | } | |
2894db84 | 507 | _.each(ctrl.savedSearch.api_params.join, function(join) { |
25523059 CW |
508 | var joinName = join[0].split(' AS '), |
509 | joinEntity = searchMeta.getEntity(joinName[0]); | |
510 | if (typeof joinEntity.optionsLoaded === 'undefined') { | |
511 | enqueue(joinEntity); | |
512 | } | |
513 | }); | |
514 | if (!_.isEmpty(entities)) { | |
515 | crmApi4(entities).then(function(results) { | |
516 | _.each(results, function(fields, entityName) { | |
517 | var entity = searchMeta.getEntity(entityName); | |
518 | _.each(fields, function(options, fieldName) { | |
519 | _.find(entity.fields, {name: fieldName}).options = options; | |
520 | }); | |
521 | entity.optionsLoaded = true; | |
522 | }); | |
523 | }); | |
524 | } | |
525 | } | |
526 | ||
25523059 CW |
527 | } |
528 | }); | |
529 | ||
530 | })(angular, CRM.$, CRM._); |