mirror of
https://github.com/Alfresco/alfresco-ng2-components.git
synced 2025-05-12 17:04:57 +00:00
ACS-3550 Fixed accessibility issues related with move and copy dialogs (#7961)
* ACS-3550 Fixed accessibility issues related with move and copy dialogs * ACS-3550 Revert changes for button role for cells * ACS-3550 Shorter css rule * ACS-3550 Fixed lint issues * ACS-3550 Changed selector to fix e2e tests
This commit is contained in:
parent
1109a73a19
commit
ba05d3a1df
@ -3,6 +3,7 @@
|
|||||||
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate">
|
[attr.aria-label]="'BREADCRUMB.ARIA-LABEL.BREADCRUMB' | translate">
|
||||||
|
|
||||||
<button
|
<button
|
||||||
|
id="dropdown-breadcrumb-button"
|
||||||
[tabindex]="hasPreviousNodes() ? 0 : -1"
|
[tabindex]="hasPreviousNodes() ? 0 : -1"
|
||||||
class="adf-dropdown-breadcrumb-trigger"
|
class="adf-dropdown-breadcrumb-trigger"
|
||||||
(click)="open()"
|
(click)="open()"
|
||||||
@ -18,7 +19,8 @@
|
|||||||
#dropdown
|
#dropdown
|
||||||
*ngIf="hasPreviousNodes()"
|
*ngIf="hasPreviousNodes()"
|
||||||
tabindex="-1"
|
tabindex="-1"
|
||||||
data-automation-id="dropdown-breadcrumb-path">
|
data-automation-id="dropdown-breadcrumb-path"
|
||||||
|
aria-labelledby="dropdown-breadcrumb-button">
|
||||||
|
|
||||||
<mat-option
|
<mat-option
|
||||||
*ngFor="let node of previousNodes;"
|
*ngFor="let node of previousNodes;"
|
||||||
|
@ -47,7 +47,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<ng-template #loading>
|
<ng-template #loading>
|
||||||
<mat-progress-bar mode="indeterminate" [attr.aria-label]="'CORE.METADATA.BASIC.DATA_LOADING' | translate">
|
<mat-progress-bar mode="indeterminate" [attr.aria-label]="'DATA_LOADING' | translate">
|
||||||
</mat-progress-bar>
|
</mat-progress-bar>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
@ -45,7 +45,7 @@
|
|||||||
<adf-toolbar>
|
<adf-toolbar>
|
||||||
<adf-toolbar-title>
|
<adf-toolbar-title>
|
||||||
<ng-container *ngIf="!showBreadcrumbs()">
|
<ng-container *ngIf="!showBreadcrumbs()">
|
||||||
<span role="heading" aria-level="3" class="adf-search-results-label">{{ 'NODE_SELECTOR.SEARCH_RESULTS' | translate }}</span>
|
<h2 class="adf-search-results-label">{{ 'NODE_SELECTOR.SEARCH_RESULTS' | translate }}</h2>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
<adf-dropdown-breadcrumb *ngIf="showBreadcrumbs()"
|
<adf-dropdown-breadcrumb *ngIf="showBreadcrumbs()"
|
||||||
class="adf-content-node-selector-content-breadcrumb"
|
class="adf-content-node-selector-content-breadcrumb"
|
||||||
@ -86,10 +86,11 @@
|
|||||||
(folderChange)="onFolderChange($event)"
|
(folderChange)="onFolderChange($event)"
|
||||||
(ready)="onFolderLoaded($event)"
|
(ready)="onFolderLoaded($event)"
|
||||||
(nodeSelected)="onCurrentSelection($event)"
|
(nodeSelected)="onCurrentSelection($event)"
|
||||||
|
[class.adf-content-node-selector-content-list-empty]="emptyList"
|
||||||
data-automation-id="content-node-selector-document-list">
|
data-automation-id="content-node-selector-document-list">
|
||||||
|
|
||||||
<adf-custom-empty-content-template>
|
<adf-custom-empty-content-template>
|
||||||
<div>{{ 'NODE_SELECTOR.NO_RESULTS' | translate }}</div>
|
<div aria-live="polite">{{ 'NODE_SELECTOR.NO_RESULTS' | translate }}</div>
|
||||||
</adf-custom-empty-content-template>
|
</adf-custom-empty-content-template>
|
||||||
|
|
||||||
<data-columns>
|
<data-columns>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
/* stylelint-disable no-descending-specificity */
|
/* stylelint-disable no-descending-specificity */
|
||||||
$content-node-selector-thumbnail-width: 35px !default;
|
$content-node-selector-thumbnail-width: 35px !default;
|
||||||
|
|
||||||
.adf-search-results-label {
|
h2.adf-search-results-label {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
font-size: var(--theme-body-1-font-size);
|
font-size: var(--theme-body-1-font-size);
|
||||||
@ -95,6 +95,13 @@ $content-node-selector-thumbnail-width: 35px !default;
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
border: 1px solid var(--theme-border-color);
|
border: 1px solid var(--theme-border-color);
|
||||||
border-top: 0;
|
border-top: 0;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
&-empty + adf-infinite-pagination {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
.adf-highlight {
|
.adf-highlight {
|
||||||
color: var(--theme-primary-color);
|
color: var(--theme-primary-color);
|
||||||
|
@ -80,6 +80,7 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
|||||||
private showSiteList = true;
|
private showSiteList = true;
|
||||||
private showSearchField = true;
|
private showSearchField = true;
|
||||||
private showCounter = false;
|
private showCounter = false;
|
||||||
|
private _emptyList = true;
|
||||||
|
|
||||||
/** If true will restrict the search and breadcrumbs to the currentFolderId */
|
/** If true will restrict the search and breadcrumbs to the currentFolderId */
|
||||||
@Input()
|
@Input()
|
||||||
@ -295,6 +296,10 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
|||||||
return this._chosenNode;
|
return this._chosenNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get emptyList(): boolean {
|
||||||
|
return this._emptyList;
|
||||||
|
}
|
||||||
|
|
||||||
getSelectedCount(): number {
|
getSelectedCount(): number {
|
||||||
return this.chosenNode?.length || 0;
|
return this.chosenNode?.length || 0;
|
||||||
}
|
}
|
||||||
@ -567,6 +572,9 @@ export class ContentNodeSelectorPanelComponent implements OnInit, OnDestroy {
|
|||||||
* Attempts to set the currently loaded node
|
* Attempts to set the currently loaded node
|
||||||
*/
|
*/
|
||||||
onFolderLoaded(nodePaging: NodePaging): void {
|
onFolderLoaded(nodePaging: NodePaging): void {
|
||||||
|
setTimeout(() => {
|
||||||
|
this._emptyList = !this.documentList.data.getRows().length;
|
||||||
|
});
|
||||||
this.updatePaginationAfterRowFilter(nodePaging);
|
this.updatePaginationAfterRowFilter(nodePaging);
|
||||||
if (!this.showingSearchResults) {
|
if (!this.showingSearchResults) {
|
||||||
this.attemptNodeSelection(this.documentList.folderNode);
|
this.attemptNodeSelection(this.documentList.folderNode);
|
||||||
|
@ -1,9 +1,4 @@
|
|||||||
<header
|
<h1 mat-dialog-title data-automation-id="content-node-selector-title">{{title}}</h1>
|
||||||
mat-dialog-title
|
|
||||||
data-automation-id="content-node-selector-title">
|
|
||||||
<h2>{{title}}</h2>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<mat-tab-group class="adf-content-node-selector-dialog-content"
|
<mat-tab-group class="adf-content-node-selector-dialog-content"
|
||||||
mat-align-tabs="start"
|
mat-align-tabs="start"
|
||||||
(selectedIndexChange)="onTabSelectionChange($event)"
|
(selectedIndexChange)="onTabSelectionChange($event)"
|
||||||
|
@ -8,9 +8,11 @@
|
|||||||
class="adf-site-dropdown-list-element"
|
class="adf-site-dropdown-list-element"
|
||||||
id="site-dropdown"
|
id="site-dropdown"
|
||||||
placeholder="{{placeholder | translate}}"
|
placeholder="{{placeholder | translate}}"
|
||||||
|
[aria-label]="ariaLabel"
|
||||||
floatPlaceholder="never"
|
floatPlaceholder="never"
|
||||||
[(value)]="selected"
|
[(value)]="selected"
|
||||||
(selectionChange)="selectedSite($event)">
|
(selectionChange)="selectedSite($event)"
|
||||||
|
role="listbox">
|
||||||
<mat-option *ngFor="let site of siteList?.list.entries;" [value]="site">
|
<mat-option *ngFor="let site of siteList?.list.entries;" [value]="site">
|
||||||
{{ site.entry.title | translate}}
|
{{ site.entry.title | translate}}
|
||||||
</mat-option>
|
</mat-option>
|
||||||
|
@ -19,6 +19,8 @@ import { Component, EventEmitter, Input, OnInit, Output, ViewEncapsulation } fro
|
|||||||
import { SitesService, LogService, InfiniteSelectScrollDirective } from '@alfresco/adf-core';
|
import { SitesService, LogService, InfiniteSelectScrollDirective } from '@alfresco/adf-core';
|
||||||
import { SitePaging, SiteEntry } from '@alfresco/js-api';
|
import { SitePaging, SiteEntry } from '@alfresco/js-api';
|
||||||
import { MatSelectChange } from '@angular/material/select';
|
import { MatSelectChange } from '@angular/material/select';
|
||||||
|
import {LiveAnnouncer} from '@angular/cdk/a11y';
|
||||||
|
import {TranslateService} from '@ngx-translate/core';
|
||||||
|
|
||||||
/* eslint-disable no-shadow */
|
/* eslint-disable no-shadow */
|
||||||
/* eslint-disable @typescript-eslint/naming-convention */
|
/* eslint-disable @typescript-eslint/naming-convention */
|
||||||
@ -74,20 +76,28 @@ export class DropdownSitesComponent implements OnInit {
|
|||||||
|
|
||||||
private loading = true;
|
private loading = true;
|
||||||
private skipCount = 0;
|
private skipCount = 0;
|
||||||
|
private _ariaLabel = '';
|
||||||
|
|
||||||
selected: SiteEntry = null;
|
selected: SiteEntry = null;
|
||||||
MY_FILES_VALUE = '-my-';
|
MY_FILES_VALUE = '-my-';
|
||||||
|
|
||||||
constructor(private sitesService: SitesService,
|
constructor(private sitesService: SitesService,
|
||||||
private logService: LogService) {
|
private logService: LogService,
|
||||||
|
private liveAnnouncer: LiveAnnouncer,
|
||||||
|
private translateService: TranslateService) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit() {
|
ngOnInit() {
|
||||||
|
this.updateAriaLabel(this.selected);
|
||||||
if (!this.siteList) {
|
if (!this.siteList) {
|
||||||
this.loadSiteList();
|
this.loadSiteList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get ariaLabel(): string {
|
||||||
|
return this._ariaLabel;
|
||||||
|
}
|
||||||
|
|
||||||
loadAllOnScroll() {
|
loadAllOnScroll() {
|
||||||
if (this.isInfiniteScrollingEnabled()) {
|
if (this.isInfiniteScrollingEnabled()) {
|
||||||
this.loading = true;
|
this.loading = true;
|
||||||
@ -96,6 +106,11 @@ export class DropdownSitesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
selectedSite(event: MatSelectChange) {
|
selectedSite(event: MatSelectChange) {
|
||||||
|
this.updateAriaLabel(event.value);
|
||||||
|
this.liveAnnouncer.announce(this.translateService.instant('ADF_DROPDOWN.SELECTION_ARIA_LABEL', {
|
||||||
|
placeholder: this.translateService.instant(this.placeholder),
|
||||||
|
selectedOption: this.translateService.instant(event.value.entry.title)
|
||||||
|
}));
|
||||||
this.change.emit(event.value);
|
this.change.emit(event.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -140,6 +155,7 @@ export class DropdownSitesComponent implements OnInit {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.selected = this.siteList.list.entries.find((site: SiteEntry) => site.entry.id === this.value);
|
this.selected = this.siteList.list.entries.find((site: SiteEntry) => site.entry.id === this.value);
|
||||||
|
this.updateAriaLabel(this.selected);
|
||||||
|
|
||||||
if (this.value && !this.selected && this.siteListHasMoreItems()) {
|
if (this.value && !this.selected && this.siteListHasMoreItems()) {
|
||||||
this.loadSiteList();
|
this.loadSiteList();
|
||||||
@ -174,4 +190,8 @@ export class DropdownSitesComponent implements OnInit {
|
|||||||
return site.entry.visibility === 'PUBLIC' ||
|
return site.entry.visibility === 'PUBLIC' ||
|
||||||
!!site.relations.members.list.entries.find((member) => member.entry.id.toLowerCase() === loggedUserName.toLowerCase());
|
!!site.relations.members.list.entries.find((member) => member.entry.id.toLowerCase() === loggedUserName.toLowerCase());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private updateAriaLabel(site: SiteEntry): void {
|
||||||
|
this._ariaLabel = `${this.translateService.instant(this.placeholder)} ${site ? this.translateService.instant(site.entry.title) : ''}`;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
"CLAIM": "CLAIM",
|
"CLAIM": "CLAIM",
|
||||||
"UNCLAIM": "RELEASE",
|
"UNCLAIM": "RELEASE",
|
||||||
"START PROCESS": "START PROCESS",
|
"START PROCESS": "START PROCESS",
|
||||||
|
"DATA_LOADING": "Data is loading",
|
||||||
"NOTIFICATIONS": {
|
"NOTIFICATIONS": {
|
||||||
"NO_MESSAGE": "You have no notifications at this time.",
|
"NO_MESSAGE": "You have no notifications at this time.",
|
||||||
"TITLE": "Notifications",
|
"TITLE": "Notifications",
|
||||||
@ -219,8 +220,7 @@
|
|||||||
"CREATED_DATE": "Created Date",
|
"CREATED_DATE": "Created Date",
|
||||||
"MODIFIER": "Modifier",
|
"MODIFIER": "Modifier",
|
||||||
"MODIFIED_DATE": "Modified Date",
|
"MODIFIED_DATE": "Modified Date",
|
||||||
"CONTENT_TYPE": "Content Type",
|
"CONTENT_TYPE": "Content Type"
|
||||||
"DATA_LOADING": "Data is loading"
|
|
||||||
},
|
},
|
||||||
"CONTENT_TYPE": {
|
"CONTENT_TYPE": {
|
||||||
"DIALOG": {
|
"DIALOG": {
|
||||||
@ -581,6 +581,7 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"ADF_DROPDOWN": {
|
"ADF_DROPDOWN": {
|
||||||
"LOADING": "Loading..."
|
"LOADING": "Loading...",
|
||||||
|
"SELECTION_ARIA_LABEL": "{{placeholder}} listbox {{selectedOption}}"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,5 +11,6 @@
|
|||||||
<mat-progress-bar *ngIf="isLoading"
|
<mat-progress-bar *ngIf="isLoading"
|
||||||
mode="indeterminate"
|
mode="indeterminate"
|
||||||
class="adf-infinite-pagination-spinner"
|
class="adf-infinite-pagination-spinner"
|
||||||
data-automation-id="adf-infinite-pagination-spinner"></mat-progress-bar>
|
data-automation-id="adf-infinite-pagination-spinner"
|
||||||
|
[attr.aria-label]="'DATA_LOADING' | translate"></mat-progress-bar>
|
||||||
</div>
|
</div>
|
||||||
|
@ -29,7 +29,7 @@ import { TestElement } from '../../core/public-api';
|
|||||||
|
|
||||||
export class ContentNodeSelectorDialogPage {
|
export class ContentNodeSelectorDialogPage {
|
||||||
dialog = $(`adf-content-node-selector`);
|
dialog = $(`adf-content-node-selector`);
|
||||||
header = this.dialog.$(`header[data-automation-id='content-node-selector-title']`);
|
header = this.dialog.$(`h1[data-automation-id='content-node-selector-title']`);
|
||||||
searchInputElement = this.dialog.$(`input[data-automation-id='content-node-selector-search-input']`);
|
searchInputElement = this.dialog.$(`input[data-automation-id='content-node-selector-search-input']`);
|
||||||
searchLabel = this.dialog.$('.adf-content-node-selector-content-input .mat-form-field-label');
|
searchLabel = this.dialog.$('.adf-content-node-selector-content-input .mat-form-field-label');
|
||||||
selectedRow = this.dialog.$(`adf-datatable-row[class*="adf-is-selected"]`);
|
selectedRow = this.dialog.$(`adf-datatable-row[class*="adf-is-selected"]`);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user