mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-07-24 17:32:15 +00:00
[ACS-6565] ADW - Document List View Header - UX Bugs (Additional fixes) (#9404)
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
(change)="changeHandler($event, option)"
|
(change)="changeHandler($event, option)"
|
||||||
class="adf-facet-filter">
|
class="adf-facet-filter">
|
||||||
<div matTooltip="{{ option.name | translate }}"
|
<div matTooltip="{{ option.name | translate }}"
|
||||||
matTooltipPosition="right"
|
matTooltipPosition="before"
|
||||||
class="adf-search-check-list-label">
|
class="adf-search-check-list-label">
|
||||||
{{ option.name | translate }}
|
{{ option.name | translate }}
|
||||||
</div>
|
</div>
|
||||||
|
@@ -27,17 +27,19 @@
|
|||||||
<mat-checkbox [indeterminate]="isSelectAllIndeterminate" [checked]="isSelectAllChecked" (change)="onSelectAllClick($event)" class="adf-checkbox-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate }}</mat-checkbox>
|
<mat-checkbox [indeterminate]="isSelectAllIndeterminate" [checked]="isSelectAllChecked" (change)="onSelectAllClick($event)" class="adf-checkbox-sr-only">{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_ALL' | translate }}</mat-checkbox>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-header"
|
<div
|
||||||
|
class="adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-header adf-datatable-cell-data"
|
||||||
*ngFor="
|
*ngFor="
|
||||||
let col of (data.getColumns() | filterOutEvery:'isHidden':true);
|
let col of (data.getColumns() | filterOutEvery:'isHidden':true);
|
||||||
let columnIndex = index"
|
let columnIndex = index
|
||||||
|
let lastColumn = last"
|
||||||
[attr.data-automation-id]="'auto_id_' + col.key"
|
[attr.data-automation-id]="'auto_id_' + col.key"
|
||||||
[ngClass]="{
|
[ngClass]="{
|
||||||
'adf-sortable': col.sortable,
|
'adf-sortable': col.sortable,
|
||||||
'adf-datatable__cursor--pointer': !isResizing,
|
'adf-datatable__cursor--pointer': !isResizing,
|
||||||
'adf-datatable__header--sorted-asc': isColumnSorted(col, 'asc'),
|
'adf-datatable__header--sorted-asc': isColumnSorted(col, 'asc'),
|
||||||
'adf-datatable__header--sorted-desc': isColumnSorted(col, 'desc')}"
|
'adf-datatable__header--sorted-desc': isColumnSorted(col, 'desc')}"
|
||||||
[ngStyle]="(col.width) && {'flex': getFlexValue(col)}"
|
[ngStyle]="(col.width) && !lastColumn && {'flex-basis': getFlexBasisValue(col)}"
|
||||||
[attr.aria-label]="col.title | translate"
|
[attr.aria-label]="col.title | translate"
|
||||||
(click)="onColumnHeaderClick(col, $event)"
|
(click)="onColumnHeaderClick(col, $event)"
|
||||||
(keyup.enter)="onColumnHeaderClick(col, $event)"
|
(keyup.enter)="onColumnHeaderClick(col, $event)"
|
||||||
@@ -45,7 +47,6 @@
|
|||||||
[attr.tabindex]="isHeaderVisible() ? 0 : null"
|
[attr.tabindex]="isHeaderVisible() ? 0 : null"
|
||||||
[attr.aria-sort]="col.sortable ? (getAriaSort(col) | translate) : null"
|
[attr.aria-sort]="col.sortable ? (getAriaSort(col) | translate) : null"
|
||||||
cdkDrag
|
cdkDrag
|
||||||
cdkDragBoundary="adf-datatable-row"
|
|
||||||
cdkDragLockAxis="x"
|
cdkDragLockAxis="x"
|
||||||
(cdkDragStarted)="isDraggingHeaderColumn = true"
|
(cdkDragStarted)="isDraggingHeaderColumn = true"
|
||||||
(cdkDragDropped)="onDropHeaderColumn($event)"
|
(cdkDragDropped)="onDropHeaderColumn($event)"
|
||||||
@@ -90,13 +91,19 @@
|
|||||||
<ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
<ng-template *ngIf="allowFiltering" [ngTemplateOutlet]="headerFilterTemplate" [ngTemplateOutletContext]="{$implicit: col}"></ng-template>
|
||||||
|
|
||||||
<span
|
<span
|
||||||
*ngIf="hoveredHeaderColumnIndex === columnIndex && col.draggable && !isResizing"
|
*ngIf="col.draggable"
|
||||||
class="adf-datatable-cell-header-drag-icon-placeholder"
|
cdkDragHandle
|
||||||
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-placeholder-'+col.key"
|
[ngClass]="{ 'adf-datatable-cell-header-drag-icon': !isResizing }"
|
||||||
></span>
|
>
|
||||||
|
<adf-icon
|
||||||
|
*ngIf="hoveredHeaderColumnIndex === columnIndex && !isResizing"
|
||||||
|
value="adf:drag_indicator"
|
||||||
|
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-'+col.key">
|
||||||
|
</adf-icon>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
*ngIf="isResizingEnabled && col.resizable"
|
*ngIf="isResizingEnabled && col.resizable && !lastColumn"
|
||||||
[ngClass]="hoveredHeaderColumnIndex === columnIndex && !isResizing || resizingColumnIndex === columnIndex ? 'adf-datatable__resize-handle-visible' : 'adf-datatable__resize-handle-hidden'"
|
[ngClass]="hoveredHeaderColumnIndex === columnIndex && !isResizing || resizingColumnIndex === columnIndex ? 'adf-datatable__resize-handle-visible' : 'adf-datatable__resize-handle-hidden'"
|
||||||
adf-resize-handle
|
adf-resize-handle
|
||||||
(click)="$event.stopPropagation()"
|
(click)="$event.stopPropagation()"
|
||||||
@@ -104,18 +111,6 @@
|
|||||||
[resizableContainer]="resizableElement">
|
[resizableContainer]="resizableElement">
|
||||||
<div class="adf-datatable__resize-handle--divider"></div>
|
<div class="adf-datatable__resize-handle--divider"></div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
*ngIf="col.draggable"
|
|
||||||
cdkDragHandle
|
|
||||||
[ngClass]="{ 'adf-datatable-cell-header-drag-icon': !isResizing }"
|
|
||||||
>
|
|
||||||
<adf-icon
|
|
||||||
*ngIf="hoveredHeaderColumnIndex === columnIndex && !isResizing"
|
|
||||||
value="adf:drag_indicator"
|
|
||||||
[attr.data-automation-id]="'adf-datatable-cell-header-drag-icon-'+col.key">
|
|
||||||
</adf-icon>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div>
|
<div class="adf-drop-header-cell-placeholder" *cdkDragPlaceholder></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -207,9 +202,11 @@
|
|||||||
{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate }}
|
{{ 'ADF-DATATABLE.ACCESSIBILITY.SELECT_FILE' | translate }}
|
||||||
</mat-checkbox>
|
</mat-checkbox>
|
||||||
</label>
|
</label>
|
||||||
<div *ngFor="let col of (data.getColumns() | filterOutEvery:'isHidden':true);"
|
<div *ngFor="
|
||||||
|
let col of (data.getColumns() | filterOutEvery:'isHidden':true),
|
||||||
|
let lastColumn = last;"
|
||||||
role="gridcell"
|
role="gridcell"
|
||||||
class="adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}}"
|
class="adf-datatable-cell adf-datatable-cell--{{col.type || 'text'}} {{col.cssClass}} adf-datatable-cell-data"
|
||||||
[attr.title]="col.title | translate"
|
[attr.title]="col.title | translate"
|
||||||
[attr.data-automation-id]="getAutomationValue(row)"
|
[attr.data-automation-id]="getAutomationValue(row)"
|
||||||
[attr.aria-selected]="row.isSelected"
|
[attr.aria-selected]="row.isSelected"
|
||||||
@@ -219,7 +216,7 @@
|
|||||||
[adf-context-menu]="getContextMenuActions(row, col)"
|
[adf-context-menu]="getContextMenuActions(row, col)"
|
||||||
[adf-context-menu-enabled]="contextMenu"
|
[adf-context-menu-enabled]="contextMenu"
|
||||||
adf-drop-zone dropTarget="cell" [dropColumn]="col" [dropRow]="row"
|
adf-drop-zone dropTarget="cell" [dropColumn]="col" [dropRow]="row"
|
||||||
[ngStyle]="(col.width) && {'flex': getFlexValue(col)}">
|
[ngStyle]="(col.width) && !lastColumn && {'flex-basis': getFlexBasisValue(col)}">
|
||||||
<div *ngIf="!col.template" class="adf-datatable-cell-container">
|
<div *ngIf="!col.template" class="adf-datatable-cell-container">
|
||||||
<ng-container [ngSwitch]="data.getColumnType(row, col)">
|
<ng-container [ngSwitch]="data.getColumnType(row, col)">
|
||||||
<div *ngSwitchCase="'image'" class="adf-cell-value">
|
<div *ngSwitchCase="'image'" class="adf-cell-value">
|
||||||
|
@@ -390,6 +390,17 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
|||||||
min-width: $data-table-cell-min-width-2;
|
min-width: $data-table-cell-min-width-2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.adf-datatable-header, .adf-datatable-body {
|
||||||
|
.adf-datatable-cell-data {
|
||||||
|
flex-grow: 0;
|
||||||
|
flex-shrink: 1;
|
||||||
|
|
||||||
|
&:not(:has(~ .adf-datatable-cell-data)) {
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* stylelint-disable-next-line no-duplicate-selectors */
|
/* stylelint-disable-next-line no-duplicate-selectors */
|
||||||
.adf-datatable-cell,
|
.adf-datatable-cell,
|
||||||
.adf-datatable-cell-header {
|
.adf-datatable-cell-header {
|
||||||
@@ -404,11 +415,6 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
|||||||
box-sizing: content-box;
|
box-sizing: content-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
padding-right: 15px;
|
|
||||||
box-sizing: content-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.adf-datatable-cell-container {
|
.adf-datatable-cell-container {
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
min-height: inherit;
|
min-height: inherit;
|
||||||
@@ -436,6 +442,7 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
|||||||
.adf-datatable-actions-menu {
|
.adf-datatable-actions-menu {
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
justify-content: end;
|
justify-content: end;
|
||||||
|
padding-right: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-cell-value {
|
.adf-cell-value {
|
||||||
@@ -626,7 +633,7 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
|||||||
.adf-datatable__header--sorted-asc,
|
.adf-datatable__header--sorted-asc,
|
||||||
.adf-datatable__header--sorted-desc {
|
.adf-datatable__header--sorted-desc {
|
||||||
color: var(--adf-theme-foreground-text-color);
|
color: var(--adf-theme-foreground-text-color);
|
||||||
padding-right: 0.5rem;
|
padding-right: 0.25rem;
|
||||||
|
|
||||||
&::after {
|
&::after {
|
||||||
@include typo-icon;
|
@include typo-icon;
|
||||||
@@ -661,10 +668,10 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
margin: 0 2px;
|
margin: 0 2px;
|
||||||
padding: 0 8px;
|
padding: 0 8px;
|
||||||
column-gap: 5px;
|
|
||||||
|
|
||||||
.adf-datatable-cell-header-drag-icon-placeholder {
|
.adf-datatable-cell-header-drag-icon-placeholder {
|
||||||
min-width: 15px;
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
&--hovered {
|
&--hovered {
|
||||||
@@ -674,19 +681,15 @@ $data-table-cell-min-width-file-size: $data-table-cell-min-width-1 !default;
|
|||||||
}
|
}
|
||||||
|
|
||||||
.adf-datatable-cell-header-drag-icon {
|
.adf-datatable-cell-header-drag-icon {
|
||||||
position: absolute;
|
margin-left: auto;
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
right: 10px;
|
|
||||||
margin: auto;
|
|
||||||
color: #ccc;
|
|
||||||
cursor: move;
|
cursor: move;
|
||||||
width: 24px;
|
margin-right: -0.5rem;
|
||||||
height: 24px;
|
padding-left: -0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.adf-datatable-cell-value {
|
.adf-datatable-cell-value {
|
||||||
padding: 10px 0 !important;
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
line-height: 24px;
|
line-height: 24px;
|
||||||
word-break: break-word;
|
word-break: break-word;
|
||||||
}
|
}
|
||||||
|
@@ -1524,21 +1524,15 @@ describe('Drag&Drop column header', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
let dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]');
|
let dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]');
|
||||||
let dragIconPlaceholder = fixture.debugElement.nativeElement.querySelector(
|
|
||||||
'[data-automation-id="adf-datatable-cell-header-drag-icon-placeholder-name"]'
|
|
||||||
);
|
|
||||||
expect(dragIcon).toBeTruthy();
|
expect(dragIcon).toBeTruthy();
|
||||||
expect(dragIconPlaceholder).toBeTruthy();
|
|
||||||
|
|
||||||
headerColumn.dispatchEvent(new MouseEvent('mouseleave'));
|
headerColumn.dispatchEvent(new MouseEvent('mouseleave'));
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]');
|
dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-name"]');
|
||||||
dragIconPlaceholder = fixture.debugElement.nativeElement.querySelector(
|
|
||||||
'[data-automation-id="adf-datatable-cell-header-drag-icon-placeholder-name"]'
|
|
||||||
);
|
|
||||||
expect(dragIcon).toBeFalsy();
|
expect(dragIcon).toBeFalsy();
|
||||||
expect(dragIconPlaceholder).toBeFalsy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should not show drag indicator icon, when drag and drop is disabled', () => {
|
it('should not show drag indicator icon, when drag and drop is disabled', () => {
|
||||||
@@ -1549,12 +1543,8 @@ describe('Drag&Drop column header', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-id"]');
|
const dragIcon = fixture.debugElement.nativeElement.querySelector('[data-automation-id="adf-datatable-cell-header-drag-icon-id"]');
|
||||||
const dragIconPlaceholder = fixture.debugElement.nativeElement.querySelector(
|
|
||||||
'[data-automation-id="adf-datatable-cell-header-drag-icon-placeholder-id"]'
|
|
||||||
);
|
|
||||||
|
|
||||||
expect(dragIcon).toBeFalsy();
|
expect(dragIcon).toBeFalsy();
|
||||||
expect(dragIconPlaceholder).toBeFalsy();
|
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should emit on change column order', () => {
|
it('should emit on change column order', () => {
|
||||||
@@ -1748,20 +1738,20 @@ describe('Column Resizing', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display resize handle for each column by default', () => {
|
it('should display resize handle for each column, but not for the last one, by default', () => {
|
||||||
dataTable.isResizingEnabled = true;
|
dataTable.isResizingEnabled = true;
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(getResizeHandlersCount()).toBe(2);
|
expect(getResizeHandlersCount()).toBe(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should NOT display resize handle for the column when the column has resizable param set to false', () => {
|
it('should NOT display resize handle for the column when the column has resizable param set to false and column is not the last one', () => {
|
||||||
dataTable.isResizingEnabled = true;
|
dataTable.isResizingEnabled = true;
|
||||||
dataTableSchema[0].resizable = false;
|
dataTableSchema[0].resizable = false;
|
||||||
dataTable.data = new ObjectDataTableAdapter([...data], [...dataTableSchema]);
|
dataTable.data = new ObjectDataTableAdapter([...data], [...dataTableSchema]);
|
||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
expect(getResizeHandlersCount()).toBe(1);
|
expect(getResizeHandlersCount()).toBe(0);
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should display resize handle when the feature is Enabled [isResizingEnabled=true]', () => {
|
it('should display resize handle when the feature is Enabled [isResizingEnabled=true]', () => {
|
||||||
@@ -1895,7 +1885,7 @@ describe('Column Resizing', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const headerColumns: HTMLElement[] = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header');
|
const headerColumns: HTMLElement[] = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header');
|
||||||
expect(headerColumns[0].style.flex).toBe('0 1 125px');
|
expect(headerColumns[0].style.flexBasis).toBe('125px');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set the column header to 100px on resizing when its width goes below 100', fakeAsync(() => {
|
it('should set the column header to 100px on resizing when its width goes below 100', fakeAsync(() => {
|
||||||
@@ -1904,7 +1894,7 @@ describe('Column Resizing', () => {
|
|||||||
fixture.detectChanges();
|
fixture.detectChanges();
|
||||||
|
|
||||||
const headerColumns: HTMLElement[] = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header');
|
const headerColumns: HTMLElement[] = fixture.debugElement.nativeElement.querySelectorAll('.adf-datatable-cell-header');
|
||||||
expect(headerColumns[0].style.flex).toBe('0 1 100px');
|
expect(headerColumns[0].style.flexBasis).toBe('100px');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set the style of all the table cells under the resizing header on resizing', fakeAsync(() => {
|
it('should set the style of all the table cells under the resizing header on resizing', fakeAsync(() => {
|
||||||
@@ -1916,8 +1906,8 @@ describe('Column Resizing', () => {
|
|||||||
const firstCell: HTMLElement = tableBody.querySelector('[data-automation-id="name1"]');
|
const firstCell: HTMLElement = tableBody.querySelector('[data-automation-id="name1"]');
|
||||||
const secondCell: HTMLElement = tableBody.querySelector('[data-automation-id="name2"]');
|
const secondCell: HTMLElement = tableBody.querySelector('[data-automation-id="name2"]');
|
||||||
|
|
||||||
expect(firstCell.style.flex).toBe('0 1 130px');
|
expect(firstCell.style.flexBasis).toBe('130px');
|
||||||
expect(secondCell.style.flex).toBe('0 1 130px');
|
expect(secondCell.style.flexBasis).toBe('130px');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should set the style of all the table cells under the resizing header to 100px on resizing when its width goes below 100', fakeAsync(() => {
|
it('should set the style of all the table cells under the resizing header to 100px on resizing when its width goes below 100', fakeAsync(() => {
|
||||||
@@ -1929,8 +1919,8 @@ describe('Column Resizing', () => {
|
|||||||
const firstCell: HTMLElement = tableBody.querySelector('[data-automation-id="name1"]');
|
const firstCell: HTMLElement = tableBody.querySelector('[data-automation-id="name1"]');
|
||||||
const secondCell: HTMLElement = tableBody.querySelector('[data-automation-id="name2"]');
|
const secondCell: HTMLElement = tableBody.querySelector('[data-automation-id="name2"]');
|
||||||
|
|
||||||
expect(firstCell.style.flex).toBe('0 1 100px');
|
expect(firstCell.style.flexBasis).toBe('100px');
|
||||||
expect(secondCell.style.flex).toBe('0 1 100px');
|
expect(secondCell.style.flexBasis).toBe('100px');
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it('should unblur the body and set the resizing to false upon resizing ends', () => {
|
it('should unblur the body and set the resizing to false upon resizing ends', () => {
|
||||||
|
@@ -971,8 +971,8 @@ export class DataTableComponent implements OnInit, AfterContentInit, OnChanges,
|
|||||||
this.updateColumnsWidths();
|
this.updateColumnsWidths();
|
||||||
}
|
}
|
||||||
|
|
||||||
getFlexValue({ width = 0 }: DataColumn): string {
|
getFlexBasisValue({ width = 0 }: DataColumn): string {
|
||||||
return `0 1 ${width < DataTableComponent.MINIMUM_COLUMN_SIZE ? DataTableComponent.MINIMUM_COLUMN_SIZE : width}px`;
|
return `${width < DataTableComponent.MINIMUM_COLUMN_SIZE ? DataTableComponent.MINIMUM_COLUMN_SIZE : width}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
filterDisabledColumns(index: number, _drag: CdkDrag, drop: CdkDropList): boolean {
|
filterDisabledColumns(index: number, _drag: CdkDrag, drop: CdkDropList): boolean {
|
||||||
|
Reference in New Issue
Block a user