forked from CIT/Vmeda.Online
		
	Merge pull request #1791 from crazyserver/MOBILE-2819
MOBILE-2819 a11y: Apply aria attributes to components
This commit is contained in:
		
						commit
						c11cfa336b
					
				| @ -7,7 +7,6 @@ $addon-mod-wiki-toc-background-color: $gray-light !default; | |||||||
| ion-app.app-root addon-mod-wiki-index { | ion-app.app-root addon-mod-wiki-index { | ||||||
|     background-color: $white; |     background-color: $white; | ||||||
| 
 | 
 | ||||||
|     .core-tabs-content-container, |  | ||||||
|     .addon-mod_wiki-page-content { |     .addon-mod_wiki-page-content { | ||||||
|         background-color: $white; |         background-color: $white; | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -28,7 +28,7 @@ import { Component, Input, OnChanges, OnDestroy, Output, EventEmitter, SimpleCha | |||||||
|  */ |  */ | ||||||
| @Component({ | @Component({ | ||||||
|     selector: 'core-chrono', |     selector: 'core-chrono', | ||||||
|     template: '<span>{{ time / 1000 | coreSecondsToHMS }}</span>' |     template: '<span role="timer">{{ time / 1000 | coreSecondsToHMS }}</span>' | ||||||
| }) | }) | ||||||
| export class CoreChronoComponent implements OnChanges, OnDestroy { | export class CoreChronoComponent implements OnChanges, OnDestroy { | ||||||
|     @Input() running: boolean; // Set it to true to start the chrono. Set it to false to stop it.
 |     @Input() running: boolean; // Set it to true to start the chrono. Set it to false to stop it.
 | ||||||
|  | |||||||
| @ -26,12 +26,14 @@ import { CoreLoggerProvider } from '@providers/logger'; | |||||||
| }) | }) | ||||||
| export class CoreContextMenuPopoverComponent { | export class CoreContextMenuPopoverComponent { | ||||||
|     title: string; |     title: string; | ||||||
|  |     uniqueId: string; | ||||||
|     items: CoreContextMenuItemComponent[]; |     items: CoreContextMenuItemComponent[]; | ||||||
|     protected logger: any; |     protected logger: any; | ||||||
| 
 | 
 | ||||||
|     constructor(navParams: NavParams, private viewCtrl: ViewController, logger: CoreLoggerProvider) { |     constructor(navParams: NavParams, private viewCtrl: ViewController, logger: CoreLoggerProvider) { | ||||||
|         this.title = navParams.get('title'); |         this.title = navParams.get('title'); | ||||||
|         this.items = navParams.get('items') || []; |         this.items = navParams.get('items') || []; | ||||||
|  |         this.uniqueId = navParams.get('id'); | ||||||
|         this.logger = logger.getInstance('CoreContextMenuPopoverComponent'); |         this.logger = logger.getInstance('CoreContextMenuPopoverComponent'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ import { Component, Input, OnInit, OnDestroy, ElementRef, Optional } from '@angu | |||||||
| import { PopoverController } from 'ionic-angular'; | import { PopoverController } from 'ionic-angular'; | ||||||
| import { TranslateService } from '@ngx-translate/core'; | import { TranslateService } from '@ngx-translate/core'; | ||||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||||
|  | import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||||
| import { CoreContextMenuItemComponent } from './context-menu-item'; | import { CoreContextMenuItemComponent } from './context-menu-item'; | ||||||
| import { CoreContextMenuPopoverComponent } from './context-menu-popover'; | import { CoreContextMenuPopoverComponent } from './context-menu-popover'; | ||||||
| import { CoreTabComponent } from '@components/tabs/tab'; | import { CoreTabComponent } from '@components/tabs/tab'; | ||||||
| @ -34,14 +35,16 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|     hideMenu = true; // It will be unhidden when items are added.
 |     hideMenu = true; // It will be unhidden when items are added.
 | ||||||
|     ariaLabel: string; |     ariaLabel: string; | ||||||
|  |     expanded = false; | ||||||
|     protected items: CoreContextMenuItemComponent[] = []; |     protected items: CoreContextMenuItemComponent[] = []; | ||||||
|     protected itemsMovedToParent: CoreContextMenuItemComponent[] = []; |     protected itemsMovedToParent: CoreContextMenuItemComponent[] = []; | ||||||
|     protected itemsChangedStream: Subject<void>; // Stream to update the hideMenu boolean when items change.
 |     protected itemsChangedStream: Subject<void>; // Stream to update the hideMenu boolean when items change.
 | ||||||
|     protected instanceId: string; |     protected instanceId: string; | ||||||
|     protected parentContextMenu: CoreContextMenuComponent; |     protected parentContextMenu: CoreContextMenuComponent; | ||||||
|  |     protected uniqueId: string; | ||||||
| 
 | 
 | ||||||
|     constructor(private translate: TranslateService, private popoverCtrl: PopoverController, elementRef: ElementRef, |     constructor(private translate: TranslateService, private popoverCtrl: PopoverController, elementRef: ElementRef, | ||||||
|             private domUtils: CoreDomUtilsProvider, @Optional() public coreTab: CoreTabComponent) { |             private domUtils: CoreDomUtilsProvider, @Optional() public coreTab: CoreTabComponent, utils: CoreUtilsProvider) { | ||||||
|         // Create the stream and subscribe to it. We ignore successive changes during 250ms.
 |         // Create the stream and subscribe to it. We ignore successive changes during 250ms.
 | ||||||
|         this.itemsChangedStream = new Subject<void>(); |         this.itemsChangedStream = new Subject<void>(); | ||||||
|         this.itemsChangedStream.auditTime(250).subscribe(() => { |         this.itemsChangedStream.auditTime(250).subscribe(() => { | ||||||
| @ -56,6 +59,9 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy { | |||||||
|             }); |             }); | ||||||
|         }); |         }); | ||||||
| 
 | 
 | ||||||
|  |         // Calculate the unique ID.
 | ||||||
|  |         this.uniqueId = 'core-context-menu-' + utils.getUniqueId('CoreContextMenuComponent'); | ||||||
|  | 
 | ||||||
|         this.instanceId = this.domUtils.storeInstanceByElement(elementRef.nativeElement, this); |         this.instanceId = this.domUtils.storeInstanceByElement(elementRef.nativeElement, this); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -170,10 +176,19 @@ export class CoreContextMenuComponent implements OnInit, OnDestroy { | |||||||
|      * @param {MouseEvent} event Event. |      * @param {MouseEvent} event Event. | ||||||
|      */ |      */ | ||||||
|     showContextMenu(event: MouseEvent): void { |     showContextMenu(event: MouseEvent): void { | ||||||
|         const popover = this.popoverCtrl.create(CoreContextMenuPopoverComponent, { title: this.title, items: this.items }); |         if (!this.expanded) { | ||||||
|         popover.present({ |             const popover = this.popoverCtrl.create(CoreContextMenuPopoverComponent, | ||||||
|             ev: event |                 { title: this.title, items: this.items, id: this.uniqueId }); | ||||||
|         }); | 
 | ||||||
|  |             popover.onDidDismiss(() => { | ||||||
|  |                 this.expanded = false; | ||||||
|  |             }); | ||||||
|  |             popover.present({ | ||||||
|  |                 ev: event | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             this.expanded = true; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| <ion-list> | <ion-list [id]="uniqueId" role="menu"> | ||||||
|     <ion-list-header *ngIf="title">{{title}}</ion-list-header> |     <ion-list-header *ngIf="title">{{title}}</ion-list-header> | ||||||
|     <a ion-item text-wrap *ngFor="let item of items" core-link [capture]="item.captureLink" [autoLogin]="item.autoLogin" [href]="item.href" (click)="itemClicked($event, item)" [attr.aria-label]="item.ariaAction" [hidden]="item.hidden" [attr.detail-none]="!item.href || item.iconAction"> |     <a ion-item text-wrap *ngFor="let item of items" core-link [capture]="item.captureLink" [autoLogin]="item.autoLogin" [href]="item.href" (click)="itemClicked($event, item)" [attr.aria-label]="item.ariaAction" [hidden]="item.hidden" [attr.detail-none]="!item.href || item.iconAction" role="menuitem" [attr.aria-controls]="uniqueId"> | ||||||
|         <core-icon *ngIf="item.iconDescription" [name]="item.iconDescription" [attr.aria-label]="item.ariaDescription" item-start></core-icon> |         <core-icon *ngIf="item.iconDescription" [name]="item.iconDescription" [attr.aria-label]="item.ariaDescription" item-start></core-icon> | ||||||
|         <core-format-text [clean]="true" [text]="item.content"></core-format-text> |         <core-format-text [clean]="true" [text]="item.content"></core-format-text> | ||||||
|         <core-icon *ngIf="(item.href || item.action) && item.iconAction && item.iconAction != 'spinner'" [name]="item.iconAction" item-end></core-icon> |         <core-icon *ngIf="(item.href || item.action) && item.iconAction && item.iconAction != 'spinner'" [name]="item.iconAction" item-end></core-icon> | ||||||
|  | |||||||
| @ -1,4 +1,4 @@ | |||||||
| <button [hidden]="hideMenu" ion-button clear icon-only [attr.aria-label]="ariaLabel" (click)="showContextMenu($event)" class="bar-button"> | <button [hidden]="hideMenu" ion-button clear icon-only [attr.aria-label]="ariaLabel" (click)="showContextMenu($event)" class="bar-button" aria-haspopup="true" [attr.aria-expanded]="expanded" [attr.aria-controls]="uniqueId"> | ||||||
|     <core-icon [name]="icon"></core-icon> |     <core-icon [name]="icon"></core-icon> | ||||||
| </button> | </button> | ||||||
| <ng-content></ng-content> | <ng-content></ng-content> | ||||||
| @ -1 +1 @@ | |||||||
| <ion-icon [name]="name" [isActive]="isActive" [md]="md" [ios]="ios" [color]="color"></ion-icon> | <ion-icon [name]="name" [isActive]="isActive" [md]="md" [ios]="ios" [color]="color" aria-hidden="true" role="presentation"></ion-icon> | ||||||
| @ -54,6 +54,8 @@ export class CoreIconComponent implements OnInit, OnDestroy { | |||||||
|             this.newElement.classList.add('icon'); |             this.newElement.classList.add('icon'); | ||||||
|             this.newElement.classList.add('fa'); |             this.newElement.classList.add('fa'); | ||||||
|             this.newElement.classList.add(this.name); |             this.newElement.classList.add(this.name); | ||||||
|  |             this.newElement.setAttribute('aria-hidden', 'true'); | ||||||
|  |             this.newElement.setAttribute('role', 'img'); | ||||||
|             if (this.isTrueProperty(this.fixedWidth)) { |             if (this.isTrueProperty(this.fixedWidth)) { | ||||||
|                 this.newElement.classList.add('fa-fw'); |                 this.newElement.classList.add('fa-fw'); | ||||||
|             } |             } | ||||||
|  | |||||||
| @ -12,5 +12,5 @@ | |||||||
|             </div> |             </div> | ||||||
|         </ng-container> |         </ng-container> | ||||||
|     </ng-container> |     </ng-container> | ||||||
|     <div *ngIf="errorText" class="core-input-error">{{ errorText }}</div> |     <div *ngIf="errorText" class="core-input-error" aria-live="assertive">{{ errorText }}</div> | ||||||
| </div> | </div> | ||||||
| @ -1,5 +1,5 @@ | |||||||
| <div class="tabbar" role="tablist" #tabbar [hidden]="hidden"> | <div class="tabbar" role="tablist" #tabbar> | ||||||
|     <a [hidden]="_loaded === false" *ngFor="let t of _tabs" [tab]="t" class="tab-button" role="tab" href="#" (ionSelect)="select(t)"></a> |     <a [hidden]="_loaded === false" *ngFor="let t of _tabs" [tab]="t" class="tab-button" role="tab" href="#" (ionSelect)="select(t)" [attr.aria-hidden]="!t.show" [attr.aria-label]="t.tabTitle || ''"></a> | ||||||
|     <div class="tab-highlight"></div> |     <div class="tab-highlight"></div> | ||||||
|     <div *ngIf="_loaded === false" class="core-ion-tabs-loading"> |     <div *ngIf="_loaded === false" class="core-ion-tabs-loading"> | ||||||
|         <span class="core-ion-tabs-loading-spinner"> |         <span class="core-ion-tabs-loading-spinner"> | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| <div [@coreShowHideAnimation] class="core-loading-container" *ngIf="!hideUntil"> | <div [@coreShowHideAnimation] class="core-loading-container" *ngIf="!hideUntil" role="status"> | ||||||
|     <span class="core-loading-spinner"> |     <span class="core-loading-spinner"> | ||||||
|         <ion-spinner></ion-spinner> |         <ion-spinner></ion-spinner> | ||||||
|         <p class="core-loading-message" *ngIf="message">{{message}}</p> |         <p class="core-loading-message" *ngIf="message" role="status">{{message}}</p> | ||||||
|     </span> |     </span> | ||||||
| </div> | </div> | ||||||
| <div #content class="core-loading-content" [id]="uniqueId"> | <div #content class="core-loading-content" [id]="uniqueId" [attr.aria-busy]="hideUntil"> | ||||||
|     <ng-content [@coreShowHideAnimation] *ngIf="hideUntil"> |     <ng-content [@coreShowHideAnimation] *ngIf="hideUntil"> | ||||||
|     </ng-content> |     </ng-content> | ||||||
| </div> | </div> | ||||||
| @ -1,5 +1,5 @@ | |||||||
| <div *ngIf="progress >= 0"> | <div *ngIf="progress >= 0"> | ||||||
|     <progress max="100" [value]="progress"> |     <progress max="100" [value]="progress" role="progressbar" aria-valuemin="0" aria-valuemax="100" [attr.aria-valuenow]="progress"> | ||||||
|         <div class="progress-bar-fallback" role="progressbar" aria-valuemin="0" aria-valuemax="100" [attr.aria-valuenow]="progress"> |         <div class="progress-bar-fallback" role="progressbar" aria-valuemin="0" aria-valuemax="100" [attr.aria-valuenow]="progress"> | ||||||
|             <span [style.width]="width"></span> |             <span [style.width]="width"></span> | ||||||
|         </div> |         </div> | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| <div [hidden]="!rteEnabled"> | <div [hidden]="!rteEnabled"> | ||||||
|     <div #editor contenteditable="true" class="core-rte-editor" tappable [attr.data-placeholder-text]="placeholder"> |     <div #editor contenteditable="true" class="core-rte-editor" tappable [attr.data-placeholder-text]="placeholder" role="textbox"> | ||||||
|     </div> |     </div> | ||||||
| 
 | 
 | ||||||
|     <!-- https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand --> |     <!-- https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand --> | ||||||
| @ -22,7 +22,7 @@ | |||||||
| </div> | </div> | ||||||
| 
 | 
 | ||||||
| <div [hidden]="rteEnabled"> | <div [hidden]="rteEnabled"> | ||||||
|     <ion-textarea #textarea class="core-textarea" [placeholder]="placeholder" [attr.name]="name" ngControl="control" (ionChange)="onChange($event)"></ion-textarea> |     <ion-textarea #textarea class="core-textarea" [placeholder]="placeholder" [attr.name]="name" ngControl="control" (ionChange)="onChange($event)" role="textbox"></ion-textarea> | ||||||
|     <div class="core-rte-toolbar" [hidden]="!editorSupported"> |     <div class="core-rte-toolbar" [hidden]="!editorSupported"> | ||||||
|         <div #decorate class="core-rte-buttons"> |         <div #decorate class="core-rte-buttons"> | ||||||
|             <button tappable [core-suppress-events] (onClick)="toggleEditor($event)"><core-icon name="fa-pencil-square-o"></core-icon> {{ 'core.vieweditor' | translate }}</button> |             <button tappable [core-suppress-events] (onClick)="toggleEditor($event)"><core-icon name="fa-pencil-square-o"></core-icon> {{ 'core.vieweditor' | translate }}</button> | ||||||
|  | |||||||
| @ -1,7 +1,7 @@ | |||||||
| <ion-card> | <ion-card> | ||||||
|     <form #f="ngForm" (ngSubmit)="submitForm($event)"> |     <form #f="ngForm" (ngSubmit)="submitForm($event)" role="search"> | ||||||
|         <ion-item> |         <ion-item> | ||||||
|             <ion-input type="text" name="search" [(ngModel)]="searchText" [placeholder]="placeholder" [autocorrect]="autocorrect" [spellcheck]="spellcheck" [core-auto-focus]="autoFocus" [disabled]="disabled"></ion-input> |             <ion-input type="search" name="search" [(ngModel)]="searchText" [placeholder]="placeholder" [autocorrect]="autocorrect" [spellcheck]="spellcheck" [core-auto-focus]="autoFocus" [disabled]="disabled" role="searchbox"></ion-input> | ||||||
|             <button item-end ion-button clear icon-only type="submit" class="button-small" [attr.aria-label]="searchLabel" [disabled]="!searchText || (searchText.length < lengthCheck)" [disabled]="disabled"> |             <button item-end ion-button clear icon-only type="submit" class="button-small" [attr.aria-label]="searchLabel" [disabled]="!searchText || (searchText.length < lengthCheck)" [disabled]="disabled"> | ||||||
|                 <ion-icon name="search"></ion-icon> |                 <ion-icon name="search"></ion-icon> | ||||||
|             </button> |             </button> | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| <form> | <form> | ||||||
|     <textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows [(ngModel)]="message" name="message" (onResize)="textareaResized()" (keydown.enter)="enterClicked($event)" (keydown.control.enter)="enterClicked($event, 'control')" (keydown.meta.enter)="enterClicked($event, 'meta')"></textarea> |     <textarea class="core-send-message-input" [core-auto-focus]="showKeyboard" [placeholder]="placeholder" rows="1" core-auto-rows [(ngModel)]="message" name="message" (onResize)="textareaResized()" (keydown.enter)="enterClicked($event)" (keydown.control.enter)="enterClicked($event, 'control')" (keydown.meta.enter)="enterClicked($event, 'meta')" aria-multiline="true"></textarea> | ||||||
|     <ion-buttons end> |     <ion-buttons end> | ||||||
|         <button ion-button icon-only clear="true" type="submit" [disabled]="!message" [attr.aria-label]="'core.send' | translate" [core-suppress-events] (onClick)="submitForm($event)"> |         <button ion-button icon-only clear="true" type="submit" [disabled]="!message" [attr.aria-label]="'core.send' | translate" [core-suppress-events] (onClick)="submitForm($event)"> | ||||||
|             <ion-icon name="send" color="dark"></ion-icon> |             <ion-icon name="send" color="dark"></ion-icon> | ||||||
|  | |||||||
| @ -1,23 +1,21 @@ | |||||||
| <core-loading [hideUntil]="hideUntil" class="core-loading-center"> | <core-loading [hideUntil]="hideUntil" class="core-loading-center"> | ||||||
|     <div class="core-tabs-bar" #topTabs [hidden]="!tabs || numTabsShown < 2"> |     <div class="core-tabs-bar" #topTabs [hidden]="!tabs || numTabsShown < 2" id="core-tabs-bar"> | ||||||
|         <ion-row> |         <ion-row> | ||||||
|             <ion-col class="col-with-arrow" (click)="slidePrev()" no-padding col-1> |             <ion-col class="col-with-arrow" (click)="slidePrev()" no-padding col-1 aria-hidden="true"> | ||||||
|                 <ion-icon *ngIf="showPrevButton" name="arrow-back" md="ios-arrow-back"></ion-icon> |                 <ion-icon *ngIf="showPrevButton" name="arrow-back" md="ios-arrow-back"></ion-icon> | ||||||
|             </ion-col> |             </ion-col> | ||||||
|             <ion-col no-padding col-10> |             <ion-col no-padding col-10> | ||||||
|                 <ion-slides (ionSlideDidChange)="slideChanged()" [slidesPerView]="slidesShown" [dir]="direction"> |                 <ion-slides (ionSlideDidChange)="slideChanged()" [slidesPerView]="slidesShown" [dir]="direction" role="tablist" [attr.aria-label]="description" aria-hidden="false"> | ||||||
|                     <ng-container *ngFor="let tab of tabs; let idx = index"> |                     <ng-container *ngFor="let tab of tabs; let idx = index"> | ||||||
|                         <ion-slide *ngIf="tab.show"> |                        <ion-slide *ngIf="tab.show" [attr.aria-selected]="selected == idx" (click)="selectTab(idx)" class="tab-slide" [attr.aria-label]="tab.title || ''" role="tab" [attr.aria-controls]="tab.id" [id]="tab.id + '-tab'" [tabindex]="selected == idx ? null : -1"> | ||||||
|                             <a [attr.aria-selected]="selected == idx" (click)="selectTab(idx)" class="tab-slide"> |                             <core-icon *ngIf="tab.icon" [name]="tab.icon"></core-icon> | ||||||
|                                 <core-icon *ngIf="tab.icon" [name]="tab.icon"></core-icon> |                             <div *ngIf="tab.title">{{ tab.title }}</div> | ||||||
|                                 <span *ngIf="tab.title">{{ tab.title }}</span> |                             <ion-badge *ngIf="tab.badge" [color]="tab.badgeStyle" class="tab-badge">{{tab.badge}}</ion-badge> | ||||||
|                                 <ion-badge *ngIf="tab.badge" [color]="tab.badgeStyle" class="tab-badge">{{tab.badge}}</ion-badge> |  | ||||||
|                             </a> |  | ||||||
|                         </ion-slide> |                         </ion-slide> | ||||||
|                     </ng-container> |                     </ng-container> | ||||||
|                 </ion-slides> |                 </ion-slides> | ||||||
|             </ion-col> |             </ion-col> | ||||||
|             <ion-col class="col-with-arrow" (click)="slideNext()" no-padding col-1> |             <ion-col class="col-with-arrow" (click)="slideNext()" no-padding col-1 aria-hidden="true"> | ||||||
|                 <ion-icon *ngIf="showNextButton" name="arrow-forward" md="ios-arrow-forward"></ion-icon> |                 <ion-icon *ngIf="showNextButton" name="arrow-forward" md="ios-arrow-forward"></ion-icon> | ||||||
|             </ion-col> |             </ion-col> | ||||||
|         </ion-row> |         </ion-row> | ||||||
|  | |||||||
| @ -16,6 +16,7 @@ import { Component, Input, Output, OnInit, OnDestroy, ElementRef, EventEmitter, | |||||||
| import { CoreTabsComponent } from './tabs'; | import { CoreTabsComponent } from './tabs'; | ||||||
| import { Content } from 'ionic-angular'; | import { Content } from 'ionic-angular'; | ||||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||||
|  | import { CoreUtilsProvider } from '@providers/utils/utils'; | ||||||
| import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons'; | import { CoreNavBarButtonsComponent } from '../navbar-buttons/navbar-buttons'; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
| @ -54,6 +55,9 @@ export class CoreTabComponent implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|             if (this.initialized && hasChanged) { |             if (this.initialized && hasChanged) { | ||||||
|                 this.tabs.tabVisibilityChanged(); |                 this.tabs.tabVisibilityChanged(); | ||||||
|  | 
 | ||||||
|  |                 this.tabElement = document.getElementById(this.id + '-tab'); | ||||||
|  |                 this.tabElement && this.tabElement.setAttribute('aria-hidden', !this._show); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| @ -70,17 +74,31 @@ export class CoreTabComponent implements OnInit, OnDestroy { | |||||||
|     loaded = false; |     loaded = false; | ||||||
|     initialized = false; |     initialized = false; | ||||||
|     _show = true; |     _show = true; | ||||||
|  |     tabElement: any; | ||||||
| 
 | 
 | ||||||
|     constructor(protected tabs: CoreTabsComponent, element: ElementRef, protected domUtils: CoreDomUtilsProvider) { |     constructor(protected tabs: CoreTabsComponent, element: ElementRef, protected domUtils: CoreDomUtilsProvider, | ||||||
|  |             utils: CoreUtilsProvider) { | ||||||
|         this.element = element.nativeElement; |         this.element = element.nativeElement; | ||||||
|  | 
 | ||||||
|  |         this.element.setAttribute('role', 'tabpanel'); | ||||||
|  |         this.element.setAttribute('tabindex', '0'); | ||||||
|  |         this.id = this.id || 'core-tab-' + utils.getUniqueId('CoreTabComponent'); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Component being initialized. |      * Component being initialized. | ||||||
|      */ |      */ | ||||||
|     ngOnInit(): void { |     ngOnInit(): void { | ||||||
|  |         this.element.setAttribute('aria-labelledby', this.id + '-tab'); | ||||||
|  |         this.element.setAttribute('id', this.id); | ||||||
|  | 
 | ||||||
|         this.tabs.addTab(this); |         this.tabs.addTab(this); | ||||||
|         this.initialized = true; |         this.initialized = true; | ||||||
|  | 
 | ||||||
|  |         setTimeout(() => { | ||||||
|  |             this.tabElement = document.getElementById(this.id + '-tab'); | ||||||
|  |             this.tabElement && this.tabElement.setAttribute('aria-hidden', !this._show); | ||||||
|  |         }, 1000); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -96,6 +114,11 @@ export class CoreTabComponent implements OnInit, OnDestroy { | |||||||
|     selectTab(): void { |     selectTab(): void { | ||||||
|         this.element.classList.add('selected'); |         this.element.classList.add('selected'); | ||||||
| 
 | 
 | ||||||
|  |         this.tabElement = this.tabElement || document.getElementById(this.id + '-tab'); | ||||||
|  | 
 | ||||||
|  |         this.tabElement && this.tabElement.setAttribute('aria-selected', true); | ||||||
|  |         this.tabElement && this.tabElement.setAttribute('aria-hidden', !this._show); | ||||||
|  | 
 | ||||||
|         this.loaded = true; |         this.loaded = true; | ||||||
|         this.ionSelect.emit(this); |         this.ionSelect.emit(this); | ||||||
|         this.showHideNavBarButtons(true); |         this.showHideNavBarButtons(true); | ||||||
| @ -114,6 +137,9 @@ export class CoreTabComponent implements OnInit, OnDestroy { | |||||||
|      * Unselect tab. |      * Unselect tab. | ||||||
|      */ |      */ | ||||||
|     unselectTab(): void { |     unselectTab(): void { | ||||||
|  |         this.tabElement && this.tabElement.setAttribute('aria-selected', false); | ||||||
|  |         this.tabElement && this.tabElement.setAttribute('aria-hidden', true); | ||||||
|  | 
 | ||||||
|         this.element.classList.remove('selected'); |         this.element.classList.remove('selected'); | ||||||
|         this.showHideNavBarButtons(false); |         this.showHideNavBarButtons(false); | ||||||
|     } |     } | ||||||
|  | |||||||
| @ -10,19 +10,20 @@ ion-app.app-root .core-tabs-bar { | |||||||
|         width: 100%; |         width: 100%; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     a.tab-slide { |     ion-slide.tab-slide { | ||||||
|         @extend .tab-button; |         @extend .tab-button; | ||||||
| 
 | 
 | ||||||
|         background: $core-top-tabs-background; |         background: $core-top-tabs-background; | ||||||
|         color: $core-top-tabs-color !important; |         color: $core-top-tabs-color !important; | ||||||
|         font-size: 1.6rem; |         font-size: 1.6rem; | ||||||
|         border: 0; |         border-bottom: 2px solid transparent !important; | ||||||
|         padding: 0 5px 0 5px !important; |         padding: 0 2px 0 2px !important; | ||||||
|         margin: 0 auto !important; |         margin: 0 auto !important; | ||||||
|         display: flex; |         display: flex; | ||||||
|         flex-direction: row; |         flex: none; | ||||||
|  |         min-width: 100px; | ||||||
| 
 | 
 | ||||||
|         span { |         div { | ||||||
|             text-overflow: ellipsis; |             text-overflow: ellipsis; | ||||||
|             white-space: nowrap; |             white-space: nowrap; | ||||||
|             overflow: hidden; |             overflow: hidden; | ||||||
| @ -44,9 +45,12 @@ ion-app.app-root .core-tabs-bar { | |||||||
| 
 | 
 | ||||||
|         &[aria-selected=true] { |         &[aria-selected=true] { | ||||||
|             color: $core-top-tabs-color-active !important; |             color: $core-top-tabs-color-active !important; | ||||||
|             border: 0 !important; |             border-bottom-color: $core-top-tabs-border-active !important; | ||||||
|             border-bottom: 2px solid $core-top-tabs-border-active !important; |         } | ||||||
|             padding: 0 !important; | 
 | ||||||
|  |         .slide-zoom { | ||||||
|  |             display: flex; | ||||||
|  |             flex-direction: column; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -64,7 +68,7 @@ ion-app.app-root .core-tabs-bar { | |||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-app.app-root.md .core-tabs-bar a.tab-slide { | ion-app.app-root.md .core-tabs-bar ion-slide.tab-slide { | ||||||
|     // @extend .tabs-md .tab-button; |     // @extend .tabs-md .tab-button; | ||||||
|     min-height: $tabs-md-tab-min-height; |     min-height: $tabs-md-tab-min-height; | ||||||
| 
 | 
 | ||||||
| @ -72,7 +76,7 @@ ion-app.app-root.md .core-tabs-bar a.tab-slide { | |||||||
|     color: $tabs-md-tab-text-color; |     color: $tabs-md-tab-text-color; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-app.app-root.ios .core-tabs-bar a.tab-slide { | ion-app.app-root.ios .core-tabs-bar ion-slide.tab-slide { | ||||||
|     // @extend .tabs-ios .tab-button; |     // @extend .tabs-ios .tab-button; | ||||||
|     max-width: $tabs-ios-tab-max-width; |     max-width: $tabs-ios-tab-max-width; | ||||||
|     min-height: $tabs-ios-tab-min-height; |     min-height: $tabs-ios-tab-min-height; | ||||||
| @ -82,7 +86,7 @@ ion-app.app-root.ios .core-tabs-bar a.tab-slide { | |||||||
|     color: $tabs-ios-tab-text-color; |     color: $tabs-ios-tab-text-color; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| ion-app.app-root.wp .core-tabs-bar a.tab-slide { | ion-app.app-root.wp .core-tabs-bar ion-slide.tab-slide { | ||||||
|     //@extend .tabs-wp .tab-button; |     //@extend .tabs-wp .tab-button; | ||||||
|     @include border-radius(0); |     @include border-radius(0); | ||||||
| 
 | 
 | ||||||
| @ -124,6 +128,7 @@ ion-app.app-root core-tabs { | |||||||
|         display: none; |         display: none; | ||||||
|         height: 100%; |         height: 100%; | ||||||
|         position: relative; |         position: relative; | ||||||
|  |         z-index: 1; | ||||||
| 
 | 
 | ||||||
|         &.selected { |         &.selected { | ||||||
|             display: block; |             display: block; | ||||||
|  | |||||||
| @ -62,6 +62,7 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe | |||||||
|     slidesShown = this.maxSlides; |     slidesShown = this.maxSlides; | ||||||
|     numTabsShown = 0; |     numTabsShown = 0; | ||||||
|     direction = 'ltr'; |     direction = 'ltr'; | ||||||
|  |     description = ''; | ||||||
| 
 | 
 | ||||||
|     protected originalTabsContainer: HTMLElement; // The container of the original tabs. It will include each tab's content.
 |     protected originalTabsContainer: HTMLElement; // The container of the original tabs. It will include each tab's content.
 | ||||||
|     protected initialized = false; |     protected initialized = false; | ||||||
| @ -238,8 +239,8 @@ export class CoreTabsComponent implements OnInit, AfterViewInit, OnChanges, OnDe | |||||||
|     /** |     /** | ||||||
|      * Get the index of tab. |      * Get the index of tab. | ||||||
|      * |      * | ||||||
|      * @param  {any}    tab [description] |      * @param  {any}    tab Tab object to check. | ||||||
|      * @return {number}     [description] |      * @return {number}     Index number on the tabs array or -1 if not found. | ||||||
|      */ |      */ | ||||||
|     getIndex(tab: any): number { |     getIndex(tab: any): number { | ||||||
|         for (let i = 0; i < this.tabs.length; i++) { |         for (let i = 0; i < this.tabs.length; i++) { | ||||||
|  | |||||||
| @ -1,5 +1,5 @@ | |||||||
| <ion-item #container class="core-timer" [attr.text-center]="align == 'center' ? true : null" [attr.text-end]="align == 'right' ? true : null"> | <ion-item #container class="core-timer" [attr.text-center]="align == 'center' ? true : null" [attr.text-end]="align == 'right' ? true : null" role="timer"> | ||||||
|     <ion-icon name="timer" item-start></ion-icon> |     <ion-icon name="timer" item-start role="presentation"></ion-icon> | ||||||
|     <label *ngIf="timeLeft > 0 && timerText">{{ timerText }}</label> |     <label *ngIf="timeLeft > 0 && timerText">{{ timerText }}</label> | ||||||
|     <span *ngIf="timeLeft > 0">{{ timeLeft | coreSecondsToHMS }}</span> |     <span *ngIf="timeLeft > 0">{{ timeLeft | coreSecondsToHMS }}</span> | ||||||
|     <span class="core-timesup" *ngIf="timeLeft <= 0">{{ 'core.timesup' | translate }}</span> |     <span class="core-timesup" *ngIf="timeLeft <= 0">{{ 'core.timesup' | translate }}</span> | ||||||
|  | |||||||
| @ -11,7 +11,7 @@ | |||||||
|         <!-- Section selector. --> |         <!-- Section selector. --> | ||||||
|         <core-dynamic-component [component]="sectionSelectorComponent" [data]="data"> |         <core-dynamic-component [component]="sectionSelectorComponent" [data]="data"> | ||||||
|             <div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between class="safe-padding-horizontal"> |             <div text-wrap *ngIf="displaySectionSelector && sections && sections.length" padding class="clearfix" ion-row justify-content-between class="safe-padding-horizontal"> | ||||||
|                 <button float-start ion-button icon-start icon-end (click)="showSectionSelector($event)" color="light" class="core-button-select button-no-uppercase" ion-col> |                 <button float-start ion-button icon-start icon-end (click)="showSectionSelector($event)" color="light" class="core-button-select button-no-uppercase" ion-col [attr.aria-label]="('core.course.sections' | translate) + ': ' + (selectedSection && (selectedSection.formattedName || selectedSection.name))" aria-haspopup="true" [attr.aria-expanded]="sectionSelectorExpanded" aria-controls="core-course-section-selector" id="core-course-section-button"> | ||||||
|                     <core-icon name="fa-folder"></core-icon> |                     <core-icon name="fa-folder"></core-icon> | ||||||
|                     <span class="core-section-selector-text">{{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }}</span> |                     <span class="core-section-selector-text">{{selectedSection && (selectedSection.formattedName || selectedSection.name) || 'core.course.sections' | translate }}</span> | ||||||
|                     <ion-icon name="arrow-dropdown" ios="md-arrow-dropdown"></ion-icon> |                     <ion-icon name="arrow-dropdown" ios="md-arrow-dropdown"></ion-icon> | ||||||
|  | |||||||
| @ -61,6 +61,7 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | |||||||
|     allSectionsComponent: any; |     allSectionsComponent: any; | ||||||
|     canLoadMore = false; |     canLoadMore = false; | ||||||
|     showSectionId = 0; |     showSectionId = 0; | ||||||
|  |     sectionSelectorExpanded = false; | ||||||
| 
 | 
 | ||||||
|     // Data to pass to the components.
 |     // Data to pass to the components.
 | ||||||
|     data: any = {}; |     data: any = {}; | ||||||
| @ -243,16 +244,27 @@ export class CoreCourseFormatComponent implements OnInit, OnChanges, OnDestroy { | |||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Display the section selector modal. |      * Display the section selector modal. | ||||||
|  |      * | ||||||
|  |      * @param {MouseEvent} event Event. | ||||||
|      */ |      */ | ||||||
|     showSectionSelector(): void { |     showSectionSelector(event: MouseEvent): void { | ||||||
|         const modal = this.modalCtrl.create('CoreCourseSectionSelectorPage', |         if (!this.sectionSelectorExpanded) { | ||||||
|             {course: this.course, sections: this.sections, selected: this.selectedSection}); |             const modal = this.modalCtrl.create('CoreCourseSectionSelectorPage', | ||||||
|         modal.onDidDismiss((newSection) => { |                 {course: this.course, sections: this.sections, selected: this.selectedSection}); | ||||||
|             if (newSection) { |             modal.onDidDismiss((newSection) => { | ||||||
|                 this.sectionChanged(newSection); |                 if (newSection) { | ||||||
|             } |                     this.sectionChanged(newSection); | ||||||
|         }); |                 } | ||||||
|         modal.present(); | 
 | ||||||
|  |                 this.sectionSelectorExpanded = false; | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             modal.present({ | ||||||
|  |                 ev: event | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |             this.sectionSelectorExpanded = true; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -1,6 +1,6 @@ | |||||||
| <a *ngIf="module && module.visibleoncoursepage !== 0" ion-item text-wrap id="core-course-module-{{module.id}}" class="core-course-module-handler {{module.handlerData.class}}" (click)="moduleClicked($event)" [ngClass]="{'item-media': module.handlerData.icon, 'core-not-clickable': !module.handlerData.action || !module.uservisible === false, 'item-dimmed': module.visible === 0 || module.uservisible === false}" [title]="module.handlerData.a11yTitle" detail-none> | <a *ngIf="module && module.visibleoncoursepage !== 0" ion-item text-wrap id="core-course-module-{{module.id}}" class="core-course-module-handler {{module.handlerData.class}}" (click)="moduleClicked($event)" [ngClass]="{'item-media': module.handlerData.icon, 'core-not-clickable': !module.handlerData.action || !module.uservisible === false, 'item-dimmed': module.visible === 0 || module.uservisible === false}" [title]="module.handlerData.a11yTitle" detail-none> | ||||||
| 
 | 
 | ||||||
|     <img item-start *ngIf="module.handlerData.icon" [src]="module.handlerData.icon" alt="" role="presentation" class="core-module-icon"> |     <img item-start *ngIf="module.handlerData.icon" [src]="module.handlerData.icon" [alt]="module.modnametranslated" class="core-module-icon"> | ||||||
|     <div class="core-module-title"> |     <div class="core-module-title"> | ||||||
|         <core-format-text [text]="module.handlerData.title"></core-format-text> |         <core-format-text [text]="module.handlerData.title"></core-format-text> | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -18,6 +18,7 @@ import { CoreEventsProvider } from '@providers/events'; | |||||||
| import { CoreSitesProvider } from '@providers/sites'; | import { CoreSitesProvider } from '@providers/sites'; | ||||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||||
| import { CoreCourseHelperProvider } from '../../providers/helper'; | import { CoreCourseHelperProvider } from '../../providers/helper'; | ||||||
|  | import { CoreCourseProvider } from '../../providers/course'; | ||||||
| import { CoreCourseModuleHandlerButton } from '../../providers/module-delegate'; | import { CoreCourseModuleHandlerButton } from '../../providers/module-delegate'; | ||||||
| import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchHandler } from '../../providers/module-prefetch-delegate'; | import { CoreCourseModulePrefetchDelegate, CoreCourseModulePrefetchHandler } from '../../providers/module-prefetch-delegate'; | ||||||
| import { CoreConstants } from '../../../constants'; | import { CoreConstants } from '../../../constants'; | ||||||
| @ -63,7 +64,8 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|     constructor(@Optional() protected navCtrl: NavController, protected prefetchDelegate: CoreCourseModulePrefetchDelegate, |     constructor(@Optional() protected navCtrl: NavController, protected prefetchDelegate: CoreCourseModulePrefetchDelegate, | ||||||
|             protected domUtils: CoreDomUtilsProvider, protected courseHelper: CoreCourseHelperProvider, |             protected domUtils: CoreDomUtilsProvider, protected courseHelper: CoreCourseHelperProvider, | ||||||
|             protected eventsProvider: CoreEventsProvider, protected sitesProvider: CoreSitesProvider) { |             protected eventsProvider: CoreEventsProvider, protected sitesProvider: CoreSitesProvider, | ||||||
|  |             protected courseProvider: CoreCourseProvider) { | ||||||
|         this.completionChanged = new EventEmitter(); |         this.completionChanged = new EventEmitter(); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
| @ -97,6 +99,8 @@ export class CoreCourseModuleComponent implements OnInit, OnDestroy { | |||||||
| 
 | 
 | ||||||
|         this.module.handlerData.a11yTitle = typeof this.module.handlerData.a11yTitle != 'undefined' ? |         this.module.handlerData.a11yTitle = typeof this.module.handlerData.a11yTitle != 'undefined' ? | ||||||
|             this.module.handlerData.a11yTitle : this.module.handlerData.title; |             this.module.handlerData.a11yTitle : this.module.handlerData.title; | ||||||
|  | 
 | ||||||
|  |         this.module.modnametranslated = this.courseProvider.translateModuleName(this.module.modname) || ''; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -9,13 +9,15 @@ | |||||||
|     </ion-navbar> |     </ion-navbar> | ||||||
| </ion-header> | </ion-header> | ||||||
| <ion-content> | <ion-content> | ||||||
|     <ng-container *ngFor="let section of sections"> |     <ion-list id="core-course-section-selector" role="menu" aria-labelledby="core-course-section-button"> | ||||||
|         <a ion-item *ngIf="!section.hiddenbynumsections && section.id != stealthModulesSectionId" text-wrap (click)="selectSection(section)" [class.core-primary-selected-item]="selected.id == section.id" [class.item-dimmed]="section.visible === 0 || section.uservisible === false" detail-none> |         <ng-container *ngFor="let section of sections"> | ||||||
|             <core-icon name="fa-folder" item-start></core-icon> |             <a ion-item *ngIf="!section.hiddenbynumsections && section.id != stealthModulesSectionId" text-wrap (click)="selectSection(section)" [class.core-primary-selected-item]="selected.id == section.id" [class.item-dimmed]="section.visible === 0 || section.uservisible === false" detail-none role="menuitem" [attr.aria-hidden]="section.uservisible === false" [attr.aria-label]="section.formattedName || section.name"> | ||||||
|             <h2><core-format-text [text]="section.formattedName || section.name"></core-format-text></h2> |                 <core-icon name="fa-folder" item-start></core-icon> | ||||||
|             <core-progress-bar *ngIf="section.progress >= 0" [progress]="section.progress"></core-progress-bar> |                 <h2><core-format-text [text]="section.formattedName || section.name"></core-format-text></h2> | ||||||
|             <ion-badge color="secondary" *ngIf="section.visible === 0 && section.uservisible !== false">{{ 'core.course.hiddenfromstudents' | translate }}</ion-badge> |                 <core-progress-bar *ngIf="section.progress >= 0" [progress]="section.progress"></core-progress-bar> | ||||||
|             <ion-badge color="secondary" *ngIf="section.availabilityinfo"><core-format-text  [text]=" section.availabilityinfo"></core-format-text></ion-badge> |                 <ion-badge color="secondary" *ngIf="section.visible === 0 && section.uservisible !== false" text-wrap>{{ 'core.course.hiddenfromstudents' | translate }}</ion-badge> | ||||||
|         </a> |                 <ion-badge color="secondary" *ngIf="section.availabilityinfo" text-wrap><core-format-text  [text]=" section.availabilityinfo"></core-format-text></ion-badge> | ||||||
|     </ng-container> |             </a> | ||||||
|  |         </ng-container> | ||||||
|  |     </ion-list> | ||||||
| </ion-content> | </ion-content> | ||||||
|  | |||||||
| @ -8,4 +8,8 @@ ion-app.app-root page-core-course-section-selector { | |||||||
|             margin: 8px 0 4px 0; |             margin: 8px 0 4px 0; | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     ion-badge { | ||||||
|  |         text-align: left; | ||||||
|  |     } | ||||||
| } | } | ||||||
| @ -30,19 +30,19 @@ | |||||||
|             </a> |             </a> | ||||||
|         </div> |         </div> | ||||||
|         <a *ngIf="showWeb" ion-item [href]="siteInfo.siteurl" core-link autoLogin="yes" title="{{ 'core.mainmenu.website' | translate }}"> |         <a *ngIf="showWeb" ion-item [href]="siteInfo.siteurl" core-link autoLogin="yes" title="{{ 'core.mainmenu.website' | translate }}"> | ||||||
|             <ion-icon name="globe" item-start></ion-icon> |             <ion-icon name="globe" item-start aria-hidden="true"></ion-icon> | ||||||
|             <p>{{ 'core.mainmenu.website' | translate }}</p> |             <p>{{ 'core.mainmenu.website' | translate }}</p> | ||||||
|         </a> |         </a> | ||||||
|         <a *ngIf="showHelp" ion-item [href]="docsUrl" core-link autoLogin="no" title="{{ 'core.mainmenu.help' | translate }}"> |         <a *ngIf="showHelp" ion-item [href]="docsUrl" core-link autoLogin="no" title="{{ 'core.mainmenu.help' | translate }}"> | ||||||
|             <ion-icon name="help-buoy" item-start></ion-icon> |             <ion-icon name="help-buoy" item-start aria-hidden="true"></ion-icon> | ||||||
|             <p>{{ 'core.mainmenu.help' | translate }}</p> |             <p>{{ 'core.mainmenu.help' | translate }}</p> | ||||||
|         </a> |         </a> | ||||||
|         <a ion-item (click)="openSettings()" title="{{ 'core.mainmenu.appsettings' | translate }}"> |         <a ion-item (click)="openSettings()" title="{{ 'core.mainmenu.appsettings' | translate }}"> | ||||||
|             <ion-icon name="cog" item-start></ion-icon> |             <ion-icon name="cog" item-start aria-hidden="true"></ion-icon> | ||||||
|             <p>{{ 'core.mainmenu.appsettings' | translate }}</p> |             <p>{{ 'core.mainmenu.appsettings' | translate }}</p> | ||||||
|         </a> |         </a> | ||||||
|         <a ion-item (click)="logout()" title="{{ logoutLabel | translate }}"> |         <a ion-item (click)="logout()" title="{{ logoutLabel | translate }}"> | ||||||
|             <ion-icon name="log-out" item-start></ion-icon> |             <ion-icon name="log-out" item-start aria-hidden="true"></ion-icon> | ||||||
|             <p>{{ logoutLabel | translate }}</p> |             <p>{{ logoutLabel | translate }}</p> | ||||||
|         </a> |         </a> | ||||||
|     </ion-list> |     </ion-list> | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user