From 5c952e51ce92926a48cf542126c19aaa7003e279 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Thu, 28 Oct 2021 09:52:25 -0400 Subject: [PATCH] SearchKit - Expose default display to the UI Adds a 'view' link to the searchKit admin listing, which links to the default display Adds a 'view' dropdown to the compose search screen, with links to the default + all other displays Updates Afform to work with default search displays --- Civi/Api4/Generic/AbstractGetAction.php | 58 +------------- Civi/Api4/Generic/Traits/SelectParamTrait.php | 77 +++++++++++++++++++ .../Civi/Api4/Action/Afform/LoadAdminData.php | 21 +++-- .../ang/afAdmin/afAdminList.controller.js | 37 ++++++--- ext/afform/admin/ang/afAdmin/afAdminList.html | 2 +- ext/afform/admin/ang/afGuiEditor.js | 6 +- .../ang/afGuiEditor/afGuiEditor.component.js | 6 +- .../ang/afGuiEditor/afGuiSearch.component.js | 4 +- .../elements/afGuiContainer.component.js | 8 +- .../elements/afGuiSearchDisplay.component.js | 2 +- .../core/Civi/Api4/Action/Afform/Get.php | 5 +- .../SearchDisplay/AbstractRunAction.php | 2 +- .../Api4/Action/SearchDisplay/GetDefault.php | 16 +++- .../crmSearchAdmin.component.js | 30 ++++---- .../ang/crmSearchAdmin/crmSearchAdmin.html | 76 ++++++++++++++++-- .../crmSearchAdminDisplay.component.js | 11 --- .../crmSearchAdmin/crmSearchAdminDisplay.html | 26 ------- .../crmSearchAdminResultsTable.component.js | 2 + .../crmSearchAdmin/searchListing/afforms.html | 7 +- .../crmSearchAdmin/searchListing/buttons.html | 7 +- .../searchListing/displays.html | 2 +- ext/search_kit/ang/crmSearchPage.module.js | 32 +++++--- .../v4/SearchDisplay/SearchDisplayTest.php | 39 ++++++++++ 23 files changed, 313 insertions(+), 163 deletions(-) create mode 100644 Civi/Api4/Generic/Traits/SelectParamTrait.php create mode 100644 ext/search_kit/tests/phpunit/api/v4/SearchDisplay/SearchDisplayTest.php diff --git a/Civi/Api4/Generic/AbstractGetAction.php b/Civi/Api4/Generic/AbstractGetAction.php index 5fd9274683..8dfff86d61 100644 --- a/Civi/Api4/Generic/AbstractGetAction.php +++ b/Civi/Api4/Generic/AbstractGetAction.php @@ -12,29 +12,14 @@ namespace Civi\Api4\Generic; -use Civi\Api4\Utils\SelectUtil; - /** * Base class for all `Get` api actions. * * @package Civi\Api4\Generic - * - * @method $this setSelect(array $selects) Set array of fields to be selected (wildcard * allowed) - * @method array getSelect() */ abstract class AbstractGetAction extends AbstractQueryAction { - /** - * Fields to return for each $ENTITY. Defaults to all fields `[*]`. - * - * Use the * wildcard by itself to select all available fields, or use it to match similarly-named fields. - * E.g. `is_*` will match fields named is_primary, is_active, etc. - * - * Set to `["row_count"]` to return only the number of $ENTITIES found. - * - * @var array - */ - protected $select = []; + use Traits\SelectParamTrait; /** * Only return the number of found items. @@ -65,37 +50,6 @@ abstract class AbstractGetAction extends AbstractQueryAction { } } - /** - * Adds all standard fields matched by the * wildcard - * - * Note: this function only deals with simple wildcard expressions. - * It ignores those containing special characters like dots or parentheses, - * they are handled separately in Api4SelectQuery. - * - * @throws \API_Exception - */ - protected function expandSelectClauseWildcards() { - if (!$this->select) { - $this->select = ['*']; - } - // Get expressions containing wildcards but no dots or parentheses - $wildFields = array_filter($this->select, function($item) { - return strpos($item, '*') !== FALSE && strpos($item, '.') === FALSE && strpos($item, '(') === FALSE && strpos($item, ' ') === FALSE; - }); - if ($wildFields) { - // Wildcards should not match "Extra" fields - $standardFields = array_filter(array_map(function($field) { - return $field['type'] === 'Extra' ? NULL : $field['name']; - }, $this->entityFields())); - foreach ($wildFields as $item) { - $pos = array_search($item, array_values($this->select)); - $matches = SelectUtil::getMatchingFields($item, $standardFields); - array_splice($this->select, $pos, 1, $matches); - } - } - $this->select = array_unique($this->select); - } - /** * Helper to parse the WHERE param for getRecords to perform simple pre-filtering. * @@ -166,14 +120,4 @@ abstract class AbstractGetAction extends AbstractQueryAction { return FALSE; } - /** - * Add one or more fields to be selected (wildcard * allowed) - * @param string ...$fieldNames - * @return $this - */ - public function addSelect(string ...$fieldNames) { - $this->select = array_merge($this->select, $fieldNames); - return $this; - } - } diff --git a/Civi/Api4/Generic/Traits/SelectParamTrait.php b/Civi/Api4/Generic/Traits/SelectParamTrait.php new file mode 100644 index 0000000000..7ecd154363 --- /dev/null +++ b/Civi/Api4/Generic/Traits/SelectParamTrait.php @@ -0,0 +1,77 @@ +select = array_merge($this->select, $fieldNames); + return $this; + } + + /** + * Adds all standard fields matched by the * wildcard + * + * Note: this function only deals with simple wildcard expressions. + * It ignores those containing special characters like dots or parentheses, + * they are handled separately in Api4SelectQuery. + * + * @throws \API_Exception + */ + protected function expandSelectClauseWildcards() { + if (!$this->select) { + $this->select = ['*']; + } + // Get expressions containing wildcards but no dots or parentheses + $wildFields = array_filter($this->select, function($item) { + return strpos($item, '*') !== FALSE && strpos($item, '.') === FALSE && strpos($item, '(') === FALSE && strpos($item, ' ') === FALSE; + }); + if ($wildFields) { + // Wildcards should not match "Extra" fields + $standardFields = array_filter(array_map(function($field) { + return $field['type'] === 'Extra' ? NULL : $field['name']; + }, $this->entityFields())); + foreach ($wildFields as $item) { + $pos = array_search($item, array_values($this->select)); + $matches = SelectUtil::getMatchingFields($item, $standardFields); + array_splice($this->select, $pos, 1, $matches); + } + } + $this->select = array_unique($this->select); + } + +} diff --git a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php index 46f4d3279d..5c73354997 100644 --- a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php +++ b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php @@ -174,18 +174,25 @@ class LoadAdminData extends \Civi\Api4\Generic\AbstractAction { } } foreach ($displayTags as $displayTag) { - $display = \Civi\Api4\SearchDisplay::get(FALSE) - ->addWhere('name', '=', $displayTag['display-name']) - ->addWhere('saved_search.name', '=', $displayTag['search-name']) - ->addSelect('*', 'type:name', 'type:icon', 'saved_search.name', 'saved_search.api_entity', 'saved_search.api_params') + if (isset($displayTag['display-name']) && strlen($displayTag['display-name'])) { + $displayGet = \Civi\Api4\SearchDisplay::get(FALSE) + ->addWhere('name', '=', $displayTag['display-name']) + ->addWhere('saved_search_id.name', '=', $displayTag['search-name']); + } + else { + $displayGet = \Civi\Api4\SearchDisplay::getDefault(FALSE) + ->setSavedSearch($displayTag['search-name']); + } + $display = $displayGet + ->addSelect('*', 'type:name', 'type:icon', 'saved_search_id.name', 'saved_search_id.api_entity', 'saved_search_id.api_params') ->execute()->first(); - $display['calc_fields'] = $this->getCalcFields($display['saved_search.api_entity'], $display['saved_search.api_params']); + $display['calc_fields'] = $this->getCalcFields($display['saved_search_id.api_entity'], $display['saved_search_id.api_params']); $info['search_displays'][] = $display; if ($newForm) { $info['definition']['layout'][0]['#children'][] = $displayTag + ['#tag' => $display['type:name']]; } - $entities[] = $display['saved_search.api_entity']; - foreach ($display['saved_search.api_params']['join'] ?? [] as $join) { + $entities[] = $display['saved_search_id.api_entity']; + foreach ($display['saved_search_id.api_params']['join'] ?? [] as $join) { $entities[] = explode(' AS ', $join[0])[0]; } } diff --git a/ext/afform/admin/ang/afAdmin/afAdminList.controller.js b/ext/afform/admin/ang/afAdmin/afAdminList.controller.js index c48d9c5586..abf0064c2e 100644 --- a/ext/afform/admin/ang/afAdmin/afAdminList.controller.js +++ b/ext/afform/admin/ang/afAdmin/afAdminList.controller.js @@ -87,17 +87,34 @@ } if (ctrl.tab === 'search') { - crmApi4('SearchDisplay', 'get', { - select: ['name', 'label', 'type:icon', 'saved_search.name', 'saved_search.label'] - }).then(function(searchDisplays) { - _.each(searchDisplays, function(searchDisplay) { - links.push({ - url: '#create/search/' + searchDisplay['saved_search.name'] + '.' + searchDisplay.name, - label: searchDisplay['saved_search.label'] + ': ' + searchDisplay.label, - icon: searchDisplay['type:icon'] - }); + var searchNames = []; + // Non-aggregated query will return the same search multiple times - once per display + crmApi4('SavedSearch', 'get', { + select: ['name', 'label', 'display.name', 'display.label', 'display.type:icon'], + where: [['api_entity', 'IS NOT NULL'], ['api_params', 'IS NOT NULL']], + join: [['SearchDisplay AS display', 'LEFT', ['id', '=', 'display.saved_search_id']]], + orderBy: {'label':'ASC'} + }).then(function(searches) { + _.each(searches, function(search) { + // Add default display for each search (track searchNames in a var to just add once per search) + if (!_.includes(searchNames, search.name)) { + searchNames.push(search.name); + links.push({ + url: '#create/search/' + search.name, + label: search.label + ': ' + ts('Search results table'), + icon: 'fa-table' + }); + } + // If the search has no displays (other than the default) this will be empty + if (search['display.name']) { + links.push({ + url: '#create/search/' + search.name + '.' + search['display.name'], + label: search.label + ': ' + search['display.label'], + icon: search['display.type:icon'] + }); + } }); - $scope.types.search.options = _.sortBy(links, 'Label'); + $scope.types.search.options = links; }); } }; diff --git a/ext/afform/admin/ang/afAdmin/afAdminList.html b/ext/afform/admin/ang/afAdmin/afAdminList.html index a40a04e388..b6459ccb27 100644 --- a/ext/afform/admin/ang/afAdmin/afAdminList.html +++ b/ext/afform/admin/ang/afAdmin/afAdminList.html @@ -75,7 +75,7 @@ {{:: afform.placement.join(', ') }} {{:: ts('Edit') }} - {{:: ts('Clone') }} + {{:: ts('Clone') }} {{ afform.has_base ? ts('Revert') : ts('Delete') }} diff --git a/ext/afform/admin/ang/afGuiEditor.js b/ext/afform/admin/ang/afGuiEditor.js index aca9acb706..b21e5a4447 100644 --- a/ext/afform/admin/ang/afGuiEditor.js +++ b/ext/afform/admin/ang/afGuiEditor.js @@ -118,7 +118,7 @@ ); } _.each(data.search_displays, function(display) { - CRM.afGuiEditor.searchDisplays[display['saved_search.name'] + '.' + display.name] = display; + CRM.afGuiEditor.searchDisplays[display['saved_search_id.name'] + (display.name ? '.' + display.name : '')] = display; }); }, @@ -133,6 +133,10 @@ return fields[fieldName] || fields[fieldName.substr(fieldName.indexOf('.') + 1)]; }, + getSearchDisplay: function(searchName, displayName) { + return CRM.afGuiEditor.searchDisplays[searchName + (displayName ? '.' + displayName : '')]; + }, + // Recursively searches a collection and its children using _.filter // Returns an array of all matches, or an object if the indexBy param is used findRecursive: function findRecursive(collection, predicate, indexBy) { diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js b/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js index 6ed1d027bd..f2c4e9dcc2 100644 --- a/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js +++ b/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js @@ -234,13 +234,13 @@ }; function getSearchFilterOptions() { - var searchDisplay = editor.meta.searchDisplays[editor.searchDisplay['search-name'] + '.' + editor.searchDisplay['display-name']], + var searchDisplay = afGui.getSearchDisplay(editor.searchDisplay['search-name'], editor.searchDisplay['display-name']), entityCount = {}, options = []; - addFields(searchDisplay['saved_search.api_entity'], ''); + addFields(searchDisplay['saved_search_id.api_entity'], ''); - _.each(searchDisplay['saved_search.api_params'].join, function(join) { + _.each(searchDisplay['saved_search_id.api_params'].join, function(join) { var joinInfo = join[0].split(' AS '); addFields(joinInfo[0], joinInfo[1] + '.'); }); diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiSearch.component.js b/ext/afform/admin/ang/afGuiEditor/afGuiSearch.component.js index 14937f6540..d746728284 100644 --- a/ext/afform/admin/ang/afGuiEditor/afGuiSearch.component.js +++ b/ext/afform/admin/ang/afGuiEditor/afGuiSearch.component.js @@ -52,7 +52,7 @@ function buildFieldList(search) { $scope.fieldList.length = 0; - var entity = afGui.getEntity(ctrl.display['saved_search.api_entity']), + var entity = afGui.getEntity(ctrl.display['saved_search_id.api_entity']), entityCount = {}; entityCount[entity.entity] = 1; $scope.fieldList.push({ @@ -61,7 +61,7 @@ fields: filterFields(entity.fields) }); - _.each(ctrl.display['saved_search.api_params'].join, function(join) { + _.each(ctrl.display['saved_search_id.api_params'].join, function(join) { var joinInfo = join[0].split(' AS '), entity = afGui.getEntity(joinInfo[0]), alias = joinInfo[1]; diff --git a/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js b/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js index f38a8a1b4f..f076241ace 100644 --- a/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js +++ b/ext/afform/admin/ang/afGuiEditor/elements/afGuiContainer.component.js @@ -323,7 +323,7 @@ prefix = _.includes(fieldName, '.') ? fieldName.split('.')[0] : null; _.each(afGui.meta.searchDisplays, function(searchDisplay) { if (prefix) { - _.each(searchDisplay['saved_search.api_params'].join, function(join) { + _.each(searchDisplay['saved_search_id.api_params'].join, function(join) { var joinInfo = join[0].split(' AS '); if (prefix === joinInfo[1]) { entityType = joinInfo[0]; @@ -331,14 +331,14 @@ } }); } - if (!entityType && fieldName && afGui.getField(searchDisplay['saved_search.api_entity'], fieldName)) { - entityType = searchDisplay['saved_search.api_entity']; + if (!entityType && fieldName && afGui.getField(searchDisplay['saved_search_id.api_entity'], fieldName)) { + entityType = searchDisplay['saved_search_id.api_entity']; } if (entityType) { return false; } }); - return entityType || _.map(afGui.meta.searchDisplays, 'saved_search.api_entity')[0]; + return entityType || _.map(afGui.meta.searchDisplays, 'saved_search_id.api_entity')[0]; }; } diff --git a/ext/afform/admin/ang/afGuiEditor/elements/afGuiSearchDisplay.component.js b/ext/afform/admin/ang/afGuiEditor/elements/afGuiSearchDisplay.component.js index c85212f81f..0dc66702f1 100644 --- a/ext/afform/admin/ang/afGuiEditor/elements/afGuiSearchDisplay.component.js +++ b/ext/afform/admin/ang/afGuiEditor/elements/afGuiSearchDisplay.component.js @@ -12,7 +12,7 @@ ctrl = this; this.$onInit = function() { - ctrl.display = afGui.meta.searchDisplays[ctrl.node['search-name'] + '.' + ctrl.node['display-name']]; + ctrl.display = afGui.getSearchDisplay(ctrl.node['search-name'], ctrl.node['display-name']); ctrl.editUrl = CRM.url('civicrm/admin/search#/edit/' + ctrl.display.saved_search_id); }; diff --git a/ext/afform/core/Civi/Api4/Action/Afform/Get.php b/ext/afform/core/Civi/Api4/Action/Afform/Get.php index cd5ed83424..629083e655 100644 --- a/ext/afform/core/Civi/Api4/Action/Afform/Get.php +++ b/ext/afform/core/Civi/Api4/Action/Afform/Get.php @@ -174,9 +174,10 @@ class Get extends \Civi\Api4\Generic\BasicGetAction { foreach ($tags[0] ?? [] as $tag) { $searchName = $displayName = []; preg_match('/search-name\\s*=\\s*[\'"]([^\'"]+)[\'"]/', $tag, $searchName); + // Note: display name will be blank when using the default (autogenerated) display preg_match('/display-name\\s*=\\s*[\'"]([^\'"]+)[\'"]/', $tag, $displayName); - if (!empty($searchName[1]) && !empty($displayName[1])) { - $searchDisplays[] = $searchName[1] . '.' . $displayName[1]; + if (!empty($searchName[1])) { + $searchDisplays[] = $searchName[1] . (empty($displayName[1]) ? '' : '.' . $displayName[1]); } } return $searchDisplays; diff --git a/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php b/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php index 309de3013f..d775985b64 100644 --- a/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php +++ b/ext/search_kit/Civi/Api4/Action/SearchDisplay/AbstractRunAction.php @@ -85,9 +85,9 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction { } elseif (is_null($this->display)) { $this->display = SearchDisplay::getDefault(FALSE) + ->addSelect('*', 'type:name') ->setSavedSearch($this->savedSearch) ->execute()->first(); - $this->display['type:name'] = 'crm-search-display-table'; } // Displays with acl_bypass must be embedded on an afform which the user has access to if ( diff --git a/ext/search_kit/Civi/Api4/Action/SearchDisplay/GetDefault.php b/ext/search_kit/Civi/Api4/Action/SearchDisplay/GetDefault.php index 7618682a4c..2e0ec09152 100644 --- a/ext/search_kit/Civi/Api4/Action/SearchDisplay/GetDefault.php +++ b/ext/search_kit/Civi/Api4/Action/SearchDisplay/GetDefault.php @@ -20,6 +20,8 @@ use Civi\API\Exception\UnauthorizedException; class GetDefault extends \Civi\Api4\Generic\AbstractAction { use SavedSearchInspectorTrait; + use \Civi\Api4\Generic\Traits\ArrayQueryActionTrait; + use \Civi\Api4\Generic\Traits\SelectParamTrait; /** * Either the name of the savedSearch or an array containing the savedSearch definition (for preview mode) @@ -43,6 +45,7 @@ class GetDefault extends \Civi\Api4\Generic\AbstractAction { throw new UnauthorizedException('Access denied'); } $this->loadSavedSearch(); + $this->expandSelectClauseWildcards(); // Use label from saved search $label = $this->savedSearch['label'] ?? ''; // Fall back on entity title as label @@ -50,13 +53,16 @@ class GetDefault extends \Civi\Api4\Generic\AbstractAction { $label = CoreUtil::getInfoItem($this->savedSearch['api_entity'], 'title_plural'); } $display = [ - 'saved_search_id' => $this->savedSearch['id'] ?? NULL, + 'id' => NULL, 'name' => NULL, + 'saved_search_id' => $this->savedSearch['id'] ?? NULL, 'label' => $label, 'type' => 'table', + 'type:label' => E::ts('Table'), + 'type:name' => 'crm-search-display-table', + 'type:icon' => 'fa-table', 'acl_bypass' => FALSE, 'settings' => [ - 'button' => E::ts('Search'), 'actions' => TRUE, 'limit' => \Civi::settings()->get('default_pager_size'), 'classes' => ['table', 'table-striped'], @@ -67,6 +73,10 @@ class GetDefault extends \Civi\Api4\Generic\AbstractAction { 'columns' => [], ], ]; + // Allow implicit-join-style selection of saved search fields + foreach ($this->savedSearch as $key => $val) { + $display['saved_search_id.' . $key] = $val; + } foreach ($this->getSelectClause() as $key => $clause) { $display['settings']['columns'][] = $this->configureColumn($clause, $key); } @@ -79,7 +89,7 @@ class GetDefault extends \Civi\Api4\Generic\AbstractAction { 'alignment' => 'text-right', 'links' => $this->getLinksMenu(), ]; - $result[] = $display; + $result->exchangeArray($this->selectArray([$display])); } /** diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js index d072d93611..235e3d6304 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js @@ -16,6 +16,8 @@ this.afformEnabled = CRM.crmSearchAdmin.afformEnabled; this.afformAdminEnabled = CRM.crmSearchAdmin.afformAdminEnabled; this.displayTypes = _.indexBy(CRM.crmSearchAdmin.displayTypes, 'id'); + this.searchDisplayPath = CRM.url('civicrm/search'); + this.afformPath = CRM.url('civicrm/admin/afform'); $scope.controls = {tab: 'compose', joinType: 'LEFT'}; $scope.joinTypes = [ @@ -156,10 +158,13 @@ } if (display.trashed && afformLoad) { afformLoad.then(function() { - if (ctrl.afforms[display.name]) { - var msg = ctrl.afforms[display.name].length === 1 ? - ts('Form "%1" will be deleted if the embedded display "%2" is deleted.', {1: ctrl.afforms[display.name][0].title, 2: display.label}) : - ts('%1 forms will be deleted if the embedded display "%2" is deleted.', {1: ctrl.afforms[display.name].length, 2: display.label}); + var displayForms = _.filter(ctrl.afforms, function(form) { + return _.includes(form.displays, ctrl.savedSearch.name + '.' + display.name); + }); + if (displayForms.length) { + var msg = displayForms.length === 1 ? + ts('Form "%1" will be deleted if the embedded display "%2" is deleted.', {1: displayForms[0].title, 2: display.label}) : + ts('%1 forms will be deleted if the embedded display "%2" is deleted.', {1: displayForms.length, 2: display.label}); CRM.alert(msg, ts('Display embedded'), 'alert'); } }); @@ -679,6 +684,7 @@ }; function loadAfforms() { + ctrl.afforms = null; if (ctrl.afformEnabled && ctrl.savedSearch.id) { var findDisplays = _.transform(ctrl.savedSearch.displays, function(findDisplays, display) { if (display.id && display.name) { @@ -689,22 +695,20 @@ select: ['name', 'title', 'search_displays'], where: [['OR', findDisplays]] }).then(function(afforms) { - ctrl.afforms = {}; + ctrl.afforms = []; _.each(afforms, function(afform) { - _.each(_.uniq(afform.search_displays), function(searchNameDisplayName) { - var displayName = searchNameDisplayName.split('.')[1] || ''; - ctrl.afforms[displayName] = ctrl.afforms[displayName] || []; - ctrl.afforms[displayName].push({ - title: afform.title, - link: ctrl.afformAdminEnabled ? CRM.url('civicrm/admin/afform#/edit/' + afform.name) : '', - }); + ctrl.afforms.push({ + title: afform.title, + displays: afform.search_displays, + link: ctrl.afformAdminEnabled ? CRM.url('civicrm/admin/afform#/edit/' + afform.name) : '', }); }); + ctrl.afformCount = ctrl.afforms.length; }); } } - // Creating an Afform opens a new tab, so when switching back to this tab, re-check for Afforms + // Creating an Afform opens a new tab, so when switching back after > 10 sec, re-check for Afforms $(window).on('focus', _.debounce(function() { $scope.$apply(loadAfforms); }, 10000, {leading: true, trailing: false})); diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.html b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.html index ca6c2a2c4b..0f4695c235 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.html +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.html @@ -19,14 +19,76 @@
-
- + +
+ +
+ + +
+ + + +
+ +
+
+
diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js index c7b2548e53..d45a4be1cf 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.component.js @@ -37,7 +37,6 @@ ctrl = this, afforms; - this.afformPath = CRM.url('civicrm/admin/afform'); this.isSuperAdmin = CRM.checkPerm('all CiviCRM permissions and ACLs'); this.aclBypassHelp = ts('Only users with "all CiviCRM permissions and ACLs" can disable permission checks.'); @@ -302,16 +301,6 @@ } }; - // @return {Array} - this.getAfforms = function() { - if (ctrl.display.name && ctrl.crmSearchAdmin.afforms) { - if (!afforms || (ctrl.crmSearchAdmin.afforms[ctrl.display.name] && afforms !== ctrl.crmSearchAdmin.afforms[ctrl.display.name])) { - afforms = ctrl.crmSearchAdmin.afforms[ctrl.display.name] || []; - } - } - return afforms; - }; - $scope.$watch('$ctrl.display.settings', function() { ctrl.stale = true; }, true); diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.html b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.html index 17110c51dc..6393bf24b9 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.html +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminDisplay.html @@ -14,32 +14,6 @@ {{:: ts('Anyone who can view this display will be able to see all results, regardless of their permission level.') }}
-
- - -
diff --git a/ext/search_kit/ang/crmSearchAdmin/resultsTable/crmSearchAdminResultsTable.component.js b/ext/search_kit/ang/crmSearchAdmin/resultsTable/crmSearchAdminResultsTable.component.js index 5c0ee89aee..0744b7aff0 100644 --- a/ext/search_kit/ang/crmSearchAdmin/resultsTable/crmSearchAdminResultsTable.component.js +++ b/ext/search_kit/ang/crmSearchAdmin/resultsTable/crmSearchAdminResultsTable.component.js @@ -18,6 +18,8 @@ function buildSettings() { ctrl.apiEntity = ctrl.search.api_entity; ctrl.settings = _.cloneDeep(CRM.crmSearchAdmin.defaultDisplay.settings); + ctrl.settings.button = ts('Search'); + // The default-display settings contain just one column (the last one, with the links menu) ctrl.settings.columns = _.transform(ctrl.search.api_params.select, function(columns, fieldExpr) { columns.push(searchMeta.fieldToColumn(fieldExpr, {label: true, sortable: true})); }).concat(ctrl.settings.columns); diff --git a/ext/search_kit/ang/crmSearchAdmin/searchListing/afforms.html b/ext/search_kit/ang/crmSearchAdmin/searchListing/afforms.html index 211d50a69c..9912d36d5c 100644 --- a/ext/search_kit/ang/crmSearchAdmin/searchListing/afforms.html +++ b/ext/search_kit/ang/crmSearchAdmin/searchListing/afforms.html @@ -1,9 +1,14 @@ -
+