Search kit: Add token selector in display admin UI, allow tokens in tooltips
[civicrm-core.git] / ext / search / ang / crmSearchDisplay.module.js
1 (function(angular, $, _) {
2 "use strict";
3
4 // Declare module
5 angular.module('crmSearchDisplay', CRM.angRequires('crmSearchDisplay'))
6
7 .factory('searchDisplayUtils', function() {
8
9 function replaceTokens(str, data) {
10 if (!str) {
11 return '';
12 }
13 _.each(data, function(value, key) {
14 str = str.replace('[' + key + ']', value);
15 });
16 return str;
17 }
18
19 function getUrl(link, row) {
20 var url = replaceTokens(link, row);
21 if (url.slice(0, 1) !== '/' && url.slice(0, 4) !== 'http') {
22 url = CRM.url(url);
23 }
24 return _.escape(url);
25 }
26
27 function formatSearchValue(row, col, value) {
28 var type = col.dataType,
29 result = value;
30 if (_.isArray(value)) {
31 return _.map(value, function(val) {
32 return formatSearchValue(col, val);
33 }).join(', ');
34 }
35 if (value && (type === 'Date' || type === 'Timestamp') && /^\d{4}-\d{2}-\d{2}/.test(value)) {
36 result = CRM.utils.formatDate(value, null, type === 'Timestamp');
37 }
38 else if (type === 'Boolean' && typeof value === 'boolean') {
39 result = value ? ts('Yes') : ts('No');
40 }
41 else if (type === 'Money' && typeof value === 'number') {
42 result = CRM.formatMoney(value);
43 }
44 result = _.escape(result);
45 if (col.link) {
46 result = '<a href="' + getUrl(col.link, row) + '">' + result + '</a>';
47 }
48 return result;
49 }
50
51 function canAggregate(fieldName, prefix, apiParams) {
52 // If the query does not use grouping, never
53 if (!apiParams.groupBy.length) {
54 return false;
55 }
56 // If the column is used for a groupBy, no
57 if (apiParams.groupBy.indexOf(prefix + fieldName) > -1) {
58 return false;
59 }
60 // If the entity this column belongs to is being grouped by id, then also no
61 return apiParams.groupBy.indexOf(prefix + 'id') < 0;
62 }
63
64 function prepareColumns(columns, apiParams) {
65 columns = _.cloneDeep(columns);
66 _.each(columns, function(col, num) {
67 var index = apiParams.select.indexOf(col.expr);
68 if (_.includes(col.expr, '(') && !_.includes(col.expr, ' AS ')) {
69 col.expr += ' AS column_' + num;
70 apiParams.select[index] += ' AS column_' + num;
71 }
72 col.key = _.last(col.expr.split(' AS '));
73 });
74 return columns;
75 }
76
77 function prepareParams(apiParams, filters, page) {
78 var params = _.cloneDeep(apiParams);
79 if (_.isEmpty(params.where)) {
80 params.where = [];
81 }
82 // Select the ids of joined entities (helps with displaying links)
83 _.each(params.join, function(join) {
84 var joinEntity = join[0].split(' AS ')[1],
85 idField = joinEntity + '.id';
86 if (!_.includes(params.select, idField) && !searchDisplayUtils.canAggregate('id', joinEntity + '.', params)) {
87 params.select.push(idField);
88 }
89 });
90 _.each(filters, function(value, key) {
91 if (value) {
92 params.where.push([key, 'CONTAINS', value]);
93 }
94 });
95 if (page) {
96 params.offset = (page - 1) * apiParams.limit;
97 params.select.push('row_count');
98 }
99 return params;
100 }
101
102 return {
103 formatSearchValue: formatSearchValue,
104 canAggregate: canAggregate,
105 prepareColumns: prepareColumns,
106 prepareParams: prepareParams,
107 replaceTokens: replaceTokens
108 };
109 });
110
111 })(angular, CRM.$, CRM._);