],
'bundles' => ['bootstrap3'],
'basePages' => ['civicrm/admin/search'],
- 'requires' => ['crmUi', 'crmUtil', 'ngRoute', 'ui.sortable', 'ui.bootstrap', 'api4', 'crmSearchTasks', 'crmRouteBinder'],
+ 'requires' => ['crmUi', 'crmUtil', 'ngRoute', 'ui.sortable', 'ui.bootstrap', 'api4', 'crmSearchTasks', 'crmRouteBinder', 'crmDialog'],
'settingsFactory' => ['\Civi\Search\Admin', 'getAdminSettings'],
'permissions' => ['all CiviCRM permissions and ACLs'],
];
})
// Controller for tabbed view of SavedSearches
- .controller('searchList', function($scope, searchMeta, formatForSelect2) {
+ .controller('searchList', function($scope, $timeout, searchMeta, formatForSelect2, dialogService) {
var ts = $scope.ts = CRM.ts('org.civicrm.search_kit'),
ctrl = $scope.$ctrl = this;
searchEntity = 'SavedSearch';
if (!this.tab) {
this.tab = this.tabs[0].name;
}
+
+ this.openImportDialog = function() {
+ var options = CRM.utils.adjustDialogDefaults({
+ autoOpen: false,
+ title: ts('Import Saved Search')
+ });
+ dialogService.open('crmSearchAdminImport', '~/crmSearchAdmin/searchListing/import.html', {}, options)
+ .then(function() {
+ // Refresh the custom tab by resetting the filters
+ ctrl.tabs[0].filters = {};
+ // Timeout ensures the change gets noticed by the display's $watch
+ $timeout(function() {
+ ctrl.tabs[0].filters = {has_base: false};
+ }, 300);
+ }, _.noop);
+ };
})
// Controller for creating a new search
--- /dev/null
+(function(angular, $, _) {
+ "use strict";
+
+ angular.module('crmSearchAdmin').component('crmSearchAdminImport', {
+ templateUrl: '~/crmSearchAdmin/crmSearchAdminImport.html',
+ controller: function ($scope, dialogService, crmApi4) {
+ var ts = $scope.ts = CRM.ts('org.civicrm.search_kit'),
+ ctrl = this;
+
+ this.values = '';
+
+ this.run = function() {
+ ctrl.running = true;
+ try {
+ var apiCalls = JSON.parse(ctrl.values);
+ _.each(apiCalls, function(apiCall) {
+ if (apiCall[1] !== 'create' || ('chain' in apiCall[2] && !_.isEmpty(apiCall[2].chain))) {
+ throw ts('Unsupported API action: only "create" is allowed.');
+ }
+ });
+ crmApi4(apiCalls)
+ .then(function(result) {
+ CRM.alert(
+ result.length === 1 ? ts('1 record successfully imported.') : ts('%1 records successfully imported.', {1: results.length}),
+ ts('Saved'),
+ 'success'
+ );
+ dialogService.close('crmSearchAdminImport');
+ }, function(error) {
+ ctrl.running = false;
+ alert(ts('Processing Error') + "\n" + error.error_message);
+ });
+ } catch(e) {
+ ctrl.running = false;
+ alert(ts('Input Error') + "\n" + e);
+ }
+ };
+ }
+ });
+
+})(angular, CRM.$, CRM._);
--- /dev/null
+<div id="bootstrap-theme" crm-dialog="crmSearchAdminImport">
+ <div class="alert alert-info">
+ <p>
+ <i class="crm-i fa-info-circle"></i>
+ {{:: ts('A Search configuration copied from the "Export" action can be pasted here.') }}
+ </p>
+ <p>
+ {{:: ts('Note: a Saved Search with the same name must not already exist.') }}
+ </p>
+ </div>
+ <textarea id="crm-search-admin-export-output-code" class="form-control" ng-model="$ctrl.values" rows="15"></textarea>
+ <crm-dialog-button text="ts('Import')" icons="{primary: 'fa-save'}" on-click="$ctrl.run()" disabled="$ctrl.running || !$ctrl.values" />
+ <crm-dialog-button text="ts('Cancel')" icons="{primary: 'fa-times'}" on-click="crmSearchAdminImport.cancel()" disabled="$ctrl.running" />
+</div>
--- /dev/null
+<crm-search-admin-import></crm-search-admin-import>
<span ng-if="$ctrl.getTags().results.length">
<input class="form-control" ng-model="tab.filters.tags" ng-list crm-ui-select="{multiple: true, data: $ctrl.getTags, placeholder: ts('Filter by tags...')}">
</span>
+ <a class="btn btn-secondary btn-sm pull-right" ng-if="tab.name === 'custom'" href ng-click="$ctrl.openImportDialog()">
+ <i class="crm-i fa-upload"></i>
+ {{:: ts('Import') }}
+ </a>
</div>
<crm-search-admin-search-listing filters="tab.filters" tab-count="tab.rowCount"></crm-search-admin-search-listing>
</div>
text-align: left;
}
-crm-search-admin-export {
+crm-search-admin-export,
+crm-search-admin-import {
display: block;
}