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 @@
-
+