MOBILE-3320 core: Improve a11y on spinners and button with spinners

main
Pau Ferrer Ocaña 2021-06-11 13:13:15 +02:00
parent ee3bf7c2e5
commit 93fe711303
38 changed files with 177 additions and 90 deletions

View File

@ -16,7 +16,8 @@
[attr.aria-valuetext]="prefetchCoursesData[selectedFilter].badgeA11yText">
{{prefetchCoursesData[selectedFilter].badge}}
</ion-badge>
<ion-spinner *ngIf="prefetchCoursesData[selectedFilter].loading" aria-hidden="true"></ion-spinner>
<ion-spinner *ngIf="prefetchCoursesData[selectedFilter].loading" [attr.aria-label]="'core.loading' | translate">
</ion-spinner>
</div>
<core-context-menu slot="end">
<core-context-menu-item *ngIf="loaded && showFilterSwitchButton()" [priority]="1000"

View File

@ -13,7 +13,8 @@
[attr.aria-valuenow]="prefetchCoursesData.count" [attr.aria-valuetext]="prefetchCoursesData.badgeA11yText">
{{prefetchCoursesData.badge}}
</ion-badge>
<ion-spinner *ngIf="!prefetchCoursesData.icon || prefetchCoursesData.loading"></ion-spinner>
<ion-spinner *ngIf="!prefetchCoursesData.icon || prefetchCoursesData.loading"
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
<core-horizontal-scroll-controls #scrollControls [aria-controls]="scrollElementId">

View File

@ -13,7 +13,8 @@
[attr.aria-valuenow]="prefetchCoursesData.count" [attr.aria-valuetext]="prefetchCoursesData.badgeA11yText">
{{prefetchCoursesData.badge}}
</ion-badge>
<ion-spinner *ngIf="!prefetchCoursesData.icon || prefetchCoursesData.loading"></ion-spinner>
<ion-spinner *ngIf="!prefetchCoursesData.icon || prefetchCoursesData.loading"
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
<core-horizontal-scroll-controls #scrollControls [aria-controls]="scrollElementId">

View File

@ -54,7 +54,7 @@
<ion-button expand="block" (click)="loadMoreEvents()" color="light" *ngIf="!loadingMore">
{{ 'core.loadmore' | translate }}
</ion-button>
<ion-spinner *ngIf="loadingMore"></ion-spinner>
<ion-spinner *ngIf="loadingMore" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
<core-empty-box *ngIf="empty" image="assets/img/icons/activities.svg" [message]="'addon.block_timeline.noevents' | translate"

View File

@ -106,7 +106,9 @@
</ion-item>
<!-- Loading groups. -->
<ion-item class="ion-text-wrap" *ngIf="loadingGroups">
<ion-label><ion-spinner *ngIf="loadingGroups"></ion-spinner></ion-label>
<ion-label>
<ion-spinner *ngIf="loadingGroups" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</ion-label>
</ion-item>
</ng-container>

View File

@ -17,10 +17,13 @@
{{ device.name }} {{ device.model }} {{ device.platform }} {{ device.version }}
<span *ngIf="device.current">({{ 'core.currentdevice' | translate }})</span>
</ion-label>
<ion-spinner *ngIf="device.updating" slot="end"></ion-spinner>
<ion-toggle [disabled]="device.updating" [(ngModel)]="device.enable"
(ngModelChange)="enableDevice(device, device.enable)">
<core-button-with-spinner [loading]="device.updating" slot="end">
<ion-toggle
[(ngModel)]="device.enable"
(ngModelChange)="enableDevice(device, device.enable)"
>
</ion-toggle>
</core-button-with-spinner>
</ion-item>
</ion-list>
</core-loading>

View File

@ -66,7 +66,7 @@
</ion-item>
</div>
<ion-item class="ion-text-center" *ngIf="favourites.loading">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
<!-- Group conversations. -->
@ -101,7 +101,7 @@
</ion-item>
</div>
<ion-item class="ion-text-center" *ngIf="group.loading">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
<ion-item
@ -138,7 +138,7 @@
</ion-item>
</div>
<ion-item class="ion-text-center" *ngIf="individual.loading">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
</ion-list>

View File

@ -76,7 +76,7 @@
</ion-button>
</div>
<div *ngIf="item.loadingMore" class="ion-padding ion-text-center">
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
</ng-container>
</ng-container>

View File

@ -66,14 +66,21 @@
<ng-container *ngIf="groupMessagingEnabled">
<ion-item class="ion-text-wrap">
<ion-label>{{ processor.displayname }}</ion-label>
<ion-spinner slot="end" *ngIf="!preferences.disableall && notification.updating"></ion-spinner>
<ion-toggle slot="end" *ngIf="!preferences.disableall && !processor.locked"
[(ngModel)]="processor.checked" (ngModelChange)="changePreference(notification, '', processor)"
[disabled]="notification.updating">
<core-button-with-spinner
*ngIf="!preferences.disableall"
[loading]="!!notification.updating"
slot="end"
>
<ion-toggle
*ngIf="!processor.locked"
[(ngModel)]="processor.checked"
(ngModelChange)="changePreference(notification, '', processor)"
>
</ion-toggle>
<ion-note slot="end" *ngIf="!preferences.disableall && processor.locked">
<ion-note *ngIf="processor.locked">
{{ processor.lockedmessage }}
</ion-note>
</core-button-with-spinner>
<ion-note slot="end" *ngIf="preferences.disableall">
{{ 'core.settings.disabled' | translate }}
</ion-note>
@ -85,17 +92,20 @@
<ion-row class="ion-text-wrap ion-hide-md-down ion-align-items-center">
<ion-col class="ion-margin-horizontal">{{ processor.displayname }}</ion-col>
<ion-col size="2" class="ion-text-center" *ngFor="let state of ['loggedin', 'loggedoff']">
<core-button-with-spinner
*ngIf="!preferences.disableall"
[loading]="notification.updating && notification.updating[state]"
>
<!-- If notifications not disabled, show toggle. -->
<ion-spinner [hidden]="preferences.disableall ||
!(notification.updating && notification.updating[state])"></ion-spinner>
<ion-toggle *ngIf="!preferences.disableall && !processor.locked"
<ion-toggle *ngIf="!processor.locked"
[(ngModel)]="processor[state].checked"
(ngModelChange)="changePreference(notification, state, processor)"
[disabled]="notification.updating && notification.updating[state]">
>
</ion-toggle>
<div class="ion-padding text-gray" *ngIf="!preferences.disableall && processor.locked">
<div class="ion-padding text-gray" *ngIf="processor.locked">
{{'core.settings.locked' | translate }}
</div>
</core-button-with-spinner>
<!-- If notifications are disabled, show "Disabled" instead of toggle. -->
<span *ngIf="preferences.disableall">{{ 'core.settings.disabled' | translate }}</span>
</ion-col>
@ -108,17 +118,19 @@
If notifications are disabled, show "Disabled" instead of toggle. -->
<ion-item *ngFor="let state of ['loggedin', 'loggedoff']" class="ion-text-wrap ion-hide-md-up">
<ion-label>{{ 'core.settings.' + state | translate }}</ion-label>
<ion-spinner slot="end"
*ngIf="!preferences.disableall && (notification.updating && notification.updating[state])">
</ion-spinner>
<ion-toggle slot="end" *ngIf="!preferences.disableall && !processor.locked"
<core-button-with-spinner slot="end"
*ngIf="!preferences.disableall"
[loading]="notification.updating && notification.updating[state]"
>
<ion-toggle *ngIf="!processor.locked"
[(ngModel)]="processor[state].checked"
(ngModelChange)="changePreference(notification, state, processor)"
[disabled]="notification.updating && notification.updating[state]">
>
</ion-toggle>
<ion-note slot="end" *ngIf="!preferences.disableall && processor.locked">
<ion-note *ngIf="processor.locked">
{{'core.settings.locked' | translate }}
</ion-note>
</core-button-with-spinner>
<ion-note slot="end" *ngIf="preferences.disableall">
{{ 'core.settings.disabled' | translate }}
</ion-note>

View File

@ -47,7 +47,7 @@
{{ 'core.loadmore' | translate }}
</ion-button>
<ion-item *ngIf="responses.responses.canLoadMore && loadingMore" class="ion-text-center">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
</ng-container>
@ -70,7 +70,7 @@
{{ 'core.loadmore' | translate }}
</ion-button>
<ion-item *ngIf="responses.anonResponses.canLoadMore && loadingMore" class="ion-text-center">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
</ng-container>
</ion-list>

View File

@ -83,7 +83,7 @@
<!-- Download progress. -->
<ion-item class="ion-text-center" *ngIf="downloading">
<ion-label>
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
<h2 *ngIf="progressMessage">{{ progressMessage | translate }}</h2>
<core-progress-bar *ngIf="showPercentage" [progress]="percentage" [a11yText]="progressMessage"></core-progress-bar>
</ion-label>

View File

@ -28,7 +28,7 @@
<ion-label><h2>{{ 'addon.mod_lesson.lessonmenu' | translate }}</h2></ion-label>
</ion-item-divider>
<ion-item class="ion-text-center" *ngIf="pageInstance.loadingMenu">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
<div *ngIf="!pageInstance.loadingMenu">
<ng-container *ngFor="let page of pageInstance.lessonPages">

View File

@ -218,7 +218,7 @@
<!-- Spinner shown while downloading or calculating. -->
<ion-item class="ion-text-center" *ngIf="showStatusSpinner">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
</ion-list>
</ion-card>

View File

@ -143,7 +143,7 @@
</ion-item>
<ion-item class="ion-text-center" *ngIf="scorm.displaycoursestructure && loadingToc">
<ion-label>
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</ion-label>
</ion-item>
<ion-item class="ion-text-wrap" *ngIf="scorm.displaycoursestructure && !loadingToc">
@ -240,7 +240,7 @@
<!-- Download progress. -->
<ion-item class="ion-text-center" *ngIf="downloading">
<ion-label>
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
<h2 *ngIf="progressMessage">{{ progressMessage | translate }}</h2>
<core-progress-bar *ngIf="showPercentage" [progress]="percentage" [a11yText]="progressMessage">
</core-progress-bar>

View File

@ -8,11 +8,12 @@
</core-format-text>
</h1>
<ion-buttons slot="end">
<ion-button fill="clear" *ngIf="showToc && !loadingToc && toc.length" (click)="openToc()"
<core-button-with-spinner *ngIf="showToc" [loading]="loadingToc">
<ion-button fill="clear" *ngIf="toc.length" (click)="openToc()"
[attr.aria-label]="'addon.mod_scorm.toc' | translate" aria-haspopup="true">
<ion-icon name="fas-bookmark" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
<ion-spinner *ngIf="showToc && loadingToc"></ion-spinner>
</core-button-with-spinner>
</ion-buttons>
</ion-toolbar>
</ion-header>

View File

@ -12,14 +12,13 @@
</ion-refresher>
<core-loading [hideUntil]="notificationsLoaded">
<div class="ion-padding" *ngIf="canMarkAllNotificationsAsRead">
<ion-button *ngIf="!loadingMarkAllNotificationsAsRead" expand="block" (click)="markAllNotificationsAsRead()"
<ion-button [disabled]="loadingMarkAllNotificationsAsRead" expand="block" (click)="markAllNotificationsAsRead()"
color="light">
<ion-icon slot="start" name="fas-check" aria-hidden="true"></ion-icon>
<ion-icon slot="start" name="fas-check" aria-hidden="true" *ngIf="!loadingMarkAllNotificationsAsRead"></ion-icon>
<ion-spinner slot="start" [attr.aria-label]="'core.loading' | translate" *ngIf="loadingMarkAllNotificationsAsRead">
</ion-spinner>
{{ 'addon.notifications.markallread' | translate }}
</ion-button>
<ion-button *ngIf="loadingMarkAllNotificationsAsRead" expand="block" color="light">
<ion-spinner></ion-spinner>
</ion-button>
</div>
<ion-card *ngFor="let notification of notifications">

View File

@ -0,0 +1,15 @@
:host {
font-size: 1.4rem;
display: flex;
flex-flow: row;
align-items: center;
justify-content: space-around;
align-content: center;
min-height: var(--a11y-min-target-size);
min-width: var(--a11y-min-target-size);
position: relative;
> * {
position: absolute;
}
}

View File

@ -0,0 +1,37 @@
// (C) Copyright 2015 Moodle Pty Ltd.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import { Component, Input } from '@angular/core';
import { CoreAnimations } from '@components/animations';
/**
* Component to show a button or a spinner when loading.
*
* Usage:
* <core-button-with-spinner [loading]="loading">
* <ion-button>...</ion-button>
* </core-button-with-spinner>
*/
@Component({
selector: 'core-button-with-spinner',
templateUrl: 'core-button-with-spinner.html',
styleUrls: ['button-with-spinner.scss'],
animations: [CoreAnimations.SHOW_HIDE],
})
export class CoreButtonWithSpinnerComponent {
@Input() loading = true;
@Input() loadingLabel = 'core.loading';
}

View File

@ -0,0 +1,6 @@
<div *ngIf="!loading" [@coreShowHideAnimation]>
<ng-content></ng-content>
</div>
<!-- Spinner. -->
<ion-spinner *ngIf="loading" [@coreShowHideAnimation] [attr.aria-label]="loadingLabel | translate"></ion-spinner>

View File

@ -57,11 +57,13 @@ import { CoreUserAvatarComponent } from './user-avatar/user-avatar';
import { CoreComboboxComponent } from './combobox/combobox';
import { CoreSpacerComponent } from './spacer/spacer';
import { CoreHorizontalScrollControlsComponent } from './horizontal-scroll-controls/horizontal-scroll-controls';
import { CoreButtonWithSpinnerComponent } from './button-with-spinner/button-with-spinner';
@NgModule({
declarations: [
CoreAttachmentsComponent,
CoreBSTooltipComponent,
CoreButtonWithSpinnerComponent,
CoreChartComponent,
CoreChronoComponent,
CoreContextMenuComponent,
@ -108,6 +110,7 @@ import { CoreHorizontalScrollControlsComponent } from './horizontal-scroll-contr
exports: [
CoreAttachmentsComponent,
CoreBSTooltipComponent,
CoreButtonWithSpinnerComponent,
CoreChartComponent,
CoreChronoComponent,
CoreContextMenuComponent,

View File

@ -13,7 +13,8 @@
<ion-icon *ngIf="(item.href || item.action) && item.iconAction && item.iconAction != 'spinner'" [name]="item.iconAction"
[class.icon-slash]="item.iconSlash" slot="end" aria-hidden="true">
</ion-icon>
<ion-spinner *ngIf="(item.href || item.action) && item.iconAction == 'spinner'" slot="end"></ion-spinner>
<ion-spinner *ngIf="(item.href || item.action) && item.iconAction == 'spinner'" slot="end"
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-badge class="{{item.badgeClass}}" slot="end" *ngIf="item.badge">
<span [attr.ara-hidden]="!!item.badgeA11yText">{{item.badge}}</span>
<span class="sr-only" *ngIf="item.badgeA11yText">

View File

@ -16,6 +16,6 @@
</ion-button>
<span class="core-loading-spinner">
<ion-spinner *ngIf="loading"></ion-spinner>
<ion-spinner *ngIf="loading" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</span>
</div>

View File

@ -25,5 +25,5 @@
</ng-container>
<div *ngIf="loadingMore" class="ion-padding ion-text-center" #spinnercontainer>
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>

View File

@ -1,5 +1,5 @@
<div class="core-loading-container" *ngIf="!hideUntil" role="status" [@coreShowHideAnimation]>
<ion-spinner color="primary"></ion-spinner>
<ion-spinner color="primary" aria-hidden="true"></ion-spinner>
<p class="core-loading-message" *ngIf="message" role="status">{{message}}</p>
</div>
<div #content class="core-loading-content" [id]="uniqueId" [attr.aria-busy]="!hideUntil" [@coreShowHideAnimation]

View File

@ -1,6 +1,6 @@
<ion-tabs class="hide-header">
<ion-tab-bar slot="top" class="core-tabs-bar" [hidden]="!tabs || numTabsShown <= 1" #tabBar>
<ion-spinner *ngIf="!hideUntil"></ion-spinner>
<ion-spinner *ngIf="!hideUntil" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-row *ngIf="hideUntil">
<ion-col class="col-with-arrow ion-no-padding" (click)="slidePrev()" size="1" [class.clickable]="showPrevButton">
<ion-icon *ngIf="showPrevButton" name="fas-chevron-left" [attr.aria-label]="'core.previous' | translate"></ion-icon>

View File

@ -1,5 +1,5 @@
<ion-tab-bar slot="top" class="core-tabs-bar" [hidden]="!tabs || numTabsShown <= 1" #tabBar>
<ion-spinner *ngIf="!hideUntil"></ion-spinner>
<ion-spinner *ngIf="!hideUntil" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-row *ngIf="hideUntil">
<ion-col class="col-with-arrow ion-no-padding" (click)="slidePrev()" size="1" [class.clickable]="showPrevButton">
<ion-icon *ngIf="showPrevButton" name="fas-chevron-left" [attr.aria-label]="'core.previous' | translate"></ion-icon>

View File

@ -114,6 +114,6 @@
[ngClass]="['core-course-module-handler', 'core-module-loading', module.handlerData.class]"
detail="false"
>
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
</ng-container>

View File

@ -111,7 +111,8 @@
slot="start" [name]="prefetchCourseData.icon" color="success"
aria-hidden="true" role="status">
</ion-icon>
<ion-spinner *ngIf="prefetchCourseData.loading" slot="start"></ion-spinner>
<ion-spinner *ngIf="prefetchCourseData.loading" slot="start"
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-label><h2>{{ 'core.course.downloadcourse' | translate }}</h2></ion-label>
</ion-item>
<ion-item button (click)="openCourse()" [attr.aria-label]="course.fullname" *ngIf="!avoidOpenCourse && canAccessCourse"

View File

@ -1,6 +1,6 @@
<ion-item button class="ion-text-wrap" (click)="action('download')" *ngIf="downloadCourseEnabled" detail="false">
<ion-icon *ngIf="!prefetch.loading" [name]="prefetch.icon" slot="start" aria-hidden="true"></ion-icon>
<ion-spinner *ngIf="prefetch.loading" slot="start"></ion-spinner>
<ion-spinner *ngIf="prefetch.loading" slot="start" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-label><h2>{{ prefetch.statusTranslatable | translate }}</h2></ion-label>
</ion-item>
<ion-item button class="ion-text-wrap" (click)="action('delete')" detail="false"

View File

@ -46,7 +46,8 @@
<div class="core-button-spinner" *ngIf="courseOptionMenuEnabled" slot="end">
<!-- Download course spinner. -->
<ion-spinner *ngIf="(downloadCourseEnabled && prefetchCourseData.icon == 'spinner') || showSpinner"></ion-spinner>
<ion-spinner *ngIf="(downloadCourseEnabled && prefetchCourseData.icon == 'spinner') || showSpinner"
[attr.aria-label]="'core.loading' | translate"></ion-spinner>
<!-- Options menu. -->
<ion-button fill="clear" color="dark" (click)="showCourseOptionsMenu($event)" *ngIf="!showSpinner"

View File

@ -59,7 +59,7 @@
<div class="core-login-site-list-found" [class.hidden]="!hasSites" [class.dimmed]="loadingSites">
<div *ngIf="loadingSites" class="core-login-site-list-loading">
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
<ng-container *ngFor="let site of sites">
<ng-container *ngTemplateOutlet="sitelisting; context: {site: site}"></ng-container>
@ -68,7 +68,7 @@
</ion-list>
<div *ngIf="!hasSites && loadingSites" class="core-login-site-nolist-loading">
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
</ng-container>

View File

@ -1,7 +1,7 @@
<ion-tabs #mainTabs [hidden]="!showTabs" [class]="'placement-' + tabsPlacement" [class.tabshidden]="hidden"
(ionTabsDidChange)="tabChanged($event)">
<ion-tab-bar slot="bottom" [hidden]="hidden" class="mainmenu-tabs">
<ion-spinner *ngIf="!loaded"></ion-spinner>
<ion-spinner *ngIf="!loaded" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
<ion-tab-button
*ngFor="let tab of tabs"

View File

@ -23,7 +23,7 @@
</ion-item>
<core-spacer></core-spacer>
<ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
<ion-item button *ngFor="let handler of handlers" [ngClass]="['core-moremenu-handler', handler.class || '']"
(click)="openHandler(handler)" [attr.aria-label]="handler.title | translate" detail="true">
@ -37,7 +37,8 @@
<span *ngIf="handler.showBadge && handler.badge && handler.badgeA11yText" class="sr-only">
{{ handler.badgeA11yText | translate: {$a : handler.badge } }}
</span>
<ion-spinner slot="end" *ngIf="handler.showBadge && handler.loading"></ion-spinner>
<ion-spinner slot="end" *ngIf="handler.showBadge && handler.loading" [attr.aria-label]="'core.loading' | translate">
</ion-spinner>
</ion-item>
<ng-container *ngFor="let item of customItems">
<ion-item button *ngIf="item.type != 'embedded'" [href]="item.url" [attr.aria-label]="item.label" core-link

View File

@ -123,7 +123,7 @@
</ion-item>
<ion-item *ngIf="deviceInfo.uuid" (longPress)="copyItemInfo($event)">
<ion-label class="ion-text-wrap">
<h2>{{ 'core.settings.cordovadeviceuuid'}}</h2>
<h2>{{ 'core.settings.cordovadeviceuuid' | translate}}</h2>
<p>{{ deviceInfo.uuid }}</p>
</ion-label>
</ion-item>

View File

@ -59,11 +59,12 @@
<ion-button fill="clear" [attr.aria-label]="'core.info' | translate" (click)="showSyncInfo()" slot="end">
<ion-icon name="fas-info-circle" color="info" slot="icon-only"></ion-icon>
</ion-button>
<ion-button fill="clear" slot="end" *ngIf="!isSynchronizing()" (click)="synchronize()"
<core-button-with-spinner [loading]="isSynchronizing()" slot="end">
<ion-button fill="clear" (click)="synchronize()"
[attr.aria-label]="'core.settings.synchronizenow' | translate">
<ion-icon name="fas-sync-alt" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
<ion-spinner slot="end" *ngIf="isSynchronizing()"></ion-spinner>
</core-button-with-spinner>
</ion-item>
</ion-card>
</ion-list>

View File

@ -38,11 +38,12 @@
<p>{{ site.fullName }}</p>
<p>{{ site.siteUrl }}</p>
</ion-label>
<ion-button fill="clear" slot="end" *ngIf="!isSynchronizing(site.id)" (click)="synchronize(site.id)"
<core-button-with-spinner [loading]="isSynchronizing(site.id)" slot="end">
<ion-button fill="clear" (click)="synchronize(site.id)"
[title]="site.siteName" [attr.aria-label]="'core.settings.synchronizenow' | translate">
<ion-icon name="fas-sync-alt" slot="icon-only" aria-hidden="true"></ion-icon>
</ion-button>
<ion-spinner slot="end" *ngIf="isSynchronizing(site.id)"></ion-spinner>
</core-button-with-spinner>
</ion-item>
</core-loading>
</ion-content>

View File

@ -48,7 +48,7 @@
</ion-label>
</ion-item>
<div *ngIf="isLoadingHandlers" class="ion-text-center core-loading-handlers">
<ion-spinner></ion-spinner>
<ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</div>
</div>
@ -61,7 +61,7 @@
</ion-label>
</ion-item>
<ion-item class="ion-text-center core-loading-handlers" *ngIf="isLoadingHandlers">
<ion-label><ion-spinner></ion-spinner></ion-label>
<ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label>
</ion-item>
<ion-item button *ngFor="let handler of newPageHandlers" class="ion-text-wrap" (click)="handlerClicked($event, handler)"
@ -80,7 +80,7 @@
[hidden]="handler.hidden" [attr.aria-label]="handler.title | translate" [disabled]="handler.spinner">
<ion-icon *ngIf="handler.icon" [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon>
{{ handler.title | translate }}
<ion-spinner *ngIf="handler.spinner" slot="end"></ion-spinner>
<ion-spinner *ngIf="handler.spinner" slot="end" [attr.aria-label]="'core.loading' | translate"></ion-spinner>
</ion-button>
</ion-label>
</ion-item>