From e7c30a8a05363948380607d4258907b4ebe458c4 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Fri, 29 Nov 2024 12:51:59 -0500 Subject: [PATCH 1/5] custom dashboard checkpoint --- .../src/services/LocationService.tsx | 1 + public/app/core/components/Page/Page.tsx | 26 +-- public/app/core/reducers/fn-slice.ts | 2 + .../AddPanelButton/AddPanelButton.tsx | 7 +- .../dashboard/containers/DashboardPage.tsx | 95 +++++--- .../dashboard/dashgrid/DashboardGrid.tsx | 202 +++++++++++++----- .../dashboard/dashgrid/DashboardPanel.tsx | 2 +- .../dashboard/dashgrid/PanelStateWrapper.tsx | 2 +- public/app/fn-app/create-mfe.ts | 1 + public/app/fn-app/fn-app-provider.tsx | 39 +++- .../fn-dashboard-page/render-fn-dashboard.tsx | 2 +- public/app/fn-app/types.ts | 1 + 12 files changed, 268 insertions(+), 112 deletions(-) diff --git a/packages/grafana-runtime/src/services/LocationService.tsx b/packages/grafana-runtime/src/services/LocationService.tsx index 5b0bcd9e0ccf8..c51b6894705e7 100644 --- a/packages/grafana-runtime/src/services/LocationService.tsx +++ b/packages/grafana-runtime/src/services/LocationService.tsx @@ -21,6 +21,7 @@ export interface LocationService { getHistory: () => H.History; getSearch: () => URLSearchParams; getSearchObject: () => UrlQueryMap; + fnPathnameChange: (path: string, queryParams: any) => void; /** * This is from the old LocationSrv interface diff --git a/public/app/core/components/Page/Page.tsx b/public/app/core/components/Page/Page.tsx index 0f82fd4ba8ced..cd29bbfb55619 100644 --- a/public/app/core/components/Page/Page.tsx +++ b/public/app/core/components/Page/Page.tsx @@ -2,7 +2,6 @@ import { css, cx } from '@emotion/css'; import { useLayoutEffect } from 'react'; import { GrafanaTheme2, PageLayoutType } from '@grafana/data'; -import { config } from '@grafana/runtime'; import { useStyles2 } from '@grafana/ui'; import { useGrafana } from 'app/core/context/GrafanaContext'; @@ -94,24 +93,13 @@ Page.Contents = PageContents; const getStyles = (theme: GrafanaTheme2) => { return { - wrapper: css( - config.featureToggles.bodyScrolling - ? { - label: 'page-wrapper', - display: 'flex', - flex: '1 1 0', - flexDirection: 'column', - position: 'relative', - } - : { - label: 'page-wrapper', - height: '100%', - display: 'flex', - flex: '1 1 0', - flexDirection: 'column', - minHeight: 0, - } - ), + wrapper: css({ + label: 'page-wrapper', + display: 'flex', + flex: '1 1 0', + flexDirection: 'column', + position: 'relative', + }), pageContent: css({ label: 'page-content', flexGrow: 1, diff --git a/public/app/core/reducers/fn-slice.ts b/public/app/core/reducers/fn-slice.ts index d71ce9aef766e..732ca579c5a6a 100644 --- a/public/app/core/reducers/fn-slice.ts +++ b/public/app/core/reducers/fn-slice.ts @@ -6,6 +6,7 @@ import { AnyObject } from '../../fn-app/types'; export interface FnGlobalState { FNDashboard: boolean; + isCustomDashboard: boolean; uid: string; slug: string; version: number; @@ -48,6 +49,7 @@ export const FN_STATE_KEY = 'fnGlobalState'; export const INITIAL_FN_STATE: FnGlobalState = { // NOTE: initial value is false FNDashboard: false, + isCustomDashboard: false, uid: '', slug: '', version: 1, diff --git a/public/app/features/dashboard/components/AddPanelButton/AddPanelButton.tsx b/public/app/features/dashboard/components/AddPanelButton/AddPanelButton.tsx index e76b3769ad076..8d7643ef6f4b4 100644 --- a/public/app/features/dashboard/components/AddPanelButton/AddPanelButton.tsx +++ b/public/app/features/dashboard/components/AddPanelButton/AddPanelButton.tsx @@ -10,9 +10,10 @@ import AddPanelMenu from './AddPanelMenu'; export interface Props { dashboard: DashboardModel; onToolbarAddMenuOpen?: () => void; + isFNDashboard?: boolean; } -const AddPanelButton = ({ dashboard, onToolbarAddMenuOpen }: Props) => { +const AddPanelButton = ({ dashboard, onToolbarAddMenuOpen, isFNDashboard }: Props) => { const [isMenuOpen, setIsMenuOpen] = useState(false); useEffect(() => { @@ -29,8 +30,8 @@ const AddPanelButton = ({ dashboard, onToolbarAddMenuOpen }: Props) => { onVisibleChange={setIsMenuOpen} > - - {config.featureToggles.vizAndWidgetSplit && ( + { + !isFNDashboard && ( + + {config.featureToggles.vizAndWidgetSplit && ( + + + + Add a widget + + + + Create lists, markdowns and other widgets + + + + + + )} - Add a widget + Import panel - Create lists, markdowns and other widgets + + Add visualizations that are shared with other dashboards. + + + + + + + Import a dashboard + + + + + Import dashboards from files or grafana.com. + + + + - )} - - - - Import panel - - - - - Add visualizations that are shared with other dashboards. - - - - - - - - - - Import a dashboard - - - - - Import dashboards from files or grafana.com. - - - - - - - + + ) + } From c602459abcfc337df02e1bb6efb811a972f0419a Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Mon, 2 Dec 2024 22:36:24 -0500 Subject: [PATCH 3/5] checkpoint --- .../dashboard/containers/DashboardPage.tsx | 14 +----- public/app/fn-app/fn-app-provider.tsx | 9 +++- .../fn-dashboard-page/render-fn-dashboard.tsx | 49 ++++++++++++------- 3 files changed, 41 insertions(+), 31 deletions(-) diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index 22165bc1b47a5..9d396536083d4 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -274,17 +274,16 @@ export class UnthemedDashboardPage extends PureComponent { }; static getDerivedStateFromProps(props: Props, state: State) { - const { dashboard, queryParams } = props; + const { dashboard, queryParams, isCustomDashboard, FNDashboard } = props; const urlEditPanelId = queryParams.editPanel; const urlViewPanelId = queryParams.viewPanel; - if (!dashboard) { + if (!dashboard || (FNDashboard && !isCustomDashboard)) { return state; } const updatedState = { ...state }; - // Entering edit mode if (!state.editPanel && urlEditPanelId) { const panel = dashboard.getPanelByUrlId(urlEditPanelId); @@ -399,15 +398,6 @@ export class UnthemedDashboardPage extends PureComponent { const isFNDashboardEditable = (isCustomDashboard && FNDashboard) || !FNDashboard; - console.log('Edit Panel: ', { editPanel, sectionNav, pageNav, isFNDashboardEditable }); - console.log('Dashboard settings: ', { editView: queryParams.editview, pageNav, sectionNav, isFNDashboardEditable }); - console.log('Add Widget: ', { - isFNDashboardEditable, - addWidget: queryParams.addWidget, - configToggle: config.featureToggles.vizAndWidgetSplit, - }); - - const pageClassName = cx({ 'panel-in-fullscreen': Boolean(viewPanel), 'page-hidden': Boolean(queryParams.editview || editPanel), diff --git a/public/app/fn-app/fn-app-provider.tsx b/public/app/fn-app/fn-app-provider.tsx index 37d64c23aa485..b9392fe9147b1 100644 --- a/public/app/fn-app/fn-app-provider.tsx +++ b/public/app/fn-app/fn-app-provider.tsx @@ -12,7 +12,9 @@ import { reportInteraction, } from '@grafana/runtime'; import { ErrorBoundaryAlert, GlobalStyles } from '@grafana/ui'; +import { AngularRoot } from 'app/angular/AngularRoot'; import { loadAndInitAngularIfEnabled } from 'app/angular/loadAndInitAngularIfEnabled'; +import { AppChrome } from 'app/core/components/AppChrome/AppChrome'; import { ModalsContextProvider } from 'app/core/context/ModalsContextProvider'; import { ThemeProvider } from 'app/core/utils/ConfigProvider'; import { FnLoader } from 'app/features/dashboard/components/DashboardLoading/FnLoader'; @@ -66,7 +68,12 @@ export const FnAppProvider: FC> = (props) - {children} +
+ + + {children} + +
diff --git a/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx b/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx index e6c2df45428b9..05d5206261aa4 100644 --- a/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx +++ b/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx @@ -1,4 +1,4 @@ -import { merge, isFunction } from 'lodash'; +import { merge, isFunction, isEqual } from 'lodash'; import { useEffect, FC, useMemo } from 'react'; import { locationService as locationSrv, HistoryWrapper } from '@grafana/runtime'; @@ -50,26 +50,39 @@ export const RenderFNDashboard: FC = (props) => { }, [firstError, setErrors]); useEffect(() => { - locationService.fnPathnameChange(window.location.pathname, queryParams); + const searchParams = getSearchParamsObject(); + if (isEqual(searchParams, queryParams)) { + return; + } + locationService.fnPathnameChange(window.location.pathname, { + ...searchParams, + ...queryParams, + }); }, [queryParams]); - const dashboardPageProps: DashboardPageProps = useMemo( - () => - merge({}, DEFAULT_DASHBOARD_PAGE_PROPS, { - ...DEFAULT_DASHBOARD_PAGE_PROPS, - match: { - params: { - ...props, - }, + const dashboardPageProps: DashboardPageProps = useMemo(() => { + return merge({}, DEFAULT_DASHBOARD_PAGE_PROPS, { + ...DEFAULT_DASHBOARD_PAGE_PROPS, + match: { + params: { + ...props, }, - location: locationService.getLocation(), - queryParams, - hiddenVariables, - controlsContainer, - isLoading, - }), - [controlsContainer, hiddenVariables, isLoading, props, queryParams] - ); + }, + location: locationService.getLocation(), + queryParams: { + ...getSearchParamsObject(), + ...queryParams, + }, + hiddenVariables, + controlsContainer, + isLoading, + }); + }, [controlsContainer, hiddenVariables, isLoading, props, queryParams]); return ; }; + +function getSearchParamsObject() { + const searchParams = new URLSearchParams(window.location.search); + return Object.fromEntries(searchParams.entries()); +} From 38e481cb1e47efce3c004049ab8be4244832cb71 Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Wed, 4 Dec 2024 19:38:28 -0500 Subject: [PATCH 4/5] checkpoint --- .../components/PanelEditor/PanelEditor.tsx | 52 ++++++++++++++----- .../dashboard/containers/DashboardPage.tsx | 6 ++- public/app/fn-app/fn-app-provider.tsx | 3 +- .../fn-app/fn-dashboard-page/fn-dashboard.tsx | 2 +- 4 files changed, 46 insertions(+), 17 deletions(-) diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index a77c269d0ca0e..9299447f5b8cb 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -72,6 +72,8 @@ const mapStateToProps = (state: StoreState, ownProps: OwnProps) => { uiState: state.panelEditor.ui, tableViewEnabled: state.panelEditor.tableViewEnabled, variables: getVariablesByKey(ownProps.dashboard.uid, state), + isMFEDashboard: state.fnGlobalState.FNDashboard, + isMFECustomDashboard: state.fnGlobalState.isCustomDashboard, }; }; @@ -431,27 +433,33 @@ export class PanelEditorUnconnected extends PureComponent { }; render() { - const { initDone, uiState, theme, sectionNav, pageNav, className, updatePanelEditorUIState } = this.props; + const { initDone, uiState, theme, sectionNav, pageNav, className, updatePanelEditorUIState, isMFECustomDashboard } = this.props; const styles = getStyles(theme, this.props); if (!initDone) { return null; } - return ( - - + { + !isMFECustomDashboard ? ( + {this.renderEditorActions()}} - /> + /> + ): ( + {this.renderEditorActions()} + ) + }
- {!uiState.isPanelOptionsVisible ? ( + {!uiState.isPanelOptionsVisible || isMFECustomDashboard ? ( this.renderPanelAndEditor(uiState, styles) ) : ( { /> )}
- + + ) + + return ( + <> + { + !isMFECustomDashboard ? ( + + {editPanelContent} + + ):
{editPanelContent}
+ } + ); } } diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index 9d396536083d4..1b086ed812084 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -423,6 +423,8 @@ export class UnthemedDashboardPage extends PureComponent { ); + const isPanelEditorVisible = editPanel && sectionNav && pageNav && isFNDashboardEditable + return ( <> { layout={PageLayoutType.Canvas} className={pageClassName} onSetScrollRef={this.setScrollRef} - style={{ minHeight: 600 }} + style={{ minHeight: 600, position: 'relative' }} > {showToolbar && (
@@ -497,7 +499,7 @@ export class UnthemedDashboardPage extends PureComponent { {inspectPanel && isFNDashboardEditable && } - {editPanel && sectionNav && pageNav && isFNDashboardEditable && ( + {isPanelEditorVisible && ( > = (props) {children}
+ diff --git a/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx b/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx index 93c50e5d3c52a..77f77f1191317 100644 --- a/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx +++ b/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx @@ -54,7 +54,7 @@ export const DashboardPortal: FC = (p) => { return ( -
{content}
+ {content}
); }; From d57e22e3971937f1d138107e710ff11ac7aa8c1a Mon Sep 17 00:00:00 2001 From: Gurinder Singh Date: Thu, 12 Dec 2024 16:56:23 -0500 Subject: [PATCH 5/5] checkpoint --- .../src/components/Portal/Portal.tsx | 1 + public/app/AppWrapper.tsx | 35 +++++++----- public/app/app.ts | 32 ++++++++--- public/app/core/context/ModalsProvider.ts | 0 .../components/PanelEditor/PanelEditor.tsx | 56 +++++++------------ .../PanelEditor/PanelEditorTabs.tsx | 9 +-- .../dashboard/containers/DashboardPage.tsx | 2 +- .../features/query/components/QueryGroup.tsx | 10 +++- public/app/fn-app/create-mfe.ts | 4 +- .../fn-app/fn-dashboard-page/fn-dashboard.tsx | 10 +++- .../fn-dashboard-page/render-fn-dashboard.tsx | 16 ++++-- 11 files changed, 103 insertions(+), 72 deletions(-) delete mode 100644 public/app/core/context/ModalsProvider.ts diff --git a/packages/grafana-ui/src/components/Portal/Portal.tsx b/packages/grafana-ui/src/components/Portal/Portal.tsx index f4f88831e72e8..62ac76b6a4f1c 100644 --- a/packages/grafana-ui/src/components/Portal/Portal.tsx +++ b/packages/grafana-ui/src/components/Portal/Portal.tsx @@ -60,6 +60,7 @@ export function PortalContainer() { return (
{ } render() { - const { app } = this.props; + const { app, isMFE, children } = this.props; const { ready } = this.state; navigationLogger('AppWrapper', false, 'rendering'); @@ -116,22 +118,29 @@ export class AppWrapper extends Component {
- - - - {pageBanners.map((Banner, index) => ( - + <> + + + + {pageBanners.map((Banner, index) => ( + + ))} + {ready && !isMFE && this.renderRoutes()} + + {bodyRenderHooks.map((Hook, index) => ( + ))} - {ready && this.renderRoutes()} - - {bodyRenderHooks.map((Hook, index) => ( - - ))} + + {children}
- - + {!isMFE && ( + <> + + + + )} diff --git a/public/app/app.ts b/public/app/app.ts index 278884385f3d5..2ebe82e9e1729 100644 --- a/public/app/app.ts +++ b/public/app/app.ts @@ -44,7 +44,7 @@ import { import { setPanelDataErrorView } from '@grafana/runtime/src/components/PanelDataErrorView'; import { setPanelRenderer } from '@grafana/runtime/src/components/PanelRenderer'; import { setPluginPage } from '@grafana/runtime/src/components/PluginPage'; -import config, { updateConfig } from 'app/core/config'; +import config, { Settings, updateConfig } from 'app/core/config'; import { arrayMove } from 'app/core/utils/arrayMove'; import { getStandardTransformers } from 'app/features/transformers/standardTransformers'; @@ -125,7 +125,7 @@ if (process.env.NODE_ENV === 'development') { export class GrafanaApp { context!: GrafanaContextType; - async init() { + async init(isMFE = false) { try { // Let iframe container know grafana has started loading parent.postMessage('GrafanaAppInit', '*'); @@ -133,7 +133,19 @@ export class GrafanaApp { const initI18nPromise = initializeI18n(config.bootData.user.language); initI18nPromise.then(({ language }) => updateConfig({ language })); - setBackendSrv(backendSrv); + if(isMFE){ + backendSrv.setGrafanaPrefix(true); + setBackendSrv(backendSrv); + const settings: Settings = await backendSrv.get('/api/frontend/settings'); + + config.panels = settings.panels; + config.datasources = settings.datasources; + config.defaultDatasource = settings.defaultDatasource; + } else { + setBackendSrv(backendSrv); + } + + initEchoSrv(); initIconCache(); // This needs to be done after the `initEchoSrv` since it is being used under the hood. @@ -270,12 +282,14 @@ export class GrafanaApp { initializeScopes(); - const root = createRoot(document.getElementById('reactRoot')!); - root.render( - createElement(AppWrapper, { - app: this, - }) - ); + if(!isMFE){ + const root = createRoot(document.getElementById('reactRoot')!); + root.render( + createElement(AppWrapper, { + app: this, + }) + ); + } } catch (error) { console.error('Failed to start Grafana', error); window.__grafana_load_failed(); diff --git a/public/app/core/context/ModalsProvider.ts b/public/app/core/context/ModalsProvider.ts deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx index 9299447f5b8cb..c95d0c6e66cfc 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditor.tsx @@ -277,6 +277,7 @@ export class PanelEditorUnconnected extends PureComponent { dashboard={dashboard} tabs={tabs} onChangeTab={this.onChangeTab} + isMfeEditPanel={this.props.isMFEDashboard} />
@@ -433,33 +434,32 @@ export class PanelEditorUnconnected extends PureComponent { }; render() { - const { initDone, uiState, theme, sectionNav, pageNav, className, updatePanelEditorUIState, isMFECustomDashboard } = this.props; + const { initDone, uiState, theme, sectionNav, pageNav, className, updatePanelEditorUIState, isMFECustomDashboard } = + this.props; const styles = getStyles(theme, this.props); if (!initDone) { return null; } - console.log('PanelEditor.tsx this.props', { - isPanelOptionVisible: uiState.isPanelOptionsVisible, - isMFECustomDashboard, - modelState: this.state.showSaveLibraryPanelModal, - }); - - const editPanelContent = ( - <> - { - !isMFECustomDashboard ? ( + return ( + + {!isMFECustomDashboard ? ( {this.renderEditorActions()}} + actions={{this.renderEditorActions()}} /> - ): ( + ) : ( {this.renderEditorActions()} - ) - } + )}
- {!uiState.isPanelOptionsVisible || isMFECustomDashboard ? ( + {!uiState.isPanelOptionsVisible ? ( this.renderPanelAndEditor(uiState, styles) ) : ( { /> )}
- - ) - - return ( - <> - { - !isMFECustomDashboard ? ( - - {editPanelContent} - - ):
{editPanelContent}
- } - + ); } } @@ -521,12 +503,16 @@ export const getStyles = stylesFactory((theme: GrafanaTheme2, props: Props) => { const paneSpacing = theme.spacing(2); return { + mfeWrapper: css({ + height: '100vh', + }), wrapper: css({ width: '100%', flexGrow: 1, minHeight: 0, display: 'flex', paddingTop: theme.spacing(2), + height: '100%', }), verticalSplitPanesWrapper: css({ display: 'flex', diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx index cad04df45f339..33240377edf1b 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditorTabs.tsx @@ -20,9 +20,10 @@ interface PanelEditorTabsProps { dashboard: DashboardModel; tabs: PanelEditorTab[]; onChangeTab: (tab: PanelEditorTab) => void; + isMfeEditPanel?: boolean; } -export const PanelEditorTabs = memo(({ panel, dashboard, tabs, onChangeTab }: PanelEditorTabsProps) => { +export const PanelEditorTabs = memo(({ panel, dashboard, tabs, onChangeTab, isMfeEditPanel }: PanelEditorTabsProps) => { const forceUpdate = useForceUpdate(); const styles = useStyles2(getStyles); @@ -49,7 +50,7 @@ export const PanelEditorTabs = memo(({ panel, dashboard, tabs, onChangeTab }: Pa return () => eventSubs.unsubscribe(); }, [panel, dashboard, forceUpdate]); - const activeTab = tabs.find((item) => item.active)!; + const activeTab = !isMfeEditPanel? tabs.find((item) => item.active)!: tabs.find((item) => item.id === PanelEditorTabId.Query)!; if (tabs.length === 0) { return null; @@ -60,7 +61,7 @@ export const PanelEditorTabs = memo(({ panel, dashboard, tabs, onChangeTab }: Pa return (
- {tabs.map((tab) => { + {!isMfeEditPanel ? tabs.map((tab) => { if (tab.id === PanelEditorTabId.Alert && alertingEnabled) { return ( ); - })} + }): null} {activeTab.id === PanelEditorTabId.Query && } diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx index 1b086ed812084..01983604dc0bf 100644 --- a/public/app/features/dashboard/containers/DashboardPage.tsx +++ b/public/app/features/dashboard/containers/DashboardPage.tsx @@ -483,7 +483,7 @@ export class UnthemedDashboardPage extends PureComponent { )} )} - {!isFNDashboardEditable && } + {initError && } {showSubMenu && (
diff --git a/public/app/features/query/components/QueryGroup.tsx b/public/app/features/query/components/QueryGroup.tsx index ffa97a3fce235..943bc721c74d2 100644 --- a/public/app/features/query/components/QueryGroup.tsx +++ b/public/app/features/query/components/QueryGroup.tsx @@ -27,7 +27,7 @@ import { dataSource as expressionDatasource } from 'app/features/expressions/Exp import { AngularDeprecationPluginNotice } from 'app/features/plugins/angularDeprecation/AngularDeprecationPluginNotice'; import { isSharedDashboardQuery } from 'app/plugins/datasource/dashboard'; import { GrafanaQuery } from 'app/plugins/datasource/grafana/types'; -import { QueryGroupOptions } from 'app/types'; +import { QueryGroupOptions, StoreState, useSelector } from 'app/types'; import { isAngularDatasourcePluginAndNotHidden } from '../../plugins/angularDeprecation/utils'; import { PanelQueryRunner } from '../state/PanelQueryRunner'; @@ -37,6 +37,7 @@ import { GroupActionComponents } from './QueryActionComponent'; import { QueryEditorRows } from './QueryEditorRows'; import { QueryGroupOptionsEditor } from './QueryGroupOptions'; + export interface Props { queryRunner: PanelQueryRunner; options: QueryGroupOptions; @@ -404,6 +405,13 @@ export function QueryGroupTopSection({ }: QueryGroupTopSectionProps) { const styles = getStyles(); const [isHelpOpen, setIsHelpOpen] = useState(false); + const { FNDashboard, isCustomDashboard } = useSelector((state: StoreState) => state.fnGlobalState); + + // do not render data source selection options in micro frontend dashboard + if(isCustomDashboard && FNDashboard){ + return null; + } + return ( <>
diff --git a/public/app/fn-app/create-mfe.ts b/public/app/fn-app/create-mfe.ts index a5d196cc7e8fd..47b84e8006fc4 100644 --- a/public/app/fn-app/create-mfe.ts +++ b/public/app/fn-app/create-mfe.ts @@ -14,6 +14,7 @@ import { GrafanaTheme2 } from '@grafana/data/src/themes/types'; import { ThemeChangedEvent } from '@grafana/runtime'; import { GrafanaBootConfig } from '@grafana/runtime/src/config'; import { getTheme } from '@grafana/ui'; +import app from 'app/app'; import appEvents from 'app/core/app_events'; import config from 'app/core/config'; import { @@ -25,7 +26,6 @@ import { fnStateProps, } from 'app/core/reducers/fn-slice'; import { backendSrv } from 'app/core/services/backend_srv'; -import fn_app from 'app/fn_app'; import { FnLoggerService } from 'app/fn_logger'; import { dispatch } from 'app/store/store'; @@ -89,7 +89,7 @@ class createMfe { } static boot() { - return () => fn_app.init(); + return () => app.init(true); } private static toggleTheme = (mode: FNDashboardProps['mode']): GrafanaThemeType.Light | GrafanaThemeType.Dark => diff --git a/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx b/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx index 77f77f1191317..e27ff542d8aff 100644 --- a/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx +++ b/public/app/fn-app/fn-dashboard-page/fn-dashboard.tsx @@ -1,9 +1,11 @@ import { FC, useMemo } from 'react'; +import { ModalRoot, PortalContainer } from '@grafana/ui'; +import { AppWrapper } from 'app/AppWrapper'; +import app from 'app/app'; import { FnGlobalState, FnPropMappedFromState } from 'app/core/reducers/fn-slice'; import { useSelector } from 'app/types'; -import { FnAppProvider } from '../fn-app-provider'; import { FNDashboardProps } from '../types'; import { RenderPortal } from '../utils'; @@ -13,9 +15,9 @@ type FNDashboardComponentProps = Omit; export const FNDashboard: FC = (props) => { return ( - + - + ); }; @@ -54,6 +56,8 @@ export const DashboardPortal: FC = (p) => { return ( + + {content} ); diff --git a/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx b/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx index 05d5206261aa4..d28dcd6c41630 100644 --- a/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx +++ b/public/app/fn-app/fn-dashboard-page/render-fn-dashboard.tsx @@ -1,5 +1,5 @@ import { merge, isFunction, isEqual } from 'lodash'; -import { useEffect, FC, useMemo } from 'react'; +import { useEffect, FC, useMemo, useRef } from 'react'; import { locationService as locationSrv, HistoryWrapper } from '@grafana/runtime'; import DashboardPage, { DashboardPageProps } from 'app/features/dashboard/containers/DashboardPage'; @@ -28,6 +28,7 @@ const DEFAULT_DASHBOARD_PAGE_PROPS: Pick = (props) => { const { queryParams, controlsContainer, setErrors, hiddenVariables, isLoading } = props; + const uidRef = useRef(null); const firstError = useSelector((state: StoreState) => { const { appNotifications } = state; @@ -50,15 +51,22 @@ export const RenderFNDashboard: FC = (props) => { }, [firstError, setErrors]); useEffect(() => { - const searchParams = getSearchParamsObject(); - if (isEqual(searchParams, queryParams)) { + let searchParams = getSearchParamsObject(); + if (isEqual(searchParams, queryParams) && uidRef.current === props.uid) { return; } + if (uidRef.current !== props.uid) { + searchParams = { + ...(searchParams.from ? { from: searchParams.from } : {}), + ...(searchParams.to ? { to: searchParams.to } : {}), + }; + } locationService.fnPathnameChange(window.location.pathname, { ...searchParams, ...queryParams, }); - }, [queryParams]); + uidRef.current = props.uid; + }, [queryParams, props.uid]); const dashboardPageProps: DashboardPageProps = useMemo(() => { return merge({}, DEFAULT_DASHBOARD_PAGE_PROPS, {