From: Coleman Watts Date: Wed, 24 Feb 2021 01:38:39 +0000 (-0500) Subject: SearchKit - add option to rewrite field output in displays X-Git-Url: https://vcs.fsf.org/?a=commitdiff_plain;h=69f0bd2bb322583d97636443a1d2353d6a4c4e5b;p=civicrm-core.git SearchKit - add option to rewrite field output in displays --- diff --git a/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js b/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js index 3627c41a51..afea8e8b60 100644 --- a/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js +++ b/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js @@ -70,20 +70,26 @@ return searchMeta.getDefaultLabel(expr); }; - function fieldToColumn(fieldExpr) { - var info = searchMeta.parseExpr(fieldExpr); - return { - key: info.alias, - label: searchMeta.getDefaultLabel(fieldExpr), - dataType: (info.fn && info.fn.name === 'COUNT') ? 'Integer' : info.field.data_type - }; + function fieldToColumn(fieldExpr, defaults) { + var info = searchMeta.parseExpr(fieldExpr), + values = _.cloneDeep(defaults); + if (defaults.key) { + values.key = info.alias; + } + if (defaults.label) { + values.label = searchMeta.getDefaultLabel(fieldExpr); + } + if (defaults.dataType) { + values.dataType = (info.fn && info.fn.name === 'COUNT') ? 'Integer' : info.field && info.field.data_type; + } + return values; } // Helper function to sort active from hidden columns and initialize each column with defaults - this.initColumns = function() { + this.initColumns = function(defaults) { if (!ctrl.display.settings.columns) { ctrl.display.settings.columns = _.transform(ctrl.savedSearch.api_params.select, function(columns, fieldExpr) { - columns.push(fieldToColumn(fieldExpr)); + columns.push(fieldToColumn(fieldExpr, defaults)); }); ctrl.hiddenColumns = []; } else { @@ -94,7 +100,7 @@ ctrl.hiddenColumns = _.transform(ctrl.savedSearch.api_params.select, function(hiddenColumns, fieldExpr) { var key = _.last(fieldExpr.split(' AS ')); if (!_.includes(activeColumns, key)) { - hiddenColumns.push(fieldToColumn(fieldExpr)); + hiddenColumns.push(fieldToColumn(fieldExpr, defaults)); } }); _.eachRight(activeColumns, function(key, index) { diff --git a/ext/search/ang/crmSearchAdmin/displays/common/fieldOptions.html b/ext/search/ang/crmSearchAdmin/displays/common/fieldOptions.html index 81f1b302f6..d05271bd36 100644 --- a/ext/search/ang/crmSearchAdmin/displays/common/fieldOptions.html +++ b/ext/search/ang/crmSearchAdmin/displays/common/fieldOptions.html @@ -7,3 +7,11 @@ +
+ + + +
diff --git a/ext/search/ang/crmSearchAdmin/displays/common/unusedColumns.html b/ext/search/ang/crmSearchAdmin/displays/common/unusedColumns.html index 08132e97c6..ed093f54e6 100644 --- a/ext/search/ang/crmSearchAdmin/displays/common/unusedColumns.html +++ b/ext/search/ang/crmSearchAdmin/displays/common/unusedColumns.html @@ -1,9 +1,8 @@ -
+
{{:: ts('Unused') }}
{{ $ctrl.parent.getFieldLabel(col.key) }}
- diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.component.js b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.component.js index 777191ef1a..54dd7008c7 100644 --- a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.component.js +++ b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.component.js @@ -38,7 +38,7 @@ pager: true }; } - ctrl.parent.initColumns(); + ctrl.parent.initColumns({key: true, dataType: true}); }; } diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html index fb02a78279..10b1a60296 100644 --- a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html +++ b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html @@ -26,22 +26,24 @@ {{:: ts('Fields') }}
{{ $ctrl.parent.getFieldLabel(col.key) }} -
- -
- -
+
+
-
- - - - -
- +
+ + + +
+
+ +
+
diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.component.js b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.component.js index ccb4fd5c8c..bd958c37bf 100644 --- a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.component.js +++ b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.component.js @@ -22,7 +22,7 @@ pager: true }; } - ctrl.parent.initColumns(); + ctrl.parent.initColumns({key: true, label: true, dataType: true}); }; } diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html index 1181480625..4836045d9b 100644 --- a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html +++ b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html @@ -16,9 +16,11 @@ {{:: ts('Columns') }}
{{ $ctrl.parent.getFieldLabel(col.key) }} -
- -
diff --git a/ext/search/ang/crmSearchDisplay.module.js b/ext/search/ang/crmSearchDisplay.module.js index f77de83380..55c18c7a55 100644 --- a/ext/search/ang/crmSearchDisplay.module.js +++ b/ext/search/ang/crmSearchDisplay.module.js @@ -6,30 +6,48 @@ .factory('searchDisplayUtils', function(crmApi4) { - function replaceTokens(str, data) { + // Replace tokens keyed to rowData. + // If rowMeta is provided, values will be formatted; if omiited, raw values will be provided. + function replaceTokens(str, rowData, rowMeta) { if (!str) { return ''; } - _.each(data, function(value, key) { - str = str.replace('[' + key + ']', value); + _.each(rowData, function(value, key) { + if (str.indexOf('[' + key + ']') >= 0) { + var column = rowMeta && _.findWhere(rowMeta, {key: key}), + replacement = column ? formatRawValue(column, value) : value; + str = str.replace(new RegExp(_.escapeRegExp('[' + key + ']', 'g')), replacement); + } }); return str; } - function getUrl(link, row) { - var url = replaceTokens(link, row); + function getUrl(link, rowData) { + var url = replaceTokens(link, rowData); if (url.slice(0, 1) !== '/' && url.slice(0, 4) !== 'http') { url = CRM.url(url); } return _.escape(url); } - function formatSearchValue(row, col, value) { - var type = col.dataType, + // Returns html-escaped display value for a single column in a row + function formatDisplayValue(rowData, key, rowMeta) { + var column = _.findWhere(rowMeta, {key: key}), + displayValue = column.rewrite ? replaceTokens(column.rewrite, rowData, rowMeta) : formatRawValue(column, rowData[key]), + result = _.escape(displayValue); + if (column.link) { + result = '' + result + ''; + } + return result; + } + + // Formats raw field value according to data type + function formatRawValue(column, value) { + var type = column && column.dataType, result = value; if (_.isArray(value)) { return _.map(value, function(val) { - return formatSearchValue(row, col, val); + return formatRawValue(column, val); }).join(', '); } if (value && (type === 'Date' || type === 'Timestamp') && /^\d{4}-\d{2}-\d{2}/.test(value)) { @@ -41,10 +59,6 @@ else if (type === 'Money' && typeof value === 'number') { result = CRM.formatMoney(value); } - result = _.escape(result); - if (col.link) { - result = '' + result + ''; - } return result; } @@ -76,7 +90,7 @@ } return { - formatSearchValue: formatSearchValue, + formatDisplayValue: formatDisplayValue, getApiParams: getApiParams, getResults: getResults, replaceTokens: replaceTokens diff --git a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js index 129d267c7f..d439fb6e8c 100644 --- a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js +++ b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js @@ -41,19 +41,13 @@ ctrl.getResults(); } - $scope.formatResult = function(row, col) { - var value = row[col.key], - formatted = searchDisplayUtils.formatSearchValue(row, col, value), - output = ''; - if (formatted.length || (col.label && col.forceLabel)) { - if (col.label && (formatted.length || col.forceLabel)) { - output += ' '; - } - if (formatted.length) { - output += (col.prefix || '') + formatted + (col.suffix || ''); - } + $scope.formatResult = function(rowData, col) { + var formatted = searchDisplayUtils.formatDisplayValue(rowData, col.key, ctrl.settings.columns); + if (col.label && (formatted.length || col.forceLabel)) { + var label = searchDisplayUtils.replaceTokens(col.label, rowData, ctrl.settings.columns); + formatted = ' ' + formatted; } - return output; + return formatted; }; } diff --git a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html index e6a29dd9cb..5d4d0deb48 100644 --- a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html +++ b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html @@ -1,4 +1,4 @@
  • -
    +
  • diff --git a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js index 6a3eca26f8..fb5999f2bd 100644 --- a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js +++ b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js @@ -76,9 +76,8 @@ ctrl.getResults(); }; - $scope.formatResult = function(row, col) { - var value = row[col.key]; - return searchDisplayUtils.formatSearchValue(row, col, value); + $scope.formatResult = function(rowData, col) { + return searchDisplayUtils.formatDisplayValue(rowData, col.key, ctrl.settings.columns); }; $scope.selectAllRows = function() { diff --git a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html index 9ad18f1fc6..f1737a82e1 100644 --- a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html +++ b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html @@ -18,7 +18,7 @@ - + diff --git a/ext/search/css/crmSearchAdmin.css b/ext/search/css/crmSearchAdmin.css index 2121cd507a..29de32e642 100644 --- a/ext/search/css/crmSearchAdmin.css +++ b/ext/search/css/crmSearchAdmin.css @@ -164,6 +164,10 @@ flex: 1; } +#bootstrap-theme .crm-search-admin-unused-columns fieldset { + min-height: 60px; +} + #bootstrap-theme input[type=search]::placeholder { font-family: FontAwesome; text-align: right;