Fixed remaining community/collection page accessibility issues

- Hide fontawesome icons for screen readers
- Replaced dangling labels with spans and added more descriptive aria label to browse link
- Fixed empty label/missing header in edit resource policy table
- Added missing comcol logo al text
- Refactored dso-edit-menu-section to not display empty link buttons and duplicate titles
This commit is contained in:
Alexandre Vryghem
2023-12-16 15:25:44 +01:00
committed by Tim Donohue
parent 8b5cd79bdc
commit 37803e9330
14 changed files with 57 additions and 49 deletions

View File

@@ -13,7 +13,7 @@
<!-- Collection logo -->
<ds-comcol-page-logo *ngIf="logoRD$"
[logo]="(logoRD$ | async)?.payload"
[alternateText]="'Collection Logo'">
[alternateText]="'collection.logo' | translate">
</ds-comcol-page-logo>
<!-- Handle -->

View File

@@ -1,17 +1,17 @@
<div class="container-fluid mb-2" *ngVar="(itemTemplateRD$ | async) as itemTemplateRD">
<label>{{ 'collection.edit.template.label' | translate}}</label>
<span class="d-inline-block mb-2">{{ 'collection.edit.template.label' | translate}}</span>
<div class="button-row space-children-mr">
<button *ngIf="!itemTemplateRD?.payload" class="btn btn-success" (click)="addItemTemplate()">
<i class="fas fa-plus"></i>
<i class="fas fa-plus" aria-hidden="true"></i>
<span class="d-none d-sm-inline">&nbsp;{{"collection.edit.template.add-button" | translate}}</span>
</button>
<button *ngIf="itemTemplateRD?.payload" class="btn btn-danger" (click)="deleteItemTemplate()">
<i class="fas fa-trash-alt"></i>
<i class="fas fa-trash-alt" aria-hidden="true"></i>
<span class="d-none d-sm-inline">&nbsp;{{"collection.edit.template.delete-button" | translate}}</span>
</button>
<button *ngIf="itemTemplateRD?.payload" class="btn btn-primary"
[routerLink]="'/collections/' + (dsoRD$ | async)?.payload.uuid + '/itemtemplate'">
<i class="fas fa-edit"></i>
<i class="fas fa-edit" aria-hidden="true"></i>
<span class="d-none d-sm-inline">&nbsp;{{"collection.edit.template.edit-button" | translate}}</span>
</button>
</div>

View File

@@ -7,7 +7,7 @@
<!-- Community name -->
<ds-comcol-page-header [name]="dsoNameService.getName(communityPayload)"></ds-comcol-page-header>
<!-- Community logo -->
<ds-comcol-page-logo *ngIf="logoRD$" [logo]="(logoRD$ | async)?.payload" [alternateText]="'Community Logo'">
<ds-comcol-page-logo *ngIf="logoRD$" [logo]="(logoRD$ | async)?.payload" [alternateText]="'community.logo' | translate">
</ds-comcol-page-logo>
<!-- Handle -->
<ds-themed-comcol-page-handle [content]="communityPayload.handle" [title]="'community.page.handle'">

View File

@@ -7,11 +7,11 @@
<div class="form-group row">
<div class="col text-right space-children-mr">
<button class="btn btn-outline-secondary" (click)="onCancel(dso)" [disabled]="(processing$ | async)">
<i class="fas fa-times"></i> {{'community.delete.cancel' | translate}}
<i class="fas fa-times" aria-hidden="true"></i> {{'community.delete.cancel' | translate}}
</button>
<button class="btn btn-danger" (click)="onConfirm(dso)" [disabled]="(processing$ | async)">
<span *ngIf="processing$ | async"><i class='fas fa-circle-notch fa-spin'></i> {{'community.delete.processing' | translate}}</span>
<span *ngIf="!(processing$ | async)"><i class="fas fa-trash"></i> {{'community.delete.confirm' | translate}}</span>
<span *ngIf="processing$ | async"><i class='fas fa-circle-notch fa-spin' aria-hidden="true"></i> {{'community.delete.processing' | translate}}</span>
<span *ngIf="!(processing$ | async)"><i class="fas fa-trash" aria-hidden="true"></i> {{'community.delete.confirm' | translate}}</span>
</button>
</div>
</div>

View File

@@ -1,13 +1,13 @@
<div class="container-fluid">
<div class="row">
<div class="col-12 d-inline-block">
<label>{{type.value + '.edit.logo.label' | translate}}</label>
<div class="col-12 d-inline-block mb-1">
<span>{{type.value + '.edit.logo.label' | translate}}</span>
</div>
<ng-container *ngVar="(dso?.logo | async)?.payload as logo">
<div class="col-12 d-inline-block alert" [ngClass]="{'alert-danger': markLogoForDeletion}" id="logo-section" *ngIf="logo">
<div class="row">
<div class="col-8 d-inline-block">
<ds-comcol-page-logo [logo]="logo"></ds-comcol-page-logo>
<ds-comcol-page-logo [alternateText]="type.value + '.logo.alt'" [logo]="logo"></ds-comcol-page-logo>
</div>
<div class="col-4 d-inline-block">
<div *ngIf="logo" class="btn-group btn-group-sm float-right" role="group">
@@ -27,6 +27,7 @@
</div>
<div *ngIf="!logo" class="col-12 d-inline-block">
<ds-uploader *ngIf="initializedUploaderOptions | async"
[ariaLabel]="type.value + '.browse.logo'"
[dropMsg]="type.value + '.edit.logo.upload'"
[dropOverDocumentMsg]="type.value + '.edit.logo.upload'"
[enableDragOverDocument]="true"
@@ -43,6 +44,6 @@
[displayCancel]="false"
(submitForm)="onSubmit()">
<button before (click)="back.emit()" class="btn btn-outline-secondary" type="button">
<i class="fas fa-arrow-left"></i> {{ type.value + '.edit.return' | translate }}
<i class="fas fa-arrow-left" aria-hidden="true"></i> {{ type.value + '.edit.return' | translate }}
</button>
</ds-form>

View File

@@ -7,7 +7,7 @@
<a class="btn btn-danger"
[routerLink]="((type === 'community') ? '/communities/' : '/collections/') + (dsoRD$ | async)?.payload.uuid + '/delete'"
data-test="delete-button">
<i class="fas fa-trash"></i> {{type + '.edit.delete' | translate}}</a>
<i class="fas fa-trash" aria-hidden="true"></i> {{type + '.edit.delete' | translate}}</a>
</div>
</div>
<div class="pt-2">
@@ -27,7 +27,7 @@
</div>
<div class="col-12 text-right">
<a *ngIf="!hideReturnButton" [routerLink]="getPageUrl((dsoRD$ | async)?.payload)" class="btn btn-outline-secondary">
<i class="fas fa-arrow-left"></i> {{ type + '.edit.return' | translate }}
<i class="fas fa-arrow-left" aria-hidden="true"></i> {{ type + '.edit.return' | translate }}
</a>
</div>
</div>

View File

@@ -1,25 +1,21 @@
<div *ngIf="!canActivate" class="dso-button-menu mb-1"
[title]="itemModel.text | translate"
[ngbTooltip]="itemModel.text | translate">
<a *ngIf="!section.model.disabled" class="d-flex flex-row flex-nowrap"
[routerLink]="itemModel.link"
href="javascript:void(0);">
<button [attr.aria-label]="itemModel.text | translate" [title]="itemModel.text | translate" class="btn btn-dark btn-sm" [disabled]="section.model.disabled">
<i class="fas fa-{{section.icon}} fa-fw"></i>
</button>
<a *ngIf="!section.model.disabled" class="btn btn-dark btn-sm"
[routerLink]="itemModel.link">
<i class="fas fa-{{section.icon}} fa-fw" aria-hidden="true"></i>
<span class="sr-only">{{itemModel.text | translate}}</span>
</a>
<div *ngIf="section.model.disabled" class="d-flex flex-row flex-nowrap">
<button [attr.aria-label]="itemModel.text | translate" [title]="itemModel.text | translate" class="btn btn-dark btn-sm" [disabled]="section.model.disabled">
<i class="fas fa-{{section.icon}} fa-fw"></i>
</button>
</div>
<button *ngIf="section.model.disabled" class="btn btn-dark btn-sm" [disabled]="true">
<i class="fas fa-{{section.icon}} fa-fw" aria-hidden="true"></i>
<span class="sr-only">{{itemModel.text | translate}}</span>
</button>
</div>
<div *ngIf="canActivate" class="dso-button-menu mb-1"
[title]="itemModel.text | translate"
[ngbTooltip]="itemModel.text | translate">
<button [attr.aria-label]="itemModel.text | translate" [title]="itemModel.text | translate" class="btn btn-dark btn-sm" [disabled]="section.model.disabled"
<button class="btn btn-dark btn-sm" [disabled]="section.model.disabled"
(click)="activate($event)">
<i class="fas fa-{{section.icon}} fa-fw"></i>
<i class="fas fa-{{section.icon}} fa-fw" aria-hidden="true"></i>
<span class="sr-only">{{itemModel.text | translate}}</span>
</button>
</div>

View File

@@ -96,7 +96,7 @@ describe('DsoEditMenuSectionComponent', () => {
});
describe('when the section model in a disabled link or text', () => {
it('should show just the button', () => {
const textButton = fixture.debugElement.query(By.css('div div button'));
const textButton = fixture.debugElement.query(By.css('div a'));
expect(textButton.nativeElement.innerHTML).toContain('fa-' + iconString);
});
});
@@ -144,7 +144,7 @@ describe('DsoEditMenuSectionComponent', () => {
});
describe('link model', () => {
describe('when the section model in a non disabled link', () => {
initAsync(dummySectionLink, menuService);
beforeEach(() => {
spyOn(menuService, 'getSubSectionsByParentID').and.returnValue(observableOf([]));
@@ -154,11 +154,8 @@ describe('DsoEditMenuSectionComponent', () => {
fixture.detectChanges();
});
describe('when the section model in a non disabled link', () => {
it('should show a link element with the button in it', () => {
const link = fixture.debugElement.query(By.css('a'));
expect(link.nativeElement.innerHTML).toContain('button');
});
it('should show the link element', () => {
expect(fixture.debugElement.query(By.css('a'))).not.toBeNull();
});
});

View File

@@ -58,11 +58,12 @@
<div class="col text-right space-children-mr">
<ng-content select="[before]"></ng-content>
<button *ngIf="displayCancel" type="reset" class="btn btn-outline-secondary" (click)="reset()">
<i class="fa fa-times"></i> {{cancelLabel | translate}}
<i class="fa fa-times" aria-hidden="true"></i> {{cancelLabel | translate}}
</button>
<ng-content select="[between]"></ng-content>
<button *ngIf="displaySubmit" type="submit" class="btn btn-primary" (click)="onSubmit()"
[disabled]="!(isValid() | async)"><i class="fas fa-save"></i> {{submitLabel | translate}}
[disabled]="!(isValid() | async)">
<i class="fas fa-save" aria-hidden="true"></i> {{submitLabel | translate}}
</button>
<ng-content select="[after]"></ng-content>
</div>

View File

@@ -5,8 +5,8 @@
[id]="entry.id"
[ngModel]="entry.checked"
(ngModelChange)="this.toggleCheckbox.emit($event);">
<label class="custom-control-label" [for]="entry.id"
[attr.aria-label]="(entry.checked ? 'resource-policies.table.headers.deselect' : 'resource-policies.table.headers.select') | translate">
<label class="custom-control-label" [for]="entry.id">
<span class="sr-only">{{(entry.checked ? 'resource-policies.table.headers.deselect' : 'resource-policies.table.headers.select') | translate}}</span>
</label>
</div>
</td>
@@ -30,12 +30,12 @@
<button class="btn btn-outline-primary btn-sm"
[title]="'resource-policies.table.headers.edit.policy' | translate"
(click)="redirectToResourcePolicyEditPage()">
<i class="fas fa-edit fa-fw"></i>
<i class="fas fa-edit fa-fw" aria-hidden="true"></i>
</button>
<button *ngIf="(groupName$ | async) !== undefined" class="btn btn-outline-primary btn-sm"
[title]="'resource-policies.table.headers.edit.group' | translate"
(click)="redirectToGroupEditPage()">
<i class="fas fa-users fa-fw"></i>
<i class="fas fa-users fa-fw" aria-hidden="true"></i>
</button>
</div>
</td>

View File

@@ -17,10 +17,10 @@
[title]="'resource-policies.delete.btn.title' | translate"
(click)="deleteSelectedResourcePolicies()">
<span *ngIf="(isProcessingDelete() | async)">
<i class='fas fa-circle-notch fa-spin'></i> {{'submission.workflow.tasks.generic.processing' | translate}}
<i class='fas fa-circle-notch fa-spin' aria-hidden="true"></i> {{'submission.workflow.tasks.generic.processing' | translate}}
</span>
<span *ngIf="!(isProcessingDelete() | async)">
<i class='fas fa-trash-alt fa-fw'></i>
<i class='fas fa-trash-alt fa-fw' aria-hidden="true"></i>
{{'resource-policies.delete.btn' | translate}}
</span>
</button>
@@ -28,7 +28,7 @@
[disabled]="(isProcessingDelete() | async)"
[title]="'resource-policies.add.for.' + resourceType | translate"
(click)="redirectToResourcePolicyCreatePage()">
<i class='fas fa-plus'></i>
<i class='fas fa-plus' aria-hidden="true"></i>
{{'resource-policies.add.button' | translate}}
</button>
</div>
@@ -42,8 +42,8 @@
class="custom-control-input"
[id]="'selectAll_' + resourceUUID"
(change)="selectAllCheckbox($event)">
<label class="custom-control-label" [for]="'selectAll_' + resourceUUID"
[attr.aria-label]="(selectAllBtn.checked ? 'resource-policies.table.headers.deselect-all' : 'resource-policies.table.headers.select-all') | translate">
<label class="custom-control-label" [for]="'selectAll_' + resourceUUID">
<span class="sr-only">{{(selectAllBtn.checked ? 'resource-policies.table.headers.deselect-all' : 'resource-policies.table.headers.select-all') | translate}}</span>
</label>
</div>
</th>

View File

@@ -23,7 +23,7 @@
<i class="fas fa-upload" aria-hidden="true"></i>
{{dropMsg | translate}}{{'uploader.or' | translate}}
<label for="inputFileUploader-{{uploaderId}}" class="btn btn-link m-0 p-0 ml-1" tabindex="0" (keyup.enter)="$event.stopImmediatePropagation(); fileInput.click()">
<span role="button" [attr.aria-label]="'uploader.browse' | translate">{{'uploader.browse' | translate}}</span>
<span role="button" [attr.aria-label]="ariaLabel | translate">{{'uploader.browse' | translate}}</span>
</label>
<input #fileInput id="inputFileUploader-{{uploaderId}}" class="d-none" type="file" ng2FileSelect [uploader]="uploader" multiple tabindex="0" />
</span>

View File

@@ -53,6 +53,11 @@ export class UploaderComponent {
*/
@Input() uploadProperties: UploaderProperties;
/**
* The aria label to describe what kind of files need to be uploaded
*/
@Input() ariaLabel: string;
/**
* The function to call when upload is completed
*/

View File

@@ -898,6 +898,8 @@
"claimed-declined-task-search-result-list-element.title": "Declined, sent back to Review Manager's workflow",
"collection.browse.logo": "Browse for a collection logo",
"collection.create.head": "Create a Collection",
"collection.create.notifications.success": "Successfully created the Collection",
@@ -1094,6 +1096,8 @@
"collection.listelement.badge": "Collection",
"collection.logo": "Collection logo",
"collection.page.browse.recent.head": "Recent Submissions",
"collection.page.browse.recent.empty": "No items to show",
@@ -1180,6 +1184,8 @@
"communityList.collapse": "Collapse {{ name }}",
"community.browse.logo": "Browse for a community logo",
"community.create.head": "Create a Community",
"community.create.notifications.success": "Successfully created the Community",
@@ -1256,6 +1262,8 @@
"community.listelement.badge": "Community",
"community.logo": "Community logo",
"comcol-role.edit.no-group": "None",
"comcol-role.edit.create": "Create",