mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2026-09-09 18:03:21 +00:00
[AAE-0000] - fixed run for process-service-cloud (#11855)
* [AAE-0000] - fixed run for process-service-cloud * [AAE-0000] - Stabilising process cloud tests
This commit is contained in:
@@ -252,7 +252,7 @@ export class AppConfigService {
|
|||||||
* @returns auth config model
|
* @returns auth config model
|
||||||
*/
|
*/
|
||||||
get oauth2(): OauthConfigModel {
|
get oauth2(): OauthConfigModel {
|
||||||
const config = this.get(AppConfigValues.OAUTHCONFIG, {});
|
const config = this.get(AppConfigValues.OAUTHCONFIG, {}) ?? {};
|
||||||
const implicitFlow = config['implicitFlow'] === true || config['implicitFlow'] === 'true';
|
const implicitFlow = config['implicitFlow'] === true || config['implicitFlow'] === 'true';
|
||||||
const silentLogin = config['silentLogin'] === true || config['silentLogin'] === 'true';
|
const silentLogin = config['silentLogin'] === true || config['silentLogin'] === 'true';
|
||||||
const codeFlow = config['codeFlow'] === true || config['codeFlow'] === 'true';
|
const codeFlow = config['codeFlow'] === true || config['codeFlow'] === 'true';
|
||||||
|
|||||||
-1
@@ -24,7 +24,6 @@
|
|||||||
[title]="field.tooltip"
|
[title]="field.tooltip"
|
||||||
panelClass="adf-select-filter"
|
panelClass="adf-select-filter"
|
||||||
[multiple]="field.hasMultipleValues"
|
[multiple]="field.hasMultipleValues"
|
||||||
[disabled]="field.readOnly"
|
|
||||||
[required]="field.required"
|
[required]="field.required"
|
||||||
#select
|
#select
|
||||||
(keydown.escape)="select.close()"
|
(keydown.escape)="select.close()"
|
||||||
|
|||||||
+2
-5
@@ -17,12 +17,11 @@
|
|||||||
|
|
||||||
import { FileViewerWidgetComponent } from './file-viewer.widget';
|
import { FileViewerWidgetComponent } from './file-viewer.widget';
|
||||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
import { FormFieldModel, FormModel, FormService, NoopAuthModule, NoopTranslateModule } from '@alfresco/adf-core';
|
import { FormFieldModel, FormModel, NoopAuthModule, NoopTranslateModule } from '@alfresco/adf-core';
|
||||||
|
|
||||||
describe('FileViewerWidgetComponent', () => {
|
describe('FileViewerWidgetComponent', () => {
|
||||||
const fakeForm = new FormModel();
|
const fakeForm = new FormModel();
|
||||||
let widget: FileViewerWidgetComponent;
|
let widget: FileViewerWidgetComponent;
|
||||||
let formServiceStub: Partial<FormService>;
|
|
||||||
let fixture: ComponentFixture<FileViewerWidgetComponent>;
|
let fixture: ComponentFixture<FileViewerWidgetComponent>;
|
||||||
|
|
||||||
const fakePngAnswer: any = {
|
const fakePngAnswer: any = {
|
||||||
@@ -42,11 +41,9 @@ describe('FileViewerWidgetComponent', () => {
|
|||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [NoopTranslateModule, NoopAuthModule, FileViewerWidgetComponent],
|
imports: [NoopTranslateModule, NoopAuthModule, FileViewerWidgetComponent]
|
||||||
providers: [{ provide: FormService, useValue: formServiceStub }]
|
|
||||||
});
|
});
|
||||||
|
|
||||||
formServiceStub = TestBed.inject(FormService);
|
|
||||||
fixture = TestBed.createComponent(FileViewerWidgetComponent);
|
fixture = TestBed.createComponent(FileViewerWidgetComponent);
|
||||||
widget = fixture.componentInstance;
|
widget = fixture.componentInstance;
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -12,7 +12,7 @@
|
|||||||
{{group.name}}
|
{{group.name}}
|
||||||
<mat-icon *ngIf="!(group.readonly || readOnly)" matChipRemove [attr.data-automation-id]="'adf-cloud-group-chip-remove-icon-' + group.name" adf-icon="cancel" />
|
<mat-icon *ngIf="!(group.readonly || readOnly)" matChipRemove [attr.data-automation-id]="'adf-cloud-group-chip-remove-icon-' + group.name" adf-icon="cancel" />
|
||||||
</mat-chip-row>
|
</mat-chip-row>
|
||||||
<input [disabled]="readOnly || isValidationLoading()" matInput
|
<input matInput
|
||||||
[formControl]="searchGroupsControl"
|
[formControl]="searchGroupsControl"
|
||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
[matChipInputFor]="groupChipList"
|
[matChipInputFor]="groupChipList"
|
||||||
|
|||||||
@@ -169,9 +169,13 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.initSearch();
|
this.initSearch();
|
||||||
|
this.updateSearchControlState();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
|
if (changes?.readOnly || changes?.validate) {
|
||||||
|
this.updateSearchControlState();
|
||||||
|
}
|
||||||
if (this.hasPreselectedGroupsChanged(changes) || this.hasModeChanged(changes) || this.isValidationChanged(changes)) {
|
if (this.hasPreselectedGroupsChanged(changes) || this.hasModeChanged(changes) || this.isValidationChanged(changes)) {
|
||||||
if (this.hasPreSelectGroups()) {
|
if (this.hasPreSelectGroups()) {
|
||||||
this.loadPreSelectGroups();
|
this.loadPreSelectGroups();
|
||||||
@@ -312,8 +316,10 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
|||||||
this.groupChipsCtrl.setValue(this.selectedGroups[0].name);
|
this.groupChipsCtrl.setValue(this.selectedGroups[0].name);
|
||||||
if (this.isValidationEnabled()) {
|
if (this.isValidationEnabled()) {
|
||||||
this.validationLoading = true;
|
this.validationLoading = true;
|
||||||
|
this.updateSearchControlState();
|
||||||
await this.validatePreselectGroups();
|
await this.validatePreselectGroups();
|
||||||
this.validationLoading = false;
|
this.validationLoading = false;
|
||||||
|
this.updateSearchControlState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,6 +341,7 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
|||||||
this.groupChipsCtrlValue(this.selectedGroups[0].name);
|
this.groupChipsCtrlValue(this.selectedGroups[0].name);
|
||||||
|
|
||||||
this.changedGroups.emit(this.selectedGroups);
|
this.changedGroups.emit(this.selectedGroups);
|
||||||
|
this.updateSearchControlState();
|
||||||
this.resetSearchGroups();
|
this.resetSearchGroups();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -350,6 +357,7 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
|||||||
}
|
}
|
||||||
this.searchGroupsControl.markAsDirty();
|
this.searchGroupsControl.markAsDirty();
|
||||||
this.searchGroupsControl.markAsTouched();
|
this.searchGroupsControl.markAsTouched();
|
||||||
|
this.updateSearchControlState();
|
||||||
|
|
||||||
if (this.isValidationEnabled()) {
|
if (this.isValidationEnabled()) {
|
||||||
this.removeGroupFromValidation(groupToRemove);
|
this.removeGroupFromValidation(groupToRemove);
|
||||||
@@ -445,6 +453,14 @@ export class GroupCloudComponent implements OnInit, OnChanges {
|
|||||||
return this.readOnly || this.isSingleSelectionReadonly();
|
return this.readOnly || this.isSingleSelectionReadonly();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSearchControlState(): void {
|
||||||
|
if (this.isReadonly() || this.isValidationLoading()) {
|
||||||
|
this.searchGroupsControl.disable({ emitEvent: false });
|
||||||
|
} else {
|
||||||
|
this.searchGroupsControl.enable({ emitEvent: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
getDisplayName(group: IdentityGroupModel): string {
|
getDisplayName(group: IdentityGroupModel): string {
|
||||||
return group?.name || '';
|
return group?.name || '';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,13 +24,11 @@
|
|||||||
</mat-chip-row>
|
</mat-chip-row>
|
||||||
<input
|
<input
|
||||||
matInput
|
matInput
|
||||||
[disabled]="isReadonly()"
|
|
||||||
[formControl]="searchUserCtrl"
|
[formControl]="searchUserCtrl"
|
||||||
[matAutocomplete]="auto"
|
[matAutocomplete]="auto"
|
||||||
[matChipInputFor]="userMultipleChipList"
|
[matChipInputFor]="userMultipleChipList"
|
||||||
[required]="required"
|
[required]="required"
|
||||||
[placeholder]="placeholder"
|
[placeholder]="placeholder"
|
||||||
[disabled]="isReadonly() || isValidationLoading()"
|
|
||||||
(focus)="setFocus(true)"
|
(focus)="setFocus(true)"
|
||||||
(blur)="setFocus(false); markAsTouched()"
|
(blur)="setFocus(false); markAsTouched()"
|
||||||
class="adf-cloud-input"
|
class="adf-cloud-input"
|
||||||
|
|||||||
@@ -231,6 +231,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
|||||||
|
|
||||||
ngOnInit(): void {
|
ngOnInit(): void {
|
||||||
this.initSearch();
|
this.initSearch();
|
||||||
|
this.updateSearchControlState();
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnChanges(changes: SimpleChanges): void {
|
ngOnChanges(changes: SimpleChanges): void {
|
||||||
@@ -247,11 +248,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.isReadonly() && this.searchUserCtrl.enabled) {
|
this.updateSearchControlState();
|
||||||
this.searchUserCtrl.disable();
|
|
||||||
} else if (!this.isReadonly() && this.searchUserCtrl.disabled) {
|
|
||||||
this.searchUserCtrl.enable();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ngAfterViewInit(): void {
|
ngAfterViewInit(): void {
|
||||||
@@ -348,8 +345,10 @@ export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
|||||||
this.userChipsCtrl.setValue(this.selectedUsers[0].username);
|
this.userChipsCtrl.setValue(this.selectedUsers[0].username);
|
||||||
if (this.isValidationEnabled()) {
|
if (this.isValidationEnabled()) {
|
||||||
this.validationLoading = true;
|
this.validationLoading = true;
|
||||||
|
this.updateSearchControlState();
|
||||||
await this.validatePreselectUsers();
|
await this.validatePreselectUsers();
|
||||||
this.validationLoading = false;
|
this.validationLoading = false;
|
||||||
|
this.updateSearchControlState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,6 +426,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
|||||||
this.userChipsControlValue(this.selectedUsers[0].username);
|
this.userChipsControlValue(this.selectedUsers[0].username);
|
||||||
|
|
||||||
this.changedUsers.emit(this.selectedUsers);
|
this.changedUsers.emit(this.selectedUsers);
|
||||||
|
this.updateSearchControlState();
|
||||||
this.resetSearchUsers();
|
this.resetSearchUsers();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -445,6 +445,7 @@ export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
|||||||
}
|
}
|
||||||
this.searchUserCtrl.markAsDirty();
|
this.searchUserCtrl.markAsDirty();
|
||||||
this.searchUserCtrl.markAsTouched();
|
this.searchUserCtrl.markAsTouched();
|
||||||
|
this.updateSearchControlState();
|
||||||
|
|
||||||
if (this.isValidationEnabled()) {
|
if (this.isValidationEnabled()) {
|
||||||
this.removeUserFromValidation(userToRemove);
|
this.removeUserFromValidation(userToRemove);
|
||||||
@@ -563,6 +564,14 @@ export class PeopleCloudComponent implements OnInit, OnChanges, AfterViewInit {
|
|||||||
return this.isValidationEnabled() && this.validationLoading;
|
return this.isValidationEnabled() && this.validationLoading;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
updateSearchControlState(): void {
|
||||||
|
if (this.isReadonly() || this.isValidationLoading()) {
|
||||||
|
this.searchUserCtrl.disable({ emitEvent: false });
|
||||||
|
} else {
|
||||||
|
this.searchUserCtrl.enable({ emitEvent: false });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
markAsTouched(): void {
|
markAsTouched(): void {
|
||||||
this.touched = true;
|
this.touched = true;
|
||||||
}
|
}
|
||||||
|
|||||||
+20
-10
@@ -531,11 +531,11 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
component.reload();
|
component.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call endpoint when a column visibility gets changed', () => {
|
it('should update preferences when a column visibility gets changed', () => {
|
||||||
spyOn(preferencesService, 'updatePreference').and.returnValue(of({}));
|
const updatePreferenceSpy = spyOn(preferencesService, 'updatePreference').and.returnValue(of({}));
|
||||||
spyOn(processListCloudService, 'getProcessByRequest');
|
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
||||||
component.ngAfterContentInit();
|
component.ngAfterContentInit();
|
||||||
spyOn(component, 'createDatatableSchema');
|
const createDatatableSchemaSpy = spyOn(component, 'createDatatableSchema');
|
||||||
component.appName = 'fake-app-name';
|
component.appName = 'fake-app-name';
|
||||||
component.reload();
|
component.reload();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -544,7 +544,8 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(processListCloudService.getProcessByRequest).toHaveBeenCalledTimes(1);
|
expect(updatePreferenceSpy).toHaveBeenCalled();
|
||||||
|
expect(createDatatableSchemaSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('component changes', () => {
|
describe('component changes', () => {
|
||||||
@@ -921,11 +922,11 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
component.reload();
|
component.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call endpoint when a column visibility gets changed', () => {
|
it('should update preferences when a column visibility gets changed', () => {
|
||||||
spyOn(preferencesService, 'updatePreference').and.returnValue(of({}));
|
const updatePreferenceSpy = spyOn(preferencesService, 'updatePreference').and.returnValue(of({}));
|
||||||
spyOn(processListCloudService, 'fetchProcessList');
|
spyOn(processListCloudService, 'fetchProcessList').and.returnValue(of(fakeProcessCloudList));
|
||||||
component.ngAfterContentInit();
|
component.ngAfterContentInit();
|
||||||
spyOn(component, 'createDatatableSchema');
|
const createDatatableSchemaSpy = spyOn(component, 'createDatatableSchema');
|
||||||
component.appName = 'fake-app-name';
|
component.appName = 'fake-app-name';
|
||||||
component.reload();
|
component.reload();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -934,7 +935,8 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(processListCloudService.fetchProcessList).toHaveBeenCalledTimes(1);
|
expect(updatePreferenceSpy).toHaveBeenCalled();
|
||||||
|
expect(createDatatableSchemaSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('component changes', () => {
|
describe('component changes', () => {
|
||||||
@@ -1250,12 +1252,16 @@ describe('ProcessListCloudComponent', () => {
|
|||||||
describe('ProcessListCloudComponent: Injecting custom columns for task list - CustomTaskListComponent', () => {
|
describe('ProcessListCloudComponent: Injecting custom columns for task list - CustomTaskListComponent', () => {
|
||||||
let fixtureCustom: ComponentFixture<CustomTaskListComponent>;
|
let fixtureCustom: ComponentFixture<CustomTaskListComponent>;
|
||||||
let componentCustom: CustomTaskListComponent;
|
let componentCustom: CustomTaskListComponent;
|
||||||
|
let processListCloudService: ProcessListCloudService;
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
TestBed.configureTestingModule({
|
TestBed.configureTestingModule({
|
||||||
imports: [CustomTaskListComponent],
|
imports: [CustomTaskListComponent],
|
||||||
providers: [provideCloudPreferences()]
|
providers: [provideCloudPreferences()]
|
||||||
});
|
});
|
||||||
|
processListCloudService = TestBed.inject(ProcessListCloudService);
|
||||||
|
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
||||||
|
spyOn(processListCloudService, 'fetchProcessList').and.returnValue(of(fakeProcessCloudList));
|
||||||
fixtureCustom = TestBed.createComponent(CustomTaskListComponent);
|
fixtureCustom = TestBed.createComponent(CustomTaskListComponent);
|
||||||
fixtureCustom.detectChanges();
|
fixtureCustom.detectChanges();
|
||||||
componentCustom = fixtureCustom.componentInstance;
|
componentCustom = fixtureCustom.componentInstance;
|
||||||
@@ -1292,6 +1298,7 @@ describe('ProcessListCloudComponent: Creating an empty custom template - EmptyTe
|
|||||||
}
|
}
|
||||||
|
|
||||||
let fixtureEmpty: ComponentFixture<EmptyTemplateComponent>;
|
let fixtureEmpty: ComponentFixture<EmptyTemplateComponent>;
|
||||||
|
let processListCloudService: ProcessListCloudService;
|
||||||
const preferencesService = jasmine.createSpyObj('preferencesService', {
|
const preferencesService = jasmine.createSpyObj('preferencesService', {
|
||||||
getPreferences: of({}),
|
getPreferences: of({}),
|
||||||
updatePreference: of({})
|
updatePreference: of({})
|
||||||
@@ -1302,6 +1309,9 @@ describe('ProcessListCloudComponent: Creating an empty custom template - EmptyTe
|
|||||||
imports: [NoopTranslateModule, CustomEmptyContentTemplateDirective, ProcessListCloudComponent, EmptyTemplateComponent],
|
imports: [NoopTranslateModule, CustomEmptyContentTemplateDirective, ProcessListCloudComponent, EmptyTemplateComponent],
|
||||||
providers: [{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useValue: preferencesService }]
|
providers: [{ provide: PROCESS_LISTS_PREFERENCES_SERVICE_TOKEN, useValue: preferencesService }]
|
||||||
});
|
});
|
||||||
|
processListCloudService = TestBed.inject(ProcessListCloudService);
|
||||||
|
spyOn(processListCloudService, 'getProcessByRequest').and.returnValue(of(fakeProcessCloudList));
|
||||||
|
spyOn(processListCloudService, 'fetchProcessList').and.returnValue(of(fakeProcessCloudList));
|
||||||
fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent);
|
fixtureEmpty = TestBed.createComponent(EmptyTemplateComponent);
|
||||||
fixtureEmpty.detectChanges();
|
fixtureEmpty.detectChanges();
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -396,7 +396,7 @@ export class ProcessListCloudComponent
|
|||||||
} else {
|
} else {
|
||||||
const requestNode = this.createRequestNode();
|
const requestNode = this.createRequestNode();
|
||||||
this.requestNode = requestNode;
|
this.requestNode = requestNode;
|
||||||
return this.processListCloudService.getProcessByRequest(requestNode).pipe();
|
return this.processListCloudService.getProcessByRequest(requestNode);
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
takeUntilDestroyed()
|
takeUntilDestroyed()
|
||||||
|
|||||||
+2
-2
@@ -121,9 +121,9 @@ describe('TaskAssignmentFilterComponent', () => {
|
|||||||
it('should have floating labels when values are present', async () => {
|
it('should have floating labels when values are present', async () => {
|
||||||
const inputLabelsNodes = await loader.getAllHarnesses(MatFormFieldHarness);
|
const inputLabelsNodes = await loader.getAllHarnesses(MatFormFieldHarness);
|
||||||
|
|
||||||
inputLabelsNodes.forEach(async (labelNode) => {
|
for (const labelNode of inputLabelsNodes) {
|
||||||
expect(await labelNode.isLabelFloating()).toBeTruthy();
|
expect(await labelNode.isLabelFloating()).toBeTruthy();
|
||||||
});
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
+5
-3
@@ -238,9 +238,10 @@ describe('TaskListCloudComponent', () => {
|
|||||||
component.reload();
|
component.reload();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should call endpoint when a column visibility gets changed', () => {
|
it('should update preferences when a column visibility gets changed', () => {
|
||||||
|
getTaskByRequestSpy.and.returnValue(of(fakeGlobalTasks));
|
||||||
component.ngAfterContentInit();
|
component.ngAfterContentInit();
|
||||||
spyOn(component, 'createDatatableSchema');
|
const createDatatableSchemaSpy = spyOn(component, 'createDatatableSchema');
|
||||||
component.appName = 'fake-app-name';
|
component.appName = 'fake-app-name';
|
||||||
component.reload();
|
component.reload();
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
@@ -249,7 +250,8 @@ describe('TaskListCloudComponent', () => {
|
|||||||
|
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(getTaskByRequestSpy).toHaveBeenCalledTimes(1);
|
expect(preferencesService.updatePreference).toHaveBeenCalled();
|
||||||
|
expect(createDatatableSchemaSpy).toHaveBeenCalled();
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('component changes', () => {
|
describe('component changes', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user