diff --git a/public/app/core/context/ModalsProvider.ts b/public/app/core/context/ModalsProvider.ts new file mode 100644 index 00000000000..e69de29bb2d diff --git a/public/app/features/alerting/unified/RedirectToRuleViewer.test.tsx b/public/app/features/alerting/unified/RedirectToRuleViewer.test.tsx index 9726a8e7cea..5be4926cf12 100644 --- a/public/app/features/alerting/unified/RedirectToRuleViewer.test.tsx +++ b/public/app/features/alerting/unified/RedirectToRuleViewer.test.tsx @@ -20,7 +20,10 @@ jest.mock('react-router-dom', () => ({ Redirect: jest.fn(({}) => `Redirected`), })); -jest.mock('react-use'); +jest.mock('react-use', () => ({ + ...jest.requireActual('react-use'), + useLocation: jest.fn(), +})); const renderRedirectToRuleViewer = (pathname: string, search?: string) => { jest.mocked(useLocation).mockReturnValue({ pathname, trigger: '', search }); diff --git a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx index 5a552704cb4..eac3ccdf927 100644 --- a/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx +++ b/public/app/features/alerting/unified/components/panel-alerts-tab/NewRuleFromPanelButton.test.tsx @@ -26,6 +26,7 @@ jest.mock('react-router-dom', () => ({ jest.spyOn(analytics, 'logInfo'); jest.mock('react-use', () => ({ + ...jest.requireActual('react-use'), useAsync: () => ({ loading: false, value: {} }), })); diff --git a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx index ff9709f52e6..cb8fd8850e0 100644 --- a/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx +++ b/public/app/features/dashboard-scene/scene/NavToolbarActions.tsx @@ -9,13 +9,14 @@ import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate'; import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbar/NavToolbarSeparator'; import { contextSrv } from 'app/core/core'; import { Trans, t } from 'app/core/internationalization'; +import { DashNavModalContextProvider, DashNavModalRoot } from 'app/features/dashboard/components/DashNav/DashNav'; import { getDashboardSrv } from 'app/features/dashboard/services/DashboardSrv'; import { playlistSrv } from 'app/features/playlist/PlaylistSrv'; import { PanelEditor } from '../panel-edit/PanelEditor'; import { ShareModal } from '../sharing/ShareModal'; import { DashboardInteractions } from '../utils/interactions'; -import { dynamicDashNavActions } from '../utils/registerDynamicDashNavAction'; +import { DynamicDashNavButtonModel, dynamicDashNavActions } from '../utils/registerDynamicDashNavAction'; import { DashboardScene } from './DashboardScene'; import { GoToSnapshotOriginButton } from './GoToSnapshotOriginButton'; @@ -27,9 +28,12 @@ interface Props { export const NavToolbarActions = React.memo(({ dashboard }) => { const actions = ( - - - + + + + + + ); return ; @@ -64,6 +68,11 @@ export function ToolbarActions({ dashboard }: Props) { const isShowingDashboard = !editview && !isViewingPanel && !isEditingPanel; const isEditingAndShowingDashboard = isEditing && isShowingDashboard; + if (!isEditingPanel) { + // This adds the precence indicators in enterprise + addDynamicActions(toolbarActions, dynamicDashNavActions.left, 'left-actions'); + } + toolbarActions.push({ group: 'icon-actions', condition: isEditingAndShowingDashboard, @@ -221,18 +230,9 @@ export function ToolbarActions({ dashboard }: Props) { ), }); - if (dynamicDashNavActions.left.length > 0 && !isEditingPanel) { - dynamicDashNavActions.left.map((action, index) => { - const props = { dashboard: getDashboardSrv().getCurrent()! }; - if (action.show(props)) { - const Component = action.component; - toolbarActions.push({ - group: 'icon-actions', - condition: true, - render: () => , - }); - } - }); + if (!isEditingPanel) { + // This adds the alert rules button and the dashboard insights button + addDynamicActions(toolbarActions, dynamicDashNavActions.right, 'icon-actions'); } toolbarActions.push({ @@ -521,6 +521,26 @@ export function ToolbarActions({ dashboard }: Props) { return actionElements; } +function addDynamicActions( + toolbarActions: ToolbarAction[], + registeredActions: DynamicDashNavButtonModel[], + group: string +) { + if (registeredActions.length > 0) { + for (const action of registeredActions) { + const props = { dashboard: getDashboardSrv().getCurrent()! }; + if (action.show(props)) { + const Component = action.component; + toolbarActions.push({ + group: group, + condition: true, + render: () => , + }); + } + } + } +} + function useEditingLibraryPanel(panelEditor?: PanelEditor) { const [isEditingLibraryPanel, setEditingLibraryPanel] = useState(false); diff --git a/public/app/features/dashboard/components/DashNav/DashNav.tsx b/public/app/features/dashboard/components/DashNav/DashNav.tsx index ff50667bc3b..c9a88c6e97f 100644 --- a/public/app/features/dashboard/components/DashNav/DashNav.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNav.tsx @@ -49,9 +49,11 @@ const mapDispatchToProps = { updateTimeZoneForSession, }; -const [useDashNavModelContext, DashNavModalContextProvider] = createStateContext<{ component: React.ReactNode }>({ - component: null, -}); +export const [useDashNavModelContext, DashNavModalContextProvider] = createStateContext<{ component: React.ReactNode }>( + { + component: null, + } +); export function useDashNavModalController() { const [_, setContextState] = useDashNavModelContext(); @@ -62,7 +64,7 @@ export function useDashNavModalController() { }; } -function DashNavModalRoot() { +export function DashNavModalRoot() { const [contextState] = useDashNavModelContext(); return <>{contextState.component};