From 5455bbed0b6dfccecc9d606cfe1de778398867d7 Mon Sep 17 00:00:00 2001 From: yanniboi Date: Fri, 16 Mar 2018 12:21:19 +0000 Subject: [PATCH 1/3] By yanniboi: Add sort and configure links to tabs. --- contacts.module | 40 ++++++- contacts.routing.yml | 12 +++ src/Controller/DashboardController.php | 14 +++ src/Element/ContactTabs.php | 1 + src/Form/DashboardTabConfigureForm.php | 141 +++++++++++++++++++++++++ templates/contacts-dash-tabs.html.twig | 9 +- 6 files changed, 211 insertions(+), 6 deletions(-) create mode 100644 src/Form/DashboardTabConfigureForm.php diff --git a/contacts.module b/contacts.module index 675d5b8..7d1aabd 100644 --- a/contacts.module +++ b/contacts.module @@ -28,7 +28,10 @@ use Drupal\Core\Session\AccountInterface; function contacts_theme() { return [ 'contacts_dash_tabs' => [ - 'variables' => ['tabs' => []], + 'variables' => [ + 'tabs' => [], + 'manage_mode' => NULL, + ], 'template' => 'contacts-dash-tabs', ], 'contacts_dash_summary' => [ @@ -130,7 +133,40 @@ function template_preprocess_contacts_dash_tabs(array &$variables) { ], ]; - foreach ($variables['tabs'] as &$tab) { + foreach ($variables['tabs'] as $tab_id => &$tab) { + if ($variables['manage_mode']) { + // Add ui icons for manage mode. + $tab['ui'] = [ + 'drag' => [ + '#type' => 'open_iconic', + '#size' => '15', + '#icon' => 'move', + '#color' => 'transparent', + '#fill' => '#000', + '#attributes' => [ + 'class' => ['contacts-ui-icon', 'icon-left', 'drag-handle'], + ], + ], + 'edit' => [ + '#type' => 'open_iconic', + '#size' => '15', + '#icon' => 'cog', + '#color' => 'transparent', + '#fill' => '#5bc0de', + '#attributes' => [ + 'class' => ['use-ajax', 'contacts-ui-icon', 'icon-left'], + 'data-ajax-url' => Url::fromRoute('contacts.tab.off_canvas_form', + [ + 'tab' => $tab_id, + ] + )->toString(), + 'data-dialog-type' => 'dialog', + 'data-dialog-renderer' => 'off_canvas', + ], + ], + + ]; + } $tab['attributes'] = !empty($tab['attributes']) ? new Attribute($tab['attributes']) : new Attribute(); $tab['link_attributes'] = !empty($tab['link_attributes']) ? new Attribute($tab['link_attributes']) : new Attribute(); } diff --git a/contacts.routing.yml b/contacts.routing.yml index b2a0f6b..7352395 100644 --- a/contacts.routing.yml +++ b/contacts.routing.yml @@ -54,3 +54,15 @@ contacts.block.off_canvas_form: type: entity:contact_tab requirements: _permission: 'administer blocks' + +contacts.tab.off_canvas_form: + path: '/admin/contacts/ajax/manage-off-canvas-tab/{tab}' + defaults: + _controller: '\Drupal\contacts\Controller\DashboardController::offCanvasTab' + _title: 'Edit tab' + options: + parameters: + tab: + type: entity:contact_tab + requirements: + _permission: 'administer blocks' diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php index 677a94d..f2112dc 100644 --- a/src/Controller/DashboardController.php +++ b/src/Controller/DashboardController.php @@ -6,6 +6,7 @@ use Drupal\contacts\ContactsTabManager; use Drupal\contacts\Entity\ContactTab; use Drupal\contacts\Form\DashboardBlockConfigureForm; +use Drupal\contacts\Form\DashboardTabConfigureForm; use Drupal\Core\Ajax\HtmlCommand; use Drupal\Core\Block\BlockManager; use Drupal\Core\Controller\ControllerBase; @@ -236,6 +237,19 @@ public function offCanvasBlock(ContactTab $tab, $block_name) { return $this->formBuilder->getForm(DashboardBlockConfigureForm::class, $tab, $block); } + /** + * Renders the off Canvas configure form for a Dashboard block. + * + * @param \Drupal\contacts\Entity\ContactTab $tab + * The the tab entity that contains the block. + * + * @return array + * The renderable block config form. + */ + public function offCanvasTab(ContactTab $tab) { + return $this->formBuilder->getForm(DashboardTabConfigureForm::class, $tab); + } + /** * Update all block regions and positions in a tab. * diff --git a/src/Element/ContactTabs.php b/src/Element/ContactTabs.php index 748ca8b..1f7da41 100644 --- a/src/Element/ContactTabs.php +++ b/src/Element/ContactTabs.php @@ -57,6 +57,7 @@ public static function preRenderTabContent(array $element) { '#theme' => 'contacts_dash_tabs', '#weight' => -1, '#tabs' => [], + '#manage_mode' => $element['#manage_mode'], '#attached' => [ 'library' => ['contacts/tabs'], ], diff --git a/src/Form/DashboardTabConfigureForm.php b/src/Form/DashboardTabConfigureForm.php new file mode 100644 index 0000000..cdba971 --- /dev/null +++ b/src/Form/DashboardTabConfigureForm.php @@ -0,0 +1,141 @@ +entityTypeManager = $entity_type_manager; + $this->tabManager = $tab_manager; + $this->classResolver = $class_resolver; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('entity_type.manager'), + $container->get('contacts.tab_manager'), + $container->get('class_resolver') + ); + } + + /** + * {@inheritdoc} + */ + public function getFormId() { + return "dashboard_tab_configure_form"; + } + + /** + * {@inheritdoc} + */ + public function buildForm(array $form, FormStateInterface $form_state) { + $this->tab = $form_state->getBuildInfo()['args'][0]; + $form['#tree'] = TRUE; + + $form['label'] = [ + '#type' => 'textfield', + '#title' => $this->t('Label'), + '#maxlength' => 255, + '#default_value' => $this->tab->label(), + '#description' => $this->t("Label for the tab."), + '#required' => TRUE, + ]; + + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ + '#type' => 'submit', + '#value' => 'Save', + '#button_type' => 'primary', + ]; + + $form['actions']['cancel'] = [ + '#type' => 'submit', + '#value' => 'Cancel', + '#limit_validation_errors' => [], + ]; + + $form['actions']['remove'] = [ + '#type' => 'submit', + '#value' => 'Remove', + '#name' => 'remove', + '#submit' => [[$this, 'removeTab']], + '#limit_validation_errors' => [], + ]; + + $form['messages'] = [ + '#type' => 'status_messages', + '#weight' => -99, + ]; + + return $form; + } + + /** + * {@inheritdoc} + */ + public function validateForm(array &$form, FormStateInterface $form_state) { + } + + /** + * {@inheritdoc} + */ + public function submitForm(array &$form, FormStateInterface $form_state) { + \Drupal::entityTypeManager() + ->getFormObject('contact_tab', 'edit') + ->setEntity($this->tab) + ->buildEntity($form, $form_state) + ->save(); + } + + /** + * {@inheritdoc} + */ + public function removeTab(array &$form, FormStateInterface $form_state) { + $this->tab->delete(); + } + +} diff --git a/templates/contacts-dash-tabs.html.twig b/templates/contacts-dash-tabs.html.twig index 1197635..e88a808 100644 --- a/templates/contacts-dash-tabs.html.twig +++ b/templates/contacts-dash-tabs.html.twig @@ -2,11 +2,12 @@ {%- for key, item in tabs -%} - {{ item.text }} + + {{ item.ui.drag }} + {{ item.ui.edit }} + {{ item.text }} + - {#
  • #} - {#Ajax {{ item.text }}#} - {#
  • #} {%- endfor -%} {% endif %} From 1126ee6114ed166f55194e259b97dbc520b238e7 Mon Sep 17 00:00:00 2001 From: yanniboi Date: Fri, 16 Mar 2018 12:45:21 +0000 Subject: [PATCH 2/3] By yanniboi: Added drag and drop sorting of tabs. --- contacts.routing.yml | 7 +++ js/dashboard.manage.js | 71 +++++++++++++++++++++++--- src/Controller/DashboardController.php | 38 ++++++++++++++ src/Element/ContactTabs.php | 20 ++++---- 4 files changed, 120 insertions(+), 16 deletions(-) diff --git a/contacts.routing.yml b/contacts.routing.yml index 7352395..7725c76 100644 --- a/contacts.routing.yml +++ b/contacts.routing.yml @@ -43,6 +43,13 @@ contacts.ajax.update_blocks: requirements: _permission: 'manage contacts dashboard' +contacts.ajax.update_tabs: + path: '/admin/contacts/ajax/update-tabs' + defaults: + _controller: '\Drupal\contacts\Controller\DashboardController::ajaxUpdateTabs' + requirements: + _permission: 'manage contacts dashboard' + contacts.block.off_canvas_form: path: '/admin/contacts/ajax/manage-off-canvas/{tab}/{block_name}' defaults: diff --git a/js/dashboard.manage.js b/js/dashboard.manage.js index e45d171..1117aab 100644 --- a/js/dashboard.manage.js +++ b/js/dashboard.manage.js @@ -54,11 +54,11 @@ } }); - var url = $(context).find('[data-contacts-manage-update-url]').data('contacts-manage-update-url'), - postData = { - regions: regions, - tab: tab - }; + var url = $(context).find('[data-contacts-manage-update-url]').data('contacts-manage-update-url'); + var postData = { + regions: regions, + tab: tab + }; $.ajax({ type: 'POST', @@ -69,6 +69,37 @@ }); } + /** + * Update the Dashboard tabs after re-ordering. + * + * @param context + * The context of the tabs. + */ + function updateDashboardTabs(context) { + var $dragArea = $(context).find('.contacts-ajax-tabs'); + + if ($dragArea.length === 0) { + return; + } + + var tabs = $dragArea.sortable("toArray", {attribute: 'data-contacts-drag-tab-id'}); + + console.log(tabs); + + var url = '/admin/contacts/ajax/update-tabs'; + var postData = { + tabs: tabs + }; + + $.ajax({ + type: 'POST', + url: url, + data: postData + }).done(function (data) { + console.log(data); + }); + } + /** * Find all dashboard blocks and set manage ajax links. */ @@ -123,7 +154,7 @@ /** * Add sorting of dashboard blocks in manage mode. */ - Drupal.behaviors.contactsDashboardManageDrag = { + Drupal.behaviors.contactsDashboardManageDragBlocks = { attach: function attach(context) { var $dragAreas = $(context).find('.drag-area'); @@ -151,6 +182,34 @@ } }; + /** + * Add sorting of dashboard tabs in manage mode. + */ + Drupal.behaviors.contactsDashboardManageDragTabs = { + attach: function attach(context) { + + var $dragAreas = $(context).find('.contacts-ajax-tabs'); + + if ($dragAreas.length === 0) { + return; + } + + $dragAreas.each(function () { + $(this).sortable({ + + placeholder: "nav-item nav-link tab-area-placeholder", + handle: '.drag-handle', + update: function update(event, ui) { + var itemRegion = ui.item.closest('.contacts-ajax-tabs'); + if (event.target === itemRegion[0]) { + updateDashboardTabs(context); + } + } + }); + }); + } + }; + $(document).on('drupalManageLinkAdded', function (event, data) { Drupal.ajax.bindAjaxLinks(data.$el[0]); }); diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php index f2112dc..8556b19 100644 --- a/src/Controller/DashboardController.php +++ b/src/Controller/DashboardController.php @@ -296,4 +296,42 @@ public function ajaxUpdateBlocks() { return $response; } + /** + * Update the order of tabs after sorting. + * + * @return \Symfony\Component\HttpFoundation\Response + * The response. + */ + public function ajaxUpdateTabs() { + $tabs = \Drupal::request()->request->get('tabs'); + + $json = []; + $previous = -101; + foreach (array_filter($tabs) as $tab) { + /* @var \Drupal\contacts\Entity\ContactTab $tab */ + $tab = $this->entityTypeManager()->getStorage('contact_tab')->load($tab); + $current_weight = $tab->get('weight'); + + // Where possible preserve the existing tab weight. + if ($previous < $current_weight) { + $new = $current_weight; + } + else { + $new = $previous + 5; + } + + $tab->set('weight', $new); + $tab->save(); + $json[] = ['id' => $tab->id(), 'weight' => $new]; + $previous = $new; + } + + $response = new Response(); + $response->setContent(json_encode($json)); + $response->headers->set('Content-Type', 'application/json'); + $response->setStatusCode(Response::HTTP_OK); + + return $response; + } + } diff --git a/src/Element/ContactTabs.php b/src/Element/ContactTabs.php index 1f7da41..169bb3b 100644 --- a/src/Element/ContactTabs.php +++ b/src/Element/ContactTabs.php @@ -64,7 +64,7 @@ public static function preRenderTabContent(array $element) { ]; foreach ($element['#tabs'] as $tab_id => $tab) { - $element['content']['#tabs'][$tab['path']] = [ + $element['content']['#tabs'][$tab_id] = [ 'text' => $tab['label'], 'link' => Url::fromRoute('page_manager.page_view_contacts_dashboard_contact', [ 'user' => $element['#user']->id(), @@ -74,22 +74,22 @@ public static function preRenderTabContent(array $element) { // Swap links for AJAX request links. if ($element['#ajax']) { - $element['content']['#tabs'][$tab['path']]['link_attributes']['data-ajax-url'] = Url::fromRoute('contacts.ajax_subpage', [ + $element['content']['#tabs'][$tab_id]['link_attributes']['data-ajax-url'] = Url::fromRoute('contacts.ajax_subpage', [ 'user' => $element['#user']->id(), 'subpage' => $tab['path'], ])->toString(); - $element['content']['#tabs'][$tab['path']]['link_attributes']['class'][] = 'use-ajax'; - $element['content']['#tabs'][$tab['path']]['link_attributes']['data-ajax-progress'] = 'fullscreen'; + $element['content']['#tabs'][$tab_id]['link_attributes']['class'][] = 'use-ajax'; + $element['content']['#tabs'][$tab_id]['link_attributes']['data-ajax-progress'] = 'fullscreen'; } // Add tab id to attributes. - $element['content']['#tabs'][$tab['path']]['link_attributes']['data-contacts-tab-id'] = $tab_id; - } + $element['content']['#tabs'][$tab_id]['attributes']['data-contacts-drag-tab-id'] = $tab_id; - // Add active class to current tab. - if (isset($element['content']['#tabs'][$element['#subpage']])) { - $element['content']['#tabs'][$element['#subpage']]['attributes']['class'][] = 'is-active'; - $element['content']['#tabs'][$element['#subpage']]['link_attributes']['class'][] = 'is-active'; + // Add active class to current tab. + if ($tab['path'] == $element['#subpage']) { + $element['content']['#tabs'][$tab_id]['attributes']['class'][] = 'is-active'; + $element['content']['#tabs'][$tab_id]['link_attributes']['class'][] = 'is-active'; + } } return $element; From 70722b3d84476f3b0eb6aa59e7b09354f870a556 Mon Sep 17 00:00:00 2001 From: yanniboi Date: Fri, 16 Mar 2018 16:07:39 +0000 Subject: [PATCH 3/3] By yanniboi: Added helper traits to improve ajax form operations. --- src/Controller/AjaxHelperTrait.php | 39 ++++++++++++++ src/Controller/DashboardController.php | 67 +++++++++++++++++++++++- src/Controller/DashboardRebuildTrait.php | 58 ++++++++++++++++++++ src/Form/AjaxFormHelperTrait.php | 59 +++++++++++++++++++++ src/Form/DashboardBlockConfigureForm.php | 61 ++++++++++++++++----- src/Form/DashboardTabConfigureForm.php | 22 ++++++++ 6 files changed, 291 insertions(+), 15 deletions(-) create mode 100644 src/Controller/AjaxHelperTrait.php create mode 100644 src/Controller/DashboardRebuildTrait.php create mode 100644 src/Form/AjaxFormHelperTrait.php diff --git a/src/Controller/AjaxHelperTrait.php b/src/Controller/AjaxHelperTrait.php new file mode 100644 index 0000000..92633f9 --- /dev/null +++ b/src/Controller/AjaxHelperTrait.php @@ -0,0 +1,39 @@ +getRequestWrapperFormat(), [ + 'drupal_ajax', + 'drupal_dialog', + 'drupal_dialog.off_canvas', + 'drupal_modal', + ]); + } + + /** + * Gets the wrapper format of the current request. + * + * @string + * The wrapper format. + */ + protected function getRequestWrapperFormat() { + return \Drupal::request()->get(MainContentViewSubscriber::WRAPPER_FORMAT); + } + +} diff --git a/src/Controller/DashboardController.php b/src/Controller/DashboardController.php index 8556b19..9832f1c 100644 --- a/src/Controller/DashboardController.php +++ b/src/Controller/DashboardController.php @@ -12,6 +12,7 @@ use Drupal\Core\Controller\ControllerBase; use Drupal\Core\Ajax\AjaxResponse; use Drupal\Core\Form\FormBuilderInterface; +use Drupal\Core\Layout\LayoutPluginManager; use Drupal\Core\Path\PathValidatorInterface; use Drupal\Core\Plugin\Context\Context; use Drupal\Core\Plugin\Context\ContextDefinition; @@ -30,6 +31,8 @@ */ class DashboardController extends ControllerBase { + use AjaxHelperTrait; + /** * The tab manager. * @@ -65,6 +68,13 @@ class DashboardController extends ControllerBase { */ protected $contextHandler; + /** + * The layout manager service. + * + * @var \Drupal\Core\Layout\LayoutPluginManager + */ + protected $layoutManager; + /** * Construct the dashboard controller. * @@ -82,8 +92,10 @@ class DashboardController extends ControllerBase { * The context handler. * @param \Drupal\Core\Form\FormBuilderInterface $form_builder * The form builder service. + * @param \Drupal\Core\Layout\LayoutPluginManager $layout_manager + * The layout manager service. */ - public function __construct(ContactsTabManager $tab_manager, BlockManager $block_manager, StateInterface $state, RequestStack $request_stack, PathValidatorInterface $path_validator, ContextHandlerInterface $context_handler, FormBuilderInterface $form_builder) { + public function __construct(ContactsTabManager $tab_manager, BlockManager $block_manager, StateInterface $state, RequestStack $request_stack, PathValidatorInterface $path_validator, ContextHandlerInterface $context_handler, FormBuilderInterface $form_builder, LayoutPluginManager $layout_manager) { $this->tabManager = $tab_manager; $this->blockManager = $block_manager; $this->state = $state; @@ -91,6 +103,7 @@ public function __construct(ContactsTabManager $tab_manager, BlockManager $block $this->pathValidator = $path_validator; $this->contextHandler = $context_handler; $this->formBuilder = $form_builder; + $this->layoutManager = $layout_manager; } /** @@ -104,7 +117,8 @@ public static function create(ContainerInterface $container) { $container->get('request_stack'), $container->get('path.validator'), $container->get('context.handler'), - $container->get('form_builder') + $container->get('form_builder'), + $container->get('plugin.manager.core.layout') ); } @@ -127,6 +141,14 @@ public function ajaxTab(UserInterface $user, $subpage) { 'subpage' => $subpage, ]); + // Return as non-ajax. + if (!$this->isAjax()) { + return $this->redirect('page_manager.page_view_contacts_dashboard_contact', [ + 'user' => $user->id(), + 'subpage' => $subpage, + ]); + } + $block = $this->blockManager->createInstance('tabs:contacts_dashboard'); // Build our contexts. @@ -200,6 +222,47 @@ public function ajaxManageMode($manage_mode = NULL) { return FALSE; } + /** + * Adds AJAX command to response to show default tab offcanvas content. + * + * @param \Drupal\contacts\Entity\ContactTab $tab + * The tab to get content for. + * + * @return \Drupal\Core\Ajax\AjaxResponse + * The response commands. + */ + public function ajaxManageModeRefresh(ContactTab $tab) { + $blocks = $this->tabManager->getBlocks($tab); + + $layout = $tab->get('layout') ?: 'contacts_tab_content.stacked'; + $layout = $this->layoutManager->createInstance($layout, []); + + // @todo Once manage mode is decoupled from user context add tabs here. + $content['content'] = [ + '#prefix' => '
    ', + '#suffix' => '
    ', + '#type' => 'contact_tab_content', + '#tab' => $tab, + '#layout' => $layout, + '#subpage' => $tab->getPath(), + '#blocks' => $blocks, + '#manage_mode' => TRUE, + '#attributes' => ['class' => ['dash-content']], + ]; + + $content['messages'] = [ + '#type' => 'status_messages', + '#weight' => -99, + ]; + + // Create AJAX Response object. + $response = new AjaxResponse(); + $response->addCommand(new HtmlCommand('#contacts-tabs-content', $content)); + + // Return ajax response. + return $response; + } + /** * Provides a title callback to get the block's admin label. * diff --git a/src/Controller/DashboardRebuildTrait.php b/src/Controller/DashboardRebuildTrait.php new file mode 100644 index 0000000..33f7b67 --- /dev/null +++ b/src/Controller/DashboardRebuildTrait.php @@ -0,0 +1,58 @@ +rebuildDashboard($tab); + $response->addCommand(new CloseDialogCommand('#drupal-off-canvas')); + return $response; + } + + /** + * Rebuilds the layout. + * + * @param \Drupal\contacts\Entity\ContactTab $tab + * The section storage. + * + * @return \Drupal\Core\Ajax\AjaxResponse + * An AJAX response to either rebuild the layout and close the dialog, or + * reload the page. + */ + protected function rebuildDashboard(ContactTab $tab) { + $this->dashboardContoller = $this->classResolver->getInstanceFromDefinition(DashboardController::class); + return $this->dashboardContoller->ajaxManageModeRefresh($tab); + } + +} diff --git a/src/Form/AjaxFormHelperTrait.php b/src/Form/AjaxFormHelperTrait.php new file mode 100644 index 0000000..4a717c8 --- /dev/null +++ b/src/Form/AjaxFormHelperTrait.php @@ -0,0 +1,59 @@ +hasAnyErrors()) { + $form['status_messages'] = [ + '#type' => 'status_messages', + '#weight' => -1000, + ]; + $response = new AjaxResponse(); + $response->addCommand(new ReplaceCommand('[data-drupal-selector="' . $form['#attributes']['data-drupal-selector'] . '"]', $form)); + } + else { + $response = $this->successfulAjaxSubmit($form, $form_state); + } + return $response; + } + + /** + * Allows the form to respond to a successful AJAX submission. + * + * @param array $form + * An associative array containing the structure of the form. + * @param \Drupal\Core\Form\FormStateInterface $form_state + * The current state of the form. + * + * @return \Drupal\Core\Ajax\AjaxResponse + * An AJAX response. + */ + abstract protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state); + +} diff --git a/src/Form/DashboardBlockConfigureForm.php b/src/Form/DashboardBlockConfigureForm.php index 8b4608b..7214658 100644 --- a/src/Form/DashboardBlockConfigureForm.php +++ b/src/Form/DashboardBlockConfigureForm.php @@ -3,6 +3,8 @@ namespace Drupal\contacts\Form; use Drupal\contacts\ContactsTabManager; +use Drupal\contacts\Controller\DashboardRebuildTrait; +use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; @@ -14,6 +16,9 @@ */ class DashboardBlockConfigureForm extends FormBase { + use AjaxFormHelperTrait; + use DashboardRebuildTrait; + /** * The block plugin being configured. * @@ -56,10 +61,13 @@ class DashboardBlockConfigureForm extends FormBase { * The entity type manager. * @param \Drupal\contacts\ContactsTabManager $tab_manager * The contacts tab manager. + * @param \Drupal\Core\DependencyInjection\ClassResolverInterface $class_resolver + * The class resolver service. */ - public function __construct(EntityTypeManager $entity_type_manager, ContactsTabManager $tab_manager) { + public function __construct(EntityTypeManager $entity_type_manager, ContactsTabManager $tab_manager, ClassResolverInterface $class_resolver) { $this->entityTypeManager = $entity_type_manager; $this->tabManager = $tab_manager; + $this->classResolver = $class_resolver; } /** @@ -68,7 +76,8 @@ public function __construct(EntityTypeManager $entity_type_manager, ContactsTabM public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager'), - $container->get('contacts.tab_manager') + $container->get('contacts.tab_manager'), + $container->get('class_resolver') ); } @@ -104,18 +113,34 @@ public function buildForm(array $form, FormStateInterface $form_state) { unset($form['settings']['context_mapping']); } - $form['submit'] = [ + $form['actions'] = ['#type' => 'actions']; + $form['actions']['submit'] = [ '#type' => 'submit', '#value' => 'Save', + '#button_type' => 'primary', ]; - $form['cancel'] = [ + $form['actions']['cancel'] = [ '#type' => 'submit', '#value' => 'Cancel', - '#submit' => [[$this, 'cancelBlock']], + '#submit' => [], + '#limit_validation_errors' => [], + ]; + + $form['actions']['remove'] = [ + '#type' => 'submit', + '#value' => 'Remove', + '#submit' => [[$this, 'removeBlock']], '#limit_validation_errors' => [], ]; + // Add ajax to actions. + if ($this->isAjax()) { + $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit'; + $form['actions']['cancel']['#ajax']['callback'] = '::ajaxSubmit'; + $form['actions']['remove']['#ajax']['callback'] = '::ajaxSubmit'; + } + return $form; } @@ -131,6 +156,11 @@ public function validateForm(array &$form, FormStateInterface $form_state) { * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state) { + $trigger = $form_state->getTriggeringElement(); + if ($trigger['#value'] == 'Cancel') { + return; + } + $sub_form_state = SubformState::createForSubform($form['settings'], $form, $form_state); $this->block->submitConfigurationForm($form, $sub_form_state); $this->tab->setBlock($this->blockName, $this->block->getConfiguration()); @@ -138,15 +168,20 @@ public function submitForm(array &$form, FormStateInterface $form_state) { } /** - * Form submission handler; removes block from tab. - * - * @param array $form - * An associative array containing the structure of the form. - * @param \Drupal\Core\Form\FormStateInterface $form_state - * The current state of the form. + * {@inheritdoc} + */ + public function removeBlock(array &$form, FormStateInterface $form_state) { + $blocks = $this->tab->getBlocks(); + unset($blocks[$this->blockName]); + $this->tab->setBlocks($blocks); + $this->tab->save(); + } + + /** + * {@inheritdoc} */ - public function cancelBlock(array &$form, FormStateInterface $form_state) { - // Do nothing. + protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) { + return $this->rebuildAndReturn($this->tab); } } diff --git a/src/Form/DashboardTabConfigureForm.php b/src/Form/DashboardTabConfigureForm.php index cdba971..96a48f4 100644 --- a/src/Form/DashboardTabConfigureForm.php +++ b/src/Form/DashboardTabConfigureForm.php @@ -3,6 +3,7 @@ namespace Drupal\contacts\Form; use Drupal\contacts\ContactsTabManager; +use Drupal\contacts\Controller\DashboardRebuildTrait; use Drupal\Core\DependencyInjection\ClassResolverInterface; use Drupal\Core\Entity\EntityTypeManager; use Drupal\Core\Form\FormBase; @@ -14,6 +15,9 @@ */ class DashboardTabConfigureForm extends FormBase { + use AjaxFormHelperTrait; + use DashboardRebuildTrait; + /** * The dashboard tab. * @@ -106,6 +110,13 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#limit_validation_errors' => [], ]; + // Add ajax to actions. + if ($this->isAjax()) { + $form['actions']['submit']['#ajax']['callback'] = '::ajaxSubmit'; + $form['actions']['cancel']['#ajax']['callback'] = '::ajaxSubmit'; + $form['actions']['remove']['#ajax']['callback'] = '::ajaxSubmit'; + } + $form['messages'] = [ '#type' => 'status_messages', '#weight' => -99, @@ -138,4 +149,15 @@ public function removeTab(array &$form, FormStateInterface $form_state) { $this->tab->delete(); } + /** + * {@inheritdoc} + */ + protected function successfulAjaxSubmit(array $form, FormStateInterface $form_state) { + $trigger = $form_state->getTriggeringElement(); + if ($trigger['#name'] == 'remove') { + $this->tab = $this->tabManager->getTab('summary'); + } + return $this->rebuildAndReturn($this->tab); + } + }