From a8c25796b968632d3c9402e50142844cccbcc244 Mon Sep 17 00:00:00 2001 From: Severin Hauser Date: Wed, 22 Mar 2023 09:51:30 +0100 Subject: [PATCH] feat: move add existing to context menus fixes #8 --- client/css/TreeView.css | 5 + client/javascript/TreeView.js | 52 +++++++- client/javascript/lang/de.js | 3 +- client/javascript/lang/en.js | 1 + src/TreeView.php | 123 ++++++++++++------ .../PageSections/TreeViewFindExistingForm.ss | 4 +- 6 files changed, 136 insertions(+), 52 deletions(-) diff --git a/client/css/TreeView.css b/client/css/TreeView.css index cadd844..8665d72 100644 --- a/client/css/TreeView.css +++ b/client/css/TreeView.css @@ -337,6 +337,11 @@ fill: #008A00; } +.add-existing-search-results > .add-existing-search-items { + margin-left: 0; + margin-right: 0; +} + /** * Dialog */ diff --git a/client/javascript/TreeView.js b/client/javascript/TreeView.js index 20221dd..a318ef1 100644 --- a/client/javascript/TreeView.js +++ b/client/javascript/TreeView.js @@ -12,6 +12,11 @@ this.addLabel = function(label) { this.$menu.append("
  • " + label + '
  • '); }; + this.addAddExistingButton = function(label, onClick = function() {}) { + var $li = $(""); + $li.click(onClick); + this.$menu.append($li); + } this.addItem = function(type, label, onClick = function() {}) { var $li = $("
  • " + label + '
  • '); $li.click(onClick); @@ -162,7 +167,11 @@ '.add-existing-search-dialog-treeview .add-existing-search-items a' ).entwine({ onclick: function() { - var link = this.closest('.add-existing-search-items').data('add-link'); + var items = this.closest('.add-existing-search-items'); + var link = items.data('add-link'); + var parents = items.data('add-parents'); + var itemId = items.data('add-item-id'); + var sort = items.data('add-sort'); var id = this.data('id'); var dialog = this.closest('.add-existing-search-dialog-treeview') @@ -176,6 +185,18 @@ { name: 'id', value: id + }, + { + name: 'parents', + value: parents || [] + }, + { + name: 'itemId', + value: itemId || null + }, + { + name: 'sort', + value: sort } ] }, @@ -282,8 +303,7 @@ var name = $treeView.data('name'); var url = $treeView.data('url'); - // Setup find existing button - $treeView.find('button[name=action_FindExisting]').click(function() { + function showFindExistingDialog(parents, itemId, sort) { var dialog = $('
    ') .appendTo('body') .dialog({ @@ -298,14 +318,21 @@ .remove(); } }); - - var url = $.get($treeView.data('url') + '/search'); + var search = new URLSearchParams(); + search.append('parents', JSON.stringify(parents)); + if (sort) { + search.append('sort', sort); + } + if (itemId) { + search.append('itemId', itemId); + } + var url = $.get($treeView.data('url') + '/search?' + search.toString()); dialog .addClass('add-existing-search-dialog-treeview') .data('treeview', $treeView) .data('origUrl', url) .loadDialog(url); - }); + } // Add new button at the very top $treeView @@ -324,6 +351,10 @@ menu.addLabel( ss.i18n._t('PageSections.TreeView.AddAChild', 'Add a child') ); + menu.addAddExistingButton(ss.i18n._t('PageSection.TreeView.FindExisting', 'Find existing'), function() { + showFindExistingDialog([], null, 1); + menu.remove(); + }); $.each(elems, function(key, value) { menu.addItem(key, value, function() { $treeView.addItem([], null, key, 1); @@ -405,6 +436,10 @@ menu.addLabel( ss.i18n._t('PageSections.TreeView.AddAChild', 'Add a child') ); + menu.addAddExistingButton(ss.i18n._t('PageSection.TreeView.FindExisting', 'Find existing'), function() { + showFindExistingDialog(parents, itemId, 1); + menu.remove(); + }); $.each(elems, function(key, value) { menu.addItem(key, value, function() { $treeView.addItem(parents, itemId, key, 1); @@ -432,7 +467,10 @@ 'Add new element' ) ); - + menu.addAddExistingButton(ss.i18n._t('PageSection.TreeView.FindExisting', 'Find existing'), function() { + showFindExistingDialog(parents.slice(0, parents.length - 1), parents[parents.length - 1], $item.data('sort') + 1); + menu.remove(); + }); $.each(elems, function(key, value) { menu.addItem(key, value, function() { $treeView.addItem( diff --git a/client/javascript/lang/de.js b/client/javascript/lang/de.js index 89b4d9a..a967bd9 100644 --- a/client/javascript/lang/de.js +++ b/client/javascript/lang/de.js @@ -3,7 +3,8 @@ if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') { console.error('Class ss.i18n not defined'); // eslint-disable-line no-console } } else { - ss.i18n.addDictionary('en', { + ss.i18n.addDictionary('de', { + "PageSections.GridField.FindExisting": "Bestehendes Element suchen", "PageSections.GridField.AddAChild": "Unterelement hinzufügen", "PageSections.GridField.Delete": "Löschen", "PageSections.GridField.DeleteAChild": "Endgültig löschen", diff --git a/client/javascript/lang/en.js b/client/javascript/lang/en.js index 615f3ee..21f6747 100644 --- a/client/javascript/lang/en.js +++ b/client/javascript/lang/en.js @@ -4,6 +4,7 @@ if (typeof(ss) === 'undefined' || typeof(ss.i18n) === 'undefined') { } } else { ss.i18n.addDictionary('en', { + "PageSections.GridField.FindExisting": "Find existing", "PageSections.GridField.AddAChild": "Add a child", "PageSections.GridField.Delete": "Delete", "PageSections.GridField.DeleteAChild": "Finally delete", diff --git a/src/TreeView.php b/src/TreeView.php index b6b70fc..7fe0abb 100644 --- a/src/TreeView.php +++ b/src/TreeView.php @@ -25,6 +25,9 @@ class TreeView extends FormField */ protected $sortField = 'SortOrder'; protected $parent = null; + /** + * @var \SilverStripe\ORM\Search\SearchContext + */ protected $context = null; protected $opens = null; @@ -280,53 +283,58 @@ public function add($request) // If we have an id then add an existing item... if (isset($data["id"])) { - $element = PageElement::get()->byID($data["id"]); - if (!$element) { + $existing = true; + $child = PageElement::get()->byID($data["id"]); + if (!$child) { Controller::curr()->getResponse()->setStatusCode( 400, "Could not find PageElement with id " . $data['id'] ); return $this->FieldHolder(); } - - $this->getItems()->Add($element); + $type = $child->ClassName; } else { // ...otherwise add a completely new item - $itemId = isset($data["itemId"]) ? intval($data["itemId"]) : null; + $existing = false; $type = $data["type"]; $child = $type::create(); - $child->Name = "New " . $child->singular_name(); - - $sort = isset($data["sort"]) ? intval($data["sort"]) : 0; - $sortBy = $this->getSortField(); - $sortArr = [$sortBy => $sort]; - - // If we have an itemId then we're adding to another element - // otherwise we're adding to the root - if ($itemId) { - $parents = array_values(array_filter(explode(",", $data["parents"]), 'strlen')); - $path = array_merge($parents, [$itemId]); - - $item = PageElement::get()->byID($itemId); - if (!in_array($type, $item->getAllowedPageElements())) { - Controller::curr()->getResponse()->setStatusCode( - 400, - "The type " . $type . " is not allowed as a child of " . $item->ClassName - ); - return $this->FieldHolder(); - } + } + + $itemId = isset($data["itemId"]) ? intval($data["itemId"]) : null; + $sort = isset($data["sort"]) ? intval($data["sort"]) : 0; + $sortBy = $this->getSortField(); + $sortArr = [$sortBy => $sort]; + + // If we have an itemId then we're adding to another element + // otherwise we're adding to the root + if ($itemId) { + $parents = array_values(array_filter(explode(",", $data["parents"]), 'strlen')); + $path = array_merge($parents, [$itemId]); + $item = PageElement::get()->byID($itemId); + if (!in_array($type, $item->getAllowedPageElements())) { + Controller::curr()->getResponse()->setStatusCode( + 400, + "The type " . $type . " is not allowed as a child of " . $item->ClassName + ); + return $this->FieldHolder(); + } + + if (!$existing) { $child->write(); - $item->Children()->Add($child, $sortArr); - $item->write(); + } + $item->Children()->Add($child, $sortArr); + $item->write(); - // Make sure we can see the child - $this->openItem(array_merge($path, [$item->ID])); - } else { + // Make sure we can see the child (an its children) + $this->openRecursive($child, [$item]); + } else { + if ($existing) { $child->write(); - $this->getItems()->Add($child, $sortArr); + $this->openRecursive($child); } + $this->getItems()->Add($child, $sortArr); } return $this->FieldHolder(); @@ -413,6 +421,15 @@ public function delete($request) return $this->FieldHolder(); } + protected function getTarget($itemId) + { + $target = $this->section; + if ($itemId && $targetElement = PageElement::get()->byID($itemId)) { + $target = $targetElement; + } + return $target; + } + /** * This action is called when the find existing dialog is shown. * @param \SilverStripe\Control\HTTPRequest $request @@ -420,6 +437,21 @@ public function delete($request) */ public function search($request) { + $parents = $request->getVar('parents') ?? []; + $itemId = $request->getVar('itemId'); + $sort = $request->getVar('sort') ?? 9999; + $target = $this->getTarget($itemId); + + $fields = $this->context->getFields(); + if ($classField = $fields->fieldByName('ClassName')) { + $allowed = $target->getAllowedPageElements(); + $classField->setSource(array_combine($allowed, $allowed)); + } + + $fields->push(HiddenField::create('parents', 'parents', $parents)); + $fields->push(HiddenField::create('itemId', 'itemId', $itemId)); + $fields->push(HiddenField::create('sort', 'sort', $sort)); + $form = Form::create( $this, 'search', @@ -435,7 +467,11 @@ public function search($request) // Check if we're requesting the form for the first time (we return the template) // or if this is a submission (we return the form, so it calls the submitted action) - if (count($request->requestVars()) === 0) { + $extraRequestVars = array_filter($request->requestVars(), function ($name) { + return !in_array($name, ['parents', 'sort', 'itemId']); + }, ARRAY_FILTER_USE_KEY); + + if (count($extraRequestVars) === 0) { return $form->forAjaxTemplate(); } return $form; @@ -448,14 +484,24 @@ public function search($request) */ public function doSearch($data, $form) { - $list = $this->context->getQuery($data, false, false); - $allowed = $this->section->getAllowedPageElements(); + $list = $this->context->getQuery([ + 'ClassName' => $data['ClassName'], + 'Name' => $data['Name'], + ], false, false); + $allowed = $this->getTarget($data['itemId'])->getAllowedPageElements(); // Remove all disallowed classes - $list = $list->filter("ClassName", $allowed); + $list = $list->filter(["ClassName" => $allowed, "Name:not" => [null, '']]); + $sql = $list->dataQuery()->getFinalisedQuery()->sql($parameters); + $list = new PaginatedList($list, $data); $data = $this->customise([ 'SearchForm' => $form, 'Items' => $list, + 'AddArguments' => [ + 'Parents' => $data['parents'], + 'ItemID' => $data['itemId'], + 'Sort' => $data['sort'], + ], ]); return $data->renderWith("FLXLabs\PageSections\TreeViewFindExistingForm"); } @@ -585,8 +631,6 @@ public function doSave($data, $form) public function getItems() { return $this->section->Elements(); - /*return $this->parent->ClassName == PageSection::class ? - $this->parent->Elements() : $this->parent->Children();*/ } /** @@ -642,11 +686,6 @@ public function FieldHolder($properties = array()) $content .= ArrayData::create([ "Button" => $addButton, ])->renderWith("\FLXLabs\PageSections\TreeViewAddNewButton"); - - // Create the find existing button - $findExisting = TreeViewFormAction::create($this, 'FindExisting', 'Find existing'); - $findExisting->addExtraClass("btn font-icon-search tree-actions-findexisting"); - $content .= $findExisting->forTemplate(); } $content .= ""; diff --git a/templates/FLXLabs/PageSections/TreeViewFindExistingForm.ss b/templates/FLXLabs/PageSections/TreeViewFindExistingForm.ss index 969fc94..f5893bd 100644 --- a/templates/FLXLabs/PageSections/TreeViewFindExistingForm.ss +++ b/templates/FLXLabs/PageSections/TreeViewFindExistingForm.ss @@ -3,10 +3,10 @@ $SearchForm

    <%t GridFieldExtensions.RESULTS "Results" %>

    <% if $Items %> -