MOBILE-4266 site: Add site theme class to html tags

main
Pau Ferrer Ocaña 2024-01-31 12:44:31 +01:00
parent 0de0394a66
commit d269225651
3 changed files with 106 additions and 22 deletions

View File

@ -16,17 +16,21 @@ import { AppComponent } from '@/app/app.component';
import { CoreEvents } from '@singletons/events';
import { CoreLang, CoreLangProvider } from '@services/lang';
import { mockSingleton, renderComponent } from '@/testing/utils';
import { mock, mockSingleton, renderComponent } from '@/testing/utils';
import { CoreNavigator, CoreNavigatorService } from '@services/navigator';
import { CoreSites } from '@services/sites';
import { Http } from '@singletons';
import { of } from 'rxjs';
import { CoreSite } from '@classes/sites/site';
import { CoreUtils } from '@services/utils/utils';
describe('AppComponent', () => {
let langProvider: CoreLangProvider;
let navigator: CoreNavigatorService;
beforeEach(() => {
navigator = mockSingleton(CoreNavigator, ['navigate']);
langProvider = mockSingleton(CoreLang, ['clearCustomStrings']);
langProvider = mockSingleton(CoreLang, mock({ getCurrentLanguage: async () => 'en' , clearCustomStrings: () => null }));
// eslint-disable-next-line @typescript-eslint/no-explicit-any
mockSingleton(Http, { get: () => of(null as any) });
});
it('should render', async () => {
@ -38,6 +42,7 @@ describe('AppComponent', () => {
it('cleans up on logout', async () => {
const fixture = await renderComponent(AppComponent);
const navigator: CoreNavigatorService = mockSingleton(CoreNavigator, ['navigate']);
fixture.componentInstance.ngOnInit();
CoreEvents.trigger(CoreEvents.LOGOUT);
@ -46,4 +51,66 @@ describe('AppComponent', () => {
expect(navigator.navigate).toHaveBeenCalledWith('/login/sites', { reset: true });
});
it('adds ionic platform and theme classes', async () => {
const fixture = await renderComponent(AppComponent);
const siteUrl = 'https://campus.example.edu';
const themeName = 'mytheme';
const themeName2 = 'anothertheme';
fixture.componentInstance.ngOnInit();
expect(document.documentElement.classList.contains('ionic7')).toBe(true);
const site = mock(new CoreSite('42', siteUrl, 'token', { info: {
sitename: 'Example Campus',
username: 'admin',
firstname: 'Admin',
lastname: 'User',
fullname: 'Admin User',
lang: 'en',
userid: 1,
siteurl: siteUrl,
userpictureurl: '',
theme: themeName,
functions: [],
} }));
mockSingleton(CoreSites, {
getSite: () => Promise.resolve(site),
getCurrentSiteId: () => '42',
});
CoreEvents.trigger(CoreEvents.LOGIN, {}, '42');
// Wait the event to be processed.
await CoreUtils.nextTick();
expect(document.documentElement.classList.contains('theme-site-'+themeName)).toBe(true);
expect(document.documentElement.classList.contains('theme-site-'+themeName2)).toBe(false);
if (site.infos) {
site.infos.theme = themeName2;
}
CoreEvents.trigger(CoreEvents.SITE_UPDATED, site.infos , '42');
// Wait the event to be processed.
await CoreUtils.nextTick();
expect(document.documentElement.classList.contains('theme-site-'+themeName2)).toBe(true);
expect(document.documentElement.classList.contains('theme-site-'+themeName)).toBe(false);
CoreEvents.trigger(CoreEvents.LOGOUT);
expect(document.documentElement.classList.contains('theme-site-'+themeName)).toBe(false);
expect(document.documentElement.classList.contains('theme-site-'+themeName2)).toBe(false);
CoreEvents.trigger(CoreEvents.SITE_ADDED, site.infos , '42');
// Wait the event to be processed.
await CoreUtils.nextTick();
expect(document.documentElement.classList.contains('theme-site-'+themeName2)).toBe(true);
expect(document.documentElement.classList.contains('theme-site-'+themeName)).toBe(false);
});
});

View File

@ -36,10 +36,12 @@ import { CoreUrl } from '@singletons/url';
import { CoreLogger } from '@singletons/logger';
import { CorePromisedValue } from '@classes/promised-value';
import { register } from 'swiper/element/bundle';
import { CoreSiteInfo, CoreSiteInfoResponse } from '@classes/sites/unauthenticated-site';
const MOODLE_SITE_URL_PREFIX = 'url-';
const MOODLE_VERSION_PREFIX = 'version-';
const MOODLEAPP_VERSION_PREFIX = 'moodleapp-';
const MOODLE_SITE_THEME_PREFIX = 'theme-site-';
register();
@ -68,7 +70,7 @@ export class AppComponent implements OnInit, AfterViewInit {
CoreLang.clearCustomStrings();
// Remove version classes from body.
this.removeModeClasses([MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX]);
this.removeSiteClasses();
// Go to sites page when user is logged out.
await CoreNavigator.navigate('/login/sites', { reset: true });
@ -122,11 +124,7 @@ export class AppComponent implements OnInit, AfterViewInit {
const site = await CoreSites.getSite(data.siteId);
const info = site.getInfo();
if (info) {
// Add version classes to body.
this.removeModeClasses([MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX]);
this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(info.release || ''));
this.addSiteUrlClass(info.siteurl);
this.addSiteClasses(info);
}
}
@ -142,11 +140,7 @@ export class AppComponent implements OnInit, AfterViewInit {
if (data.siteId === CoreSites.getCurrentSiteId()) {
this.loadCustomStrings();
// Add version classes to body.
this.removeModeClasses([MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX]);
this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(data.release || ''));
this.addSiteUrlClass(data.siteurl);
this.addSiteClasses(data);
}
});
@ -154,11 +148,7 @@ export class AppComponent implements OnInit, AfterViewInit {
if (data.siteId === CoreSites.getCurrentSiteId()) {
this.loadCustomStrings();
// Add version classes to body.
this.removeModeClasses([MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX]);
this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(data.release || ''));
this.addSiteUrlClass(data.siteurl);
this.addSiteClasses(data);
}
});
@ -320,6 +310,33 @@ export class AppComponent implements OnInit, AfterViewInit {
}
}
/**
* Convenience function to add site classes to html.
*
* @param siteInfo Site Info.
*/
protected addSiteClasses(siteInfo: CoreSiteInfo | CoreSiteInfoResponse): void {
// Add version classes to html tag.
this.removeSiteClasses();
this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(siteInfo.release || ''));
this.addSiteUrlClass(siteInfo.siteurl);
if (siteInfo.theme) {
CoreDomUtils.toggleModeClass(MOODLE_SITE_THEME_PREFIX + siteInfo.theme, true);
}
}
/**
* Convenience function to remove all site mode classes form html.
*/
protected removeSiteClasses(): void {
// Remove version classes from html tag.
this.removeModeClasses(
[MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX, MOODLE_SITE_THEME_PREFIX],
);
}
/**
* Converts the provided URL into a CSS class that be used within the page.
* This is primarily used to add the siteurl to the body tag as a CSS class.

View File

@ -1402,7 +1402,7 @@ export type CoreCourseSearchedData = CoreCourseBasicSearchedData & {
enablecompletion?: number; // Completion enabled? 1: yes 0: no.
completionnotify?: number; // 1: yes 0: no.
lang?: string; // Forced course language.
theme?: string; // Fame of the forced theme.
theme?: string; // Name of the forced theme.
marker?: number; // Current course marker.
legacyfiles?: number; // If legacy files are enabled.
calendartype?: string; // Calendar type.