Merge remote-tracking branch 'origin/v16/dev'
This commit is contained in:
@@ -276,4 +276,4 @@
|
||||
"access": "public",
|
||||
"registry": "https://registry.npmjs.org/"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2897,29 +2897,52 @@ export default {
|
||||
ar: 'العربية',
|
||||
bs: 'Bosanski',
|
||||
cs: 'Česky',
|
||||
'cs-cz': 'Česky (Czechia)',
|
||||
cy: 'Cymraeg',
|
||||
'cy-gb': 'Cymraeg (UK)',
|
||||
da: 'Dansk',
|
||||
'da-dk': 'Dansk (Danmark)',
|
||||
de: 'Deutsch',
|
||||
'de-de': 'Deutsch (Deutschland)',
|
||||
'de-ch': 'Deutsch (Schweiz)',
|
||||
en: 'English (UK)',
|
||||
'en-us': 'English (US)',
|
||||
es: 'Español',
|
||||
'es-es': 'Español (España)',
|
||||
fr: 'Français',
|
||||
he: 'Hebrew',
|
||||
'fr-fr': 'Français (France)',
|
||||
'fr-ch': 'Français (Suisse)',
|
||||
he: 'עברית',
|
||||
'he-il': 'עברית (ישראל)',
|
||||
hr: 'Hrvatski',
|
||||
'hr-hr': 'Hrvatski (Hrvatska)',
|
||||
it: 'Italiano',
|
||||
'it-it': 'Italiano (Italia)',
|
||||
'it-ch': 'Italiano (Svizzera)',
|
||||
ja: '日本語',
|
||||
'ja-jp': '日本語 (日本)',
|
||||
ko: '한국어',
|
||||
'ko-kr': '한국어 (한국)',
|
||||
nb: 'Norsk Bokmål',
|
||||
'nb-no': 'Norsk (Bokmål)',
|
||||
nl: 'Nederlands',
|
||||
'nl-nl': 'Nederlands (Nederland)',
|
||||
pl: 'Polski',
|
||||
'pl-pl': 'Polski (Polska)',
|
||||
pt: 'Português',
|
||||
'pt-br': 'Português (Brasil)',
|
||||
ro: 'Romana',
|
||||
ro: 'Română',
|
||||
'ro-ro': 'Română (România)',
|
||||
ru: 'Русский',
|
||||
'ru-ru': 'Русский (Россия)',
|
||||
sv: 'Svenska',
|
||||
'sv-se': 'Svenska (Sverige)',
|
||||
tr: 'Türkçe',
|
||||
'tr-tr': 'Türkçe (Türkiye Cumhuriyeti)',
|
||||
uk: 'Українська',
|
||||
'uk-ua': 'Українська (Україна)',
|
||||
zh: '中文',
|
||||
'zh-cn': '中文(简体,中国)',
|
||||
'zh-tw': '中文(正體,台灣)',
|
||||
vi: 'Tiếng Việt',
|
||||
},
|
||||
|
||||
@@ -2819,34 +2819,4 @@ export default {
|
||||
resetUrlMessage: 'Bạn có chắc chắn muốn đặt lại URL này không?',
|
||||
resetUrlLabel: 'Đặt lại',
|
||||
},
|
||||
uiCulture: {
|
||||
ar: 'العربية',
|
||||
bs: 'Bosanski',
|
||||
cs: 'Česky',
|
||||
cy: 'Cymraeg',
|
||||
da: 'Dansk',
|
||||
de: 'Deutsch',
|
||||
en: 'English (UK)',
|
||||
'en-us': 'English (US)',
|
||||
es: 'Español',
|
||||
fr: 'Français',
|
||||
he: 'Hebrew',
|
||||
hr: 'Hrvatski',
|
||||
it: 'Italiano',
|
||||
ja: '日本語',
|
||||
ko: '한국어',
|
||||
nb: 'Norsk Bokmål',
|
||||
nl: 'Nederlands',
|
||||
pl: 'Polski',
|
||||
pt: 'Português',
|
||||
'pt-br': 'Português (Brasil)',
|
||||
ro: 'Romana',
|
||||
ru: 'Русский',
|
||||
sv: 'Svenska',
|
||||
tr: 'Türkçe',
|
||||
uk: 'Українська',
|
||||
zh: '中文',
|
||||
'zh-tw': '中文(正體,台灣)',
|
||||
vi: 'Tiếng Việt',
|
||||
},
|
||||
} as UmbLocalizationDictionary;
|
||||
|
||||
@@ -4,281 +4,335 @@ export const manifests: Array<ManifestLocalization> = [
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.AR',
|
||||
weight: 100,
|
||||
name: 'Arabic Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'ar',
|
||||
},
|
||||
meta: { culture: 'ar' },
|
||||
js: () => import('../../../assets/lang/ar.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.BS',
|
||||
weight: 100,
|
||||
name: 'Bosnian Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'bs',
|
||||
},
|
||||
meta: { culture: 'bs' },
|
||||
js: () => import('../../../assets/lang/bs.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.CS',
|
||||
weight: 100,
|
||||
name: 'Czech Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'cs',
|
||||
},
|
||||
meta: { culture: 'cs' },
|
||||
js: () => import('../../../assets/lang/cs.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.CS_CZ',
|
||||
name: 'Czech (Czechia) Backoffice UI Localization',
|
||||
meta: { culture: 'cs-CZ' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.CY',
|
||||
weight: 100,
|
||||
name: 'Welsh Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'cy',
|
||||
},
|
||||
meta: { culture: 'cy' },
|
||||
js: () => import('../../../assets/lang/cy.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.CY_GB',
|
||||
name: 'Welsh (UK) Backoffice UI Localization',
|
||||
meta: { culture: 'cy-GB' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.DA',
|
||||
weight: 100,
|
||||
name: 'Danish Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'da',
|
||||
},
|
||||
meta: { culture: 'da' },
|
||||
js: () => import('../../../assets/lang/da.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.DA-DK',
|
||||
name: 'Danish (Denmark) Backoffice UI Localization',
|
||||
meta: { culture: 'da-DK' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.DE',
|
||||
weight: 100,
|
||||
name: 'German Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'de',
|
||||
},
|
||||
meta: { culture: 'de' },
|
||||
js: () => import('../../../assets/lang/de.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.DE_DE',
|
||||
name: 'German (Germany) Backoffice UI Localization',
|
||||
meta: { culture: 'de-DE' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.DE_CH',
|
||||
name: 'German (Switzerland) Backoffice UI Localization',
|
||||
meta: { culture: 'de-CH' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.EN',
|
||||
weight: 100,
|
||||
name: 'English (United Kingdom) Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'en',
|
||||
},
|
||||
meta: { culture: 'en' },
|
||||
js: () => import('../../../assets/lang/en.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.EN_US',
|
||||
weight: 100,
|
||||
name: 'English (United States) Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'en-US',
|
||||
},
|
||||
meta: { culture: 'en-US' },
|
||||
js: () => import('../../../assets/lang/en-us.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.ES',
|
||||
weight: 100,
|
||||
name: 'Spanish Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'es',
|
||||
},
|
||||
meta: { culture: 'es' },
|
||||
js: () => import('../../../assets/lang/es.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.ES_ES',
|
||||
name: 'Spanish (Spain) Backoffice UI Localization',
|
||||
meta: { culture: 'es-ES' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.FR',
|
||||
weight: 100,
|
||||
name: 'French Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'fr',
|
||||
},
|
||||
meta: { culture: 'fr' },
|
||||
js: () => import('../../../assets/lang/fr.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.FR_FR',
|
||||
name: 'French (France) Backoffice UI Localization',
|
||||
meta: { culture: 'fr-FR' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.FR_CH',
|
||||
name: 'French (Switzerland) Backoffice UI Localization',
|
||||
meta: { culture: 'fr-CH' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.HE',
|
||||
weight: 100,
|
||||
name: 'Hebrew Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'he',
|
||||
},
|
||||
meta: { culture: 'he' },
|
||||
js: () => import('../../../assets/lang/he.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.HE_IL',
|
||||
name: 'Hebrew (Israel) Backoffice UI Localization',
|
||||
meta: { culture: 'he-IL' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.HR',
|
||||
weight: 100,
|
||||
name: 'Croatian Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'hr',
|
||||
},
|
||||
meta: { culture: 'hr' },
|
||||
js: () => import('../../../assets/lang/hr.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.HR_HR',
|
||||
name: 'Croatian (Croatia) Backoffice UI Localization',
|
||||
meta: { culture: 'hr-HR' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.IT',
|
||||
weight: 100,
|
||||
name: 'Italian Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'it',
|
||||
},
|
||||
meta: { culture: 'it' },
|
||||
js: () => import('../../../assets/lang/it.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.IT_IT',
|
||||
name: 'Italian (Italy) Backoffice UI Localization',
|
||||
meta: { culture: 'it-IT' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.IT_CH',
|
||||
name: 'Italian (Switzerland) Backoffice UI Localization',
|
||||
meta: { culture: 'it-CH' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.JA',
|
||||
weight: 100,
|
||||
name: 'Japanese Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'ja',
|
||||
},
|
||||
meta: { culture: 'ja' },
|
||||
js: () => import('../../../assets/lang/ja.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.JA_JP',
|
||||
name: 'Japanese (Japan) Backoffice UI Localization',
|
||||
meta: { culture: 'ja-JP' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.KO',
|
||||
weight: 100,
|
||||
name: 'Korean Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'ko',
|
||||
},
|
||||
meta: { culture: 'ko' },
|
||||
js: () => import('../../../assets/lang/ko.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.KO_KR',
|
||||
name: 'Korean (Korea) Backoffice UI Localization',
|
||||
meta: { culture: 'ko-KR' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.NB',
|
||||
weight: 100,
|
||||
name: 'Norwegian Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'nb',
|
||||
},
|
||||
meta: { culture: 'nb' },
|
||||
js: () => import('../../../assets/lang/nb.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.NB_NO',
|
||||
name: 'Norwegian (Norway) Backoffice UI Localization',
|
||||
meta: { culture: 'nb-NO' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.NL',
|
||||
weight: 100,
|
||||
name: 'Dutch Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'nl',
|
||||
},
|
||||
meta: { culture: 'nl' },
|
||||
js: () => import('../../../assets/lang/nl.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.NL_NL',
|
||||
name: 'Dutch (Netherlands) Backoffice UI Localization',
|
||||
meta: { culture: 'nl-NL' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.PL',
|
||||
weight: 100,
|
||||
name: 'Polish Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'pl',
|
||||
},
|
||||
meta: { culture: 'pl' },
|
||||
js: () => import('../../../assets/lang/pl.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.PL_PL',
|
||||
name: 'Polish (Poland) Backoffice UI Localization',
|
||||
meta: { culture: 'pl-PL' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.PT',
|
||||
weight: 100,
|
||||
name: 'Portuguese Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'pt',
|
||||
},
|
||||
meta: { culture: 'pt' },
|
||||
js: () => import('../../../assets/lang/pt.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.PT_BR',
|
||||
weight: 100,
|
||||
name: 'Portuguese (Brazil) Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'pt-BR',
|
||||
},
|
||||
meta: { culture: 'pt-BR' },
|
||||
js: () => import('../../../assets/lang/pt-br.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.RO',
|
||||
weight: 100,
|
||||
name: 'Romanian Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'ro',
|
||||
},
|
||||
meta: { culture: 'ro' },
|
||||
js: () => import('../../../assets/lang/ro.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.RO_RO',
|
||||
name: 'Romanian (Romania) Backoffice UI Localization',
|
||||
meta: { culture: 'ro-RO' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.RU',
|
||||
weight: 100,
|
||||
name: 'Russian Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'ru',
|
||||
},
|
||||
meta: { culture: 'ru' },
|
||||
js: () => import('../../../assets/lang/ru.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.RU_RU',
|
||||
name: 'Russian (Russia) Backoffice UI Localization',
|
||||
meta: { culture: 'ru-RU' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.SV',
|
||||
weight: 100,
|
||||
name: 'Swedish Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'sv',
|
||||
},
|
||||
meta: { culture: 'sv' },
|
||||
js: () => import('../../../assets/lang/sv.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.SV_SE',
|
||||
name: 'Swedish (Sweden) Backoffice UI Localization',
|
||||
meta: { culture: 'sv-SE' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.TR',
|
||||
weight: 100,
|
||||
name: 'Turkish Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'tr',
|
||||
},
|
||||
meta: { culture: 'tr' },
|
||||
js: () => import('../../../assets/lang/tr.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.TR_TR',
|
||||
name: 'Turkish (Türkiye) Backoffice UI Localization',
|
||||
meta: { culture: 'tr-TR' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.UK',
|
||||
weight: 100,
|
||||
name: 'Ukrainian Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'uk',
|
||||
},
|
||||
meta: { culture: 'uk' },
|
||||
js: () => import('../../../assets/lang/uk.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.UK_UA',
|
||||
name: 'Ukrainian (Ukraine) Backoffice UI Localization',
|
||||
meta: { culture: 'uk-UA' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.ZH',
|
||||
weight: 100,
|
||||
name: 'Chinese Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'zh',
|
||||
},
|
||||
meta: { culture: 'zh' },
|
||||
js: () => import('../../../assets/lang/zh.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.ZH_CN',
|
||||
name: 'Chinese (Simplified, China) Backoffice UI Localization',
|
||||
meta: { culture: 'zh-CN' },
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.ZH_TW',
|
||||
weight: 100,
|
||||
name: 'Chinese (Taiwan) Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'zh-TW',
|
||||
},
|
||||
meta: { culture: 'zh-TW' },
|
||||
js: () => import('../../../assets/lang/zh-tw.js'),
|
||||
},
|
||||
{
|
||||
type: 'localization',
|
||||
alias: 'Umb.Localization.VI',
|
||||
weight: 100,
|
||||
name: 'Vietnamese Backoffice UI Localization',
|
||||
meta: {
|
||||
culture: 'vi',
|
||||
},
|
||||
meta: { culture: 'vi' },
|
||||
js: () => import('../../../assets/lang/vi.js'),
|
||||
},
|
||||
];
|
||||
|
||||
@@ -416,3 +416,22 @@ test('can add a variant block element with invariant RTE Tiptap in the content',
|
||||
await umbracoApi.documentType.ensureNameNotExists(customElementTypeName);
|
||||
await umbracoApi.language.ensureNameNotExists('Danish');
|
||||
});
|
||||
|
||||
// Tests regression issue: https://github.com/umbraco/Umbraco-CMS/issues/20680
|
||||
test('can move away from a content node with a block grid after making no changes without seeing discard unsaved changes', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const customDataTypeId = await umbracoApi.dataType.createBlockGridWithPermissions(customDataTypeName, elementTypeId, true, true);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
|
||||
// Act
|
||||
await umbracoUi.documentType.goToSection(ConstantHelper.sections.settings);
|
||||
|
||||
// Assert
|
||||
// We do this to make sure that there is no discard changes button visible, if the discard changes was visible, we would not be able to go to the document type
|
||||
await umbracoUi.documentType.goToDocumentType(documentTypeName);
|
||||
});
|
||||
|
||||
|
||||
@@ -360,3 +360,21 @@ test('can add a variant block element with invariant RTE Tiptap in the content',
|
||||
await umbracoApi.documentType.ensureNameNotExists(customElementTypeName);
|
||||
await umbracoApi.language.ensureNameNotExists('Danish');
|
||||
});
|
||||
|
||||
// Tests regression issue: https://github.com/umbraco/Umbraco-CMS/issues/20680
|
||||
test('can move away from a content node with a block list after making no changes without seeing discard unsaved changes', {tag: '@smoke'}, async ({umbracoApi, umbracoUi}) => {
|
||||
// Arrange
|
||||
const customDataTypeId = await umbracoApi.dataType.createBlockListDataTypeWithABlock(customDataTypeName, elementTypeId);
|
||||
const documentTypeId = await umbracoApi.documentType.createDocumentTypeWithPropertyEditor(documentTypeName, customDataTypeName, customDataTypeId);
|
||||
await umbracoApi.document.createDefaultDocument(contentName, documentTypeId);
|
||||
await umbracoUi.goToBackOffice();
|
||||
await umbracoUi.content.goToSection(ConstantHelper.sections.content);
|
||||
await umbracoUi.content.goToContentWithName(contentName);
|
||||
|
||||
// Act
|
||||
await umbracoUi.documentType.goToSection(ConstantHelper.sections.settings);
|
||||
|
||||
// Assert
|
||||
// We do this to make sure that there is no discard changes button visible, if the discard changes was visible, we would not be able to go to the document type
|
||||
await umbracoUi.documentType.goToDocumentType(documentTypeName);
|
||||
});
|
||||
|
||||
@@ -20,4 +20,4 @@
|
||||
"setVersionVariables": true,
|
||||
"setAllVariables": true
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user