Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
49 changes: 43 additions & 6 deletions public/app/fn-app/create-mfe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
updateMfeMode,
} from 'app/store/configureMfeStore';

import { FNDashboardProps, FailedToMountGrafanaErrorName } from './types';
import { FNDashboardProps, FailedToMountGrafanaErrorName, MfeContainer } from './types';

/**
* NOTE:
Expand Down Expand Up @@ -59,6 +59,7 @@ type DeepPartial<T> = {

class createMfe {
private static readonly containerSelector = '#grafanaRoot';
private static themeStyleRoot: MfeContainer | null = null;
private static logger = FnLoggerService;

mode: FNDashboardProps['mode'];
Expand Down Expand Up @@ -101,6 +102,28 @@ class createMfe {
return stylesheetLink;
}

private static setThemeStyleRoot(container: FNDashboardProps['container']) {
if (container) {
createMfe.themeStyleRoot = container;
}
}

private static getThemeStyleRoot() {
if (!createMfe.themeStyleRoot) {
throw new Error('[FN Grafana]: Failed to load theme. MFE container does not exist.');
}

return createMfe.themeStyleRoot;
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

private static getThemeLinkTarget(styleRoot: MfeContainer) {
return styleRoot instanceof Document ? styleRoot.body : styleRoot;
}

private static getThemeLinks(styleRoot: MfeContainer) {
return Array.from(styleRoot.querySelectorAll('link'));
}

private static createGrafanaTheme2(mode: FNDashboardProps['mode']) {
config.theme2 = createTheme({
colors: {
Expand Down Expand Up @@ -135,8 +158,12 @@ class createMfe {
}

// NOTE: based on grafana function: 'toggleTheme'
private static removeThemeLinks(modeToBeTurnedOff: GrafanaThemeType.Light | GrafanaThemeType.Dark, timeout?: number) {
Array.from(document.getElementsByTagName('link')).forEach(createMfe.removeThemeLink(modeToBeTurnedOff, timeout));
private static removeThemeLinks(
modeToBeTurnedOff: GrafanaThemeType.Light | GrafanaThemeType.Dark,
styleRoot: MfeContainer,
timeout?: number
) {
createMfe.getThemeLinks(styleRoot).forEach(createMfe.removeThemeLink(modeToBeTurnedOff, timeout));
}

private static removeThemeLink(modeToBeTurnedOff: FNDashboardProps['mode'], timeout?: number) {
Expand All @@ -162,7 +189,11 @@ class createMfe {
* NOTE:
* If isRuntimeOnly then the stylesheets of the turned off theme are not removed
*/
private static loadFnTheme = (mode: FNDashboardProps['mode'] = GrafanaThemeType.Light, isRuntimeOnly = false) => {
private static loadFnTheme = (
mode: FNDashboardProps['mode'] = GrafanaThemeType.Light,
isRuntimeOnly = false,
styleRoot?: MfeContainer
) => {
createMfe.logger.info('Trying to load theme.', { mode });

const grafanaTheme2 = createMfe.createGrafanaTheme2(mode);
Expand All @@ -179,11 +210,13 @@ class createMfe {
return;
}

createMfe.removeThemeLinks(createMfe.toggleTheme(mode));
const themeStyleRoot = styleRoot ?? createMfe.getThemeStyleRoot();

createMfe.removeThemeLinks(createMfe.toggleTheme(mode), themeStyleRoot);

const newCssLink = createMfe.styleSheetLink;
newCssLink.href = config.bootData.themePaths[mode];
document.body.appendChild(newCssLink);
createMfe.getThemeLinkTarget(themeStyleRoot).appendChild(newCssLink);

createMfe.logger.info('Successfully loaded theme.', { mode });
};
Expand All @@ -198,6 +231,7 @@ class createMfe {
const lifeCycleFn: FrameworkLifeCycles['mount'] = (props: FNDashboardProps) => {
return new Promise((res, rej) => {
try {
createMfe.setThemeStyleRoot(props.container);
createMfe.loadFnTheme(props.mode);
createMfe.Component = Component;

Expand Down Expand Up @@ -260,10 +294,13 @@ class createMfe {
static updateFnApp() {
const lifeCycleFn: FrameworkLifeCycles['update'] = ({
mode,
container,
...other
}: FNDashboardProps & {
readonly renderingDashboardUid?: string;
}) => {
createMfe.setThemeStyleRoot(container);

if (mode && mfeGetStoreState().fnGlobalReducer.mode !== mode) {
mfeDispatch(updateMfeMode(mode));

Expand Down
5 changes: 4 additions & 1 deletion public/app/fn-app/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@ export type GrafanaMicroFrontendActions = {
export type AnyObject<K extends string | number | symbol = string, V = any> = {
[key in K]: V;
};

export type MfeContainer = Document | DocumentFragment | HTMLElement;

export interface FNDashboardProps extends FnState {
name: string;
fnError?: ReactNode;
isLoading: (isLoading: boolean) => void;
setErrors: (errors?: { [K: number | string]: string }) => void;
container?: HTMLElement | null;
container?: MfeContainer | null;
mode: FnGlobalState['mode'];
}