diff --git a/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php b/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php index 797768d9b5902d22f88c43a5d7ee86edf87d391e..2dcbbf645e5c3614c45c797d681f1d10a399b907 100644 --- a/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php +++ b/core/modules/layout_builder/tests/src/FunctionalJavascript/InlineBlockTest.php @@ -597,6 +597,8 @@ public function testAddWorkFlow(): void { // Confirm that Create Content block opt out logic works for Navigation. $this->drupalGet('/admin/config/user-interface/navigation-block'); + $this->getSession()->getPage()->pressButton('Enable edit mode'); + $this->assertSession()->assertWaitOnAjaxRequest(); $page->clickLink('Add block'); $assert_session->assertWaitOnAjaxRequest(); $assert_session->pageTextContains('Choose a block'); diff --git a/core/modules/navigation/src/Form/LayoutForm.php b/core/modules/navigation/src/Form/LayoutForm.php index 51b04c104170c0b3ab2440b1805e6887223e7580..ab01a70eea1aefff5d6061a278b06e407a6b2952 100644 --- a/core/modules/navigation/src/Form/LayoutForm.php +++ b/core/modules/navigation/src/Form/LayoutForm.php @@ -60,24 +60,56 @@ public static function create(ContainerInterface $container): static { ); } + /** + * Handles switching the configuration type selector. + * + * @return array + * An associative array containing the structure of the form. + */ + public function enableEditMode($form, FormStateInterface $form_state): array { + if ($form_state::hasAnyErrors()) { + return $form; + } + + $this->handleFormElementsVisibility($form); + return $form; + } + /** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state, ?SectionStorageInterface $section_storage = NULL) { + $form['#prefix'] = '<div id="js-config-form-wrapper">'; + $form['#suffix'] = '</div>'; $form['#attributes']['class'][] = 'layout-builder-form'; + $this->sectionStorage = $section_storage; + $form['layout_builder'] = [ '#type' => 'layout_builder', '#section_storage' => $section_storage, ]; $form['#attached']['library'][] = 'navigation/navigation.layoutBuilder'; - $this->sectionStorage = $section_storage; $form['actions'] = [ + 'enable_edit_mode' => [ + '#type' => 'submit', + '#value' => $this->t('Enable edit mode'), + '#name' => 'enable_edit_mode', + '#ajax' => [ + 'callback' => '::enableEditMode', + 'wrapper' => 'js-config-form-wrapper', + 'effect' => 'fade', + ], + ], 'submit' => [ '#type' => 'submit', '#value' => $this->t('Save'), + '#name' => 'save', ], ] + $this->buildActionsElement([]); + + $this->handleFormElementsVisibility($form, FALSE); + return $form; } @@ -85,8 +117,45 @@ public function buildForm(array $form, FormStateInterface $form_state, ?SectionS * {@inheritdoc} */ public function submitForm(array &$form, FormStateInterface $form_state): void { + $user_input = $form_state->getUserInput(); + if (isset($user_input['save'])) { + $this->save($form, $form_state); + } + } + + /** + * Saves the Layout changes. + * + * @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. + */ + public function save(array &$form, FormStateInterface $form_state): void { $this->sectionStorage->save(); $this->saveTasks($form_state, new TranslatableMarkup('Saved navigation blocks')); } + /** + * Handles visibility of the form elements based on the edit mode status. + * + * @param array $form + * An associative array containing the structure of the form. + * @param bool $edit_mode_enabled + * Boolean indicating whether the Navigation layout edit mode is enabled. + */ + protected function handleFormElementsVisibility(array &$form, bool $edit_mode_enabled = TRUE): array { + // Edit mode elements are visible only in edit mode. + $form['actions']['submit']['#access'] = + $form['actions']['discard_changes']['#access'] = + $form['actions']['preview_toggle']['#access'] = + $form['actions']['preview_toggle']['toggle_content_preview']['#access'] = + $form['layout_builder']['#access'] = $edit_mode_enabled; + + // Edit mode flag element is only visible when edit mode is disabled. + $form['actions']['enable_edit_mode']['#access'] = !$edit_mode_enabled; + + return $form; + } + } diff --git a/core/modules/navigation/src/Hook/NavigationHooks.php b/core/modules/navigation/src/Hook/NavigationHooks.php index 11bf1773dfe365b9b410c9995bc5adea6a8ae1a0..673f53255808fc117a4c3e8e0720ad8849c4ada4 100644 --- a/core/modules/navigation/src/Hook/NavigationHooks.php +++ b/core/modules/navigation/src/Hook/NavigationHooks.php @@ -31,8 +31,6 @@ class NavigationHooks { * The module handler. * @param \Drupal\Core\Session\AccountInterface $currentUser * The current user. - * @param \Drupal\Core\Routing\RouteMatchInterface $routeMatch - * The route match. * @param \Drupal\navigation\NavigationRenderer $navigationRenderer * The navigation renderer. * @param \Drupal\Core\Config\Action\ConfigActionManager $configActionManager @@ -43,7 +41,6 @@ class NavigationHooks { public function __construct( protected ModuleHandlerInterface $moduleHandler, protected AccountInterface $currentUser, - protected RouteMatchInterface $routeMatch, protected NavigationRenderer $navigationRenderer, #[Autowire('@plugin.manager.config_action')] protected ConfigActionManager $configActionManager, @@ -70,7 +67,7 @@ public function help($route_name, RouteMatchInterface $route_match): ?string { } if (str_starts_with($route_name, $configuration_route)) { $output = '<p>' . $this->t('This layout builder tool allows you to configure the blocks in the navigation toolbar.') . '</p>'; - $output .= '<p>' . $this->t('Forms and links inside the content of the layout builder tool have been disabled.') . '</p>'; + $output .= '<p>' . $this->t('Forms and links inside the content of the layout builder tool are disabled in Edit mode.') . '</p>'; return $output; } return NULL; @@ -85,23 +82,7 @@ public function pageTop(array &$page_top): void { return; } $this->navigationRenderer->removeToolbar($page_top); - if ($this->routeMatch->getRouteName() !== 'layout_builder.navigation.view') { - // Don't render the admin toolbar if in layout edit mode. - $this->navigationRenderer->buildNavigation($page_top); - $this->navigationRenderer->buildTopBar($page_top); - return; - } - // But if in layout mode, add an empty element to leave space. We need to - // use an empty .admin-toolbar element because the css uses the adjacent - // sibling selector. The actual rendering of the navigation blocks/layout - // occurs in the layout form. - $page_top['navigation'] = [ - '#type' => 'html_tag', - '#tag' => 'aside', - '#attributes' => [ - 'class' => 'admin-toolbar', - ], - ]; + $this->navigationRenderer->buildNavigation($page_top); $this->navigationRenderer->buildTopBar($page_top); } diff --git a/core/modules/navigation/tests/src/Functional/NavigationSafeBlockDefinitionTest.php b/core/modules/navigation/tests/src/Functional/NavigationSafeBlockDefinitionTest.php index 2f0ab834a27d1356d05b81ce7185699d15f007f4..3e6bf8756af9bd19c9edf32372415958eedbda90 100644 --- a/core/modules/navigation/tests/src/Functional/NavigationSafeBlockDefinitionTest.php +++ b/core/modules/navigation/tests/src/Functional/NavigationSafeBlockDefinitionTest.php @@ -51,9 +51,8 @@ protected function setUp(): void { */ public function testNavigationSafeBlockDefinition(): void { // Confirm that default blocks are available. - $layout_url = '/admin/config/user-interface/navigation-block'; + $layout_url = '/layout_builder/choose/block/navigation/navigation.block_layout/0/content'; $this->drupalGet($layout_url); - $this->clickLink('Add block'); $this->assertSession()->linkExists('Administration'); $this->assertSession()->linkExists('Content'); diff --git a/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php b/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php index 39ae6026cfb75630fc011f07e3cacd9d4f913676..87d100d40aa78694ca626317b374026678a05f3b 100644 --- a/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php +++ b/core/modules/navigation/tests/src/FunctionalJavascript/NavigationBlockUiTest.php @@ -80,6 +80,8 @@ public function testNavigationBlockAdminUiPageNestedForm(): void { // Edit the layout and add a block that contains a form. $this->drupalGet($layout_url); + $this->getSession()->getPage()->pressButton('Enable edit mode'); + $this->assertSession()->assertWaitOnAjaxRequest(); $this->openAddBlockForm('Layout Builder form block test form api form block'); $this->getSession()->getPage()->checkField('settings[label_display]'); @@ -98,6 +100,8 @@ public function testNavigationBlockAdminUiPageNestedForm(): void { // Try to save the layout again and confirm it can save because there are no // nested form tags. $this->drupalGet($layout_url); + $this->getSession()->getPage()->pressButton('Enable edit mode'); + $this->assertSession()->assertWaitOnAjaxRequest(); $this->getSession()->getPage()->checkField('toggle_content_preview'); $this->getSession()->getPage()->pressButton('Save'); $this->assertSession()->statusMessageNotContains($unexpected_save_message); @@ -126,6 +130,8 @@ public function testNavigationBlockAdminUiPage(): void { $this->drupalLogin($this->adminUser); $this->drupalGet($layout_url); $page = $this->getSession()->getPage(); + $this->getSession()->getPage()->pressButton('Enable edit mode'); + $this->assertSession()->assertWaitOnAjaxRequest(); // Add section should not be present $this->assertSession()->linkNotExists('Add section'); @@ -166,17 +172,24 @@ public function testNavigationBlockAdminUiPage(): void { $this->drupalGet($front); $this->assertSession()->pageTextNotContains('New Shortcuts'); - // When returning to the layout edit mode, the new block is visible. + // When returning to the layout page, the new block is not visible. $this->drupalGet($layout_url); + $this->assertSession()->pageTextNotContains('New Shortcuts'); + + // When returning to the layout edit mode, the new block is visible. + $this->getSession()->getPage()->pressButton('Enable edit mode'); + $this->assertSession()->assertWaitOnAjaxRequest(); $this->assertSession()->pageTextContains('New Shortcuts'); - // Save the layout, and the new block is visible. + // Save the layout, and the new block is visible in the front page. $page->pressButton('Save'); $this->drupalGet($front); $this->assertSession()->pageTextContains('New Shortcuts'); // Reconfigure a block and ensure that the layout content is updated. $this->drupalGet($layout_url); + $this->getSession()->getPage()->pressButton('Enable edit mode'); + $this->assertSession()->assertWaitOnAjaxRequest(); $this->clickContextualLink('.layout-builder .block-navigation-shortcuts', 'Configure'); $this->assertOffCanvasFormAfterWait('layout_builder_update_block');