diff --git a/core/modules/block_place/block_place.install b/core/modules/block_place/block_place.install new file mode 100644 index 0000000000..c51492ff67 --- /dev/null +++ b/core/modules/block_place/block_place.install @@ -0,0 +1,25 @@ +deleteAll(); +} + diff --git a/core/modules/block_place/block_place.libraries.yml b/core/modules/block_place/block_place.libraries.yml index 7d1941976d..87af7de5a3 100644 --- a/core/modules/block_place/block_place.libraries.yml +++ b/core/modules/block_place/block_place.libraries.yml @@ -15,5 +15,6 @@ drupal.block_place.js: js: js/block_place.js: {} dependencies: - - outside_in/ drupal.outside_in + - core/jquery + - core/drupal diff --git a/core/modules/block_place/block_place.links.contextual.yml b/core/modules/block_place/block_place.links.contextual.yml new file mode 100644 index 0000000000..9c482cf154 --- /dev/null +++ b/core/modules/block_place/block_place.links.contextual.yml @@ -0,0 +1,4 @@ +block_place.sort: + title: 'Sort blocks' + route_name: 'block_place.sort' + group: 'block' diff --git a/core/modules/block_place/block_place.module b/core/modules/block_place/block_place.module index 01243e8de3..c9dfccc6a9 100644 --- a/core/modules/block_place/block_place.module +++ b/core/modules/block_place/block_place.module @@ -7,6 +7,7 @@ use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; +use Drupal\block\Entity\Block; /** * Implements hook_help(). @@ -77,8 +78,12 @@ function block_place_toolbar() { '#attached' => [ 'library' => [ 'block_place/drupal.block_place.icons', + // This JS library only needs to be attached here so that the new + // contextual link works with Ajax. Remove + // in https://www.drupal.org/node/2764931. + 'block_place/drupal.block_place.js', ], - ], + ], ]; return $items; } @@ -93,12 +98,58 @@ function block_place_page_top(array &$page_top) { $page_top['#attached']['library'][] = 'block_place/drupal.block_place.js'; $destination = \Drupal::destination()->get(); $destination = explode('?', $destination)[0]; - $theme = \Drupal::theme()->getActiveTheme(); + $theme = \Drupal::theme()->getActiveTheme(); $url = Url::fromRoute('block_place.sort', ['region' => $region_sort, 'theme' => $theme->getName()], ['query' => ['destination' => $destination]]); $page_top['#attached']['drupalSettings']['block_place'] = [ 'dialog_url' => $url->setAbsolute()->toString(), + // @todo Always use 'off_canvas' in https://www.drupal.org/node/2784443. 'dialog_type' => \Drupal::moduleHandler()->moduleExists('outside_in') ? 'dialog_off_canvas' : 'modal', ]; } } +/** + * Implements hook_contextual_links_view_alter(). + */ +function block_place_contextual_links_view_alter(&$element, $items) { + if (isset($element['#links']['block-placesort']) && isset($items['block_configure']['route_parameters']['block'])) { + + // Add arguments to sort blocks url. + /** @var \Drupal\block\Entity\Block $block */ + $block = Block::load($items['block_configure']['route_parameters']['block']); + /** @var \Drupal\Core\Url $url */ + $url = &$element['#links']['block-placesort']['url']; + $url->setRouteParameters( + [ + 'theme' => $block->getTheme(), + 'region' => $block->getRegion(), + ] + ); + + // @todo Always use 'off_canvas' in https://www.drupal.org/node/2784443. + $attributes = [ + 'class' => ['use-ajax'], + ]; + if (\Drupal::moduleHandler()->moduleExists('outside_in')) { + $attributes['data-dialog-type'] = 'dialog'; + $attributes['data-dialog-renderer'] = 'off_canvas'; + } + else { + $attributes['data-dialog-type'] = 'modal'; + } + $element['#links']['block-placesort']['attributes'] = $attributes; + } +} + + +/** + * Implements hook_block_view_alter(). + */ +function block_place_block_view_alter(array &$build) { + // Force a new 'data-contextual-id' attribute on blocks when this module is + // enabled so as not to reuse stale data cached client-side. + // @todo Remove when https://www.drupal.org/node/2773591 is fixed. + $build['#contextual_links']['block_place'] = [ + 'route_parameters' => [], + ]; +} diff --git a/core/modules/block_place/js/block_place.es6.js b/core/modules/block_place/js/block_place.es6.js new file mode 100644 index 0000000000..92f259549d --- /dev/null +++ b/core/modules/block_place/js/block_place.es6.js @@ -0,0 +1,31 @@ +/** + * @file + * Block Place behaviors. + */ + +(function ($, window, Drupal, drupalSettings) { + Drupal.behaviors.blockPlace = { + attach: function (context, settings) { + // If drupalSettings.block_place is set open open dialog. + if (drupalSettings.hasOwnProperty('block_place') && drupalSettings.block_place.hasOwnProperty('dialog_url')) { + $(window).once('block_sort').each(function () { + const blockSort = Drupal.ajax({ + dialog: {}, + dialogType: drupalSettings.block_place.dialog_type, + selector: '.ckeditor-dialog-loading-link', + url: drupalSettings.block_place.dialog_url, + progress: {type: 'throbber' }, + }); + blockSort.execute(); + }); + } + }, + }; + + // Make sure contextual links work with Ajax. + // Remove in https://www.drupal.org/node/2764931. + $(document).once('contextual-ajax').on('drupalContextualLinkAdded', function (event, data) { + Drupal.attachBehaviors(data.$el[0]); + }); + +})(jQuery, window, Drupal, drupalSettings); diff --git a/core/modules/block_place/js/block_place.js b/core/modules/block_place/js/block_place.js index 140b7c5579..5162837201 100644 --- a/core/modules/block_place/js/block_place.js +++ b/core/modules/block_place/js/block_place.js @@ -1,15 +1,13 @@ /** - * @file - * Block Place behaviors. - */ +* DO NOT EDIT THIS FILE. +* See the following change record for more information, +* https://www.drupal.org/node/2815083 +* @preserve +**/ (function ($, window, Drupal, drupalSettings) { - - 'use strict'; - Drupal.behaviors.blockPlace = { - attach: function (context, settings) { - // If drupalSettings.block_place is set open open dialog. + attach: function attach(context, settings) { if (drupalSettings.hasOwnProperty('block_place') && drupalSettings.block_place.hasOwnProperty('dialog_url')) { $(window).once('block_sort').each(function () { var blockSort = Drupal.ajax({ @@ -17,13 +15,15 @@ dialogType: drupalSettings.block_place.dialog_type, selector: '.ckeditor-dialog-loading-link', url: drupalSettings.block_place.dialog_url, - progress: {type: 'throbber'} + progress: { type: 'throbber' } }); blockSort.execute(); }); } - } }; -})(jQuery, window, Drupal, drupalSettings); + $(document).once('contextual-ajax').on('drupalContextualLinkAdded', function (event, data) { + Drupal.attachBehaviors(data.$el[0]); + }); +})(jQuery, window, Drupal, drupalSettings); \ No newline at end of file diff --git a/core/modules/block_place/src/Controller/PlaceBlockLibraryController.php b/core/modules/block_place/src/Controller/PlaceBlockLibraryController.php index 297fa2e310..b44f365b5a 100644 --- a/core/modules/block_place/src/Controller/PlaceBlockLibraryController.php +++ b/core/modules/block_place/src/Controller/PlaceBlockLibraryController.php @@ -20,6 +20,7 @@ public function listBlocks(Request $request, $theme) { $build = parent::listBlocks($request, $theme); // Alter all 'Place Block' links to use the Offcanvas tray. if (isset($build['blocks']['#rows'])) { + // @todo Always use 'off_canvas' in https://www.drupal.org/node/2784443. if ($this->moduleHandler()->moduleExists('outside_in')) { $data_dialog_attributes = [ 'data-dialog-type' => 'dialog', diff --git a/core/modules/block_place/src/Form/BlockRegionSorterForm.php b/core/modules/block_place/src/Form/BlockRegionSorterForm.php index 30eb16ebf3..b47dd9aaac 100644 --- a/core/modules/block_place/src/Form/BlockRegionSorterForm.php +++ b/core/modules/block_place/src/Form/BlockRegionSorterForm.php @@ -2,6 +2,7 @@ namespace Drupal\block_place\Form; +use Drupal\block\Entity\Block; use Drupal\Core\Entity\EntityTypeManagerInterface; use Drupal\Core\Form\FormBase; use Drupal\Core\Form\FormStateInterface; @@ -43,6 +44,10 @@ public static function create(ContainerInterface $container) { */ public function buildForm(array $form, FormStateInterface $form_state, $theme = NULL, $region = NULL) { $blocks = $this->entityTypeManager->getStorage('block')->loadByProperties(['region' => $region, 'theme' => $theme]); + // Make sure the blocks are in the correct order. + usort($blocks, function (Block $blocka, Block $blockb) { + return $blocka->getWeight() - $blockb->getWeight(); + }); $form['#tree'] = TRUE; $form['blocks'] = [ '#type' => 'table',