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 1eb8ae0
Show file tree
Hide file tree
Showing 25 changed files with 185 additions and 123 deletions.
6 changes: 3 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,10 @@ 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;
}

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

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

.core-logo-container {
display: var(--core-site-logo-display, block);
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);
}
101 changes: 101 additions & 0 deletions src/core/components/site-logo/site-logo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
// (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() fallbackLogo = 'assets/img/top_logo.png'; // Should be a local path.
@Input() siteNameMode: CoreSiteLogoSiteNameMode = CoreSiteLogoSiteNameMode.NOTAG;
@Input({ transform: toBoolean }) showLogo = true;
@Input() site?: CoreSite;

siteName?: string;
siteId?: string;
siteLogo?: string;
logoLoaded = false;

protected updateSiteObserver: CoreEventObserver;

constructor() {
this.siteId = CoreSites.getCurrentSiteId();

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

/**
* @inheritdoc
*/
async ngOnInit(): Promise<void> {
await this.loadSiteName();
}

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

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

// Get the public config to avoid race conditions when retrieving the logo.
const siteConfig = await CorePromiseUtils.ignoreErrors(site.getPublicConfig());

this.siteLogo = site.getLogoUrl(siteConfig);
this.logoLoaded = true;
}

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

}

export const enum CoreSiteLogoSiteNameMode {
HEADING2 = 'h2',
PARAGRAPH = 'p',
NOTAG = '',
}
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 />
</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 fallbackLogo="assets/img/login_logo.png" siteNameMode="h2" [site]="site" />
<p class="core-siteurl" *ngIf="displaySiteUrl">{{site.siteUrl}}</p>
</div>

Expand Down
6 changes: 0 additions & 6 deletions src/core/features/login/pages/credentials/credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {

credForm!: FormGroup;
site!: CoreUnauthenticatedSite;
siteName?: string;
logoUrl?: string;
authInstructions?: string;
canSignup?: boolean;
pageLoaded = false;
Expand Down Expand Up @@ -104,11 +102,9 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
}

this.site = CoreSitesFactory.makeUnauthenticatedSite(siteUrl, this.siteConfig);
this.logoUrl = this.site.getLogoUrl(this.siteConfig);
this.urlToOpen = CoreNavigator.getRouteParam('urlToOpen');
this.supportConfig = this.siteConfig && new CoreUserGuestSupportConfig(this.site, this.siteConfig);
this.displaySiteUrl = this.site.shouldDisplayInformativeLinks();
this.siteName = await this.site.getSiteName();
} catch (error) {
CoreDomUtils.showErrorModal(error);

Expand Down Expand Up @@ -220,8 +216,6 @@ export class CoreLoginCredentialsPage implements OnInit, OnDestroy {
if (this.site.isDemoModeSite()) {
this.showScanQR = false;
} else {
this.siteName = this.siteConfig.sitename;
this.logoUrl = this.site.getLogoUrl(this.siteConfig);
this.showScanQR = await CoreLoginHelper.displayQRInCredentialsScreen(this.siteConfig.tool_mobile_qrcodetype);
}

Expand Down
10 changes: 1 addition & 9 deletions src/core/features/login/pages/reconnect/reconnect.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,8 @@ <h1>{{ 'core.login.reconnect' | translate }}</h1>

<div class="ion-text-wrap ion-text-center core-login-info-box">
<div class="core-login-site">
<div class="core-login-site-logo" *ngIf="!showUserAvatar">
<!-- Show site logo or a default image. -->
<img *ngIf="logoUrl" [src]="logoUrl" role="presentation" onError="this.src='assets/img/login_logo.png'" alt=""
core-external-content [siteId]="siteId">
<img *ngIf="!logoUrl" src="assets/img/login_logo.png" role="presentation" alt="">
</div>
<core-site-logo fallbackLogo="assets/img/login_logo.png" siteNameMode="p" [showLogo]="!showUserAvatar" [site]="site" />

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

Expand Down
2 changes: 0 additions & 2 deletions src/core/features/login/pages/reconnect/reconnect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {

credForm: FormGroup;
site!: CoreSite;
logoUrl?: string;
displaySiteUrl = false;
showForgottenPassword = true;
showUserAvatar = false;
Expand Down Expand Up @@ -202,7 +201,6 @@ export class CoreLoginReconnectPage implements OnInit, OnDestroy {
}

this.isBrowserSSO = CoreLoginHelper.isSSOLoginNeeded(this.siteConfig.typeoflogin);
this.logoUrl = this.site.getLogoUrl();

await CoreSites.checkApplication(this.siteConfig);
}
Expand Down
3 changes: 2 additions & 1 deletion src/core/features/login/pages/site/site.scss
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
}

@include media-breakpoint-up(md) {
ion-content .core-login-site-logo {
ion-content .core-login-site-logo,
ion-content core-site-logo {
margin-top: 20%;
&.hidden {
margin-top: 0;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 1eb8ae0

Please sign in to comment.