MOBILE-3807 mainmenu: Add new user menu modal
This commit is contained in:
		
							parent
							
								
									289e8e1ce7
								
							
						
					
					
						commit
						81fdd00902
					
				
							
								
								
									
										33
									
								
								src/core/features/mainmenu/components/components.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/core/features/mainmenu/components/components.module.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | |||||||
|  | // (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 { NgModule } from '@angular/core'; | ||||||
|  | import { CoreSharedModule } from '@/core/shared.module'; | ||||||
|  | import { CoreMainMenuUserButtonComponent } from './user-menu-button/user-menu-button'; | ||||||
|  | import { CoreMainMenuUserMenuComponent } from './user-menu/user-menu'; | ||||||
|  | 
 | ||||||
|  | @NgModule({ | ||||||
|  |     declarations: [ | ||||||
|  |         CoreMainMenuUserButtonComponent, | ||||||
|  |         CoreMainMenuUserMenuComponent, | ||||||
|  |     ], | ||||||
|  |     imports: [ | ||||||
|  |         CoreSharedModule, | ||||||
|  |     ], | ||||||
|  |     exports: [ | ||||||
|  |         CoreMainMenuUserButtonComponent, | ||||||
|  |         CoreMainMenuUserMenuComponent, | ||||||
|  |     ], | ||||||
|  | }) | ||||||
|  | export class CoreMainMenuComponentsModule {} | ||||||
| @ -0,0 +1,9 @@ | |||||||
|  | <core-user-avatar | ||||||
|  |     *ngIf="siteInfo" | ||||||
|  |     [user]="siteInfo" | ||||||
|  |     class="core-bar-button-image clickable" | ||||||
|  |     [linkProfile]="false" | ||||||
|  |     (ariaButtonClick)="openUserMenu($event)" | ||||||
|  |     role="button" | ||||||
|  |     tabindex="0" | ||||||
|  | ></core-user-avatar> | ||||||
| @ -0,0 +1,55 @@ | |||||||
|  | // (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 } from '@angular/core'; | ||||||
|  | import { CoreSiteInfo } from '@classes/site'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
|  | import { CoreDomUtils } from '@services/utils/dom'; | ||||||
|  | import { CoreMainMenuUserMenuComponent } from '../user-menu/user-menu'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Component to display an avatar on the header to open user menu. | ||||||
|  |  * | ||||||
|  |  * Example: <core-user-menu-button></core-user-menu-button> | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'core-user-menu-button', | ||||||
|  |     templateUrl: 'user-menu-button.html', | ||||||
|  | }) | ||||||
|  | export class CoreMainMenuUserButtonComponent { | ||||||
|  | 
 | ||||||
|  |     siteInfo?: CoreSiteInfo; | ||||||
|  | 
 | ||||||
|  |     constructor() { | ||||||
|  |         const currentSite = CoreSites.getRequiredCurrentSite(); | ||||||
|  | 
 | ||||||
|  |         // @TODO: Check if the page where I currently am is at level 0.
 | ||||||
|  |         this.siteInfo = currentSite.getInfo(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Open User menu | ||||||
|  |      * | ||||||
|  |      * @param event Click event. | ||||||
|  |      */ | ||||||
|  |     openUserMenu(event: Event): void { | ||||||
|  |         event.preventDefault(); | ||||||
|  |         event.stopPropagation(); | ||||||
|  | 
 | ||||||
|  |         CoreDomUtils.openModal<void>({ | ||||||
|  |             component: CoreMainMenuUserMenuComponent, | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -0,0 +1,63 @@ | |||||||
|  | <ion-header> | ||||||
|  |     <ion-toolbar> | ||||||
|  |         <ion-buttons slot="start"> | ||||||
|  |             <ion-button fill="clear" (click)="close($event)" [attr.aria-label]="'core.close' | translate"> | ||||||
|  |                 <ion-icon name="fas-times" slot="icon-only" aria-hidden="true"></ion-icon> | ||||||
|  |             </ion-button> | ||||||
|  |         </ion-buttons> | ||||||
|  |         <h1> | ||||||
|  |             {{'core.user.account' | translate}} | ||||||
|  |         </h1> | ||||||
|  |     </ion-toolbar> | ||||||
|  | </ion-header> | ||||||
|  | <ion-content> | ||||||
|  |     <core-loading [hideUntil]="true"> | ||||||
|  |         <ion-list> | ||||||
|  |             <ion-item class="ion-text-center core-user-profile-maininfo" *ngIf="siteInfo"> | ||||||
|  |                 <core-user-avatar [user]="siteInfo" [userId]="siteInfo.userid" [linkProfile]="false"></core-user-avatar> | ||||||
|  |                 <ion-label> | ||||||
|  |                     <h2>{{ siteInfo.fullname }}</h2> | ||||||
|  |                     <p class="core-usermenu-siteinfo core-usermenu-sitename"> | ||||||
|  |                         <core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true"> | ||||||
|  |                         </core-format-text> | ||||||
|  |                     </p> | ||||||
|  |                     <p class="core-usermenu-siteinfo core-usermenu-siteurl">{{ siteUrl }}</p> | ||||||
|  |                 </ion-label> | ||||||
|  |             </ion-item> | ||||||
|  | 
 | ||||||
|  |             <ion-item button class="ion-text-wrap core-usermenu-handler" (click)="openUserProfile($event)" | ||||||
|  |                 [attr.aria-label]="'core.user.details' | translate" detail="true"> | ||||||
|  |                 <ion-icon name="fas-user" slot="start" aria-hidden="true"></ion-icon> | ||||||
|  |                 <ion-label> | ||||||
|  |                     <p class="item-heading">{{ 'core.user.details' | translate }}</p> | ||||||
|  |                 </ion-label> | ||||||
|  |             </ion-item> | ||||||
|  | 
 | ||||||
|  |             <ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded"> | ||||||
|  |                 <ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label> | ||||||
|  |             </ion-item> | ||||||
|  | 
 | ||||||
|  |             <ion-item button *ngFor="let handler of handlers" class="ion-text-wrap" (click)="handlerClicked($event, handler)" | ||||||
|  |                 [ngClass]="['core-user-menu-handler', handler.class || '']" [hidden]="handler.hidden" | ||||||
|  |                 [attr.aria-label]="handler.title | translate" detail="true"> | ||||||
|  |                 <ion-icon *ngIf="handler.icon" [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon> | ||||||
|  |                 <ion-label> | ||||||
|  |                     <p class="item-heading">{{ handler.title | translate }}</p> | ||||||
|  |                 </ion-label> | ||||||
|  |             </ion-item> | ||||||
|  | 
 | ||||||
|  |             <ion-item button (click)="openPreferences($event)" [attr.aria-label]="'core.settings.preferences' | translate" detail="true"> | ||||||
|  |                 <ion-icon name="fas-wrench" slot="start" aria-hidden="true"></ion-icon> | ||||||
|  |                 <ion-label> | ||||||
|  |                     <p class="item-heading">{{ 'core.settings.preferences' | translate }}</p> | ||||||
|  |                 </ion-label> | ||||||
|  |             </ion-item> | ||||||
|  |         </ion-list> | ||||||
|  |     </core-loading> | ||||||
|  | </ion-content> | ||||||
|  | <ion-footer class="ion-padding"> | ||||||
|  |     <ion-button (click)="logout($event)" expand="block" color="danger" [attr.aria-label]="logoutLabel | translate" class="ion-text-wrap"> | ||||||
|  |         <ion-icon name="fas-sign-out-alt" slot="start" aria-hidden="true"></ion-icon> | ||||||
|  |         {{ logoutLabel | translate }} | ||||||
|  |     </ion-button> | ||||||
|  | </ion-footer> | ||||||
| @ -0,0 +1,38 @@ | |||||||
|  | @import "~theme/globals"; | ||||||
|  | 
 | ||||||
|  | :host { | ||||||
|  |     .core-user-profile-maininfo::part(native) { | ||||||
|  |         flex-direction: column; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     ::ng-deep { | ||||||
|  |         core-user-avatar { | ||||||
|  |             display: block; | ||||||
|  |             --core-avatar-size: var(--core-large-avatar-size); | ||||||
|  |             height: calc(var(--core-avatar-size) + 16px); | ||||||
|  | 
 | ||||||
|  |             img { | ||||||
|  |                 margin: 8px auto; | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | @if ($core-user-hide-siteinfo) { | ||||||
|  |     .core-usermenu-siteinfo { | ||||||
|  |         display: none; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @if ($core-user-hide-sitename) { | ||||||
|  |     .core-usermenu-sitename { | ||||||
|  |         display: none; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | @if ($core-user-hide-siteurl) { | ||||||
|  |     .core-usermenu-siteurl { | ||||||
|  |         display: none; | ||||||
|  |     } | ||||||
|  | } | ||||||
							
								
								
									
										153
									
								
								src/core/features/mainmenu/components/user-menu/user-menu.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/core/features/mainmenu/components/user-menu/user-menu.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,153 @@ | |||||||
|  | // (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, OnDestroy, OnInit } from '@angular/core'; | ||||||
|  | import { CoreSiteInfo } from '@classes/site'; | ||||||
|  | import { CoreLoginHelper } from '@features/login/services/login-helper'; | ||||||
|  | import { CoreUser, CoreUserProfile } from '@features/user/services/user'; | ||||||
|  | import { CoreUserProfileHandlerData, CoreUserDelegate, CoreUserDelegateService } from '@features/user/services/user-delegate'; | ||||||
|  | import { CoreNavigator } from '@services/navigator'; | ||||||
|  | import { CoreSites } from '@services/sites'; | ||||||
|  | import { ModalController } from '@singletons'; | ||||||
|  | import { Subscription } from 'rxjs'; | ||||||
|  | 
 | ||||||
|  | /** | ||||||
|  |  * Component to display a user menu. | ||||||
|  |  */ | ||||||
|  | @Component({ | ||||||
|  |     selector: 'core-main-menu-user-menu', | ||||||
|  |     templateUrl: 'user-menu.html', | ||||||
|  |     styleUrls: ['user-menu.scss'], | ||||||
|  | }) | ||||||
|  | export class CoreMainMenuUserMenuComponent implements OnInit, OnDestroy { | ||||||
|  | 
 | ||||||
|  |     siteInfo?: CoreSiteInfo; | ||||||
|  |     siteName?: string; | ||||||
|  |     logoutLabel = 'core.mainmenu.changesite'; | ||||||
|  |     siteUrl?: string; | ||||||
|  |     handlers: CoreUserProfileHandlerData[] = []; | ||||||
|  |     handlersLoaded = false; | ||||||
|  |     user?: CoreUserProfile; | ||||||
|  | 
 | ||||||
|  |     protected subscription!: Subscription; | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     async ngOnInit(): Promise<void> { | ||||||
|  | 
 | ||||||
|  |         const currentSite = CoreSites.getRequiredCurrentSite(); | ||||||
|  | 
 | ||||||
|  |         this.siteInfo = currentSite.getInfo(); | ||||||
|  |         this.siteName = currentSite.getSiteName(); | ||||||
|  |         this.siteUrl = currentSite.getURL(); | ||||||
|  |         this.logoutLabel = CoreLoginHelper.getLogoutLabel(currentSite); | ||||||
|  | 
 | ||||||
|  |         // Load the handlers.
 | ||||||
|  |         if (this.siteInfo) { | ||||||
|  |             this.user = await CoreUser.getProfile(this.siteInfo.userid); | ||||||
|  | 
 | ||||||
|  |             this.subscription = CoreUserDelegate.getProfileHandlersFor(this.user).subscribe((handlers) => { | ||||||
|  |                 if (!handlers || !this.user) { | ||||||
|  |                     return; | ||||||
|  |                 } | ||||||
|  | 
 | ||||||
|  |                 this.handlers = []; | ||||||
|  |                 handlers.forEach((handler) => { | ||||||
|  |                     if (handler.type == CoreUserDelegateService.TYPE_NEW_PAGE) { | ||||||
|  |                         this.handlers.push(handler.data); | ||||||
|  |                     } | ||||||
|  |                 }); | ||||||
|  | 
 | ||||||
|  |                 this.handlersLoaded = CoreUserDelegate.areHandlersLoaded(this.user.id); | ||||||
|  |             }); | ||||||
|  | 
 | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Opens User profile page. | ||||||
|  |      * | ||||||
|  |      * @param event Click event. | ||||||
|  |      */ | ||||||
|  |     async openUserProfile(event: Event): Promise<void> { | ||||||
|  |         if (!this.siteInfo) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         await this.close(event); | ||||||
|  | 
 | ||||||
|  |         CoreNavigator.navigateToSitePath('user/about', { | ||||||
|  |             params: { | ||||||
|  |                 userId: this.siteInfo.userid, | ||||||
|  |             }, | ||||||
|  |         }); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Opens preferences. | ||||||
|  |      * | ||||||
|  |      * @param event Click event. | ||||||
|  |      */ | ||||||
|  |     async openPreferences(event: Event): Promise<void> { | ||||||
|  |         await this.close(event); | ||||||
|  | 
 | ||||||
|  |         CoreNavigator.navigateToSitePath('preferences'); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * A handler was clicked. | ||||||
|  |      * | ||||||
|  |      * @param event Click event. | ||||||
|  |      * @param handler Handler that was clicked. | ||||||
|  |      */ | ||||||
|  |     async handlerClicked(event: Event, handler: CoreUserProfileHandlerData): Promise<void> { | ||||||
|  |         if (!this.user) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         await this.close(event); | ||||||
|  | 
 | ||||||
|  |         handler.action(event, this.user); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Logout the user. | ||||||
|  |      * | ||||||
|  |      * @param event Click event | ||||||
|  |      */ | ||||||
|  |     async logout(event: Event): Promise<void> { | ||||||
|  |         await this.close(event); | ||||||
|  | 
 | ||||||
|  |         CoreSites.logout(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Close modal. | ||||||
|  |      */ | ||||||
|  |     async close(event: Event): Promise<void> { | ||||||
|  |         event.preventDefault(); | ||||||
|  |         event.stopPropagation(); | ||||||
|  | 
 | ||||||
|  |         await ModalController.dismiss(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     ngOnDestroy(): void { | ||||||
|  |         this.subscription?.unsubscribe(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  | } | ||||||
| @ -5,97 +5,76 @@ | |||||||
|         </ion-buttons> |         </ion-buttons> | ||||||
| 
 | 
 | ||||||
|         <h1><core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0"></core-format-text></h1> |         <h1><core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0"></core-format-text></h1> | ||||||
|  | 
 | ||||||
|  |         <ion-buttons slot="end"> | ||||||
|  |             <core-user-menu-button></core-user-menu-button> | ||||||
|  |         </ion-buttons> | ||||||
|     </ion-toolbar> |     </ion-toolbar> | ||||||
| </ion-header> | </ion-header> | ||||||
| <ion-content> | <ion-content> | ||||||
|     <core-loading [hideUntil]="!loggedOut"> |     <ion-list> | ||||||
|         <ion-list> |         <ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded"> | ||||||
|             <ion-item button *ngIf="siteInfo" class="ion-text-wrap" core-user-link [userId]="siteInfo.userid" detail="true"> |             <ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label> | ||||||
|                 <core-user-avatar [user]="siteInfo" slot="start"></core-user-avatar> |         </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"> | ||||||
|  |             <ion-icon [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon> | ||||||
|  |             <ion-label> | ||||||
|  |                 <p class="item-heading">{{ handler.title | translate}}</p> | ||||||
|  |             </ion-label> | ||||||
|  |             <ion-badge slot="end" *ngIf="handler.showBadge" [hidden]="handler.loading || !handler.badge" aria-hidden="true"> | ||||||
|  |                 {{handler.badge}} | ||||||
|  |             </ion-badge> | ||||||
|  |             <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" [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 | ||||||
|  |                 [capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" class="core-moremenu-customitem" detail="true" | ||||||
|  |                 [detailIcon]="item.type == 'browser' ? 'open-outline' : 'chevron-forward'"> | ||||||
|  |                 <ion-icon [name]="item.icon" slot="start" aria-hidden="true"></ion-icon> | ||||||
|                 <ion-label> |                 <ion-label> | ||||||
|                     <p class="item-heading">{{siteInfo.fullname}}</p> |                     <p class="item-heading">{{item.label}}</p> | ||||||
|                     <p class="core-moremenu-siteinfo core-moremenu-sitename"> |  | ||||||
|                         <core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true"> |  | ||||||
|                         </core-format-text> |  | ||||||
|                     </p> |  | ||||||
|                     <p class="core-moremenu-siteinfo core-moremenu-siteurl">{{ siteUrl }}</p> |  | ||||||
|                 </ion-label> |                 </ion-label> | ||||||
|             </ion-item> |             </ion-item> | ||||||
|             <core-spacer></core-spacer> |             <ion-item button *ngIf="item.type == 'embedded'" (click)="openItem(item)" [attr.aria-label]="item.label" | ||||||
|             <ion-item class="ion-text-center" *ngIf="(!handlers || !handlers.length) && !handlersLoaded"> |                 class="core-moremenu-customitem" detail="true"> | ||||||
|                 <ion-label><ion-spinner [attr.aria-label]="'core.loading' | translate"></ion-spinner></ion-label> |                 <ion-icon [name]="item.icon" slot="start" aria-hidden="true"></ion-icon> | ||||||
|             </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"> |  | ||||||
|                 <ion-icon [name]="handler.icon" slot="start" aria-hidden="true"></ion-icon> |  | ||||||
|                 <ion-label> |                 <ion-label> | ||||||
|                     <p class="item-heading">{{ handler.title | translate}}</p> |                     <p class="item-heading">{{item.label}}</p> | ||||||
|                 </ion-label> |  | ||||||
|                 <ion-badge slot="end" *ngIf="handler.showBadge" [hidden]="handler.loading || !handler.badge" aria-hidden="true"> |  | ||||||
|                     {{handler.badge}} |  | ||||||
|                 </ion-badge> |  | ||||||
|                 <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" [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 |  | ||||||
|                     [capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" class="core-moremenu-customitem" detail="true" |  | ||||||
|                     [detailIcon]="item.type == 'browser' ? 'open-outline' : 'chevron-forward'"> |  | ||||||
|                     <ion-icon [name]="item.icon" slot="start" aria-hidden="true"></ion-icon> |  | ||||||
|                     <ion-label> |  | ||||||
|                         <p class="item-heading">{{item.label}}</p> |  | ||||||
|                     </ion-label> |  | ||||||
|                 </ion-item> |  | ||||||
|                 <ion-item button *ngIf="item.type == 'embedded'" (click)="openItem(item)" [attr.aria-label]="item.label" |  | ||||||
|                     class="core-moremenu-customitem" detail="true"> |  | ||||||
|                     <ion-icon [name]="item.icon" slot="start" aria-hidden="true"></ion-icon> |  | ||||||
|                     <ion-label> |  | ||||||
|                         <p class="item-heading">{{item.label}}</p> |  | ||||||
|                     </ion-label> |  | ||||||
|                 </ion-item> |  | ||||||
|             </ng-container> |  | ||||||
|             <ion-item button *ngIf="showScanQR" (click)="scanQR()" detail="true"> |  | ||||||
|                 <ion-icon name="fas-qrcode" slot="start" aria-hidden="true"></ion-icon> |  | ||||||
|                 <ion-label> |  | ||||||
|                     <p class="item-heading">{{ 'core.scanqr' | translate }}</p> |  | ||||||
|                 </ion-label> |                 </ion-label> | ||||||
|             </ion-item> |             </ion-item> | ||||||
|             <ion-item button *ngIf="showWeb && siteInfo" [href]="siteInfo.siteurl" core-link autoLogin="yes" |         </ng-container> | ||||||
|                 [attr.aria-label]="'core.mainmenu.website' | translate" detail="true" detailIcon="open-outline"> |         <ion-item button *ngIf="showScanQR" (click)="scanQR()" detail="true"> | ||||||
|                 <ion-icon name="fas-globe" slot="start" aria-hidden="true"></ion-icon> |             <ion-icon name="fas-qrcode" slot="start" aria-hidden="true"></ion-icon> | ||||||
|                 <ion-label> |             <ion-label> | ||||||
|                     <p class="item-heading">{{ 'core.mainmenu.website' | translate }}</p> |                 <p class="item-heading">{{ 'core.scanqr' | translate }}</p> | ||||||
|                 </ion-label> |             </ion-label> | ||||||
|             </ion-item> |         </ion-item> | ||||||
|             <ion-item button *ngIf="showHelp" [href]="docsUrl" core-link autoLogin="no" |         <ion-item button *ngIf="showWeb && siteInfo" [href]="siteInfo.siteurl" core-link autoLogin="yes" | ||||||
|                 [attr.aria-label]="'core.mainmenu.help' | translate" detail="true" detailIcon="open-outline"> |             [attr.aria-label]="'core.mainmenu.website' | translate" detail="true" detailIcon="open-outline"> | ||||||
|                 <ion-icon name="far-life-ring" slot="start" aria-hidden="true"></ion-icon> |             <ion-icon name="fas-globe" slot="start" aria-hidden="true"></ion-icon> | ||||||
|                 <ion-label> |             <ion-label> | ||||||
|                     <p class="item-heading">{{ 'core.mainmenu.help' | translate }}</p> |                 <p class="item-heading">{{ 'core.mainmenu.website' | translate }}</p> | ||||||
|                 </ion-label> |             </ion-label> | ||||||
|             </ion-item> |         </ion-item> | ||||||
|             <ion-item button (click)="openPreferences()" [attr.aria-label]="'core.settings.preferences' | translate" detail="true"> |         <ion-item button *ngIf="showHelp" [href]="docsUrl" core-link autoLogin="no" | ||||||
|                 <ion-icon name="fas-wrench" slot="start" aria-hidden="true"></ion-icon> |             [attr.aria-label]="'core.mainmenu.help' | translate" detail="true" detailIcon="open-outline"> | ||||||
|                 <ion-label> |             <ion-icon name="far-life-ring" slot="start" aria-hidden="true"></ion-icon> | ||||||
|                     <p class="item-heading">{{ 'core.settings.preferences' | translate }}</p> |             <ion-label> | ||||||
|                 </ion-label> |                 <p class="item-heading">{{ 'core.mainmenu.help' | translate }}</p> | ||||||
|             </ion-item> |             </ion-label> | ||||||
|             <ion-item button (click)="logout()" [attr.aria-label]="logoutLabel | translate" detail="true"> |         </ion-item> | ||||||
|                 <ion-icon name="fas-sign-out-alt" slot="start" aria-hidden="true"></ion-icon> |     </ion-list> | ||||||
|                 <ion-label> |  | ||||||
|                     <p class="item-heading">{{ logoutLabel | translate }}</p> |  | ||||||
|                 </ion-label> |  | ||||||
|             </ion-item> |  | ||||||
|             <core-spacer></core-spacer> |  | ||||||
|             <ion-item button (click)="openSettings()" [attr.aria-label]="'core.settings.appsettings' | translate" detail="true"> |  | ||||||
|                 <ion-icon name="fas-cogs" slot="start" aria-hidden="true"></ion-icon> |  | ||||||
|                 <ion-label> |  | ||||||
|                     <p class="item-heading">{{ 'core.settings.appsettings' | translate }}</p> |  | ||||||
|                 </ion-label> |  | ||||||
|             </ion-item> |  | ||||||
|         </ion-list> |  | ||||||
|     </core-loading> |  | ||||||
| </ion-content> | </ion-content> | ||||||
|  | <ion-footer> | ||||||
|  |     <ion-item button (click)="openSettings()" [attr.aria-label]="'core.settings.appsettings' | translate" detail="true"> | ||||||
|  |         <ion-icon name="fas-cogs" slot="start" aria-hidden="true"></ion-icon> | ||||||
|  |         <ion-label> | ||||||
|  |             <p class="item-heading">{{ 'core.settings.appsettings' | translate }}</p> | ||||||
|  |         </ion-label> | ||||||
|  |     </ion-item> | ||||||
|  | </ion-footer> | ||||||
|  | |||||||
| @ -19,10 +19,12 @@ import { CoreSharedModule } from '@/core/shared.module'; | |||||||
| import { CoreMainMenuMorePage } from './more'; | import { CoreMainMenuMorePage } from './more'; | ||||||
| import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; | import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; | ||||||
| import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu'; | import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu'; | ||||||
|  | import { CoreMainMenuComponentsModule } from '@features/mainmenu/components/components.module'; | ||||||
| 
 | 
 | ||||||
| @NgModule({ | @NgModule({ | ||||||
|     imports: [ |     imports: [ | ||||||
|         CoreSharedModule, |         CoreSharedModule, | ||||||
|  |         CoreMainMenuComponentsModule, | ||||||
|     ], |     ], | ||||||
|     providers: [ |     providers: [ | ||||||
|         { |         { | ||||||
|  | |||||||
| @ -17,21 +17,3 @@ ion-item { | |||||||
|         color: var(--core-more-icon, inherit); |         color: var(--core-more-icon, inherit); | ||||||
|     } |     } | ||||||
| } | } | ||||||
| 
 |  | ||||||
| @if ($core-more-hide-siteinfo) { |  | ||||||
|     .core-moremenu-siteinfo { |  | ||||||
|         display: none; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @if ($core-more-hide-sitename) { |  | ||||||
|     .core-moremenu-sitename { |  | ||||||
|         display: none; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| @if ($core-more-hide-siteurl) { |  | ||||||
|     .core-moremenu-siteurl { |  | ||||||
|         display: none; |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  | |||||||
| @ -18,7 +18,6 @@ import { Subscription } from 'rxjs'; | |||||||
| import { CoreSites } from '@services/sites'; | import { CoreSites } from '@services/sites'; | ||||||
| import { CoreUtils } from '@services/utils/utils'; | import { CoreUtils } from '@services/utils/utils'; | ||||||
| import { CoreSiteInfo } from '@classes/site'; | import { CoreSiteInfo } from '@classes/site'; | ||||||
| import { CoreLoginHelper } from '@features/login/services/login-helper'; |  | ||||||
| import { CoreMainMenuDelegate, CoreMainMenuHandlerData } from '../../services/mainmenu-delegate'; | import { CoreMainMenuDelegate, CoreMainMenuHandlerData } from '../../services/mainmenu-delegate'; | ||||||
| import { CoreMainMenu, CoreMainMenuCustomItem } from '../../services/mainmenu'; | import { CoreMainMenu, CoreMainMenuCustomItem } from '../../services/mainmenu'; | ||||||
| import { CoreEventObserver, CoreEvents } from '@singletons/events'; | import { CoreEventObserver, CoreEvents } from '@singletons/events'; | ||||||
| @ -39,19 +38,16 @@ import { Translate } from '@singletons'; | |||||||
| export class CoreMainMenuMorePage implements OnInit, OnDestroy { | export class CoreMainMenuMorePage implements OnInit, OnDestroy { | ||||||
| 
 | 
 | ||||||
|     handlers?: CoreMainMenuHandlerData[]; |     handlers?: CoreMainMenuHandlerData[]; | ||||||
|     allHandlers?: CoreMainMenuHandlerData[]; |  | ||||||
|     handlersLoaded = false; |     handlersLoaded = false; | ||||||
|     siteInfo?: CoreSiteInfo; |     siteInfo?: CoreSiteInfo; | ||||||
|     siteName?: string; |     siteName?: string; | ||||||
|     logoutLabel = 'core.mainmenu.changesite'; |  | ||||||
|     showScanQR: boolean; |     showScanQR: boolean; | ||||||
|     showWeb?: boolean; |     showWeb?: boolean; | ||||||
|     showHelp?: boolean; |     showHelp?: boolean; | ||||||
|     docsUrl?: string; |     docsUrl?: string; | ||||||
|     customItems?: CoreMainMenuCustomItem[]; |     customItems?: CoreMainMenuCustomItem[]; | ||||||
|     siteUrl?: string; |  | ||||||
|     loggedOut = false; |  | ||||||
| 
 | 
 | ||||||
|  |     protected allHandlers?: CoreMainMenuHandlerData[]; | ||||||
|     protected subscription!: Subscription; |     protected subscription!: Subscription; | ||||||
|     protected langObserver: CoreEventObserver; |     protected langObserver: CoreEventObserver; | ||||||
|     protected updateSiteObserver: CoreEventObserver; |     protected updateSiteObserver: CoreEventObserver; | ||||||
| @ -70,7 +66,7 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Initialize component. |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     ngOnInit(): void { |     ngOnInit(): void { | ||||||
|         // Load the handlers.
 |         // Load the handlers.
 | ||||||
| @ -84,7 +80,7 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { | |||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Page destroyed. |      * @inheritdoc | ||||||
|      */ |      */ | ||||||
|     ngOnDestroy(): void { |     ngOnDestroy(): void { | ||||||
|         window.removeEventListener('resize', this.initHandlers.bind(this)); |         window.removeEventListener('resize', this.initHandlers.bind(this)); | ||||||
| @ -116,16 +112,10 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { | |||||||
|      * Load the site info required by the view. |      * Load the site info required by the view. | ||||||
|      */ |      */ | ||||||
|     protected async loadSiteInfo(): Promise<void> { |     protected async loadSiteInfo(): Promise<void> { | ||||||
|         const currentSite = CoreSites.getCurrentSite(); |         const currentSite = CoreSites.getRequiredCurrentSite(); | ||||||
| 
 |  | ||||||
|         if (!currentSite) { |  | ||||||
|             return; |  | ||||||
|         } |  | ||||||
| 
 | 
 | ||||||
|         this.siteInfo = currentSite.getInfo(); |         this.siteInfo = currentSite.getInfo(); | ||||||
|         this.siteName = currentSite.getSiteName(); |         this.siteName = currentSite.getSiteName(); | ||||||
|         this.siteUrl = currentSite.getURL(); |  | ||||||
|         this.logoutLabel = CoreLoginHelper.getLogoutLabel(currentSite); |  | ||||||
|         this.showWeb = !currentSite.isFeatureDisabled('CoreMainMenuDelegate_website'); |         this.showWeb = !currentSite.isFeatureDisabled('CoreMainMenuDelegate_website'); | ||||||
|         this.showHelp = !currentSite.isFeatureDisabled('CoreMainMenuDelegate_help'); |         this.showHelp = !currentSite.isFeatureDisabled('CoreMainMenuDelegate_help'); | ||||||
| 
 | 
 | ||||||
| @ -154,13 +144,6 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { | |||||||
|         CoreNavigator.navigateToSitePath('viewer/iframe', { params: { title: item.label, url: item.url } }); |         CoreNavigator.navigateToSitePath('viewer/iframe', { params: { title: item.label, url: item.url } }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Open preferences. |  | ||||||
|      */ |  | ||||||
|     openPreferences(): void { |  | ||||||
|         CoreNavigator.navigateToSitePath('preferences'); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |     /** | ||||||
|      * Open settings. |      * Open settings. | ||||||
|      */ |      */ | ||||||
| @ -200,12 +183,4 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { | |||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |  | ||||||
|      * Logout the user. |  | ||||||
|      */ |  | ||||||
|     logout(): void { |  | ||||||
|         this.loggedOut = true; |  | ||||||
|         CoreSites.logout(); |  | ||||||
|     } |  | ||||||
| 
 |  | ||||||
| } | } | ||||||
|  | |||||||
| @ -1,5 +1,6 @@ | |||||||
| { | { | ||||||
|     "address": "Address", |     "address": "Address", | ||||||
|  |     "account": "Account", | ||||||
|     "city": "City/town", |     "city": "City/town", | ||||||
|     "contact": "Contact", |     "contact": "Contact", | ||||||
|     "country": "Country", |     "country": "Country", | ||||||
| @ -14,6 +15,7 @@ | |||||||
|     "interests": "Interests", |     "interests": "Interests", | ||||||
|     "lastname": "Surname", |     "lastname": "Surname", | ||||||
|     "manager": "Manager", |     "manager": "Manager", | ||||||
|  |     "myprofile": "My profile", | ||||||
|     "newpicture": "New picture", |     "newpicture": "New picture", | ||||||
|     "noparticipants": "No participants found for this course", |     "noparticipants": "No participants found for this course", | ||||||
|     "participants": "Participants", |     "participants": "Participants", | ||||||
|  | |||||||
| @ -127,7 +127,15 @@ $core-login-loading-color-dark: $text-color-dark !default; | |||||||
| $core-login-hide-forgot-password: false !default; | $core-login-hide-forgot-password: false !default; | ||||||
| $core-login-hide-need-help: false !default; | $core-login-hide-need-help: false !default; | ||||||
| 
 | 
 | ||||||
| // Configuration options for more page. | // Configuration options for more page. (deprecated on 4.0) | ||||||
| $core-more-hide-siteinfo: false !default; | $core-more-hide-siteinfo: false !default; | ||||||
| $core-more-hide-sitename: false !default; | $core-more-hide-sitename: false !default; | ||||||
| $core-more-hide-siteurl: false !default; | $core-more-hide-siteurl: false !default; | ||||||
|  | 
 | ||||||
|  | // Configuration options for user page. | ||||||
|  | $core-user-hide-siteinfo: $core-more-hide-siteinfo !default; | ||||||
|  | $core-user-hide-sitename: $core-more-hide-sitename !default; | ||||||
|  | $core-user-hide-siteurl: $core-more-hide-siteurl !default; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user