MOBILE-4266 site: Add site theme class to html tags
parent
0de0394a66
commit
d269225651
|
@ -16,17 +16,21 @@ import { AppComponent } from '@/app/app.component';
|
||||||
import { CoreEvents } from '@singletons/events';
|
import { CoreEvents } from '@singletons/events';
|
||||||
import { CoreLang, CoreLangProvider } from '@services/lang';
|
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 { 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', () => {
|
describe('AppComponent', () => {
|
||||||
|
|
||||||
let langProvider: CoreLangProvider;
|
let langProvider: CoreLangProvider;
|
||||||
let navigator: CoreNavigatorService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
navigator = mockSingleton(CoreNavigator, ['navigate']);
|
langProvider = mockSingleton(CoreLang, mock({ getCurrentLanguage: async () => 'en' , clearCustomStrings: () => null }));
|
||||||
langProvider = mockSingleton(CoreLang, ['clearCustomStrings']);
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||||
|
mockSingleton(Http, { get: () => of(null as any) });
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should render', async () => {
|
it('should render', async () => {
|
||||||
|
@ -38,6 +42,7 @@ describe('AppComponent', () => {
|
||||||
|
|
||||||
it('cleans up on logout', async () => {
|
it('cleans up on logout', async () => {
|
||||||
const fixture = await renderComponent(AppComponent);
|
const fixture = await renderComponent(AppComponent);
|
||||||
|
const navigator: CoreNavigatorService = mockSingleton(CoreNavigator, ['navigate']);
|
||||||
|
|
||||||
fixture.componentInstance.ngOnInit();
|
fixture.componentInstance.ngOnInit();
|
||||||
CoreEvents.trigger(CoreEvents.LOGOUT);
|
CoreEvents.trigger(CoreEvents.LOGOUT);
|
||||||
|
@ -46,4 +51,66 @@ describe('AppComponent', () => {
|
||||||
expect(navigator.navigate).toHaveBeenCalledWith('/login/sites', { reset: true });
|
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);
|
||||||
|
});
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -36,10 +36,12 @@ import { CoreUrl } from '@singletons/url';
|
||||||
import { CoreLogger } from '@singletons/logger';
|
import { CoreLogger } from '@singletons/logger';
|
||||||
import { CorePromisedValue } from '@classes/promised-value';
|
import { CorePromisedValue } from '@classes/promised-value';
|
||||||
import { register } from 'swiper/element/bundle';
|
import { register } from 'swiper/element/bundle';
|
||||||
|
import { CoreSiteInfo, CoreSiteInfoResponse } from '@classes/sites/unauthenticated-site';
|
||||||
|
|
||||||
const MOODLE_SITE_URL_PREFIX = 'url-';
|
const MOODLE_SITE_URL_PREFIX = 'url-';
|
||||||
const MOODLE_VERSION_PREFIX = 'version-';
|
const MOODLE_VERSION_PREFIX = 'version-';
|
||||||
const MOODLEAPP_VERSION_PREFIX = 'moodleapp-';
|
const MOODLEAPP_VERSION_PREFIX = 'moodleapp-';
|
||||||
|
const MOODLE_SITE_THEME_PREFIX = 'theme-site-';
|
||||||
|
|
||||||
register();
|
register();
|
||||||
|
|
||||||
|
@ -68,7 +70,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
CoreLang.clearCustomStrings();
|
CoreLang.clearCustomStrings();
|
||||||
|
|
||||||
// Remove version classes from body.
|
// 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.
|
// Go to sites page when user is logged out.
|
||||||
await CoreNavigator.navigate('/login/sites', { reset: true });
|
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 site = await CoreSites.getSite(data.siteId);
|
||||||
const info = site.getInfo();
|
const info = site.getInfo();
|
||||||
if (info) {
|
if (info) {
|
||||||
// Add version classes to body.
|
this.addSiteClasses(info);
|
||||||
this.removeModeClasses([MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX]);
|
|
||||||
|
|
||||||
this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(info.release || ''));
|
|
||||||
this.addSiteUrlClass(info.siteurl);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,11 +140,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
if (data.siteId === CoreSites.getCurrentSiteId()) {
|
if (data.siteId === CoreSites.getCurrentSiteId()) {
|
||||||
this.loadCustomStrings();
|
this.loadCustomStrings();
|
||||||
|
|
||||||
// Add version classes to body.
|
this.addSiteClasses(data);
|
||||||
this.removeModeClasses([MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX]);
|
|
||||||
|
|
||||||
this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(data.release || ''));
|
|
||||||
this.addSiteUrlClass(data.siteurl);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -154,11 +148,7 @@ export class AppComponent implements OnInit, AfterViewInit {
|
||||||
if (data.siteId === CoreSites.getCurrentSiteId()) {
|
if (data.siteId === CoreSites.getCurrentSiteId()) {
|
||||||
this.loadCustomStrings();
|
this.loadCustomStrings();
|
||||||
|
|
||||||
// Add version classes to body.
|
this.addSiteClasses(data);
|
||||||
this.removeModeClasses([MOODLE_VERSION_PREFIX, MOODLE_SITE_URL_PREFIX]);
|
|
||||||
|
|
||||||
this.addVersionClass(MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(data.release || ''));
|
|
||||||
this.addSiteUrlClass(data.siteurl);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -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.
|
* 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.
|
* This is primarily used to add the siteurl to the body tag as a CSS class.
|
||||||
|
|
|
@ -1402,7 +1402,7 @@ export type CoreCourseSearchedData = CoreCourseBasicSearchedData & {
|
||||||
enablecompletion?: number; // Completion enabled? 1: yes 0: no.
|
enablecompletion?: number; // Completion enabled? 1: yes 0: no.
|
||||||
completionnotify?: number; // 1: yes 0: no.
|
completionnotify?: number; // 1: yes 0: no.
|
||||||
lang?: string; // Forced course language.
|
lang?: string; // Forced course language.
|
||||||
theme?: string; // Fame of the forced theme.
|
theme?: string; // Name of the forced theme.
|
||||||
marker?: number; // Current course marker.
|
marker?: number; // Current course marker.
|
||||||
legacyfiles?: number; // If legacy files are enabled.
|
legacyfiles?: number; // If legacy files are enabled.
|
||||||
calendartype?: string; // Calendar type.
|
calendartype?: string; // Calendar type.
|
||||||
|
|
Loading…
Reference in New Issue