From 3ee3a8829ec6ceade287e5eea9ed6d355ed7e3cc Mon Sep 17 00:00:00 2001 From: colemanw Date: Sun, 24 Sep 2023 11:22:47 -0400 Subject: [PATCH] Afform - Switch to user-oriented breadcrumbs, move admin link to hover button Before: In full-page mode, breadcrumbs were orieted toward form-building, with links to edit the form and browse FormBuilder. After: In full-page mode, breadcrumbs are oriented toward general users, with links to parent-pages. Parent pages are, by default calculated based off the route. This adds a 'title' key in function `afform_civicrm_alterMenu` for the benefit of`CRM_Core_Menu::buildBreadcrumb`. Alternately, if the Afform has been placed in the navigation menu, then the breadcrumb is calculated based on the parent menu item. --- CRM/Utils/System.php | 2 +- .../Civi/AfformAdmin/AfformAdminInjector.php | 55 +++++++++++++++++++ ext/afform/admin/info.xml | 1 + .../core/CRM/Afform/Page/AfformBase.php | 33 ++++++----- .../Civi/Afform/AfformMetadataInjector.php | 5 +- ext/afform/core/afform.php | 3 +- ext/afform/core/ang/afCore.css | 12 ++++ 7 files changed, 93 insertions(+), 18 deletions(-) create mode 100644 ext/afform/admin/Civi/AfformAdmin/AfformAdminInjector.php diff --git a/CRM/Utils/System.php b/CRM/Utils/System.php index c70d83af3a..03c260f8cc 100644 --- a/CRM/Utils/System.php +++ b/CRM/Utils/System.php @@ -26,7 +26,7 @@ * @method static mixed permissionDenied() Show access denied screen. * @method static mixed logout() Log out the current user. * @method static mixed updateCategories() Clear CMS caches related to the user registration/profile forms. - * @method static void appendBreadCrumb(array $breadCrumbs) Append an additional breadcrumb tag to the existing breadcrumbs. + * @method static void appendBreadCrumb(array $breadCrumbs) Append an additional breadcrumb link to the existing breadcrumbs. * @method static void resetBreadCrumb() Reset an additional breadcrumb tag to the existing breadcrumb. * @method static void addHTMLHead(string $head) Append a string to the head of the HTML file. * @method static string postURL(int $action) Determine the post URL for a form. diff --git a/ext/afform/admin/Civi/AfformAdmin/AfformAdminInjector.php b/ext/afform/admin/Civi/AfformAdmin/AfformAdminInjector.php new file mode 100644 index 0000000000..6248442082 --- /dev/null +++ b/ext/afform/admin/Civi/AfformAdmin/AfformAdminInjector.php @@ -0,0 +1,55 @@ + 'preprocess', + ]; + } + + /** + * @param \Civi\Core\Event\GenericHookEvent $e + * @see CRM_Utils_Hook::alterAngular() + */ + public static function preprocess($e) { + $changeSet = \Civi\Angular\ChangeSet::create('afformAdmin') + ->alterHtml(';\\.aff\\.html$;', function($doc, $path) { + try { + $moduleName = basename($path, '.aff.html'); + // If the user has "administer CiviCRM", inject edit link + if (\CRM_Core_Permission::check('administer CiviCRM')) { + $url = \CRM_Utils_System::url('civicrm/admin/afform', NULL, FALSE, '/edit/' . $moduleName, TRUE); + // Append link to afform directive element (using loop but there should be only one) + foreach (pq('af-form[ctrl]', $doc) as $afForm) { + pq($afForm)->append(' ' . E::ts('Edit Form') . ''); + } + } + } + catch (\Exception $e) { + } + }); + $e->angular->add($changeSet); + } + +} diff --git a/ext/afform/admin/info.xml b/ext/afform/admin/info.xml index 2d999535a4..1d5eaecad3 100644 --- a/ext/afform/admin/info.xml +++ b/ext/afform/admin/info.xml @@ -32,6 +32,7 @@ + scan-classes@1.0.0 ang-php@1.0.0 menu-xml@1.0.0 mgd-php@1.0.0 diff --git a/ext/afform/core/CRM/Afform/Page/AfformBase.php b/ext/afform/core/CRM/Afform/Page/AfformBase.php index d01b9d7814..8f310390bd 100644 --- a/ext/afform/core/CRM/Afform/Page/AfformBase.php +++ b/ext/afform/core/CRM/Afform/Page/AfformBase.php @@ -1,4 +1,6 @@ [['name', '=', $pageArgs['afform']]], - 'select' => ['title', 'module_name', 'directive_name', 'type', 'is_public'], + 'select' => ['title', 'module_name', 'directive_name', 'navigation', 'server_route', 'is_public'], ], 0); $this->assign('directive', $afform['directive_name']); @@ -18,25 +20,30 @@ class CRM_Afform_Page_AfformBase extends CRM_Core_Page { Civi::service('angularjs.loader') ->addModules([$afform['module_name'], 'afformStandalone']); + // Title will be supplied by AfformBase.tpl. + // @see crmUi.directive(crmPageTitle) + CRM_Utils_System::setTitle(''); + $isFrontEndPage = !empty($afform['is_public']); - // If not being shown on the front-end website, append breadcrumb for CiviCRM users + // If not being shown on the front-end website, calculate breadcrumbs if (!$isFrontEndPage && CRM_Core_Permission::check('access CiviCRM')) { - CRM_Utils_System::appendBreadCrumb([['title' => E::ts('CiviCRM'), 'url' => CRM_Utils_System::url('civicrm')]]); - // If the user has "admin civicrm" & the admin extension is enabled - if (CRM_Core_Permission::check('administer CiviCRM')) { - if (($pagePath[1] ?? NULL) === 'admin') { - CRM_Utils_System::appendBreadCrumb([['title' => E::ts('Administer'), 'url' => CRM_Utils_System::url('civicrm/admin')]]); - } - if ($afform['type'] !== 'system' && - \CRM_Extension_System::singleton()->getMapper()->isActiveModule('afform_admin') - ) { - CRM_Utils_System::appendBreadCrumb([['title' => E::ts('FormBuilder'), 'url' => CRM_Utils_System::url('civicrm/admin/afform')]]); - CRM_Utils_System::appendBreadCrumb([['title' => E::ts('Edit Form'), 'url' => CRM_Utils_System::url('civicrm/admin/afform', NULL, FALSE, '/edit/' . $pageArgs['afform'])]]); + // CiviCRM has already constructed a breadcrumb based on the server_route (see CRM_Core_Menu::buildBreadcrumb) + // But if this afform is in the navigation menu, reset breadcrumb and build on that instead + if (!empty($afform['navigation']['parent'])) { + $navParent = Navigation::get(FALSE) + ->addWhere('name', '=', $afform['navigation']['parent']) + ->addWhere('domain_id', '=', 'current_domain') + ->execute()->first(); + if (!empty($navParent['url'])) { + CRM_Utils_System::resetBreadCrumb(); + CRM_Utils_System::appendBreadCrumb([['title' => E::ts('CiviCRM'), 'url' => Civi::url('civicrm')]]); + CRM_Utils_System::appendBreadCrumb([['title' => $navParent['label'], 'url' => Civi::url($navParent['url'])]]); } } } + // Add current afform page to breadcrumb if (!empty($afform['title'])) { $title = strip_tags($afform['title']); if (!$isFrontEndPage) { diff --git a/ext/afform/core/Civi/Afform/AfformMetadataInjector.php b/ext/afform/core/Civi/Afform/AfformMetadataInjector.php index 2aa4dbac14..69bd0ebb52 100644 --- a/ext/afform/core/Civi/Afform/AfformMetadataInjector.php +++ b/ext/afform/core/Civi/Afform/AfformMetadataInjector.php @@ -14,7 +14,6 @@ namespace Civi\Afform; use CRM_Afform_ExtensionUtil as E; /** - * Class AfformMetadataInjector * @package Civi\Afform */ class AfformMetadataInjector { @@ -30,8 +29,8 @@ class AfformMetadataInjector { $module = \Civi::service('angular')->getModule(basename($path, '.aff.html')); $meta = \Civi\Api4\Afform::get(FALSE)->addWhere('name', '=', $module['_afform'])->setSelect(['join_entity', 'entity_type'])->execute()->first(); - // Add ngForm directive to afForm controllers - foreach (pq('af-form[ctrl]') as $afForm) { + // Add ngForm directive to afForm controller (using loop but there should be only one) + foreach (pq('af-form[ctrl]', $doc) as $afForm) { pq($afForm)->attr('ng-form', $module['_afform']); } } diff --git a/ext/afform/core/afform.php b/ext/afform/core/afform.php index c53576ecda..674f44be72 100644 --- a/ext/afform/core/afform.php +++ b/ext/afform/core/afform.php @@ -391,7 +391,7 @@ function afform_civicrm_alterMenu(&$items) { try { $afforms = \Civi\Api4\Afform::get(FALSE) ->addWhere('server_route', 'IS NOT EMPTY') - ->addSelect('name', 'server_route', 'is_public') + ->addSelect('name', 'server_route', 'is_public', 'title') ->execute()->indexBy('name'); } catch (Exception $e) { @@ -402,6 +402,7 @@ function afform_civicrm_alterMenu(&$items) { foreach ($afforms as $name => $meta) { if (!empty($meta['server_route'])) { $items[$meta['server_route']] = [ + 'title' => $meta['title'], 'page_callback' => 'CRM_Afform_Page_AfformBase', 'page_arguments' => 'afform=' . urlencode($name), 'access_arguments' => [["@afform:$name"], 'and'], diff --git a/ext/afform/core/ang/afCore.css b/ext/afform/core/ang/afCore.css index 35e095925c..d7dae0164c 100644 --- a/ext/afform/core/ang/afCore.css +++ b/ext/afform/core/ang/afCore.css @@ -28,6 +28,7 @@ a.af-api4-action-idle { af-form { display: block; + position: relative; } #bootstrap-theme .input-group .crm-af-field { @@ -84,3 +85,14 @@ af-form { #bootstrap-theme .af-container-style-pane.af-collapsed > .af-title { margin-bottom: 0; } + +/* Admin edit links */ +af-form a.af-admin-edit-form-link { + position: absolute; + right: 0; + top: 0; + display: none; +} +af-form:hover a.af-admin-edit-form-link { + display: block; +} -- 2.25.1