Skip to content

Commit

Permalink
SearchKit/Afform - Provide contextual titles to search Afforms in sta…
Browse files Browse the repository at this point in the history
…ndalone mode

When displaying a full-page search with contextual filters, e.g. submissions for a particular form,
provides a contextual title based on the url filter arg, e.g. "My Great Form Submissions"
  • Loading branch information
colemanw committed Dec 26, 2021
1 parent e3d2783 commit 007167d
Show file tree
Hide file tree
Showing 14 changed files with 128 additions and 22 deletions.
9 changes: 7 additions & 2 deletions ang/crmUi.js
Original file line number Diff line number Diff line change
Expand Up @@ -1083,15 +1083,20 @@
function update() {
$timeout(function() {
var newPageTitle = _.trim($el.html()),
newDocumentTitle = scope.crmDocumentTitle || $el.text();
newDocumentTitle = scope.crmDocumentTitle || $el.text(),
h1Count = 0;
document.title = $('title').text().replace(documentTitle, newDocumentTitle);
// If the CMS has already added title markup to the page, use it
$('h1').not('.crm-container h1').each(function() {
if (_.trim($(this).html()) === pageTitle) {
if ($(this).hasClass('crm-page-title') || _.trim($(this).html()) === pageTitle) {
$(this).addClass('crm-page-title').html(newPageTitle);
$el.hide();
++h1Count;
}
});
if (!h1Count) {
$el.show();
}
pageTitle = newPageTitle;
documentTitle = newDocumentTitle;
});
Expand Down
6 changes: 0 additions & 6 deletions ext/afform/admin/ang/afAdminFormSubmissionList.aff.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
<div
ng-if="routeParams.name"
af-api4="['Afform', 'get', {select: ['title'], where: [['name', '=', routeParams.name]]}, 0]"
af-api4-ctrl="api4">
<h2>{{ ts('%1 Submissions', {1: api4.result.title || ts('Loading')}) }}</h2>
</div>
<div af-fieldset="">
<crm-search-display-table search-name="AfAdmin_Submission_List" display-name="AfAdmin_Submission_List_Display" filters="{afform_name: routeParams.name}">
</crm-search-display-table>
Expand Down
2 changes: 1 addition & 1 deletion ext/afform/admin/ang/afAdminFormSubmissionList.aff.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"type": "search",
"title": "Form Submissions",
"title": "Submissions",
"server_route": "civicrm/admin/afform/submissions",
"permission": "administer CiviCRM"
}
1 change: 0 additions & 1 deletion ext/afform/core/CRM/Afform/Page/AfformBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ public function run() {

if (!empty($afform['title'])) {
$title = strip_tags($afform['title']);
CRM_Utils_System::setTitle($title);
if (!$isFrontEndPage) {
CRM_Utils_System::appendBreadCrumb([
[
Expand Down
3 changes: 1 addition & 2 deletions ext/afform/core/afform.php
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ function afform_civicrm_buildAsset($asset, $params, &$mimeType, &$content) {
$moduleName = _afform_angular_module_name($params['name'], 'camel');
$formMetaData = (array) civicrm_api4('Afform', 'get', [
'checkPermissions' => FALSE,
'select' => ['redirect', 'name'],
'select' => ['redirect', 'name', 'title'],
'where' => [['name', '=', $params['name']]],
], 0);
$smarty = CRM_Core_Smarty::singleton();
Expand Down Expand Up @@ -366,7 +366,6 @@ function afform_civicrm_alterMenu(&$items) {
$items[$meta['server_route']] = [
'page_callback' => 'CRM_Afform_Page_AfformBase',
'page_arguments' => 'afform=' . urlencode($name),
'title' => $meta['title'] ?? '',
'access_arguments' => [["@afform:$name"], 'and'],
'is_public' => $meta['is_public'],
];
Expand Down
8 changes: 8 additions & 0 deletions ext/afform/core/ang/afCore.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,14 @@
$scope.$watch(function() {return $location.search();}, function(params) {
$scope.routeParams = params;
});

$scope.$parent.afformTitle = meta.title;

// Prepends a string to the afform title
// Provides contextual titles to search Afforms in standalone mode
$scope.addTitle = function(addition) {
$scope.$parent.afformTitle = addition + ' ' + meta.title;
};
}
};
return d;
Expand Down
6 changes: 5 additions & 1 deletion ext/afform/core/ang/afformStandalone.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
(function(angular, $, _) {
// Empty module just loads all available modules.
angular.module('afformStandalone', CRM.angular.modules);
angular.module('afformStandalone', CRM.angular.modules)

.controller('AfformStandalonePageCtrl', function($scope) {
$scope.afformTitle = '';
});

})(angular, CRM.$, CRM._);
5 changes: 4 additions & 1 deletion ext/afform/core/templates/CRM/Afform/Page/AfformBase.tpl
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
<crm-angular-js modules="afformStandalone">
<form id="bootstrap-theme">
<form id="bootstrap-theme" ng-controller="AfformStandalonePageCtrl">
{literal}
<h1 style="display: none" crm-page-title ng-if="afformTitle">{{ afformTitle }}</h1>
{/literal}
<{$directive}></{$directive}>
</form>
</crm-angular-js>
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,14 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
*/
protected $filters = [];

/**
* Filters passed directly into this display via Afform markup
* will have their labels appended to the Afform title.
*
* @var array
*/
protected $filterLabels = [];

/**
* Integer used as a seed when ordering by RAND().
* This keeps the order stable enough to use a pager with random sorting.
Expand All @@ -67,6 +75,14 @@ abstract class AbstractRunAction extends \Civi\Api4\Generic\AbstractAction {
*/
private $_afform;

/**
* Override execute method to change the result object type
* @return \Civi\Api4\Result\SearchDisplayRunResult
*/
public function execute() {
return parent::execute();
}

/**
* @param \Civi\Api4\Generic\Result $result
* @throws UnauthorizedException
Expand Down Expand Up @@ -105,7 +121,7 @@ public function _run(\Civi\Api4\Generic\Result $result) {
$this->processResult($result);
}

abstract protected function processResult(\Civi\Api4\Generic\Result $result);
abstract protected function processResult(\Civi\Api4\Result\SearchDisplayRunResult $result);

/**
* Transforms each row into an array of raw data and an array of formatted columns
Expand Down Expand Up @@ -587,7 +603,8 @@ protected function formatViewValue($key, $rawValue) {
*/
protected function applyFilters() {
// Allow all filters that are included in SELECT clause or are fields on the Afform.
$allowedFilters = array_merge($this->getSelectAliases(), $this->getAfformFilters());
$afformFilters = $this->getAfformFilters();
$allowedFilters = array_merge($this->getSelectAliases(), $afformFilters);

// Ignore empty strings
$filters = array_filter($this->filters, [$this, 'hasValue']);
Expand All @@ -600,6 +617,9 @@ protected function applyFilters() {
if (in_array($key, $allowedFilters, TRUE) || !array_diff($fieldNames, $allowedFilters)) {
$this->applyFilter($fieldNames, $value);
}
if (in_array($key, $afformFilters, TRUE)) {
$this->addFilterLabel($key, $value);
}
}
}

Expand Down Expand Up @@ -941,4 +961,45 @@ public static function getPseudoFields(): array {
];
}

/**
* Sets $this->filterLabels to provide contextual titles to search Afforms
*
* @param $fieldName
* @param $value
* @throws \API_Exception
* @throws \Civi\API\Exception\NotImplementedException
*/
private function addFilterLabel($fieldName, $value) {
$field = $this->getField($fieldName);
if (!$field || !$value) {
return;
}
$idField = CoreUtil::getIdFieldName($field['entity']);
if ($field['name'] === $idField) {
$field['fk_entity'] = $field['entity'];
}
if (!empty($field['options'])) {
$options = civicrm_api4($field['entity'], 'getFields', [
'loadOptions' => TRUE,
'where' => [['name', '=', $field['name']]],
])->first()['options'] ?? [];
if (!empty($options[$value])) {
$this->filterLabels[] = $options[$value];
}
}
elseif (!empty($field['fk_entity'])) {
$idField = CoreUtil::getIdFieldName($field['fk_entity']);
$labelField = CoreUtil::getInfoItem($field['fk_entity'], 'label_field');
if ($labelField) {
$record = civicrm_api4($field['fk_entity'], 'get', [
'where' => [[$idField, '=', $value]],
'select' => [$labelField],
])->first() ?? NULL;
if (isset($record[$labelField])) {
$this->filterLabels[] = $record[$labelField];
}
}
}
}

}
4 changes: 2 additions & 2 deletions ext/search_kit/Civi/Api4/Action/SearchDisplay/Download.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ class Download extends AbstractRunAction {
];

/**
* @param \Civi\Api4\Generic\Result $result
* @param \Civi\Api4\Result\SearchDisplayRunResult $result
* @throws \API_Exception
*/
protected function processResult(\Civi\Api4\Generic\Result $result) {
protected function processResult(\Civi\Api4\Result\SearchDisplayRunResult $result) {
$entityName = $this->savedSearch['api_entity'];
$apiParams =& $this->_apiParams;
$settings = $this->display['settings'];
Expand Down
5 changes: 3 additions & 2 deletions ext/search_kit/Civi/Api4/Action/SearchDisplay/Run.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ class Run extends AbstractRunAction {
protected $limit;

/**
* @param \Civi\Api4\Generic\Result $result
* @param \Civi\Api4\Result\SearchDisplayRunResult $result
* @throws \API_Exception
*/
protected function processResult(\Civi\Api4\Generic\Result $result) {
protected function processResult(\Civi\Api4\Result\SearchDisplayRunResult $result) {
$entityName = $this->savedSearch['api_entity'];
$apiParams =& $this->_apiParams;
$settings = $this->display['settings'];
Expand Down Expand Up @@ -77,6 +77,7 @@ protected function processResult(\Civi\Api4\Generic\Result $result) {
}
else {
$result->exchangeArray($this->formatResult($apiResult));
$result->labels = $this->filterLabels;
}

}
Expand Down
26 changes: 26 additions & 0 deletions ext/search_kit/Civi/Api4/Result/SearchDisplayRunResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?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\Api4\Result;

/**
* Class ReplaceResult
*
* @package Civi\Api4\Result
*/
class SearchDisplayRunResult extends \Civi\Api4\Generic\Result {
/**
* @var array
*/
public $labels = [];

}
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,12 @@

if (this.afFieldset) {
$scope.$watch(this.afFieldset.getFieldData, onChangeFilters, true);
// Add filter title to Afform
this.onPostRun.push(function(results) {
if (results.labels && results.labels.length && $scope.$parent.addTitle) {
$scope.$parent.addTitle(results.labels.join(' '));
}
});
}
if (this.settings.pager && this.settings.pager.expose_limit) {
$scope.$watch('$ctrl.limit', onChangePageSize);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,14 +59,14 @@
this.runSearch();
},

// Overwrite empty onChangeFilters array from searchDisplayBaseTrait
// Add onChangeFilters callback (gets merged with others via angular.extend)
onChangeFilters: [function() {
// Reset selection when filters are changed
this.selectedRows.length = 0;
this.allRowsSelected = false;
}],

// Overwrite empty onPostRun array from searchDisplayBaseTrait
// Add onPostRun callback (gets merged with others via angular.extend)
onPostRun: [function(results, status, editedRow) {
if (editedRow && status === 'success') {
// If edited row disappears (because edits cause it to not meet search criteria), deselect it
Expand Down

0 comments on commit 007167d

Please sign in to comment.