diff --git a/src/core/features/mainmenu/components/components.module.ts b/src/core/features/mainmenu/components/components.module.ts new file mode 100644 index 000000000..9a688ae75 --- /dev/null +++ b/src/core/features/mainmenu/components/components.module.ts @@ -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 {} diff --git a/src/core/features/mainmenu/components/user-menu-button/user-menu-button.html b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.html new file mode 100644 index 000000000..1d9f61bde --- /dev/null +++ b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.html @@ -0,0 +1,9 @@ + \ No newline at end of file diff --git a/src/core/features/mainmenu/components/user-menu-button/user-menu-button.ts b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.ts new file mode 100644 index 000000000..f8d3291f7 --- /dev/null +++ b/src/core/features/mainmenu/components/user-menu-button/user-menu-button.ts @@ -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: + */ +@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({ + component: CoreMainMenuUserMenuComponent, + }); + } + +} diff --git a/src/core/features/mainmenu/components/user-menu/user-menu.html b/src/core/features/mainmenu/components/user-menu/user-menu.html new file mode 100644 index 000000000..8c89de390 --- /dev/null +++ b/src/core/features/mainmenu/components/user-menu/user-menu.html @@ -0,0 +1,63 @@ + + + + + + + +

+ {{'core.user.account' | translate}} +

+
+
+ + + + + + + + +

{{ 'core.user.details' | translate }}

+
+
+ + + + + + + + +

{{ handler.title | translate }}

+
+
+ + + + +

{{ 'core.settings.preferences' | translate }}

+
+
+
+
+
+ + + + {{ logoutLabel | translate }} + + \ No newline at end of file diff --git a/src/core/features/mainmenu/components/user-menu/user-menu.scss b/src/core/features/mainmenu/components/user-menu/user-menu.scss new file mode 100644 index 000000000..7466e6dd8 --- /dev/null +++ b/src/core/features/mainmenu/components/user-menu/user-menu.scss @@ -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; + } +} diff --git a/src/core/features/mainmenu/components/user-menu/user-menu.ts b/src/core/features/mainmenu/components/user-menu/user-menu.ts new file mode 100644 index 000000000..71c8cc9f7 --- /dev/null +++ b/src/core/features/mainmenu/components/user-menu/user-menu.ts @@ -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 { + + 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 { + 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 { + 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 { + 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 { + await this.close(event); + + CoreSites.logout(); + } + + /** + * Close modal. + */ + async close(event: Event): Promise { + event.preventDefault(); + event.stopPropagation(); + + await ModalController.dismiss(); + } + + /** + * @inheritdoc + */ + ngOnDestroy(): void { + this.subscription?.unsubscribe(); + } + +} diff --git a/src/core/features/mainmenu/pages/more/more.html b/src/core/features/mainmenu/pages/more/more.html index 3f3fcff68..69a4e046c 100644 --- a/src/core/features/mainmenu/pages/more/more.html +++ b/src/core/features/mainmenu/pages/more/more.html @@ -5,97 +5,76 @@

+ + + + - - - - + + + + + + + +

{{ handler.title | translate}}

+
+ + + {{ handler.badgeA11yText | translate: {$a : handler.badge } }} + + + +
+ + + -

{{siteInfo.fullname}}

-

- - -

-

{{ siteUrl }}

+

{{item.label}}

- - - - - - + + -

{{ handler.title | translate}}

-
- - - {{ handler.badgeA11yText | translate: {$a : handler.badge } }} - - - -
- - - - -

{{item.label}}

-
-
- - - -

{{item.label}}

-
-
-
- - - -

{{ 'core.scanqr' | translate }}

+

{{item.label}}

- - - -

{{ 'core.mainmenu.website' | translate }}

-
-
- - - -

{{ 'core.mainmenu.help' | translate }}

-
-
- - - -

{{ 'core.settings.preferences' | translate }}

-
-
- - - -

{{ logoutLabel | translate }}

-
-
- - - - -

{{ 'core.settings.appsettings' | translate }}

-
-
-
-
+ + + + +

{{ 'core.scanqr' | translate }}

+
+
+ + + +

{{ 'core.mainmenu.website' | translate }}

+
+
+ + + +

{{ 'core.mainmenu.help' | translate }}

+
+
+
+ + + + +

{{ 'core.settings.appsettings' | translate }}

+
+
+
diff --git a/src/core/features/mainmenu/pages/more/more.module.ts b/src/core/features/mainmenu/pages/more/more.module.ts index 1999f1b49..770fa3d9b 100644 --- a/src/core/features/mainmenu/pages/more/more.module.ts +++ b/src/core/features/mainmenu/pages/more/more.module.ts @@ -19,10 +19,12 @@ import { CoreSharedModule } from '@/core/shared.module'; import { CoreMainMenuMorePage } from './more'; import { buildTabMainRoutes } from '@features/mainmenu/mainmenu-tab-routing.module'; import { CoreMainMenuProvider } from '@features/mainmenu/services/mainmenu'; +import { CoreMainMenuComponentsModule } from '@features/mainmenu/components/components.module'; @NgModule({ imports: [ CoreSharedModule, + CoreMainMenuComponentsModule, ], providers: [ { diff --git a/src/core/features/mainmenu/pages/more/more.scss b/src/core/features/mainmenu/pages/more/more.scss index c5b62e00a..9b1b544d2 100644 --- a/src/core/features/mainmenu/pages/more/more.scss +++ b/src/core/features/mainmenu/pages/more/more.scss @@ -17,21 +17,3 @@ ion-item { 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; - } -} diff --git a/src/core/features/mainmenu/pages/more/more.ts b/src/core/features/mainmenu/pages/more/more.ts index 733c8a0aa..a8b93f285 100644 --- a/src/core/features/mainmenu/pages/more/more.ts +++ b/src/core/features/mainmenu/pages/more/more.ts @@ -18,7 +18,6 @@ import { Subscription } from 'rxjs'; import { CoreSites } from '@services/sites'; import { CoreUtils } from '@services/utils/utils'; import { CoreSiteInfo } from '@classes/site'; -import { CoreLoginHelper } from '@features/login/services/login-helper'; import { CoreMainMenuDelegate, CoreMainMenuHandlerData } from '../../services/mainmenu-delegate'; import { CoreMainMenu, CoreMainMenuCustomItem } from '../../services/mainmenu'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; @@ -39,19 +38,16 @@ import { Translate } from '@singletons'; export class CoreMainMenuMorePage implements OnInit, OnDestroy { handlers?: CoreMainMenuHandlerData[]; - allHandlers?: CoreMainMenuHandlerData[]; handlersLoaded = false; siteInfo?: CoreSiteInfo; siteName?: string; - logoutLabel = 'core.mainmenu.changesite'; showScanQR: boolean; showWeb?: boolean; showHelp?: boolean; docsUrl?: string; customItems?: CoreMainMenuCustomItem[]; - siteUrl?: string; - loggedOut = false; + protected allHandlers?: CoreMainMenuHandlerData[]; protected subscription!: Subscription; protected langObserver: CoreEventObserver; protected updateSiteObserver: CoreEventObserver; @@ -70,7 +66,7 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { } /** - * Initialize component. + * @inheritdoc */ ngOnInit(): void { // Load the handlers. @@ -84,7 +80,7 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { } /** - * Page destroyed. + * @inheritdoc */ ngOnDestroy(): void { 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. */ protected async loadSiteInfo(): Promise { - const currentSite = CoreSites.getCurrentSite(); - - if (!currentSite) { - return; - } + const currentSite = CoreSites.getRequiredCurrentSite(); this.siteInfo = currentSite.getInfo(); this.siteName = currentSite.getSiteName(); - this.siteUrl = currentSite.getURL(); - this.logoutLabel = CoreLoginHelper.getLogoutLabel(currentSite); this.showWeb = !currentSite.isFeatureDisabled('CoreMainMenuDelegate_website'); 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 } }); } - /** - * Open preferences. - */ - openPreferences(): void { - CoreNavigator.navigateToSitePath('preferences'); - } - /** * Open settings. */ @@ -200,12 +183,4 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy { } } - /** - * Logout the user. - */ - logout(): void { - this.loggedOut = true; - CoreSites.logout(); - } - } diff --git a/src/core/features/user/lang.json b/src/core/features/user/lang.json index 610e0fae4..3435a4c4a 100644 --- a/src/core/features/user/lang.json +++ b/src/core/features/user/lang.json @@ -1,5 +1,6 @@ { "address": "Address", + "account": "Account", "city": "City/town", "contact": "Contact", "country": "Country", @@ -14,6 +15,7 @@ "interests": "Interests", "lastname": "Surname", "manager": "Manager", + "myprofile": "My profile", "newpicture": "New picture", "noparticipants": "No participants found for this course", "participants": "Participants", diff --git a/src/theme/globals.variables.scss b/src/theme/globals.variables.scss index e2a39b886..abc13bfce 100644 --- a/src/theme/globals.variables.scss +++ b/src/theme/globals.variables.scss @@ -127,7 +127,15 @@ $core-login-loading-color-dark: $text-color-dark !default; $core-login-hide-forgot-password: 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-sitename: 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; + + +