Skip to content

Commit

Permalink
MOBILE-4653 core: Add site logo component
Browse files Browse the repository at this point in the history
  • Loading branch information
crazyserver committed Dec 9, 2024
1 parent 53baee7 commit db2aaee
Show file tree
Hide file tree
Showing 29 changed files with 224 additions and 130 deletions.
1 change: 1 addition & 0 deletions moodle.config.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@
"enableonboarding": true,
"forceColorScheme": "",
"forceLoginLogo": false,
"showTopLogo": "hidden",
"ioswebviewscheme": "moodleappfs",
"appstores": {
"android": "com.moodle.moodlemobile",
Expand Down
30 changes: 27 additions & 3 deletions src/core/classes/sites/unauthenticated-site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ export class CoreUnauthenticatedSite {
}

/**
* Check whether the app should use the local logo instead of the remote one.
* Check whether the app should use the local logo instead or the remote one.
*
* @returns Whether local logo is forced.
*/
Expand All @@ -180,10 +180,34 @@ export class CoreUnauthenticatedSite {
getLogoUrl(config?: CoreSitePublicConfigResponse): string | undefined {
config = config ?? this.publicConfig;
if (!config || this.forcesLocalLogo()) {
return 'assets/img/login_logo.png';
return;
}

return config.logourl || config.compactlogourl || 'assets/img/login_logo.png';
return config.logourl || config.compactlogourl || undefined;
}

/**
* Check show top logo mode.
*
* @returns The top logo mode.
*/
getShowTopLogo(): 'online' | 'offline' | 'hidden' {
return this.isDemoModeSite() ? 'hidden' : CoreConstants.CONFIG.showTopLogo;
}

/**
* Get logo URL from a site public config.
*
* @param config Site public config.
* @returns Logo URL.
*/
getTopLogoUrl(config?: CoreSitePublicConfigResponse): string | undefined {
config = config ?? this.publicConfig;
if (!config || this.getShowTopLogo() !== 'online') {
return;
}

return config.logourl || config.compactlogourl || undefined;
}

/**
Expand Down
14 changes: 14 additions & 0 deletions src/core/components/site-logo/site-logo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<div class="core-logo-container" *ngIf="showLogo && logoLoaded">
<img *ngIf="siteLogo" [src]="siteLogo" class="core-logo" [alt]="siteName" core-external-content [siteId]="siteId"
(error)="imageError()">
<img *ngIf="!siteLogo" [src]="fallbackLogo" class="core-logo" [alt]="siteName">
</div>

<p *ngIf="showSiteName && siteNameMode === 'p' && siteName" class="ion-no-margin ion-no-padding core-logo-sitename">
<core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" [siteId]="siteId" />
</p>
<core-format-text *ngIf="showSiteName && siteNameMode === '' && siteName" [text]="siteName" contextLevel="system" [contextInstanceId]="0"
class="core-logo-sitename" [siteId]="siteId" />
<h2 *ngIf="showSiteName && siteNameMode === 'h2' && siteName" class="ion-margin-top ion-no-padding core-logo-sitename">
<core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" [siteId]="siteId" />
</h2>
22 changes: 22 additions & 0 deletions src/core/components/site-logo/site-logo.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
:host {
display: block;
}

.core-logo-container {
margin-bottom: var(--core-site-logo-margin-bottom, 0px);
}

img.core-logo {
max-height: var(--core-site-logo-max-height);
max-width: var(--core-site-logo-max-width, 100%);


width: var(--core-site-logo-width, auto);
margin: var(--core-site-logo-margin, 0px);
}

.core-logo-sitename {
display: var(--core-site-logo-sitename-display, block);
font: var(--core-site-logo-sitename-font);
margin-bottom: var(--core-site-logo-sitename-margin-bottom, 0px);
}
115 changes: 115 additions & 0 deletions src/core/components/site-logo/site-logo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
// (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, OnInit, OnDestroy, Input } from '@angular/core';
import { CoreSharedModule } from '@/core/shared.module';
import { CoreSites } from '@services/sites';
import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { CoreSite } from '@classes/sites/site';
import { toBoolean } from '@/core/transforms/boolean';
import { CorePromiseUtils } from '@singletons/promise-utils';

/**
* Component to render the site logo.
*/
@Component({
selector: 'core-site-logo',
templateUrl: 'site-logo.html',
styleUrl: 'site-logo.scss',
standalone: true,
imports: [CoreSharedModule],

})
export class CoreSiteLogoComponent implements OnInit, OnDestroy {

@Input({ transform: toBoolean }) hideOnError = false;
@Input() siteNameMode: CoreSiteLogoSiteNameMode = CoreSiteLogoSiteNameMode.NOTAG;
@Input({ transform: toBoolean }) showLogo = true;
@Input() site?: CoreSite;
@Input() logoType: 'top' | 'login' = 'login';

siteName?: string;
siteId?: string;
siteLogo?: string;
logoLoaded = false;
fallbackLogo = '';
showSiteName = true;

protected updateSiteObserver: CoreEventObserver;

constructor() {
this.siteId = this.site?.getId() ?? CoreSites.getCurrentSiteId();

this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, async () => {
await this.loadInfo();
}, this.siteId);
}

/**
* @inheritdoc
*/
async ngOnInit(): Promise<void> {
this.fallbackLogo = this.logoType === 'top' ? 'assets/img/top_logo.png' : 'assets/img/login_logo.png';
this.showSiteName = this.logoType !== 'top';

await this.loadInfo();
}

/**
* Function to handle the image error.
*/
imageError(): void {
if (this.hideOnError) {
this.showLogo = false;
}
this.siteLogo = undefined;
}

/**
* Load the site name and logo.
*/
protected async loadInfo(): Promise<void> {
const site = this.site ?? CoreSites.getRequiredCurrentSite();
this.siteName = await site.getSiteName() || '';

this.showSiteName = this.logoType !== 'top' || site.getShowTopLogo() === 'hidden';

if (this.logoType === 'top' && site.getShowTopLogo() === 'hidden') {
this.showLogo = false;
} else {
// Get the public config to avoid race conditions when retrieving the logo.
const siteConfig = await CorePromiseUtils.ignoreErrors(site.getPublicConfig());

this.siteLogo = this.logoType === 'top'
? site.getTopLogoUrl(siteConfig)
: site.getLogoUrl(siteConfig);
}

this.logoLoaded = true;
}

/**
* @inheritdoc
*/
ngOnDestroy(): void {
this.updateSiteObserver.off();
}

}

export const enum CoreSiteLogoSiteNameMode {
HEADING2 = 'h2',
PARAGRAPH = 'p',
NOTAG = '',
}
4 changes: 4 additions & 0 deletions src/core/directives/format-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ export class CoreFormatTextDirective implements OnChanges, OnDestroy, AsyncDirec
this.element.addEventListener('click', (event) => this.elementClicked(event));

this.siteId = this.siteId || CoreSites.getCurrentSiteId();

if (!this.siteId) {
this.filter = false;
}
}

/**
Expand Down
2 changes: 2 additions & 0 deletions src/core/features/courses/courses-my-lazy.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { CoreBlockComponentsModule } from '@features/block/components/components

import { CoreMainMenuComponentsModule } from '@features/mainmenu/components/components.module';
import { CoreCoursesMyPage } from '@features/courses/pages/my/my';
import { CoreSiteLogoComponent } from '@/core/components/site-logo/site-logo';

const routes: Routes = [
{
Expand All @@ -34,6 +35,7 @@ const routes: Routes = [
CoreSharedModule,
CoreBlockComponentsModule,
CoreMainMenuComponentsModule,
CoreSiteLogoComponent,
],
declarations: [
CoreCoursesMyPage,
Expand Down
3 changes: 1 addition & 2 deletions src/core/features/courses/pages/my/my.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
</ion-buttons>
<ion-title>
<h1>
<core-format-text [text]="siteName" contextLevel="system" [contextInstanceId]="0" class="core-header-sitename" />
<img src="assets/img/top_logo.png" class="core-header-logo" [alt]="siteName">
<core-site-logo logoType="top" />
</h1>
</ion-title>
<ion-buttons slot="end">
Expand Down
13 changes: 0 additions & 13 deletions src/core/features/courses/pages/my/my.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export class CoreCoursesMyPage implements OnInit, OnDestroy, AsyncDirective {

@ViewChild(CoreBlockComponent) block!: CoreBlockComponent;

siteName = '';
downloadCoursesEnabled = false;
userId: number;
loadedBlock?: Partial<CoreCourseBlock>;
Expand All @@ -66,8 +65,6 @@ export class CoreCoursesMyPage implements OnInit, OnDestroy, AsyncDirective {
// Refresh the enabled flags if site is updated.
this.updateSiteObserver = CoreEvents.on(CoreEvents.SITE_UPDATED, async () => {
this.downloadCoursesEnabled = !CoreCourses.isDownloadCoursesDisabledInSite();
await this.loadSiteName();

}, CoreSites.getCurrentSiteId());

this.userId = CoreSites.getCurrentSiteUserId();
Expand Down Expand Up @@ -98,8 +95,6 @@ export class CoreCoursesMyPage implements OnInit, OnDestroy, AsyncDirective {

CoreSites.loginNavigationFinished();

await this.loadSiteName();

this.loadContent(true);
}

Expand Down Expand Up @@ -156,14 +151,6 @@ export class CoreCoursesMyPage implements OnInit, OnDestroy, AsyncDirective {
this.logView();
}

/**
* Load the site name.
*/
protected async loadSiteName(): Promise<void> {
const site = CoreSites.getRequiredCurrentSite();
this.siteName = await site.getSiteName() || '';
}

/**
* Load fallback blocks.
*/
Expand Down
2 changes: 2 additions & 0 deletions src/core/features/login/login-credentials-lazy.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { RouterModule, Routes } from '@angular/router';
import { CoreSharedModule } from '@/core/shared.module';
import { CoreLoginComponentsModule } from '@features/login/components/components.module';
import { CoreLoginCredentialsPage } from '@features/login/pages/credentials/credentials';
import { CoreSiteLogoComponent } from '@/core/components/site-logo/site-logo';

const routes: Routes = [
{
Expand All @@ -31,6 +32,7 @@ const routes: Routes = [
RouterModule.forChild(routes),
CoreSharedModule,
CoreLoginComponentsModule,
CoreSiteLogoComponent,
],
declarations: [
CoreLoginCredentialsPage,
Expand Down
2 changes: 2 additions & 0 deletions src/core/features/login/login-reconnect-lazy.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { RouterModule, Routes } from '@angular/router';
import { CoreSharedModule } from '@/core/shared.module';
import { CoreLoginComponentsModule } from '@features/login/components/components.module';
import { CoreLoginReconnectPage } from '@features/login/pages/reconnect/reconnect';
import { CoreSiteLogoComponent } from '@/core/components/site-logo/site-logo';

const routes: Routes = [
{
Expand All @@ -31,6 +32,7 @@ const routes: Routes = [
RouterModule.forChild(routes),
CoreSharedModule,
CoreLoginComponentsModule,
CoreSiteLogoComponent,
],
declarations: [
CoreLoginReconnectPage,
Expand Down
27 changes: 12 additions & 15 deletions src/core/features/login/login.scss
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,14 @@
margin-bottom: 32px;

.core-login-site {
.core-login-site-logo {
width: 90%;
max-width: 300px;
margin: 0px auto;

img {
max-width: 100%;
max-height: 104px;
}
}

.core-sitename {
font-size: 1.2rem;
margin-bottom: 8px;
core-site-logo {
--core-site-logo-max-height: 104px;
--core-site-logo-sitename-margin-bottom: 8px;
--core-site-logo-sitename-font: var(--mdl-typography-subtitle-font-lg);

--core-site-logo-max-width: 300px;
--core-site-logo-width: 90%;
--core-site-logo-margin: 0 auto;
}

.core-siteurl {
Expand Down Expand Up @@ -89,9 +83,12 @@
}

@if ($core-fixed-url) {
.core-sitename, .core-siteurl {
.core-siteurl {
display: none;
}
core-site-logo {
--core-site-logo-sitename-display: none;
}
}

@if ($core-login-button-outline) {
Expand Down
11 changes: 1 addition & 10 deletions src/core/features/login/pages/credentials/credentials.html
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,7 @@ <h1>{{ 'core.login.login' | translate }}</h1>
<ng-container *ngIf="!siteCheckError && site && credForm">
<div class="ion-text-wrap ion-text-center core-login-info-box">
<div class="core-login-site">
<div class="core-login-site-logo">
<!-- Show site logo or a default image. -->
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" alt="" core-external-content
onError="this.src='assets/img/login_logo.png'">
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation" alt="">
</div>

<h2 *ngIf="siteName" class="ion-margin-top ion-no-padding core-sitename">
<core-format-text [text]="siteName" [filter]="false" />
</h2>
<core-site-logo siteNameMode="h2" [site]="site" />
<p class="core-siteurl" *ngIf="displaySiteUrl">{{site.siteUrl}}</p>
</div>

Expand Down
Loading

0 comments on commit db2aaee

Please sign in to comment.