From 2ef64700d2d940794bb33588f743cd53f66e8b30 Mon Sep 17 00:00:00 2001 From: Coleman Watts Date: Thu, 28 Jan 2021 14:04:32 -0500 Subject: [PATCH] Afform Gui - Support editing search forms This permits search forms to be edited and saved in the Afform GUI, and also provides a link to do so from the Search Kit admin screen. --- .../Civi/Api4/Action/Afform/LoadAdminData.php | 50 ++++++- .../ang/afAdmin/afAdminList.controller.js | 15 +++ ext/afform/admin/ang/afAdmin/afAdminList.html | 4 +- ext/afform/admin/ang/afGuiEditor.css | 12 ++ ext/afform/admin/ang/afGuiEditor.js | 7 +- .../ang/afGuiEditor/afGuiEditor.component.js | 7 +- .../ang/afGuiEditor/afGuiEditorPalette.html | 8 ++ .../ang/afGuiEditor/afGuiSearch.component.js | 127 ++++++++++++++++++ .../admin/ang/afGuiEditor/afGuiSearch.html | 28 ++++ .../elements/afGuiContainer.component.js | 37 ++++- .../afGuiEditor/elements/afGuiContainer.html | 3 +- .../elements/afGuiField.component.js | 28 ++-- .../ang/afGuiEditor/elements/afGuiField.html | 13 +- .../elements/afGuiSearchDisplay.component.js | 21 +++ .../elements/afGuiSearchDisplay.html | 8 ++ ext/search/Civi/Search/Admin.php | 8 ++ .../crmSearchAdmin/searchList.controller.js | 31 ++++- ext/search/ang/crmSearchAdmin/searchList.html | 36 ++++- ext/search/css/crmSearchAdmin.css | 13 ++ 19 files changed, 426 insertions(+), 30 deletions(-) create mode 100644 ext/afform/admin/ang/afGuiEditor/afGuiSearch.component.js create mode 100644 ext/afform/admin/ang/afGuiEditor/afGuiSearch.html create mode 100644 ext/afform/admin/ang/afGuiEditor/elements/afGuiSearchDisplay.component.js create mode 100644 ext/afform/admin/ang/afGuiEditor/elements/afGuiSearchDisplay.html diff --git a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php index 350ea8252a..db3dcb3b4d 100644 --- a/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php +++ b/ext/afform/admin/Civi/Api4/Action/Afform/LoadAdminData.php @@ -56,6 +56,20 @@ class LoadAdminData extends \Civi\Api4\Generic\AbstractAction { 'layout' => [], ]; break; + + case 'search': + $info['definition'] = $this->definition + [ + 'title' => '', + 'permission' => 'access CiviCRM', + 'layout' => [ + [ + '#tag' => 'div', + 'af-fieldset' => '', + '#children' => [], + ], + ], + ]; + break; } } @@ -133,9 +147,39 @@ class LoadAdminData extends \Civi\Api4\Generic\AbstractAction { $entities[] = $info['definition']['join'] ?? $info['definition']['block']; } + if ($info['definition']['type'] === 'search') { + $getFieldsMode = 'search'; + $displayTags = []; + if ($newForm) { + [$searchName, $displayName] = array_pad(explode('.', $this->entity ?? ''), 2, ''); + $displayTags[] = ['search-name' => $searchName, 'display-name' => $displayName]; + } + else { + foreach (\Civi\Search\Display::getDisplayTypes(['name']) as $displayType) { + $displayTags = array_merge($displayTags, \CRM_Utils_Array::findAll($info['definition']['layout'], ['#tag' => $displayType['name']])); + } + } + foreach ($displayTags as $displayTag) { + $display = \Civi\Api4\SearchDisplay::get(FALSE) + ->addWhere('name', '=', $displayTag['display-name']) + ->addWhere('saved_search.name', '=', $displayTag['search-name']) + ->addSelect('*', 'type:name', 'type:icon', 'saved_search.name', 'saved_search.api_entity', 'saved_search.api_params') + ->execute()->first(); + $info['search_displays'][] = $display; + if ($newForm) { + $info['definition']['layout'][0]['#children'][] = $displayTag + ['#tag' => $display['type:name']]; + } + $entities[] = $display['saved_search.api_entity']; + foreach ($display['saved_search.api_params']['join'] ?? [] as $join) { + $entities[] = explode(' AS ', $join[0])[0]; + } + } + $entities = array_unique($entities); + } + // Optimization - since contact fields are a combination of these three, // we'll combine them client-side rather than sending them via ajax. - if (array_intersect($entities, ['Individual', 'Household', 'Organization'])) { + elseif (array_intersect($entities, ['Individual', 'Household', 'Organization'])) { $entities = array_diff($entities, ['Contact']); } @@ -169,6 +213,10 @@ class LoadAdminData extends \Civi\Api4\Generic\AbstractAction { 'name' => 'fields', 'data_type' => 'Array', ], + [ + 'name' => 'search_displays', + 'data_type' => 'Array', + ], ]; } diff --git a/ext/afform/admin/ang/afAdmin/afAdminList.controller.js b/ext/afform/admin/ang/afAdmin/afAdminList.controller.js index 10f4e7fc9d..f1d8003439 100644 --- a/ext/afform/admin/ang/afAdmin/afAdminList.controller.js +++ b/ext/afform/admin/ang/afAdmin/afAdminList.controller.js @@ -63,6 +63,21 @@ }); $scope.tabs.block.options = _.sortBy(links, 'Label'); } + + if (ctrl.tab === 'search') { + crmApi4('SearchDisplay', 'get', { + select: ['name', 'label', 'type:icon', 'saved_search.name', 'saved_search.label'] + }).then(function(searchDisplays) { + _.each(searchDisplays, function(searchDisplay) { + links.push({ + url: '#create/search/' + searchDisplay['saved_search.name'] + '.' + searchDisplay.name, + label: searchDisplay['saved_search.label'] + ': ' + searchDisplay.label, + icon: searchDisplay['type:icon'] + }); + }); + $scope.tabs.search.options = _.sortBy(links, 'Label'); + }); + } }; this.revert = function(afform) { diff --git a/ext/afform/admin/ang/afAdmin/afAdminList.html b/ext/afform/admin/ang/afAdmin/afAdminList.html index c4b0901d18..09111b0a5e 100644 --- a/ext/afform/admin/ang/afAdmin/afAdminList.html +++ b/ext/afform/admin/ang/afAdmin/afAdminList.html @@ -38,8 +38,8 @@ {{:: ts('Title') }} {{:: ts('Name') }} - {{:: ts('Server Route') }} - {{:: ts('Frontend?') }} + {{:: ts('Page') }} + {{:: ts('Style') }} diff --git a/ext/afform/admin/ang/afGuiEditor.css b/ext/afform/admin/ang/afGuiEditor.css index 55703580bf..d38dfc3ac5 100644 --- a/ext/afform/admin/ang/afGuiEditor.css +++ b/ext/afform/admin/ang/afGuiEditor.css @@ -120,6 +120,11 @@ background-color: #b3b3b3; } +#afGuiEditor .af-gui-bar > .form-inline > span { + color: #696969; + font-style: italic; +} + #afGuiEditor .af-gui-element { position: relative; padding: 0 3px 3px; @@ -140,6 +145,13 @@ display: block; } +#afGuiEditor .af-gui-search-display { + border: 1px dotted gray; + color: gray; + padding: 3em; + background-color: #f9f9f9; +} + #afGuiEditor .af-gui-container-type-fieldset { box-shadow: 0 0 5px #bbbbbb; } diff --git a/ext/afform/admin/ang/afGuiEditor.js b/ext/afform/admin/ang/afGuiEditor.js index ca6947e87f..17fb4d5aee 100644 --- a/ext/afform/admin/ang/afGuiEditor.js +++ b/ext/afform/admin/ang/afGuiEditor.js @@ -72,6 +72,7 @@ delete entity.fields; }); CRM.afGuiEditor.blocks = {}; + CRM.afGuiEditor.searchDisplays = {}; }, // Takes the results from api.Afform.loadAdminData and processes the metadata @@ -111,6 +112,9 @@ (CRM.afGuiEditor.entities.Organization || {}).fields ); } + _.each(data.search_displays, function(display) { + CRM.afGuiEditor.searchDisplays[display['saved_search.name'] + '.' + display.name] = display; + }); }, meta: CRM.afGuiEditor, @@ -120,7 +124,8 @@ }, getField: function(entityName, fieldName) { - return CRM.afGuiEditor.entities[entityName].fields[fieldName]; + var fields = CRM.afGuiEditor.entities[entityName].fields; + return fields[fieldName] || fields[fieldName.substr(fieldName.indexOf('.') + 1)]; }, // Recursively searches a collection and its children using _.filter diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js b/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js index 092505cb20..4cbe9a44f2 100644 --- a/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js +++ b/ext/afform/admin/ang/afGuiEditor/afGuiEditor.component.js @@ -51,7 +51,7 @@ } } - else if ($scope.afform.type === 'block') { + if ($scope.afform.type === 'block') { editor.layout['#children'] = $scope.afform.layout; editor.blockEntity = $scope.afform.join || $scope.afform.block; $scope.entities[editor.blockEntity] = { @@ -61,6 +61,11 @@ }; } + if ($scope.afform.type === 'search') { + editor.layout['#children'] = afGui.findRecursive($scope.afform.layout, {'af-fieldset': ''})[0]['#children']; + + } + // Set changesSaved to true on initial load, false thereafter whenever changes are made to the model $scope.changesSaved = editor.mode === 'edit' ? 1 : false; $scope.$watch('afform', function () { diff --git a/ext/afform/admin/ang/afGuiEditor/afGuiEditorPalette.html b/ext/afform/admin/ang/afGuiEditor/afGuiEditorPalette.html index f166d96ed1..1db7dd3043 100644 --- a/ext/afform/admin/ang/afGuiEditor/afGuiEditorPalette.html +++ b/ext/afform/admin/ang/afGuiEditor/afGuiEditorPalette.html @@ -12,6 +12,11 @@ +
  • + + {{ searchDisplay.label }} + +