From daa4e55af1b9889207a3fd1b3aaee408bf2c8c7c Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Thu, 25 Feb 2021 17:07:37 -0500 Subject: [PATCH] SearchKit - Add links/menus/buttons to search displays --- ext/search/CRM/Search/Upgrader.php | 1 + ext/search/Civi/Search/Admin.php | 45 +++++--- ext/search/ang/crmSearchAdmin.module.js | 34 +++++- .../crmSearchAdminDisplay.component.js | 100 ++++++++++++++++- .../crmSearchAdminLinkGroup.component.js | 101 ++++++++++++++++++ .../crmSearchAdminLinkGroup.html | 66 ++++++++++++ .../crmSearchAdminLinkSelect.component.js | 44 +------- .../crmSearchAdminLinkSelect.html | 1 - .../displays/colType/buttons.html | 13 +++ .../fieldOptions.html => colType/field.html} | 2 +- .../displays/colType/links.html | 2 + .../crmSearchAdmin/displays/colType/menu.html | 32 ++++++ .../displays/common/addColMenu.html | 9 ++ .../displays/common/unusedColumns.html | 6 +- .../searchAdminDisplayList.component.js | 2 +- .../displays/searchAdminDisplayList.html | 53 ++++----- .../searchAdminDisplayTable.component.js | 2 +- .../displays/searchAdminDisplayTable.html | 46 ++++---- ext/search/ang/crmSearchDisplay.module.js | 7 +- .../ang/crmSearchDisplay/colType/buttons.html | 6 ++ .../ang/crmSearchDisplay/colType/field.html | 1 + .../ang/crmSearchDisplay/colType/links.html | 6 ++ .../ang/crmSearchDisplay/colType/menu.html | 14 +++ .../crmSearchDisplayList.component.js | 9 +- .../crmSearchDisplayListItems.html | 6 +- .../crmSearchDisplayTable.component.js | 5 +- .../crmSearchDisplayTable.html | 4 +- ext/search/css/crmSearchAdmin.css | 26 +++++ 28 files changed, 517 insertions(+), 126 deletions(-) create mode 100644 ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js create mode 100644 ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html create mode 100644 ext/search/ang/crmSearchAdmin/displays/colType/buttons.html rename ext/search/ang/crmSearchAdmin/displays/{common/fieldOptions.html => colType/field.html} (93%) create mode 100644 ext/search/ang/crmSearchAdmin/displays/colType/links.html create mode 100644 ext/search/ang/crmSearchAdmin/displays/colType/menu.html create mode 100644 ext/search/ang/crmSearchAdmin/displays/common/addColMenu.html create mode 100644 ext/search/ang/crmSearchDisplay/colType/buttons.html create mode 100644 ext/search/ang/crmSearchDisplay/colType/field.html create mode 100644 ext/search/ang/crmSearchDisplay/colType/links.html create mode 100644 ext/search/ang/crmSearchDisplay/colType/menu.html diff --git a/ext/search/CRM/Search/Upgrader.php b/ext/search/CRM/Search/Upgrader.php index 697e5bafbeab..670d3ca54594 100644 --- a/ext/search/CRM/Search/Upgrader.php +++ b/ext/search/CRM/Search/Upgrader.php @@ -74,6 +74,7 @@ public function upgrade_1001() { $key = $newAliases[$column['expr']] ?? $column['expr']; unset($display['settings']['columns'][$c]['expr']); $display['settings']['columns'][$c]['key'] = explode(' AS ', $key)[1] ?? $key; + $display['settings']['columns'][$c]['type'] = 'field'; } \Civi\Api4\SearchDisplay::update(FALSE) ->setValues($display) diff --git a/ext/search/Civi/Search/Admin.php b/ext/search/Civi/Search/Admin.php index 4a58faf12b85..711a8378ca16 100644 --- a/ext/search/Civi/Search/Admin.php +++ b/ext/search/Civi/Search/Admin.php @@ -11,6 +11,8 @@ namespace Civi\Search; +use CRM_Search_ExtensionUtil as E; + /** * Class Admin * @package Civi\Search @@ -28,6 +30,7 @@ public static function getAdminSettings():array { 'operators' => \CRM_Utils_Array::makeNonAssociative(self::getOperators()), 'functions' => \CRM_Api4_Page_Api4Explorer::getSqlFunctions(), 'displayTypes' => Display::getDisplayTypes(['id', 'name', 'label', 'description', 'icon']), + 'styles' => \CRM_Utils_Array::makeNonAssociative(self::getStyles()), 'afformEnabled' => (bool) \CRM_Utils_Array::findAll( \CRM_Extension_System::singleton()->getMapper()->getActiveModuleFiles(), ['fullName' => 'org.civicrm.afform'] @@ -50,15 +53,29 @@ public static function getOperators():array { '<' => '<', '>=' => '≥', '<=' => '≤', - 'CONTAINS' => ts('Contains'), - 'IN' => ts('Is One Of'), - 'NOT IN' => ts('Not One Of'), - 'LIKE' => ts('Is Like'), - 'NOT LIKE' => ts('Not Like'), - 'BETWEEN' => ts('Is Between'), - 'NOT BETWEEN' => ts('Not Between'), - 'IS NULL' => ts('Is Null'), - 'IS NOT NULL' => ts('Not Null'), + 'CONTAINS' => E::ts('Contains'), + 'IN' => E::ts('Is One Of'), + 'NOT IN' => E::ts('Not One Of'), + 'LIKE' => E::ts('Is Like'), + 'NOT LIKE' => E::ts('Not Like'), + 'BETWEEN' => E::ts('Is Between'), + 'NOT BETWEEN' => E::ts('Not Between'), + 'IS NULL' => E::ts('Is Null'), + 'IS NOT NULL' => E::ts('Not Null'), + ]; + } + + /** + * @return string[] + */ + public static function getStyles():array { + return [ + 'default' => E::ts('Default'), + 'primary' => E::ts('Primary'), + 'success' => E::ts('Success'), + 'info' => E::ts('Info'), + 'warning' => E::ts('Warning'), + 'danger' => E::ts('Danger'), ]; } @@ -84,15 +101,15 @@ public static function getSchema() { unset($entity['paths'][$action]); switch ($action) { case 'view': - $title = ts('View %1', [1 => $entity['title']]); + $title = E::ts('View %1', [1 => $entity['title']]); break; case 'update': - $title = ts('Edit %1', [1 => $entity['title']]); + $title = E::ts('Edit %1', [1 => $entity['title']]); break; case 'delete': - $title = ts('Delete %1', [1 => $entity['title']]); + $title = E::ts('Delete %1', [1 => $entity['title']]); break; default: @@ -239,7 +256,7 @@ public static function getJoins(array $allowedEntities) { $alias = $baseEntity['name'] . "_{$bridge}_" . $targetEntityName; $joins[$baseEntity['name']][] = [ 'label' => $baseEntity['title'] . ' ' . $targetsTitle, - 'description' => ts('Multiple %1 per %2', [1 => $targetsTitle, 2 => $baseEntity['title']]), + 'description' => E::ts('Multiple %1 per %2', [1 => $targetsTitle, 2 => $baseEntity['title']]), 'entity' => $targetEntityName, 'conditions' => array_merge( [$bridge], @@ -254,7 +271,7 @@ public static function getJoins(array $allowedEntities) { $alias = $targetEntityName . "_{$bridge}_" . $baseEntity['name']; $joins[$targetEntityName][] = [ 'label' => $targetEntity['title'] . ' ' . $baseEntity['title_plural'], - 'description' => ts('Multiple %1 per %2', [1 => $baseEntity['title_plural'], 2 => $targetEntity['title']]), + 'description' => E::ts('Multiple %1 per %2', [1 => $baseEntity['title_plural'], 2 => $targetEntity['title']]), 'entity' => $baseEntity['name'], 'conditions' => array_merge( [$bridge], diff --git a/ext/search/ang/crmSearchAdmin.module.js b/ext/search/ang/crmSearchAdmin.module.js index 6db8c6ba143f..6ade8b2cd0b8 100644 --- a/ext/search/ang/crmSearchAdmin.module.js +++ b/ext/search/ang/crmSearchAdmin.module.js @@ -81,7 +81,7 @@ $scope.$ctrl = this; }) - .factory('searchMeta', function() { + .factory('searchMeta', function($q) { function getEntity(entityName) { if (entityName) { return _.find(CRM.crmSearchAdmin.schema, {name: entityName}); @@ -227,8 +227,40 @@ } }); }); + }, + pickIcon: function() { + var deferred = $q.defer(); + $('#crm-search-admin-icon-picker').off('change').siblings('.crm-icon-picker-button').click(); + $('#crm-search-admin-icon-picker').on('change', function() { + deferred.resolve($(this).val()); + }); + return deferred.promise; + } + }; + }) + .directive('contenteditable', function() { + return { + require: 'ngModel', + link: function(scope, elm, attrs, ctrl) { + // view -> model + elm.on('blur', function() { + ctrl.$setViewValue(elm.html()); + }); + + // model -> view + ctrl.$render = function() { + elm.html(ctrl.$viewValue); + }; } }; }); + // Shoehorn in a non-angular widget for picking icons + $(function() { + $('#crm-container').append('
'); + CRM.loadScript(CRM.config.resourceBase + 'js/jquery/jquery.crmIconPicker.js').done(function() { + $('#crm-search-admin-icon-picker').crmIconPicker(); + }); + }); + })(angular, CRM.$, CRM._); diff --git a/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js b/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js index afea8e8b60a9..2e3fd7aebec2 100644 --- a/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js +++ b/ext/search/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js @@ -38,13 +38,55 @@ this.preview = this.stale = false; + this.colTypes = { + links: { + label: ts('Links'), + icon: 'fa-link', + defaults: { + links: [] + } + }, + buttons: { + label: ts('Buttons'), + icon: 'fa-square-o', + defaults: { + size: 'btn-sm', + links: [] + } + }, + menu: { + label: ts('Menu'), + icon: 'fa-bars', + defaults: { + text: ts('Actions'), + style: 'default', + size: 'btn-sm', + icon: 'fa-bars', + links: [] + } + }, + }; + this.sortableOptions = { connectWith: '.crm-search-admin-edit-columns', containment: '.crm-search-admin-edit-columns-wrapper' }; + this.styles = CRM.crmSearchAdmin.styles; + + this.addCol = function(type) { + var col = _.cloneDeep(this.colTypes[type].defaults); + col.type = type; + if (this.display.type === 'table') { + col.alignment = 'text-right'; + } + ctrl.display.settings.columns.push(col); + }; + this.removeCol = function(index) { - ctrl.hiddenColumns.push(ctrl.display.settings.columns[index]); + if (ctrl.display.settings.columns[index].type === 'field') { + ctrl.hiddenColumns.push(ctrl.display.settings.columns[index]); + } ctrl.display.settings.columns.splice(index, 1); }; @@ -70,6 +112,13 @@ return searchMeta.getDefaultLabel(expr); }; + this.getColLabel = function(col) { + if (col.type === 'field') { + return ctrl.getFieldLabel(col.key); + } + return ctrl.colTypes[col.type].label; + }; + function fieldToColumn(fieldExpr, defaults) { var info = searchMeta.parseExpr(fieldExpr), values = _.cloneDeep(defaults); @@ -85,6 +134,53 @@ return values; } + this.getLinks = function() { + if (!ctrl.links) { + ctrl.links = buildLinks(); + } + return ctrl.links; + }; + + // Build a list of all possible links to main entity or join entities + function buildLinks() { + // Links to main entity + var links = _.cloneDeep(searchMeta.getEntity(ctrl.savedSearch.api_entity).paths || []); + // Links to explicitly joined entities + _.each(ctrl.savedSearch.api_params.join, function(join) { + var joinName = join[0].split(' AS '), + joinEntity = searchMeta.getEntity(joinName[0]); + _.each(joinEntity.paths, function(path) { + var link = _.cloneDeep(path); + link.path = link.path.replace(/\[/g, '[' + joinName[1] + '.'); + links.push(link); + }); + }); + // Links to implicit joins + _.each(ctrl.savedSearch.api_params.select, function(fieldName) { + if (!_.includes(fieldName, ' AS ')) { + var info = searchMeta.parseExpr(fieldName); + if (info.field && !info.suffix && !info.fn && (info.field.fk_entity || info.field.entity !== info.field.baseEntity)) { + var idField = info.field.fk_entity ? fieldName : fieldName.substr(0, fieldName.lastIndexOf('.')) + '_id'; + if (!ctrl.crmSearchAdmin.canAggregate(idField)) { + var joinEntity = searchMeta.getEntity(info.field.fk_entity || info.field.entity); + _.each(joinEntity.paths, function(path) { + var link = _.cloneDeep(path); + link.path = link.path.replace(/\[id/g, '[' + idField); + links.push(link); + }); + } + } + } + }); + return links; + } + + this.pickIcon = function(model, key) { + searchMeta.pickIcon().then(function(icon) { + model[key] = icon; + }); + }; + // Helper function to sort active from hidden columns and initialize each column with defaults this.initColumns = function(defaults) { if (!ctrl.display.settings.columns) { @@ -104,7 +200,7 @@ } }); _.eachRight(activeColumns, function(key, index) { - if (!_.includes(selectAliases, key)) { + if (key && !_.includes(selectAliases, key)) { ctrl.display.settings.columns.splice(index, 1); } }); diff --git a/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js new file mode 100644 index 000000000000..2708c98909bb --- /dev/null +++ b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.component.js @@ -0,0 +1,101 @@ +(function(angular, $, _) { + "use strict"; + + angular.module('crmSearchAdmin').component('crmSearchAdminLinkGroup', { + bindings: { + group: '<', + apiEntity: '<', + apiParams: '<', + links: '<' + }, + templateUrl: '~/crmSearchAdmin/crmSearchAdminLinkGroup.html', + controller: function ($scope, $element, $timeout, searchMeta) { + var ts = $scope.ts = CRM.ts(), + ctrl = this; + + this.styles = CRM.crmSearchAdmin.styles; + + this.setValue = function(val, index) { + var link = ctrl.getLink(val), + item = ctrl.group[index]; + if (item.path === val) { + return; + } + item.path = val; + item.icon = link ? defaultIcons[link.action] : 'fa-external-link'; + if (val === 'civicrm/') { + $timeout(function () { + $('tr:eq(' + index + ') input[type=text]', $element).focus(); + }); + } + }; + + this.sortableOptions = { + containment: 'tbody', + direction: 'vertical', + helper: function(e, ui) { + // Prevent table row width from changing during drag + ui.children().each(function() { + $(this).width($(this).width()); + }); + return ui; + } + }; + + var defaultIcons = { + view: 'fa-external-link', + update: 'fa-pencil', + delete: 'fa-trash' + }; + + var defaultStyles = { + view: 'primary', + update: 'warning', + delete: 'danger' + }; + + $scope.pickIcon = function(index) { + searchMeta.pickIcon().then(function(icon) { + ctrl.group[index].icon = icon; + }); + }; + + this.addItem = function(path) { + var link = ctrl.getLink(path); + ctrl.group.push({ + path: path, + style: link && defaultStyles[link.action] || 'default', + text: link ? link.title : '', + icon: link && defaultIcons[link.action] || 'fa-external-link' + }); + }; + + this.$onInit = function() { + if (!ctrl.group.length) { + if (ctrl.links.length) { + _.each(_.pluck(ctrl.links, 'path'), ctrl.addItem); + } else { + ctrl.addItem('civicrm/'); + } + } + $element.on('change', 'select.crm-search-admin-select-path', function() { + var $select = $(this); + $scope.$apply(function() { + if ($select.closest('tfoot').length) { + ctrl.addItem($select.val()); + $select.val(''); + } else { + ctrl.setValue($select.val(), $select.closest('tr').index()); + } + }); + }); + }; + + this.getLink = function(path) { + return _.findWhere(ctrl.links, {path: path}); + }; + + } + }); + +})(angular, CRM.$, CRM._); diff --git a/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html new file mode 100644 index 000000000000..2846b6007396 --- /dev/null +++ b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkGroup.html @@ -0,0 +1,66 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + +
{{:: ts('Icon') }}{{:: ts('Text') }}{{:: ts('Link') }}{{:: ts('Style') }}
+ + + + + + + + + + + + + + + +
+ +
diff --git a/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.component.js b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.component.js index dc916ad98d79..2bac3383c037 100644 --- a/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.component.js +++ b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.component.js @@ -5,50 +5,14 @@ bindings: { column: '<', apiEntity: '<', - apiParams: '<' - }, - require: { - crmSearchAdmin: '^^crmSearchAdmin' + apiParams: '<', + links: '<' }, templateUrl: '~/crmSearchAdmin/crmSearchAdminLinkSelect.html', - controller: function ($scope, $element, $timeout, searchMeta) { + controller: function ($scope, $element, $timeout) { var ts = $scope.ts = CRM.ts(), ctrl = this; - // Return all possible links to main entity or join entities - function getLinks() { - // Links to main entity - var links = _.cloneDeep(searchMeta.getEntity(ctrl.apiEntity).paths || []); - // Links to explicitly joined entities - _.each(ctrl.apiParams.join, function(join) { - var joinName = join[0].split(' AS '), - joinEntity = searchMeta.getEntity(joinName[0]); - _.each(joinEntity.paths, function(path) { - var link = _.cloneDeep(path); - link.path = link.path.replace(/\[/g, '[' + joinName[1] + '.'); - links.push(link); - }); - }); - // Links to implicit joins - _.each(ctrl.crmSearchAdmin.savedSearch.api_params.select, function(fieldName) { - if (!_.includes(fieldName, ' AS ')) { - var info = searchMeta.parseExpr(fieldName); - if (info.field && !info.suffix && !info.fn && (info.field.fk_entity || info.field.entity !== info.field.baseEntity)) { - var idField = info.field.fk_entity ? fieldName : fieldName.substr(0, fieldName.lastIndexOf('.')) + '_id'; - if (!ctrl.crmSearchAdmin.canAggregate(idField)) { - var joinEntity = searchMeta.getEntity(info.field.fk_entity || info.field.entity); - _.each(joinEntity.paths, function(path) { - var link = _.cloneDeep(path); - link.path = link.path.replace(/\[id/g, '[' + idField); - links.push(link); - }); - } - } - } - }); - return links; - } - this.setValue = function(val) { var link = ctrl.getLink(val), oldLink = ctrl.getLink(ctrl.column.link); @@ -78,8 +42,6 @@ } this.$onInit = function() { - this.links = getLinks(); - $('select', $element).on('change', function() { $scope.$apply(onChange); }); diff --git a/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.html b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.html index 3f0fa40aeba5..855f9fdb71e8 100644 --- a/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.html +++ b/ext/search/ang/crmSearchAdmin/crmSearchAdminLinkSelect.html @@ -3,7 +3,6 @@ {{ $ctrl.column.link ? ts('Link:') : ts('Link') }} + + + + + + +
+ diff --git a/ext/search/ang/crmSearchAdmin/displays/common/fieldOptions.html b/ext/search/ang/crmSearchAdmin/displays/colType/field.html similarity index 93% rename from ext/search/ang/crmSearchAdmin/displays/common/fieldOptions.html rename to ext/search/ang/crmSearchAdmin/displays/colType/field.html index d05271bd3641..20e1976e79a0 100644 --- a/ext/search/ang/crmSearchAdmin/displays/common/fieldOptions.html +++ b/ext/search/ang/crmSearchAdmin/displays/colType/field.html @@ -1,4 +1,4 @@ - +
diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.component.js b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.component.js index 54dd7008c75d..546fdb84d028 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({key: true, dataType: true}); + ctrl.parent.initColumns({key: true, dataType: true, type: 'field'}); }; } diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html index 10b1a60296fc..0ec003a6c9de 100644 --- a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html +++ b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayList.html @@ -22,32 +22,35 @@
-
+
{{:: ts('Fields') }} -
- {{ $ctrl.parent.getFieldLabel(col.key) }} -
- - -
-
- - - -
-
- -
- +
+
+
+ {{ $ctrl.parent.getColLabel(col) }} +
+ +
-
-
-
+
+ + + +
+
+ +
+ +
+
+
+
+
-
+
diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.component.js b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.component.js index bd958c37bf6f..72b48eaaea89 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({key: true, label: true, dataType: true}); + ctrl.parent.initColumns({key: true, label: true, dataType: true, type: 'field'}); }; } diff --git a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html index 4836045d9bb4..0ade234aebd7 100644 --- a/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html +++ b/ext/search/ang/crmSearchAdmin/displays/searchAdminDisplayTable.html @@ -12,28 +12,30 @@
-
+
{{:: ts('Columns') }} -
- {{ $ctrl.parent.getFieldLabel(col.key) }} -
- - -      - -
-
- - -
-
-
+
+
+
+ {{ $ctrl.parent.getColLabel(col) }} +
+ + + +
+
+ + +
+
+
+
-
+
diff --git a/ext/search/ang/crmSearchDisplay.module.js b/ext/search/ang/crmSearchDisplay.module.js index 55c18c7a55c3..312782f53632 100644 --- a/ext/search/ang/crmSearchDisplay.module.js +++ b/ext/search/ang/crmSearchDisplay.module.js @@ -27,7 +27,7 @@ if (url.slice(0, 1) !== '/' && url.slice(0, 4) !== 'http') { url = CRM.url(url); } - return _.escape(url); + return url; } // Returns html-escaped display value for a single column in a row @@ -36,7 +36,7 @@ displayValue = column.rewrite ? replaceTokens(column.rewrite, rowData, rowMeta) : formatRawValue(column, rowData[key]), result = _.escape(displayValue); if (column.link) { - result = '' + result + ''; + result = '' + result + ''; } return result; } @@ -93,7 +93,8 @@ formatDisplayValue: formatDisplayValue, getApiParams: getApiParams, getResults: getResults, - replaceTokens: replaceTokens + replaceTokens: replaceTokens, + getUrl: getUrl }; }); diff --git a/ext/search/ang/crmSearchDisplay/colType/buttons.html b/ext/search/ang/crmSearchDisplay/colType/buttons.html new file mode 100644 index 000000000000..f18030cf3c2a --- /dev/null +++ b/ext/search/ang/crmSearchDisplay/colType/buttons.html @@ -0,0 +1,6 @@ + + + + {{:: item.text }} + + diff --git a/ext/search/ang/crmSearchDisplay/colType/field.html b/ext/search/ang/crmSearchDisplay/colType/field.html new file mode 100644 index 000000000000..1c6106010025 --- /dev/null +++ b/ext/search/ang/crmSearchDisplay/colType/field.html @@ -0,0 +1 @@ + diff --git a/ext/search/ang/crmSearchDisplay/colType/links.html b/ext/search/ang/crmSearchDisplay/colType/links.html new file mode 100644 index 000000000000..d0a248047338 --- /dev/null +++ b/ext/search/ang/crmSearchDisplay/colType/links.html @@ -0,0 +1,6 @@ + + + + {{:: item.text }} + + diff --git a/ext/search/ang/crmSearchDisplay/colType/menu.html b/ext/search/ang/crmSearchDisplay/colType/menu.html new file mode 100644 index 000000000000..a11b5319be60 --- /dev/null +++ b/ext/search/ang/crmSearchDisplay/colType/menu.html @@ -0,0 +1,14 @@ +
+ + +
diff --git a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js index d439fb6e8cbb..255814f5e182 100644 --- a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js +++ b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayList.component.js @@ -41,13 +41,8 @@ ctrl.getResults(); } - $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 formatted; + this.formatFieldValue = function(rowData, col) { + return searchDisplayUtils.formatDisplayValue(rowData, col.key, ctrl.settings.columns); }; } diff --git a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html index 5d4d0deb4872..e99f04b04f09 100644 --- a/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html +++ b/ext/search/ang/crmSearchDisplayList/crmSearchDisplayListItems.html @@ -1,4 +1,8 @@
  • -
    +
    + +
  • diff --git a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js index fb5999f2bdbd..8ba836c4cbfe 100644 --- a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js +++ b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.component.js @@ -63,6 +63,9 @@ * @param $event */ $scope.setSort = function(col, $event) { + if (col.type !== 'field') { + return; + } var dir = $scope.getSort(col) === 'fa-sort-asc' ? 'DESC' : 'ASC'; if (!$event.shiftKey || !ctrl.sort) { ctrl.sort = []; @@ -76,7 +79,7 @@ ctrl.getResults(); }; - $scope.formatResult = function(rowData, col) { + this.formatFieldValue = function(rowData, col) { return searchDisplayUtils.formatDisplayValue(rowData, col.key, ctrl.settings.columns); }; diff --git a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html index f1737a82e1d6..3c408c3b885d 100644 --- a/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html +++ b/ext/search/ang/crmSearchDisplayTable/crmSearchDisplayTable.html @@ -8,7 +8,7 @@ - + {{ col.label }} @@ -18,7 +18,7 @@ - + diff --git a/ext/search/css/crmSearchAdmin.css b/ext/search/css/crmSearchAdmin.css index 29de32e6429a..f5f877557f33 100644 --- a/ext/search/css/crmSearchAdmin.css +++ b/ext/search/css/crmSearchAdmin.css @@ -153,6 +153,10 @@ top: 0; } +#bootstrap-theme .crm-search-admin-edit-columns { + height: 100%; +} + #bootstrap-theme .crm-search-admin-flex-row { display: flex; align-items: center; @@ -168,6 +172,28 @@ min-height: 60px; } +#bootstrap-theme.crm-search .crm-editable-enabled { + display: inline-block; + padding: 0 4px !important; + border: 2px solid transparent !important; + min-width: 21px; +} +#bootstrap-theme.crm-search .crm-editable-enabled:hover:not(:focus) { + border: 2px dashed grey !important; +} +#bootstrap-theme.crm-search .crm-editable-enabled:before, +#bootstrap-theme.crm-search .crm-editable-enabled:after { + content: ''; + display: none; +} + +#bootstrap-theme .crm-search-admin-icon-col { + width: 24px; +} +#bootstrap-theme tbody .crm-search-admin-icon-col { + text-align: center; +} + #bootstrap-theme input[type=search]::placeholder { font-family: FontAwesome; text-align: right;