Afform - Improve admin links to include search displays
authorcolemanw <coleman@civicrm.org>
Sun, 19 Nov 2023 20:15:46 +0000 (15:15 -0500)
committercolemanw <coleman@civicrm.org>
Sun, 19 Nov 2023 20:21:36 +0000 (15:21 -0500)
Fixes https://lab.civicrm.org/dev/core/-/issues/4786

ext/afform/admin/Civi/AfformAdmin/AfformAdminInjector.php
ext/afform/core/ang/afCore.css
ext/afform/core/ang/afCore.js

index 62484420828732f6fc9d323481153b0e34c5dd98..bc146467948d146304f417897f62a7cc2483806c 100644 (file)
@@ -11,6 +11,8 @@
 
 namespace Civi\AfformAdmin;
 
+use Civi\Api4\Afform;
+use Civi\Api4\SavedSearch;
 use Civi\Core\Service\AutoSubscriber;
 use CRM_Afform_ExtensionUtil as E;
 
@@ -36,14 +38,58 @@ class AfformAdminInjector extends AutoSubscriber {
     $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 the user has "administer CiviCRM", inject gear menu with edit links
           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('<a href="' . $url . '" target="_blank" class="af-admin-edit-form-link"><i class="crm-i fa-gear"></i> ' . E::ts('Edit Form') . '</a>');
+            $afform = Afform::get()
+              ->addWhere('module_name', '=', basename($path, '.aff.html'))
+              ->addSelect('name', 'search_displays', 'title')
+              ->execute()->single();
+            // Create a link to edit the form, plus all embedded SavedSearches
+            $links = [
+              [
+                'url' => \CRM_Utils_System::url('civicrm/admin/afform', NULL, FALSE, "/edit/{$afform['name']}", TRUE),
+                'text' => E::ts('Edit %1 in FormBuilder', [1 => "<em>{$afform['title']}</em>"]),
+                'icon' => 'fa-pencil',
+              ],
+            ];
+            if ($afform['search_displays']) {
+              $searchNames = [];
+              foreach ($afform['search_displays'] as $searchAndDisplayName) {
+                $searchNames[] = explode('.', $searchAndDisplayName)[0];
+              }
+              $savedSearches = SavedSearch::get()
+                ->addWhere('name', 'IN', $searchNames)
+                ->addSelect('id', 'label')
+                ->execute();
+              foreach ($savedSearches as $savedSearch) {
+                $links[] = [
+                  'url' => \CRM_Utils_System::url('civicrm/admin/search', NULL, FALSE, "/edit/{$savedSearch['id']}", TRUE),
+                  'text' => E::ts('Edit %1 in SearchKit', [1 => "<em>{$savedSearch['label']}</em>"]),
+                  'icon' => 'fa-search-plus',
+                ];
+              }
             }
+            $linksMarkup = '';
+            foreach ($links as $link) {
+              $linksMarkup .= <<<HTML
+                <li>
+                  <a href="{$link['url']}" target="_blank">
+                    <i class="crm-i fa-fw {$link['icon']}"></i> {$link['text']}
+                  </a>
+                </li>
+              HTML;
+            }
+            $editMenu = <<<HTML
+              <div class="pull-right btn-group af-admin-edit-form-link">
+                <button type="button" class="btn dropdown-toggle btn-sm" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+                  <i class="crm-i fa-gear"></i> <span class="caret"></span>
+                </button>
+                <ul class="dropdown-menu">$linksMarkup</ul>
+              </div>
+            HTML;
+            // Append link to end of afform markup so it has the highest z-index and is clickable.
+            // afCore.css will control placement at the top of the form.
+            pq($doc)->append($editMenu);
           }
         }
         catch (\Exception $e) {
index d7dae0164c6ff59fd756aec3ce6e980589915a05..28eea63df2f2675a1dabd09382440825a2ecd978 100644 (file)
@@ -26,6 +26,7 @@ a.af-api4-action-idle {
   width: 100%;
 }
 
+.afform-directive,
 af-form {
   display: block;
   position: relative;
@@ -87,12 +88,13 @@ af-form {
 }
 
 /* Admin edit links */
-af-form a.af-admin-edit-form-link {
-  position: absolute;
+.afform-directive .af-admin-edit-form-link {
+  position: absolute !important;
   right: 0;
   top: 0;
-  display: none;
+  opacity: .5;
 }
-af-form:hover a.af-admin-edit-form-link {
-  display: block;
+.afform-directive .af-admin-edit-form-link.open,
+.afform-directive:hover .af-admin-edit-form-link {
+  opacity: 1;
 }
index a1dc17aa2284a70f76274613c83c7eaedd121648..3eb7abf0cf84e346c70d8312d0a12e3cff51d725 100644 (file)
@@ -17,6 +17,8 @@
           $scope.crmUiAlert = crmUiAlert;
           $scope.crmUrl = CRM.url;
 
+          $el.addClass('afform-directive');
+
           // Afforms do not use routing, but some forms get input from search params
           var dialog = $el.closest('.ui-dialog-content');
           if (!dialog.length) {