mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
PublicDashboards: Tag is rerendered when dashboard meta changes in state (#55414)
Can update dashboard meta state using dashboard events.
This commit is contained in:
parent
862a6a2fa6
commit
aae2c3c4f4
17
public/app/core/hooks/useBusEvent.ts
Normal file
17
public/app/core/hooks/useBusEvent.ts
Normal file
@ -0,0 +1,17 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
|
||||
import { BusEvent, BusEventType, EventBus } from '@grafana/data';
|
||||
|
||||
/**
|
||||
A bit more efficient than using useObservable(eventBus.getStream(MyEventType)) as that will create a new Observable and subscription every render
|
||||
*/
|
||||
export function useBusEvent<T extends BusEvent>(eventBus: EventBus, eventType: BusEventType<T>): T | undefined {
|
||||
const [event, setEvent] = useState<T | undefined>();
|
||||
|
||||
useEffect(() => {
|
||||
const sub = eventBus.subscribe(eventType, setEvent);
|
||||
return () => sub.unsubscribe();
|
||||
}, [eventBus, eventType]);
|
||||
|
||||
return event;
|
||||
}
|
@ -0,0 +1,54 @@
|
||||
import { act, render, screen, waitFor } from '@testing-library/react';
|
||||
import React from 'react';
|
||||
import { Provider } from 'react-redux';
|
||||
import { Router } from 'react-router-dom';
|
||||
|
||||
import { locationService } from '@grafana/runtime/src';
|
||||
import { GrafanaContext } from 'app/core/context/GrafanaContext';
|
||||
|
||||
import { getGrafanaContextMock } from '../../../../../test/mocks/getGrafanaContextMock';
|
||||
import { setStarred } from '../../../../core/reducers/navBarTree';
|
||||
import { configureStore } from '../../../../store/configureStore';
|
||||
import { updateTimeZoneForSession } from '../../../profile/state/reducers';
|
||||
import { DashboardModel } from '../../state';
|
||||
|
||||
import { DashNav } from './DashNav';
|
||||
|
||||
describe('Public dashboard title tag', () => {
|
||||
it('will be rendered when publicDashboardEnabled set to true in dashboard meta', async () => {
|
||||
let dashboard = new DashboardModel({}, { publicDashboardEnabled: false });
|
||||
|
||||
const store = configureStore();
|
||||
const context = getGrafanaContextMock();
|
||||
const props = {
|
||||
setStarred: jest.fn() as unknown as typeof setStarred,
|
||||
updateTimeZoneForSession: jest.fn() as unknown as typeof updateTimeZoneForSession,
|
||||
};
|
||||
|
||||
render(
|
||||
<Provider store={store}>
|
||||
<GrafanaContext.Provider value={context}>
|
||||
<Router history={locationService.getHistory()}>
|
||||
<DashNav
|
||||
{...props}
|
||||
dashboard={dashboard}
|
||||
hideTimePicker={true}
|
||||
isFullscreen={false}
|
||||
onAddPanel={() => {}}
|
||||
title="test"
|
||||
/>
|
||||
</Router>
|
||||
</GrafanaContext.Provider>
|
||||
</Provider>
|
||||
);
|
||||
|
||||
const publicTag = screen.queryByText('Public');
|
||||
expect(publicTag).not.toBeInTheDocument();
|
||||
|
||||
act(() => {
|
||||
dashboard.updateMeta({ publicDashboardEnabled: true });
|
||||
});
|
||||
|
||||
await waitFor(() => screen.getByText('Public'));
|
||||
});
|
||||
});
|
@ -19,12 +19,14 @@ import { AppChromeUpdate } from 'app/core/components/AppChrome/AppChromeUpdate';
|
||||
import { NavToolbarSeparator } from 'app/core/components/AppChrome/NavToolbarSeparator';
|
||||
import config from 'app/core/config';
|
||||
import { useGrafana } from 'app/core/context/GrafanaContext';
|
||||
import { useBusEvent } from 'app/core/hooks/useBusEvent';
|
||||
import { DashboardCommentsModal } from 'app/features/dashboard/components/DashboardComments/DashboardCommentsModal';
|
||||
import { SaveDashboardDrawer } from 'app/features/dashboard/components/SaveDashboard/SaveDashboardDrawer';
|
||||
import { ShareModal } from 'app/features/dashboard/components/ShareModal';
|
||||
import { playlistSrv } from 'app/features/playlist/PlaylistSrv';
|
||||
import { updateTimeZoneForSession } from 'app/features/profile/state/reducers';
|
||||
import { KioskMode } from 'app/types';
|
||||
import { DashboardMetaChangedEvent } from 'app/types/events';
|
||||
|
||||
import { setStarred } from '../../../../core/reducers/navBarTree';
|
||||
import { getDashboardSrv } from '../../services/DashboardSrv';
|
||||
@ -75,6 +77,9 @@ export const DashNav = React.memo<Props>((props) => {
|
||||
const forceUpdate = useForceUpdate();
|
||||
const { chrome } = useGrafana();
|
||||
|
||||
// We don't really care about the event payload here only that it triggeres a re-render of this component
|
||||
useBusEvent(props.dashboard.events, DashboardMetaChangedEvent);
|
||||
|
||||
const onStarDashboard = () => {
|
||||
const dashboardSrv = getDashboardSrv();
|
||||
const { dashboard, setStarred } = props;
|
||||
|
@ -119,6 +119,7 @@ describe('SharePublic', () => {
|
||||
await screen.findByText('Welcome to Grafana public dashboards alpha!');
|
||||
expect(screen.getByText('Last 6 hours')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
it('renders default absolute time in input 2', async () => {
|
||||
config.featureToggles.publicDashboards = true;
|
||||
const mockDashboard = new DashboardModel({
|
||||
|
@ -65,10 +65,7 @@ export const SharePublicDashboard = (props: Props) => {
|
||||
usage: false,
|
||||
});
|
||||
|
||||
const timeRange = getTimeRange(
|
||||
{ from: props.dashboard.getDefaultTime().from, to: props.dashboard.getDefaultTime().to },
|
||||
props.dashboard.timezone
|
||||
);
|
||||
const timeRange = getTimeRange(props.dashboard.getDefaultTime(), props.dashboard);
|
||||
|
||||
useEffect(() => {
|
||||
reportInteraction('grafana_dashboards_public_share_viewed');
|
||||
@ -96,7 +93,7 @@ export const SharePublicDashboard = (props: Props) => {
|
||||
return;
|
||||
}
|
||||
|
||||
savePublicDashboardConfig(props.dashboard.uid, publicDashboard, setPublicDashboardConfig).catch();
|
||||
savePublicDashboardConfig(props.dashboard, publicDashboard, setPublicDashboardConfig).catch();
|
||||
};
|
||||
|
||||
const onAcknowledge = useCallback(
|
||||
|
@ -6,6 +6,8 @@ import { VariableModel } from 'app/features/variables/types';
|
||||
import { dispatch } from 'app/store/store';
|
||||
import { DashboardDataDTO, DashboardMeta } from 'app/types/dashboard';
|
||||
|
||||
import { DashboardModel } from '../../state';
|
||||
|
||||
export interface PublicDashboard {
|
||||
accessToken?: string;
|
||||
isEnabled: boolean;
|
||||
@ -28,12 +30,12 @@ export const getPublicDashboardConfig = async (
|
||||
};
|
||||
|
||||
export const savePublicDashboardConfig = async (
|
||||
dashboardUid: string,
|
||||
dashboard: DashboardModel,
|
||||
publicDashboardConfig: PublicDashboard,
|
||||
setPublicDashboard: React.Dispatch<React.SetStateAction<PublicDashboard>>
|
||||
) => {
|
||||
const pdResp: PublicDashboard = await getBackendSrv().post(
|
||||
savePublicDashboardConfigUrl(dashboardUid),
|
||||
savePublicDashboardConfigUrl(dashboard.uid),
|
||||
publicDashboardConfig
|
||||
);
|
||||
|
||||
@ -43,6 +45,12 @@ export const savePublicDashboardConfig = async (
|
||||
|
||||
dispatch(notifyApp(createSuccessNotification('Dashboard sharing configuration saved')));
|
||||
setPublicDashboard(pdResp);
|
||||
|
||||
// Update runtime emta flag
|
||||
dashboard.updateMeta({
|
||||
publicDashboardUid: pdResp.uid,
|
||||
publicDashboardEnabled: publicDashboardConfig.isEnabled,
|
||||
});
|
||||
};
|
||||
|
||||
export const getPublicDashboardConfigUrl = (dashboardUid: string) => {
|
||||
|
@ -25,7 +25,7 @@ import { variableAdapters } from 'app/features/variables/adapters';
|
||||
import { onTimeRangeUpdated } from 'app/features/variables/state/actions';
|
||||
import { GetVariables, getVariablesByKey } from 'app/features/variables/state/selectors';
|
||||
import { CoreEvents, DashboardMeta, KioskMode } from 'app/types';
|
||||
import { DashboardPanelsChangedEvent, RenderEvent } from 'app/types/events';
|
||||
import { DashboardMetaChangedEvent, DashboardPanelsChangedEvent, RenderEvent } from 'app/types/events';
|
||||
|
||||
import { appEvents } from '../../../core/core';
|
||||
import { dispatch } from '../../../store/store';
|
||||
@ -480,6 +480,11 @@ export class DashboardModel implements TimeModel {
|
||||
this.events.publish(new DashboardPanelsChangedEvent());
|
||||
}
|
||||
|
||||
updateMeta(updates: Partial<DashboardMeta>) {
|
||||
this.meta = { ...this.meta, ...updates };
|
||||
this.events.publish(new DashboardMetaChangedEvent());
|
||||
}
|
||||
|
||||
sortPanelsByGridPos() {
|
||||
this.panels.sort((panelA, panelB) => {
|
||||
if (panelA.gridPos.y === panelB.gridPos.y) {
|
||||
|
@ -124,6 +124,10 @@ export class DashboardPanelsChangedEvent extends BusEventBase {
|
||||
static type = 'dashboard-panels-changed';
|
||||
}
|
||||
|
||||
export class DashboardMetaChangedEvent extends BusEventBase {
|
||||
static type = 'dashboard-meta-changed';
|
||||
}
|
||||
|
||||
export class PanelDirectiveReadyEvent extends BusEventBase {
|
||||
static type = 'panel-directive-ready';
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user