diff --git a/ext/search_kit/ang/crmSearchAdmin.module.js b/ext/search_kit/ang/crmSearchAdmin.module.js index b8e0790ec168..476b2de94ee0 100644 --- a/ext/search_kit/ang/crmSearchAdmin.module.js +++ b/ext/search_kit/ang/crmSearchAdmin.module.js @@ -9,6 +9,8 @@ angular.module('crmSearchAdmin', CRM.angRequires('crmSearchAdmin')) .config(function($routeProvider) { + const ts = CRM.ts('org.civicrm.search_kit'); + $routeProvider.when('/list', { controller: 'searchList', reloadOnSearch: false, @@ -41,6 +43,30 @@ } } }); + $routeProvider.when('/clone/:id', { + controller: 'searchClone', + template: '', + resolve: { + // Load saved search + savedSearch: function($route, crmApi4) { + var params = $route.current.params; + return crmApi4('SavedSearch', 'get', { + select: ['label', 'description', 'api_entity', 'api_params', 'expires_date', 'GROUP_CONCAT(DISTINCT entity_tag.tag_id) AS tag_id'], + where: [['id', '=', params.id]], + join: [ + ['EntityTag AS entity_tag', 'LEFT', ['entity_tag.entity_table', '=', '"civicrm_saved_search"'], ['id', '=', 'entity_tag.entity_id']], + ], + groupBy: ['id'], + chain: { + displays: ['SearchDisplay', 'get', { + select: ['label', 'type', 'settings'], + where: [['saved_search_id', '=', '$id']], + }] + } + }, 0); + } + } + }); }) // Controller for tabbed view of SavedSearches @@ -100,6 +126,19 @@ $scope.$ctrl = this; }) + // Controller for cloning a SavedSearch + .controller('searchClone', function($scope, savedSearch) { + searchEntity = savedSearch.api_entity; + savedSearch.label += ' (' + ts('copy') + ')'; + delete savedSearch.id; + savedSearch.displays.forEach(display => { + delete display.id; + display.label += ' (' + ts('copy') + ')'; + }); + this.savedSearch = savedSearch; + $scope.$ctrl = this; + }) + .factory('searchMeta', function($q, crmApi4, formatForSelect2) { function getEntity(entityName) { if (entityName) { diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js index ff4f90c3f674..42dfd941063d 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdmin.component.js @@ -94,7 +94,9 @@ this.savedSearch.tag_id = this.savedSearch.tag_id || []; this.groupExists = !!this.savedSearch.groups.length; - if (!this.savedSearch.id) { + const path = $location.path(); + // In create mode, set defaults and bind params to route for easy copy/paste + if (path.includes('create/')) { var defaults = { version: 4, select: searchMeta.getEntity(ctrl.savedSearch.api_entity).default_columns, @@ -115,7 +117,7 @@ }); // Set default label - ctrl.savedSearch.label = ts('%1 Search by %2', { + ctrl.savedSearch.label = ctrl.savedSearch.label || ts('%1 Search by %2', { 1: searchMeta.getEntity(ctrl.savedSearch.api_entity).title, 2: CRM.crmSearchAdmin.myName }); diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.component.js b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.component.js index a307b60ddfd2..e2b83b54feeb 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.component.js +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.component.js @@ -3,9 +3,7 @@ angular.module('crmSearchAdmin').component('crmSearchAdminExport', { bindings: { - savedSearchId: '<', - savedSearchName: '<', - displayNames: '<' + savedSearch: '<' }, templateUrl: '~/crmSearchAdmin/crmSearchAdminExport.html', controller: function ($scope, $element, crmApi4) { @@ -20,15 +18,19 @@ ]; this.$onInit = function() { - this.apiExplorerLink = CRM.url('civicrm/api4#/explorer/SavedSearch/export?_format=php&cleanup=always&id=' + ctrl.savedSearchId); + this.apiExplorerLink = CRM.url('civicrm/api4#/explorer/SavedSearch/export?_format=php&cleanup=always&id=' + ctrl.savedSearch.id); + this.simpleLink = CRM.url('civicrm/admin/search#/create/' + ctrl.savedSearch.api_entity + '?params=' + encodeURI(angular.toJson(ctrl.savedSearch.api_params))); - var findDisplays = _.transform(ctrl.displayNames, function(findDisplays, displayName) { - findDisplays.push(['search_displays', 'CONTAINS', ctrl.savedSearchName + '.' + displayName]); - }, [['search_displays', 'CONTAINS', ctrl.savedSearchName]]); - var apiCalls = [ - ['SavedSearch', 'export', {id: ctrl.savedSearchId}], + let apiCalls = [ + ['SavedSearch', 'export', {id: ctrl.savedSearch.id}], ]; if (ctrl.afformEnabled) { + let findDisplays = [['search_displays', 'CONTAINS', ctrl.savedSearch.name]]; + if (ctrl.savedSearch.display_name) { + ctrl.savedSearch.display_name.forEach(displayName => { + findDisplays.push(['search_displays', 'CONTAINS', `${ctrl.savedSearch.name}.${displayName}`]); + }); + } apiCalls.push(['Afform', 'get', {layoutFormat: 'html', where: [['type', '=', 'search'], ['OR', findDisplays]]}]); } crmApi4(apiCalls) diff --git a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.html b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.html index c95e6274ae92..6d8f91e43995 100644 --- a/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.html +++ b/ext/search_kit/ang/crmSearchAdmin/crmSearchAdminExport.html @@ -4,11 +4,22 @@ {{:: ts('Search configuration can be copied from here, then pasted into "Import" to e.g. transfer between sites.') }}

+

+ + {{:: ts('Copyable link:') }} + + {{:: ts('Saved Search Criteria') }} +

{{:: ts('To package for distribution in an extension, use') }} + + {{:: ts('Civix Export') }} + + + {{:: ts('or') }} - {{:: ts('API Explorer Export') }} + {{:: ts('API Explorer') }}

diff --git a/ext/search_kit/ang/crmSearchAdmin/searchListing/buttons.html b/ext/search_kit/ang/crmSearchAdmin/searchListing/buttons.html index 90128ecac37e..256f154e94d4 100644 --- a/ext/search_kit/ang/crmSearchAdmin/searchListing/buttons.html +++ b/ext/search_kit/ang/crmSearchAdmin/searchListing/buttons.html @@ -20,7 +20,7 @@
  • - + {{:: ts('Clone...') }} diff --git a/ext/search_kit/ang/crmSearchAdmin/searchListing/crmSearchAdminSearchListing.component.js b/ext/search_kit/ang/crmSearchAdmin/searchListing/crmSearchAdminSearchListing.component.js index 4062f7b7ea7b..8360063e09aa 100644 --- a/ext/search_kit/ang/crmSearchAdmin/searchListing/crmSearchAdminSearchListing.component.js +++ b/ext/search_kit/ang/crmSearchAdmin/searchListing/crmSearchAdminSearchListing.component.js @@ -119,10 +119,6 @@ updateAfformCounts(); }); - this.encode = function(params) { - return encodeURI(angular.toJson(params)); - }; - this.deleteOrRevert = function(row) { var search = row.data, revert = !!search['base_module:label']; diff --git a/ext/search_kit/ang/crmSearchAdmin/searchListing/export.html b/ext/search_kit/ang/crmSearchAdmin/searchListing/export.html index e75e5e3e4a48..ce5283447115 100644 --- a/ext/search_kit/ang/crmSearchAdmin/searchListing/export.html +++ b/ext/search_kit/ang/crmSearchAdmin/searchListing/export.html @@ -1 +1 @@ - +