return [
'operators' => \CRM_Utils_Array::makeNonAssociative(self::getOperators()),
'functions' => \CRM_Api4_Page_Api4Explorer::getSqlFunctions(),
- 'displayTypes' => self::getDisplayTypes(['name', 'label', 'description', 'icon']),
+ 'displayTypes' => Display::getDisplayTypes(['name', 'label', 'description', 'icon']),
];
}
return array_filter($results);
}
- /**
- * @param array $props
- * @return array
- */
- public static function getDisplayTypes(array $props):array {
- try {
- return \Civi\Api4\SearchDisplay::getFields(FALSE)
- ->setLoadOptions($props)
- ->addWhere('name', '=', 'type')
- ->execute()
- ->first()['options'];
- }
- catch (\Exception $e) {
- return [];
- }
- }
-
}
--- /dev/null
+<?php
+/*
+ +--------------------------------------------------------------------+
+ | Copyright CiviCRM LLC. All rights reserved. |
+ | |
+ | This work is published under the GNU AGPLv3 license with some |
+ | permitted exceptions and without any warranty. For full license |
+ | and copyright information, see https://civicrm.org/licensing |
+ +--------------------------------------------------------------------+
+ */
+
+namespace Civi\Search;
+
+/**
+ * Class Display
+ * @package Civi\Search
+ */
+class Display {
+
+ /**
+ * @return array
+ */
+ public static function getPageSettings():array {
+ return [
+ 'displayTypes' => self::getDisplayTypes(['name']),
+ ];
+ }
+
+ /**
+ * @param array $props
+ * @return array
+ */
+ public static function getDisplayTypes(array $props):array {
+ try {
+ return \Civi\Api4\SearchDisplay::getFields(FALSE)
+ ->setLoadOptions($props)
+ ->addWhere('name', '=', 'type')
+ ->execute()
+ ->first()['options'];
+ }
+ catch (\Exception $e) {
+ return [];
+ }
+ }
+
+}
],
'basePages' => ['civicrm/search'],
'requires' => ['ngRoute', 'api4', 'crmUi', 'crmSearchDisplay'],
+ 'settingsFactory' => ['\Civi\Search\Display', 'getPageSettings'],
];
// Declare module
angular.module('crmSearchPage', CRM.angRequires('crmSearchPage'))
-
.config(function($routeProvider) {
+ // Load & render a SearchDisplay
$routeProvider.when('/display/:savedSearchName/:displayName', {
controller: 'crmSearchPageDisplay',
- templateUrl: '~/crmSearchPage/display.html',
+ // Dynamic template generates the directive for each display type
+ template: function() {
+ var html =
+ '<h1 crm-page-title>{{:: $ctrl.display.label }}</h1>\n' +
+ '<div ng-switch="$ctrl.display.type" id="bootstrap-theme">\n';
+ _.each(CRM.crmSearchPage.displayTypes, function(type) {
+ html +=
+ ' <div ng-switch-when="' + type.name + '">\n' +
+ ' <crm-search-display-' + type.name + ' api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" settings="$ctrl.display.settings"></crm-search-display-' + type.name + '>\n' +
+ ' </div>\n';
+ });
+ html += '</div>';
+ return html;
+ },
resolve: {
// Load saved search display
display: function($route, crmApi4) {
// Controller for displaying a search
.controller('crmSearchPageDisplay', function($scope, $routeParams, $location, display) {
this.display = display;
+ this.apiEntity = display['saved_search.api_entity'];
+ this.apiParams = display['saved_search.api_params'];
$scope.$ctrl = this;
});
+++ /dev/null
-<h1 crm-page-title>{{:: $ctrl.display.label }}</h1>
-
-<div ng-switch="$ctrl.display.type" id="bootstrap-theme">
- <div ng-switch-when="table">
- <crm-search-display-table api-entity="$ctrl.display['saved_search.api_entity']" api-params="$ctrl.display['saved_search.api_params']" settings="$ctrl.display.settings"></crm-search-display-table>
- </div>
-</div>
</div>
<div ng-switch-default>
<div ng-repeat="display in $ctrl.savedSearch.displays" ng-if="controls.tab === ('display_' + $index)">
- <div ng-include="'~/searchAdmin/display.html'"></div>
+ <crm-search-admin-display display="display" saved-search="$ctrl.savedSearch"></crm-search-admin-display>
</div>
</div>
</div>
--- /dev/null
+(function(angular, $, _) {
+ "use strict";
+
+ angular.module('searchAdmin').component('crmSearchAdminDisplay', {
+ bindings: {
+ savedSearch: '<',
+ display: '<'
+ },
+ template: function() {
+ // Dynamic template generates switch condition for each display type
+ var html =
+ '<div ng-include="\'~/searchAdmin/crmSearchAdminDisplay.html\'"></div>\n' +
+ '<div ng-switch="$ctrl.display.type">\n';
+ _.each(CRM.searchAdmin.displayTypes, function(type) {
+ html +=
+ '<div ng-switch-when="' + type.name + '">\n' +
+ ' <search-admin-display-' + type.name + ' api-entity="$ctrl.savedSearch.api_entity" api-params="$ctrl.savedSearch.api_params" display="$ctrl.display"></search-admin-display-' + type.name + '>\n' +
+ ' <hr>\n' +
+ ' <button type="button" class="btn btn-{{ !$ctrl.stale ? \'success\' : $ctrl.preview ? \'warning\' : \'primary\' }}" ng-click="$ctrl.previewDisplay()" ng-disabled="!$ctrl.stale">\n' +
+ ' <i class="crm-i ' + type.icon + '"></i>' +
+ ' {{ $ctrl.preview && $ctrl.stale ? ts("Refresh") : ts("Preview") }}\n' +
+ ' </button>\n' +
+ ' <hr>\n' +
+ ' <div ng-if="$ctrl.preview">\n' +
+ ' <crm-search-display-' + type.name + ' api-entity="$ctrl.savedSearch.api_entity" api-params="$ctrl.savedSearch.api_params" settings="$ctrl.display.settings"></crm-search-display-' + type.name + '>\n' +
+ ' </div>\n' +
+ '</div>\n';
+ });
+ html += '</div>';
+ return html;
+ },
+ controller: function($scope, $timeout) {
+ var ts = $scope.ts = CRM.ts(),
+ ctrl = this;
+
+ this.preview = this.stale = false;
+
+ this.previewDisplay = function() {
+ ctrl.preview = !ctrl.preview;
+ ctrl.stale = false;
+ if (!ctrl.preview) {
+ $timeout(function() {
+ ctrl.preview = true;
+ }, 100);
+ }
+ };
+
+ $scope.$watch('$ctrl.display.settings', function() {
+ ctrl.stale = true;
+ }, true);
+ }
+ });
+
+})(angular, CRM.$, CRM._);
--- /dev/null
+<fieldset>
+ <div class="form-inline">
+ <label for="search_display_label">{{:: ts('Name:') }} <span class="crm-marker">*</span></label>
+ <input id="search_display_label" type="text" class="form-control" ng-model="$ctrl.display.label" required />
+ <label class="pull-right">{{:: $ctrl.displayTypes[$ctrl.display.type].label }}</label>
+ </div>
+</fieldset>
+++ /dev/null
-<fieldset>
- <div class="form-inline">
- <label for="search_display_label">{{:: ts('Name:') }} <span class="crm-marker">*</span></label>
- <input id="search_display_label" type="text" class="form-control" ng-model="display.label" required />
- <label class="pull-right">{{:: $ctrl.displayTypes[display.type].label }}</label>
- </div>
-</fieldset>
-<!-- Load template with the name of this display type, e.g. 'table.html' -->
-<div ng-if="display.type" ng-include="'~/searchAdmin/displays/' + display.type + '.html'"></div>
};
this.$onInit = function () {
- ctrl.display.settings.limit = parseInt(ctrl.display.settings.limit || 0, 10);
ctrl.getFieldLabel = ctrl.crmSearchAdmin.getFieldLabel;
if (!ctrl.display.settings.columns) {
ctrl.display.settings.columns = _.transform(ctrl.apiParams.select, function(columns, fieldExpr) {
+++ /dev/null
-<search-admin-display-table api-entity="$ctrl.savedSearch.api_entity" api-params="$ctrl.savedSearch.api_params" display="display"></search-admin-display-table>
-<hr>
-<!--<crm-search-display-table api-entity="$ctrl.apiEntity" api-params="$ctrl.apiParams" settings="display.settings"></crm-search-display-table>-->
{{:: ts('Smart Group') }}
</a>
</li>
+ <li class="dropdown-header">{{ ts('Display:') }}</li>
<li ng-repeat="type in ::$ctrl.displayTypes">
<a href ng-click="$ctrl.addDisplay(type.name)">
<i class="crm-i {{:: type.icon }}"></i>
function search_civicrm_alterAngular($angular) {
$changeSet = \Civi\Angular\ChangeSet::create('searchSettings')
->alterHtml(';\\.aff\\.html$;', function($doc, $path) {
- $displayTypes = array_column(\Civi\Search\Admin::getDisplayTypes(['name']), 'name');
+ $displayTypes = array_column(\Civi\Search\Display::getDisplayTypes(['name']), 'name');
if ($displayTypes) {
$componentNames = 'crm-search-display-' . implode(', crm-search-display-', $displayTypes);