IE11 fixes.
This commit is contained in:
parent
66d08103e1
commit
c979a93099
14
ui-ngx/package-lock.json
generated
14
ui-ngx/package-lock.json
generated
@ -11724,17 +11724,17 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"schema-inspector": {
|
"schema-inspector": {
|
||||||
"version": "1.6.9",
|
"version": "1.6.8",
|
||||||
"resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-1.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/schema-inspector/-/schema-inspector-1.6.8.tgz",
|
||||||
"integrity": "sha512-MNS3SOn6noecIv9R+gwroIgiOLQoRY1IRXToFvVBo2QMfnXy1E+SGRVWJFsJPqgy0lAivUfPLaVLhvAI35HKRg==",
|
"integrity": "sha1-ueU5g8xV/y29e2Xj2+CF2dEoXyo=",
|
||||||
"requires": {
|
"requires": {
|
||||||
"async": "^3.1.0"
|
"async": "^1.5.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"async": {
|
"async": {
|
||||||
"version": "3.1.1",
|
"version": "1.5.2",
|
||||||
"resolved": "https://registry.npmjs.org/async/-/async-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz",
|
||||||
"integrity": "sha512-X5Dj8hK1pJNC2Wzo2Rcp9FBVdJMGRR/S7V+lH46s8GVFhtbo5O4Le5GECCF/8PISVdkUA6mMPvgz7qTTD1rf1g=="
|
"integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@ -74,7 +74,7 @@
|
|||||||
"react-dropzone": "^10.2.1",
|
"react-dropzone": "^10.2.1",
|
||||||
"reactcss": "^1.2.3",
|
"reactcss": "^1.2.3",
|
||||||
"rxjs": "^6.5.4",
|
"rxjs": "^6.5.4",
|
||||||
"schema-inspector": "^1.6.9",
|
"schema-inspector": "1.6.8",
|
||||||
"screenfull": "^5.0.1",
|
"screenfull": "^5.0.1",
|
||||||
"split.js": "^1.5.11",
|
"split.js": "^1.5.11",
|
||||||
"systemjs": "0.21.5",
|
"systemjs": "0.21.5",
|
||||||
|
|||||||
@ -109,7 +109,7 @@ export function isString(value: any): boolean {
|
|||||||
|
|
||||||
export function formatValue(value: any, dec?: number, units?: string, showZeroDecimals?: boolean): string | undefined {
|
export function formatValue(value: any, dec?: number, units?: string, showZeroDecimals?: boolean): string | undefined {
|
||||||
if (isDefined(value) &&
|
if (isDefined(value) &&
|
||||||
value != null && isNumeric(value)) {
|
value !== null && isNumeric(value)) {
|
||||||
let formatted: string | number = Number(value);
|
let formatted: string | number = Number(value);
|
||||||
if (isDefined(dec)) {
|
if (isDefined(dec)) {
|
||||||
formatted = formatted.toFixed(dec);
|
formatted = formatted.toFixed(dec);
|
||||||
@ -123,10 +123,14 @@ export function formatValue(value: any, dec?: number, units?: string, showZeroDe
|
|||||||
}
|
}
|
||||||
return formatted;
|
return formatted;
|
||||||
} else {
|
} else {
|
||||||
return value;
|
return value !== null ? value : '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function objectValues(obj: any): any[] {
|
||||||
|
return Object.keys(obj).map(e => obj[e]);
|
||||||
|
}
|
||||||
|
|
||||||
export function deleteNullProperties(obj: any) {
|
export function deleteNullProperties(obj: any) {
|
||||||
if (isUndefined(obj) || obj == null) {
|
if (isUndefined(obj) || obj == null) {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@ -15,7 +15,7 @@
|
|||||||
limitations under the License.
|
limitations under the License.
|
||||||
|
|
||||||
-->
|
-->
|
||||||
<form [formGroup]="alarmFormGroup" style="width: 600px;">
|
<form [formGroup]="alarmFormGroup" style="min-width: 600px;">
|
||||||
<mat-toolbar fxLayout="row" color="primary">
|
<mat-toolbar fxLayout="row" color="primary">
|
||||||
<h2>{{ 'alarm.alarm-details' | translate }}</h2>
|
<h2>{{ 'alarm.alarm-details' | translate }}</h2>
|
||||||
<span fxFlex></span>
|
<span fxFlex></span>
|
||||||
|
|||||||
@ -221,7 +221,7 @@
|
|||||||
'tb-current-entity': dataSource.isCurrentEntity(entity)}"
|
'tb-current-entity': dataSource.isCurrentEntity(entity)}"
|
||||||
*matRowDef="let entity; columns: displayedColumns;" (click)="onRowClick($event, entity)"></mat-row>
|
*matRowDef="let entity; columns: displayedColumns;" (click)="onRowClick($event, entity)"></mat-row>
|
||||||
</mat-table>
|
</mat-table>
|
||||||
<span [fxShow]="dataSource.isEmpty() | async"
|
<span [fxShow]="!(isLoading$ | async) && (dataSource.isEmpty() | async)"
|
||||||
fxLayoutAlign="center center"
|
fxLayoutAlign="center center"
|
||||||
class="no-data-found" translate>{{ translations.noEntities }}</span>
|
class="no-data-found" translate>{{ translations.noEntities }}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -419,7 +419,7 @@ export class EntitiesTableComponent extends PageComponent implements AfterViewIn
|
|||||||
}
|
}
|
||||||
return res;
|
return res;
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -18,11 +18,9 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
.tb-table-widget {
|
.tb-table-widget {
|
||||||
mat-footer-row, mat-row {
|
mat-footer-row, mat-row {
|
||||||
min-height: 38px;
|
|
||||||
height: 38px;
|
height: 38px;
|
||||||
}
|
}
|
||||||
mat-header-row {
|
mat-header-row {
|
||||||
min-height: 40px;
|
|
||||||
height: 40px;
|
height: 40px;
|
||||||
}
|
}
|
||||||
mat-toolbar {
|
mat-toolbar {
|
||||||
|
|||||||
@ -426,7 +426,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
|
|
||||||
this.initialize().subscribe(
|
this.initialize().subscribe(
|
||||||
() => {
|
() => {
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
this.onInit();
|
this.onInit();
|
||||||
},
|
},
|
||||||
(err) => {
|
(err) => {
|
||||||
@ -435,6 +435,12 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private detectChanges() {
|
||||||
|
if (!this.destroyed) {
|
||||||
|
this.cd.detectChanges();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private isReady(): boolean {
|
private isReady(): boolean {
|
||||||
return this.subscriptionInited && this.widgetSizeDetected;
|
return this.subscriptionInited && this.widgetSizeDetected;
|
||||||
}
|
}
|
||||||
@ -546,7 +552,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
this.widgetContext.reset();
|
this.widgetContext.reset();
|
||||||
this.subscriptionInited = true;
|
this.subscriptionInited = true;
|
||||||
this.configureDynamicWidgetComponent();
|
this.configureDynamicWidgetComponent();
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
this.onInit();
|
this.onInit();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -564,7 +570,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
this.widgetContext.reset();
|
this.widgetContext.reset();
|
||||||
this.subscriptionInited = true;
|
this.subscriptionInited = true;
|
||||||
this.configureDynamicWidgetComponent();
|
this.configureDynamicWidgetComponent();
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
this.onInit();
|
this.onInit();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -760,22 +766,18 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
dataLoading: (subscription) => {
|
dataLoading: (subscription) => {
|
||||||
if (this.loadingData !== subscription.loadingData) {
|
if (this.loadingData !== subscription.loadingData) {
|
||||||
this.loadingData = subscription.loadingData;
|
this.loadingData = subscription.loadingData;
|
||||||
if (!this.destroyed) {
|
this.detectChanges();
|
||||||
this.cd.detectChanges();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
legendDataUpdated: (subscription, detectChanges) => {
|
legendDataUpdated: (subscription, detectChanges) => {
|
||||||
if (detectChanges && !this.destroyed) {
|
if (detectChanges) {
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
timeWindowUpdated: (subscription, timeWindowConfig) => {
|
timeWindowUpdated: (subscription, timeWindowConfig) => {
|
||||||
this.ngZone.run(() => {
|
this.ngZone.run(() => {
|
||||||
this.widget.config.timewindow = timeWindowConfig;
|
this.widget.config.timewindow = timeWindowConfig;
|
||||||
if (!this.destroyed) {
|
this.detectChanges();
|
||||||
this.cd.detectChanges();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -836,7 +838,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
if (this.dynamicWidgetComponent) {
|
if (this.dynamicWidgetComponent) {
|
||||||
this.dynamicWidgetComponent.rpcEnabled = subscription.rpcEnabled;
|
this.dynamicWidgetComponent.rpcEnabled = subscription.rpcEnabled;
|
||||||
this.dynamicWidgetComponent.executingRpcRequest = subscription.executingRpcRequest;
|
this.dynamicWidgetComponent.executingRpcRequest = subscription.executingRpcRequest;
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRpcSuccess: (subscription) => {
|
onRpcSuccess: (subscription) => {
|
||||||
@ -844,7 +846,7 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
this.dynamicWidgetComponent.executingRpcRequest = subscription.executingRpcRequest;
|
this.dynamicWidgetComponent.executingRpcRequest = subscription.executingRpcRequest;
|
||||||
this.dynamicWidgetComponent.rpcErrorText = subscription.rpcErrorText;
|
this.dynamicWidgetComponent.rpcErrorText = subscription.rpcErrorText;
|
||||||
this.dynamicWidgetComponent.rpcRejection = subscription.rpcRejection;
|
this.dynamicWidgetComponent.rpcRejection = subscription.rpcRejection;
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRpcFailed: (subscription) => {
|
onRpcFailed: (subscription) => {
|
||||||
@ -852,14 +854,14 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
this.dynamicWidgetComponent.executingRpcRequest = subscription.executingRpcRequest;
|
this.dynamicWidgetComponent.executingRpcRequest = subscription.executingRpcRequest;
|
||||||
this.dynamicWidgetComponent.rpcErrorText = subscription.rpcErrorText;
|
this.dynamicWidgetComponent.rpcErrorText = subscription.rpcErrorText;
|
||||||
this.dynamicWidgetComponent.rpcRejection = subscription.rpcRejection;
|
this.dynamicWidgetComponent.rpcRejection = subscription.rpcRejection;
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onRpcErrorCleared: (subscription) => {
|
onRpcErrorCleared: (subscription) => {
|
||||||
if (this.dynamicWidgetComponent) {
|
if (this.dynamicWidgetComponent) {
|
||||||
this.dynamicWidgetComponent.rpcErrorText = null;
|
this.dynamicWidgetComponent.rpcErrorText = null;
|
||||||
this.dynamicWidgetComponent.rpcRejection = null;
|
this.dynamicWidgetComponent.rpcRejection = null;
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -873,16 +875,16 @@ export class WidgetComponent extends PageComponent implements OnInit, AfterViewI
|
|||||||
createSubscriptionSubject.error(err);
|
createSubscriptionSubject.error(err);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
} else if (this.widget.type === widgetType.static) {
|
} else if (this.widget.type === widgetType.static) {
|
||||||
this.loadingData = false;
|
this.loadingData = false;
|
||||||
createSubscriptionSubject.next();
|
createSubscriptionSubject.next();
|
||||||
createSubscriptionSubject.complete();
|
createSubscriptionSubject.complete();
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
} else {
|
} else {
|
||||||
createSubscriptionSubject.next();
|
createSubscriptionSubject.next();
|
||||||
createSubscriptionSubject.complete();
|
createSubscriptionSubject.complete();
|
||||||
this.cd.detectChanges();
|
this.detectChanges();
|
||||||
}
|
}
|
||||||
return createSubscriptionSubject.asObservable();
|
return createSubscriptionSubject.asObservable();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,7 @@ import { BehaviorSubject, Observable, of, ReplaySubject } from 'rxjs';
|
|||||||
import { emptyPageData, PageData } from '@shared/models/page/page-data';
|
import { emptyPageData, PageData } from '@shared/models/page/page-data';
|
||||||
import { BaseData, HasId } from '@shared/models/base-data';
|
import { BaseData, HasId } from '@shared/models/base-data';
|
||||||
import { CollectionViewer, DataSource } from '@angular/cdk/typings/collections';
|
import { CollectionViewer, DataSource } from '@angular/cdk/typings/collections';
|
||||||
import { catchError, map, take, tap } from 'rxjs/operators';
|
import { catchError, map, share, take, tap } from 'rxjs/operators';
|
||||||
import { SelectionModel } from '@angular/cdk/collections';
|
import { SelectionModel } from '@angular/cdk/collections';
|
||||||
import {EntityBooleanFunction} from '@home/models/entity/entities-table-config.models';
|
import {EntityBooleanFunction} from '@home/models/entity/entities-table-config.models';
|
||||||
|
|
||||||
@ -78,19 +78,22 @@ export class EntitiesDataSource<T extends BaseData<HasId>, P extends PageLink =
|
|||||||
isAllSelected(): Observable<boolean> {
|
isAllSelected(): Observable<boolean> {
|
||||||
const numSelected = this.selection.selected.length;
|
const numSelected = this.selection.selected.length;
|
||||||
return this.entitiesSubject.pipe(
|
return this.entitiesSubject.pipe(
|
||||||
map((entities) => numSelected === this.selectableEntitiesCount(entities))
|
map((entities) => numSelected === this.selectableEntitiesCount(entities)),
|
||||||
|
share()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
isEmpty(): Observable<boolean> {
|
isEmpty(): Observable<boolean> {
|
||||||
return this.entitiesSubject.pipe(
|
return this.entitiesSubject.pipe(
|
||||||
map((entities) => !entities.length)
|
map((entities) => !entities.length),
|
||||||
|
share()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
total(): Observable<number> {
|
total(): Observable<number> {
|
||||||
return this.pageDataSubject.pipe(
|
return this.pageDataSubject.pipe(
|
||||||
map((pageData) => pageData.totalElements)
|
map((pageData) => pageData.totalElements),
|
||||||
|
share()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -84,7 +84,7 @@ export class EntityTableColumn<T extends BaseData<HasId>> extends BaseEntityTabl
|
|||||||
constructor(public key: string,
|
constructor(public key: string,
|
||||||
public title: string,
|
public title: string,
|
||||||
public width: string = '0px',
|
public width: string = '0px',
|
||||||
public cellContentFunction: CellContentFunction<T> = (entity, property) => entity[property],
|
public cellContentFunction: CellContentFunction<T> = (entity, property) => entity[property] ? entity[property] : '',
|
||||||
public cellStyleFunction: CellStyleFunction<T> = () => ({}),
|
public cellStyleFunction: CellStyleFunction<T> = () => ({}),
|
||||||
public sortable: boolean = true,
|
public sortable: boolean = true,
|
||||||
public headerCellStyleFunction: HeaderCellStyleFunction<T> = () => ({}),
|
public headerCellStyleFunction: HeaderCellStyleFunction<T> = () => ({}),
|
||||||
|
|||||||
@ -18,7 +18,6 @@
|
|||||||
<div class="mat-padding" fxLayout="column">
|
<div class="mat-padding" fxLayout="column">
|
||||||
<form #ruleNodeLinkForm="ngForm" [formGroup]="ruleNodeLinkFormGroup">
|
<form #ruleNodeLinkForm="ngForm" [formGroup]="ruleNodeLinkFormGroup">
|
||||||
<tb-link-labels
|
<tb-link-labels
|
||||||
fxFlex
|
|
||||||
required
|
required
|
||||||
formControlName="labels"
|
formControlName="labels"
|
||||||
[allowedLabels]="allowedLabels"
|
[allowedLabels]="allowedLabels"
|
||||||
|
|||||||
@ -23,6 +23,7 @@ import { AppState } from '@app/core/core.state';
|
|||||||
import { TranslateService } from '@ngx-translate/core';
|
import { TranslateService } from '@ngx-translate/core';
|
||||||
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
import { coerceBooleanProperty } from '@angular/cdk/coercion';
|
||||||
import { MessageType, messageTypeNames } from '@shared/models/rule-node.models';
|
import { MessageType, messageTypeNames } from '@shared/models/rule-node.models';
|
||||||
|
import { objectValues } from '@core/utils';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'tb-message-type-autocomplete',
|
selector: 'tb-message-type-autocomplete',
|
||||||
@ -109,7 +110,7 @@ export class MessageTypeAutocompleteComponent implements ControlValueAccessor, O
|
|||||||
this.modelValue = value;
|
this.modelValue = value;
|
||||||
let res: MessageType | string = null;
|
let res: MessageType | string = null;
|
||||||
if (value) {
|
if (value) {
|
||||||
if (Object.values(MessageType).includes(value)) {
|
if (objectValues(MessageType).includes(value)) {
|
||||||
res = MessageType[value];
|
res = MessageType[value];
|
||||||
} else {
|
} else {
|
||||||
res = value;
|
res = value;
|
||||||
@ -129,7 +130,7 @@ export class MessageTypeAutocompleteComponent implements ControlValueAccessor, O
|
|||||||
updateView(value: MessageType | string | null) {
|
updateView(value: MessageType | string | null) {
|
||||||
let res: string = null;
|
let res: string = null;
|
||||||
if (value) {
|
if (value) {
|
||||||
if (Object.values(MessageType).includes(value)) {
|
if (objectValues(MessageType).includes(value)) {
|
||||||
res = MessageType[value];
|
res = MessageType[value];
|
||||||
} else {
|
} else {
|
||||||
res = value;
|
res = value;
|
||||||
@ -143,7 +144,7 @@ export class MessageTypeAutocompleteComponent implements ControlValueAccessor, O
|
|||||||
|
|
||||||
displayMessageTypeFn(messageType?: MessageType | string): string | undefined {
|
displayMessageTypeFn(messageType?: MessageType | string): string | undefined {
|
||||||
if (messageType) {
|
if (messageType) {
|
||||||
if (Object.values(MessageType).includes(messageType)) {
|
if (objectValues(MessageType).includes(messageType)) {
|
||||||
return messageTypeNames.get(MessageType[messageType]);
|
return messageTypeNames.get(MessageType[messageType]);
|
||||||
} else {
|
} else {
|
||||||
return messageType;
|
return messageType;
|
||||||
|
|||||||
@ -120,7 +120,7 @@ export function getDashboardAssignedCustomersText(dashboard: DashboardInfo): str
|
|||||||
.map(customerInfo => customerInfo.title)
|
.map(customerInfo => customerInfo.title)
|
||||||
.join(', ');
|
.join(', ');
|
||||||
} else {
|
} else {
|
||||||
return null;
|
return '';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -521,15 +521,17 @@ mat-label {
|
|||||||
}
|
}
|
||||||
|
|
||||||
mat-header-row {
|
mat-header-row {
|
||||||
min-height: 60px;
|
|
||||||
height: 60px;
|
height: 60px;
|
||||||
}
|
}
|
||||||
|
|
||||||
mat-footer-row, mat-row {
|
mat-footer-row, mat-row {
|
||||||
min-height: 52px;
|
|
||||||
height: 52px;
|
height: 52px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mat-header-row, mat-footer-row, mat-row {
|
||||||
|
min-height: auto;
|
||||||
|
}
|
||||||
|
|
||||||
.mat-row,
|
.mat-row,
|
||||||
.mat-header-row {
|
.mat-header-row {
|
||||||
display: table-row;
|
display: table-row;
|
||||||
@ -537,17 +539,23 @@ mat-label {
|
|||||||
|
|
||||||
|
|
||||||
.mat-header-row.mat-table-sticky {
|
.mat-header-row.mat-table-sticky {
|
||||||
|
background-clip: padding-box;
|
||||||
.mat-header-cell {
|
.mat-header-cell {
|
||||||
position: sticky;
|
position: sticky;
|
||||||
top: 0;
|
top: 0;
|
||||||
z-index: 10;
|
z-index: 10;
|
||||||
background: inherit;
|
background: inherit;
|
||||||
|
background-clip: padding-box;
|
||||||
&.mat-table-sticky {
|
&.mat-table-sticky {
|
||||||
z-index: 11 !important;
|
z-index: 11 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.mat-cell.mat-table-sticky {
|
||||||
|
background-clip: padding-box;
|
||||||
|
}
|
||||||
|
|
||||||
.mat-row {
|
.mat-row {
|
||||||
transition: background-color .2s;
|
transition: background-color .2s;
|
||||||
&:hover:not(.tb-current-entity) {
|
&:hover:not(.tb-current-entity) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user