updated contrib modules
This commit is contained in:
@@ -1,7 +1,30 @@
|
||||
Admin Toolbar 8.1.22, 2017-XX-XX
|
||||
Admin Toolbar 8.1.23, 2018-02-06
|
||||
--------------------------------
|
||||
Changes since 8.1.22:
|
||||
|
||||
- #2924266 by sunlix, romainj, adriancid, samerali: Add a menu link for the
|
||||
media module.
|
||||
- #2941184 by daniel.nitsche, adriancid: Remove unwanted comment from
|
||||
admin.toolbar.css.
|
||||
- #2912503 by Amsteri, m.abdulqader: Right to left language direction support.
|
||||
- #2937982 by romainj, adriancid: Auto-generation of menu links conflicts with
|
||||
other modules.
|
||||
- #2932873 by vaplas, saravanaprasanth, adriancid: Horizontal mode only works if
|
||||
the page is loaded in horizontal mode.
|
||||
- #2935311 by romainj, adriancid: Use the $entityTypeManager variable instead of
|
||||
the \Drupal::entityTypeManager service.
|
||||
- #2935449 by adriancid: Add the release information for the 1.22 version in the
|
||||
CHANGELOG.txt.
|
||||
- #2932476 by romainj: toolbar.tree library should have a dependency to the
|
||||
core/drupal library.
|
||||
- #2931503 by K3vin_nl: Admin toolbar generates invalid class names.
|
||||
|
||||
Admin Toolbar 8.1.22, 2018-01-02
|
||||
--------------------------------
|
||||
Changes since 8.1.21:
|
||||
|
||||
- #2929053 by kkuhnen, eme, adriancid: admin_toolbar.js should use Drupal
|
||||
behaviors.
|
||||
- #2929061 by romainj, dsnopek, adriancid: admin_toolbar_links_access_filter
|
||||
doesn't do anything unless admin_toolbar is enabled.
|
||||
- #2928836 by eme: One extra pixel line under the admin toolbar.
|
||||
|
||||
@@ -8,8 +8,8 @@ type: module
|
||||
dependencies:
|
||||
- drupal:toolbar
|
||||
|
||||
# Information added by Drupal.org packaging script on 2018-01-02
|
||||
version: '8.x-1.22'
|
||||
# Information added by Drupal.org packaging script on 2018-02-06
|
||||
version: '8.x-1.23'
|
||||
core: '8.x'
|
||||
project: 'admin_toolbar'
|
||||
datestamp: 1514888588
|
||||
datestamp: 1517936588
|
||||
|
||||
@@ -7,3 +7,4 @@ toolbar.tree:
|
||||
js/admin_toolbar.js: {}
|
||||
dependencies:
|
||||
- core/jquery
|
||||
- core/drupal
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
use Drupal\Core\Menu\MenuTreeParameters;
|
||||
use Drupal\Core\Routing\RouteMatchInterface;
|
||||
use Drupal\Core\Url;
|
||||
use Drupal\Component\Utility\Html;
|
||||
|
||||
/**
|
||||
* Implements hook_toolbar_alter().
|
||||
@@ -90,7 +91,7 @@ function toolbar_tools_menu_navigation_links(array $tree) {
|
||||
|
||||
$element->options['attributes']['class'][] = 'toolbar-icon';
|
||||
$string = strtolower(str_replace(['.', ' ', '_'], ['-', '-', '-'], $definition['id']));
|
||||
$element->options['attributes']['class'][] = 'toolbar-icon-' . $string;
|
||||
$element->options['attributes']['class'][] = Html::cleanCssIdentifier('toolbar-icon-' . $string);
|
||||
$element->options['attributes']['title'] = $link->getDescription();
|
||||
}
|
||||
return $tree;
|
||||
|
||||
+7
-5
@@ -1,13 +1,15 @@
|
||||
name: Admin Toolbar Links Access Filter
|
||||
description: Provides a workaround for the common problem that users with 'Use the administration pages and help' permission see menu links they don't have access permission for. Once the issue <a href='https://www.drupal.org/node/296693'>https://www.drupal.org/node/296693</a> be solved, this module will be deprecated.
|
||||
package: Administration
|
||||
dependencies:
|
||||
- admin_toolbar:admin_toolbar
|
||||
|
||||
type: module
|
||||
# core: 8.x
|
||||
|
||||
# Information added by Drupal.org packaging script on 2018-01-02
|
||||
version: '8.x-1.22'
|
||||
dependencies:
|
||||
- admin_toolbar:admin_toolbar
|
||||
|
||||
# Information added by Drupal.org packaging script on 2018-02-06
|
||||
version: '8.x-1.23'
|
||||
core: '8.x'
|
||||
project: 'admin_toolbar'
|
||||
datestamp: 1514888588
|
||||
datestamp: 1517936588
|
||||
|
||||
+3
-3
@@ -8,8 +8,8 @@ type: module
|
||||
dependencies:
|
||||
- admin_toolbar:admin_toolbar
|
||||
|
||||
# Information added by Drupal.org packaging script on 2018-01-02
|
||||
version: '8.x-1.22'
|
||||
# Information added by Drupal.org packaging script on 2018-02-06
|
||||
version: '8.x-1.23'
|
||||
core: '8.x'
|
||||
project: 'admin_toolbar'
|
||||
datestamp: 1514888588
|
||||
datestamp: 1517936588
|
||||
|
||||
+60
-116
@@ -273,7 +273,7 @@ function admin_toolbar_tools_menu_links_discovered_alter(&$links) {
|
||||
'weight' => -5,
|
||||
];
|
||||
// Add node links for each content type.
|
||||
foreach (\Drupal::entityTypeManager()->getStorage('node_type')->loadMultiple() as $type) {
|
||||
foreach ($entityTypeManager->getStorage('node_type')->loadMultiple() as $type) {
|
||||
$links['node.add.' . $type->id()] = [
|
||||
'title' => t($type->label()),
|
||||
'route_name' => 'node.add',
|
||||
@@ -418,7 +418,7 @@ function admin_toolbar_tools_menu_links_discovered_alter(&$links) {
|
||||
'weight' => '-1',
|
||||
];
|
||||
if ($moduleHandler->moduleExists('webprofiler')) {
|
||||
$links['admin_menu_tools.devel.webprofiler'] = [
|
||||
$links['admin_toolbar_tools.devel.webprofiler'] = [
|
||||
'title' => t('Web Profiler settings'),
|
||||
'route_name' => 'webprofiler.settings',
|
||||
'menu_name' => 'admin',
|
||||
@@ -478,20 +478,33 @@ function admin_toolbar_tools_menu_links_discovered_alter(&$links) {
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'admin_development',
|
||||
];
|
||||
// Menu link for the Toolbar module.
|
||||
$links['admin_toolbar_tools.toolbar.settings'] = [
|
||||
'title' => t('Toolbar settings'),
|
||||
'route_name' => 'devel.toolbar.settings_form',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'devel.admin_settings',
|
||||
];
|
||||
}
|
||||
|
||||
// If module Views Ui enabled.
|
||||
if ($moduleHandler->moduleExists('views_ui')) {
|
||||
$links['views_ui.add'] = [
|
||||
$links['admin_toolbar_tools.views_ui.add'] = [
|
||||
'title' => t('Add new view'),
|
||||
'route_name' => 'views_ui.add',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'entity.view.collection',
|
||||
'weight' => -5,
|
||||
];
|
||||
$links['admin_toolbar_tools.views_ui.field_list'] = [
|
||||
'title' => t('Used in views'),
|
||||
'route_name' => 'views_ui.reports_fields',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'entity.field_storage_config.collection',
|
||||
];
|
||||
}
|
||||
|
||||
$links['system.theme_settings_'] = [
|
||||
$links['admin_toolbar_tools.system.theme_settings'] = [
|
||||
'title' => t('Settings'),
|
||||
'route_name' => 'system.theme_settings',
|
||||
'menu_name' => 'admin',
|
||||
@@ -499,13 +512,14 @@ function admin_toolbar_tools_menu_links_discovered_alter(&$links) {
|
||||
];
|
||||
|
||||
if ($moduleHandler->moduleExists('webprofiler')) {
|
||||
$links['admin_menu_tools.devel.webprofiler'] = [
|
||||
$links['admin_toolbar_tools.devel.webprofiler'] = [
|
||||
'title' => t('Webprofiler settings'),
|
||||
'route_name' => 'webprofiler.settings',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'admin_development',
|
||||
];
|
||||
}
|
||||
|
||||
if ($moduleHandler->moduleExists('update')) {
|
||||
$links['update.theme_install_'] = [
|
||||
'title' => t('Install new theme'),
|
||||
@@ -534,122 +548,52 @@ function admin_toolbar_tools_menu_links_discovered_alter(&$links) {
|
||||
}
|
||||
}
|
||||
|
||||
// Add menu links for local tasks that sit below any admin menu link routes.
|
||||
$manager = \Drupal::service('plugin.manager.menu.local_task');
|
||||
foreach ($links as $key => $link) {
|
||||
// If module Language enabled.
|
||||
if ($moduleHandler->moduleExists('language')) {
|
||||
$links['admin_toolbar_tools.language.negotiation'] = [
|
||||
'title' => t('Detection and selection'),
|
||||
'route_name' => 'language.negotiation',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'entity.configurable_language.collection',
|
||||
];
|
||||
}
|
||||
|
||||
// Ignore menu links that have no route name.
|
||||
if (empty($link['route_name'])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ignore links that are not in the admin menu, include parents in the
|
||||
// check as they inherit the menu name from the parent if not set.
|
||||
$link_to_check = $link;
|
||||
do {
|
||||
// @todo Use configuration for admin menu name once added in
|
||||
// https://www.drupal.org/node/1869638.
|
||||
if (isset($link_to_check['menu_name'])) {
|
||||
// If the link belongs to the admin menu, then skip this loop and
|
||||
// look for local tasks.
|
||||
if ($link_to_check['menu_name'] === 'admin') {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// If it is explicitly not in the admin menu, skip.
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($link_to_check['parent']) && isset($links[$link_to_check['parent']])) {
|
||||
$link_to_check = $links[$link_to_check['parent']];
|
||||
}
|
||||
else {
|
||||
// No parent and we found no menu_name, skip.
|
||||
continue 2;
|
||||
}
|
||||
} while ($link_to_check);
|
||||
|
||||
$route = $link['route_name'];
|
||||
$route_local_tasks = $manager->getLocalTasksForRoute($route);
|
||||
if (empty($route_local_tasks[0])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
foreach ($route_local_tasks[0] as $task_plugin) {
|
||||
$definition = $task_plugin->getPluginDefinition();
|
||||
$local_route = $definition['route_name'];
|
||||
if (empty($local_route)) {
|
||||
continue;
|
||||
}
|
||||
$exists = FALSE;
|
||||
$param = FALSE;
|
||||
if (isset($link['route_parameters'])) {
|
||||
$param = $link['route_parameters'];
|
||||
}
|
||||
// Check if local task has an already registered link in toolbar.
|
||||
foreach ($links as $link2) {
|
||||
// Route_name that could be a 'class'.
|
||||
if (!(isset($link2['route_name']) && ($link2['route_name'] == $local_route))) {
|
||||
continue;
|
||||
}
|
||||
// If route are equal, the parameters could be different.
|
||||
// @todo: check if this is true.
|
||||
if ($param) {
|
||||
if (isset($link2['route_parameters']) && ($param == $link2['route_parameters'])) {
|
||||
$exists = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$exists = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
$parent = FALSE;
|
||||
|
||||
if ($exists) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$title = $definition['title'];
|
||||
$title = $param ? $title . ' ' . $link['title'] : $title;
|
||||
|
||||
// The following code is to choose the parent of the added link.
|
||||
// If the parent of the current tab also has the tab as local task
|
||||
// for example: "Content" has "File" as task" and and
|
||||
// "Content>Comment" also has "File" as a tab then we decide to
|
||||
// set this one as parent of the added link if not the current tab
|
||||
// will be the parent.
|
||||
if (!empty($link['parent']) && isset($links[$link['parent']])) {
|
||||
$parentlink = $links[$link['parent']];
|
||||
$parentlink_route = $parentlink['route_name'];
|
||||
$parent_primary = $manager->getLocalTasks($parentlink_route, 0);
|
||||
foreach ($parent_primary['tabs'] as $parent_tab) {
|
||||
if ($parent_tab['#link']['url']) {
|
||||
$parent_route = $parent_tab['#link']['url']->getRouteName();
|
||||
if ($parent_route == $local_route) {
|
||||
$parent = $link['parent'];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$parent = $parent ? $parent : $key;
|
||||
// Make sure the key of the route is unique.
|
||||
$links[$key . '_' . $local_route] = [
|
||||
'title' => $title,
|
||||
'route_name' => $local_route,
|
||||
'menu_name' => 'admin',
|
||||
'parent' => $parent,
|
||||
'att' => TRUE,
|
||||
// If module Media enabled.
|
||||
if ($moduleHandler->moduleExists('media')) {
|
||||
$links['admin_toolbar_tools.add_media'] = [
|
||||
'title' => t('Add media'),
|
||||
'route_name' => 'entity.media.add_page',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'system.admin_content',
|
||||
];
|
||||
// Add node links for each media type.
|
||||
foreach (\Drupal::entityTypeManager()->getStorage('media_type')->loadMultiple() as $type) {
|
||||
$links['node.add.' . $type->id()] = [
|
||||
'title' => t($type->label()),
|
||||
'route_name' => 'entity.media.add_form',
|
||||
'parent' => 'admin_toolbar_tools.add_media',
|
||||
'route_parameters' => ['media_type' => $type->id()],
|
||||
];
|
||||
if ($param) {
|
||||
$links[$key . '_' . $local_route]['route_parameters'] = $param;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If module Config enabled.
|
||||
if ($moduleHandler->moduleExists('config')) {
|
||||
$links['admin_toolbar_tools.config.import'] = [
|
||||
'title' => t('Import'),
|
||||
'route_name' => 'config.import_full',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'config.sync',
|
||||
'weight' => 1,
|
||||
];
|
||||
$links['admin_toolbar_tools.config.export'] = [
|
||||
'title' => t('Export'),
|
||||
'route_name' => 'config.export_full',
|
||||
'menu_name' => 'admin',
|
||||
'parent' => 'config.sync',
|
||||
'weight' => 2,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
/*---------------------- menu horizontal hover---- Krout Fethi FrontEnd Developer-----*/
|
||||
.toolbar-tray-horizontal .menu-item:hover {
|
||||
background: #fff;
|
||||
}
|
||||
@@ -105,32 +104,79 @@
|
||||
display: block;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal .toolbar .level-2 > ul {
|
||||
[dir="rtl"] .toolbar-tray-horizontal .menu-item:hover {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal .menu-item a:focus {
|
||||
background: #abeae4;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal .toolbar-menu:not(:first-child) li.menu-item--expanded > a:focus {
|
||||
background-position: center right;
|
||||
background-image: url('../misc/icons/0074bd/chevron-right.svg');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal .menu-item--expanded .menu {
|
||||
background: #fff;
|
||||
width: auto;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal .menu-item--expanded {
|
||||
background-color: #f5f5f2;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal ul li li.menu-item {
|
||||
border-top: none transparent;
|
||||
border-right: 1px solid #dddddd;
|
||||
border-bottom: 1px solid #dddddd;
|
||||
border-left: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar .toolbar-tray-horizontal .menu-item:last-child {
|
||||
border-left: 1px solid #dddddd;
|
||||
border-right: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar .toolbar-tray-horizontal ul ul li.menu-item:first-child {
|
||||
border-top: 1px solid #dddddd;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul,
|
||||
[dir="rtl"] .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul ul,
|
||||
[dir="rtl"] .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul ul ul,
|
||||
[dir="rtl"] .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul ul ul ul ul {
|
||||
display: none;
|
||||
left: -999em; /* LTR */
|
||||
}
|
||||
|
||||
/* Lists nested under hovered list items */
|
||||
[dir="rtl"] .toolbar-tray-horizontal li.menu-item--expanded.hover-intent ul,
|
||||
[dir="rtl"] .toolbar-tray-horizontal li li.menu-item--expanded.hover-intent ul,
|
||||
[dir="rtl"] .toolbar-tray-horizontal li li li.menu-item--expanded.hover-intent ul,
|
||||
[dir="rtl"] .toolbar-tray-horizontal li li li li.menu-item--expanded.hover-intent ul,
|
||||
[dir="rtl"] .toolbar-tray-horizontal li li li li li.menu-item--expanded.hover-intent ul {
|
||||
display: block;
|
||||
left: auto; /* LTR */
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal .menu ul li a,
|
||||
[dir="rtl"] .toolbar-tray-horizontal .menu ul .toolbar-icon {
|
||||
padding: 12px 15px 12px 12px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded.hover-intent ul {
|
||||
display: block;
|
||||
position: absolute;
|
||||
padding-top: 0;
|
||||
top: 0;
|
||||
right: 200px;
|
||||
width: 200px;
|
||||
box-shadow: 2px 2px 3px hsla(0, 0%, 0%, 0.4);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal li:hover ul li {
|
||||
float: none !important;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal li:focus ul li {
|
||||
float: none !important;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar .toolbar-menu ul .toolbar-icon {
|
||||
padding-left: 1.3333em;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item:hover ul {
|
||||
margin: -40px 197px 0 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item:focus ul {
|
||||
margin: -40px 197px 0 0;
|
||||
[dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item > ul {
|
||||
display: none;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded ul li.menu-item--expanded {
|
||||
@@ -138,3 +184,28 @@
|
||||
background-image: url('../misc/icons/0074bd/chevron-left.svg');
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item.hover-intent ul {
|
||||
display: block;
|
||||
margin: -40px 197px 0 0;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal li:hover ul li {
|
||||
float: none;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal li.hover-intent ul li {
|
||||
float: none;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar-tray-horizontal .toolbar .level-2 > ul {
|
||||
position: absolute;
|
||||
padding-top: 0;
|
||||
top: 0;
|
||||
left: 200px;
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
[dir="rtl"] .toolbar .toolbar-tray-vertical li.open > ul.toolbar-menu.clearfix {
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
(function ($) {
|
||||
(function ($, Drupal) {
|
||||
Drupal.behaviors.adminToolbar = {
|
||||
attach: function (context, settings) {
|
||||
|
||||
$('a.toolbar-icon', context).removeAttr('title');
|
||||
|
||||
$('.toolbar-tray-horizontal li.menu-item--expanded, .toolbar-tray-horizontal ul li.menu-item--expanded .menu-item', context).hoverIntent({
|
||||
|
||||
$('.toolbar-tray li.menu-item--expanded, .toolbar-tray ul li.menu-item--expanded .menu-item', context).hoverIntent({
|
||||
over: function () {
|
||||
// At the current depth, we should delete all "hover-intent" classes.
|
||||
// Other wise we get unwanted behaviour where menu items are expanded while already in hovering other ones.
|
||||
@@ -16,13 +16,13 @@
|
||||
},
|
||||
timeout: 250
|
||||
});
|
||||
|
||||
|
||||
// Make the toolbar menu navigable with keyboard.
|
||||
$('ul.toolbar-menu li.menu-item--expanded a', context).on('focusin', function () {
|
||||
$('li.menu-item--expanded', context).removeClass('hover-intent');
|
||||
$(this).parents('li.menu-item--expanded').addClass('hover-intent');
|
||||
});
|
||||
|
||||
|
||||
$('ul.toolbar-menu li.menu-item a', context).keydown(function (e) {
|
||||
if ((e.shiftKey && (e.keyCode || e.which) == 9)) {
|
||||
if ($(this).parent('.menu-item').prev().hasClass('menu-item--expanded')) {
|
||||
@@ -30,15 +30,15 @@
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('.toolbar-menu:first-child > .menu-item:not(.menu-item--expanded) a, .toolbar-tab > a', context).on('focusin', function () {
|
||||
$('.menu-item--expanded').removeClass('hover-intent');
|
||||
});
|
||||
|
||||
|
||||
$('.toolbar-menu:first-child > .menu-item', context).on('hover', function () {
|
||||
$(this,'a').css("background: #fff;");
|
||||
$(this, 'a').css("background: #fff;");
|
||||
});
|
||||
|
||||
|
||||
$('ul:not(.toolbar-menu)', context).on({
|
||||
mousemove: function () {
|
||||
$('li.menu-item--expanded').removeClass('hover-intent');
|
||||
@@ -50,4 +50,4 @@
|
||||
|
||||
}
|
||||
};
|
||||
})(jQuery);
|
||||
})(jQuery, Drupal);
|
||||
|
||||
Reference in New Issue
Block a user