From ad69de4a104373a084552b786021ff6d12000904 Mon Sep 17 00:00:00 2001 From: Ryan McKinley Date: Wed, 20 Oct 2021 13:01:21 -0700 Subject: [PATCH] AppEvents: export appEvents in @grafana/runtime and support copy panel (#40715) --- .../grafana-runtime/src/services/appEvents.ts | 59 +++++++++++++++++++ .../grafana-runtime/src/services/index.ts | 1 + public/app/angular/panel/panel_directive.ts | 3 +- public/app/core/services/toggleTheme.ts | 2 +- public/app/core/services/util_srv.ts | 3 + public/app/core/utils/ConfigProvider.tsx | 3 +- .../DashNav/DashNavTimeControls.tsx | 3 +- .../components/DashboardRow/DashboardRow.tsx | 4 +- .../PanelEditor/PanelEditorTableView.tsx | 2 +- .../components/SubMenu/DashboardLinks.tsx | 2 +- .../dashboard/dashgrid/PanelChrome.tsx | 4 +- .../dashboard/state/DashboardModel.ts | 3 +- .../features/dashboard/state/PanelModel.ts | 3 +- public/app/features/dashboard/utils/panel.ts | 4 +- .../app/features/inspector/QueryInspector.tsx | 3 +- .../DashboardQueryRunner.ts | 2 +- public/app/routes/GrafanaCtrl.ts | 2 + public/app/types/events.ts | 21 +------ 18 files changed, 85 insertions(+), 39 deletions(-) create mode 100644 packages/grafana-runtime/src/services/appEvents.ts diff --git a/packages/grafana-runtime/src/services/appEvents.ts b/packages/grafana-runtime/src/services/appEvents.ts new file mode 100644 index 00000000000..c430a554df9 --- /dev/null +++ b/packages/grafana-runtime/src/services/appEvents.ts @@ -0,0 +1,59 @@ +import { BusEventBase, BusEventWithPayload, EventBus, GrafanaTheme2, PanelModel, TimeRange } from '@grafana/data'; + +/** + * Called when a dashboard is refreshed + * + * @public + */ +export class RefreshEvent extends BusEventBase { + static type = 'refresh'; +} + +/** + * Called when the theme settings change + * + * @public + */ +export class ThemeChangedEvent extends BusEventWithPayload { + static type = 'theme-changed'; +} + +/** + * Called when time range is updated + * + * @public + */ +export class TimeRangeUpdatedEvent extends BusEventWithPayload { + static type = 'time-range-updated'; +} + +/** + * Called to copy a panel JSON into local storage + * + * @public + */ +export class CopyPanelEvent extends BusEventWithPayload { + static type = 'copy-panel'; +} + +// Internal singleton instance +let singletonInstance: EventBus; + +/** + * Used during startup by Grafana to set the LocationSrv so it is available + * via the {@link getLocationSrv} to the rest of the application. + * + * @internal + */ +export function setAppEvents(instance: EventBus) { + singletonInstance = instance; +} + +/** + * Used to retrieve an event bus that manages application level events + * + * @public + */ +export function getAppEvents(): EventBus { + return singletonInstance; +} diff --git a/packages/grafana-runtime/src/services/index.ts b/packages/grafana-runtime/src/services/index.ts index 85a9671b4d8..04b7de736fd 100644 --- a/packages/grafana-runtime/src/services/index.ts +++ b/packages/grafana-runtime/src/services/index.ts @@ -7,3 +7,4 @@ export * from './templateSrv'; export * from './legacyAngularInjector'; export * from './live'; export * from './LocationService'; +export * from './appEvents'; diff --git a/public/app/angular/panel/panel_directive.ts b/public/app/angular/panel/panel_directive.ts index 7f0c5b642e8..90142b54c0e 100644 --- a/public/app/angular/panel/panel_directive.ts +++ b/public/app/angular/panel/panel_directive.ts @@ -4,8 +4,9 @@ import { PanelEvents } from '@grafana/data'; import { PanelModel } from '../../features/dashboard/state'; import { PanelCtrl } from './panel_ctrl'; import { Subscription } from 'rxjs'; -import { PanelDirectiveReadyEvent, RefreshEvent, RenderEvent } from 'app/types/events'; +import { PanelDirectiveReadyEvent, RenderEvent } from 'app/types/events'; import { coreModule } from 'app/core/core_module'; +import { RefreshEvent } from '@grafana/runtime'; const panelTemplate = ` diff --git a/public/app/core/services/toggleTheme.ts b/public/app/core/services/toggleTheme.ts index 7a2b5220fbc..2cb4d1b7770 100644 --- a/public/app/core/services/toggleTheme.ts +++ b/public/app/core/services/toggleTheme.ts @@ -1,4 +1,4 @@ -import { ThemeChangedEvent } from 'app/types/events'; +import { ThemeChangedEvent } from '@grafana/runtime'; import appEvents from '../app_events'; import { config } from '../config'; import { PreferencesService } from './PreferencesService'; diff --git a/public/app/core/services/util_srv.ts b/public/app/core/services/util_srv.ts index 509f6404fd5..4ad5e32ca82 100644 --- a/public/app/core/services/util_srv.ts +++ b/public/app/core/services/util_srv.ts @@ -16,6 +16,8 @@ import { } from '../../types/events'; import { ConfirmModal, ConfirmModalProps } from '@grafana/ui'; import { deprecationWarning, textUtil } from '@grafana/data'; +import { CopyPanelEvent } from '@grafana/runtime'; +import { copyPanel } from 'app/features/dashboard/utils/panel'; export class UtilSrv { modalScope: any; @@ -32,6 +34,7 @@ export class UtilSrv { appEvents.subscribe(HideModalEvent, this.hideModal.bind(this)); appEvents.subscribe(ShowConfirmModalEvent, (e) => this.showConfirmModal(e.payload)); appEvents.subscribe(ShowModalReactEvent, (e) => this.showModalReact(e.payload)); + appEvents.subscribe(CopyPanelEvent, (e) => copyPanel(e.payload)); } showModalReact(options: any) { diff --git a/public/app/core/utils/ConfigProvider.tsx b/public/app/core/utils/ConfigProvider.tsx index fe35ba0adba..fe9e64d28bb 100644 --- a/public/app/core/utils/ConfigProvider.tsx +++ b/public/app/core/utils/ConfigProvider.tsx @@ -1,8 +1,7 @@ import React, { useEffect, useState } from 'react'; -import { config, GrafanaBootConfig } from '@grafana/runtime'; +import { config, GrafanaBootConfig, ThemeChangedEvent } from '@grafana/runtime'; import { ThemeContext } from '@grafana/ui'; import { appEvents } from '../core'; -import { ThemeChangedEvent } from 'app/types/events'; import { createTheme } from '@grafana/data'; export const ConfigContext = React.createContext(config); diff --git a/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx b/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx index e2ae0dcb69c..94313c0ec21 100644 --- a/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx +++ b/public/app/features/dashboard/components/DashNav/DashNavTimeControls.tsx @@ -1,6 +1,7 @@ // Libraries import React, { Component } from 'react'; import { dateMath, TimeRange, TimeZone } from '@grafana/data'; +import { TimeRangeUpdatedEvent } from '@grafana/runtime'; // Types import { DashboardModel } from '../../state'; @@ -12,7 +13,7 @@ import { TimePickerWithHistory } from 'app/core/components/TimePicker/TimePicker // Utils & Services import { getTimeSrv } from 'app/features/dashboard/services/TimeSrv'; import { appEvents } from 'app/core/core'; -import { ShiftTimeEvent, ShiftTimeEventPayload, TimeRangeUpdatedEvent, ZoomOutEvent } from '../../../../types/events'; +import { ShiftTimeEvent, ShiftTimeEventPayload, ZoomOutEvent } from '../../../../types/events'; import { Unsubscribable } from 'rxjs'; export interface Props { diff --git a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx index 378974b47de..94213237567 100644 --- a/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx +++ b/public/app/features/dashboard/components/DashboardRow/DashboardRow.tsx @@ -5,8 +5,8 @@ import { PanelModel } from '../../state/PanelModel'; import { DashboardModel } from '../../state/DashboardModel'; import appEvents from 'app/core/app_events'; import { RowOptionsButton } from '../RowOptions/RowOptionsButton'; -import { getTemplateSrv } from '@grafana/runtime'; -import { RefreshEvent, ShowConfirmModalEvent } from '../../../../types/events'; +import { getTemplateSrv, RefreshEvent } from '@grafana/runtime'; +import { ShowConfirmModalEvent } from '../../../../types/events'; import { Unsubscribable } from 'rxjs'; export interface DashboardRowProps { diff --git a/public/app/features/dashboard/components/PanelEditor/PanelEditorTableView.tsx b/public/app/features/dashboard/components/PanelEditor/PanelEditorTableView.tsx index 3748c712951..e8368fa62f3 100644 --- a/public/app/features/dashboard/components/PanelEditor/PanelEditorTableView.tsx +++ b/public/app/features/dashboard/components/PanelEditor/PanelEditorTableView.tsx @@ -4,7 +4,7 @@ import React, { useEffect, useState } from 'react'; import { PanelModel, DashboardModel } from '../../state'; import { usePanelLatestData } from './usePanelLatestData'; import { PanelOptions } from 'app/plugins/panel/table/models.gen'; -import { RefreshEvent } from 'app/types/events'; +import { RefreshEvent } from '@grafana/runtime'; import { applyPanelTimeOverrides } from 'app/features/dashboard/utils/panel'; import { getTimeSrv, TimeSrv } from '../../services/TimeSrv'; interface Props { diff --git a/public/app/features/dashboard/components/SubMenu/DashboardLinks.tsx b/public/app/features/dashboard/components/SubMenu/DashboardLinks.tsx index 909e5daaa26..0e9d8d0c00b 100644 --- a/public/app/features/dashboard/components/SubMenu/DashboardLinks.tsx +++ b/public/app/features/dashboard/components/SubMenu/DashboardLinks.tsx @@ -9,7 +9,7 @@ import { DashboardLink } from '../../state/DashboardModel'; import { linkIconMap } from '../LinksSettings/LinkSettingsEdit'; import { useEffectOnce } from 'react-use'; import { selectors } from '@grafana/e2e-selectors'; -import { TimeRangeUpdatedEvent } from 'app/types/events'; +import { TimeRangeUpdatedEvent } from '@grafana/runtime'; export interface Props { dashboard: DashboardModel; diff --git a/public/app/features/dashboard/dashgrid/PanelChrome.tsx b/public/app/features/dashboard/dashgrid/PanelChrome.tsx index 4892a66e113..44f89fa57e6 100644 --- a/public/app/features/dashboard/dashgrid/PanelChrome.tsx +++ b/public/app/features/dashboard/dashgrid/PanelChrome.tsx @@ -1,7 +1,7 @@ import React, { PureComponent } from 'react'; import classNames from 'classnames'; import { Subscription } from 'rxjs'; -import { locationService } from '@grafana/runtime'; +import { locationService, RefreshEvent } from '@grafana/runtime'; import { AbsoluteTimeRange, AnnotationChangeEvent, @@ -30,7 +30,7 @@ import config from 'app/core/config'; import { DashboardModel, PanelModel } from '../state'; import { PANEL_BORDER } from 'app/core/constants'; import { loadSnapshotData } from '../utils/loadSnapshotData'; -import { RefreshEvent, RenderEvent } from 'app/types/events'; +import { RenderEvent } from 'app/types/events'; import { changeSeriesColorConfigFactory } from 'app/plugins/panel/timeseries/overrides/colorSeriesConfigFactory'; import { seriesVisibilityConfigFactory } from './SeriesVisibilityConfigFactory'; import { deleteAnnotation, saveAnnotation, updateAnnotation } from '../../annotations/api'; diff --git a/public/app/features/dashboard/state/DashboardModel.ts b/public/app/features/dashboard/state/DashboardModel.ts index 71d79862a44..3246b275027 100644 --- a/public/app/features/dashboard/state/DashboardModel.ts +++ b/public/app/features/dashboard/state/DashboardModel.ts @@ -42,10 +42,11 @@ import { variableAdapters } from 'app/features/variables/adapters'; import { onTimeRangeUpdated } from 'app/features/variables/state/actions'; import { dispatch } from '../../../store/store'; import { isAllVariable } from '../../variables/utils'; -import { DashboardPanelsChangedEvent, RefreshEvent, RenderEvent, TimeRangeUpdatedEvent } from 'app/types/events'; +import { DashboardPanelsChangedEvent, RenderEvent } from 'app/types/events'; import { getTimeSrv } from '../services/TimeSrv'; import { mergePanels, PanelMergeInfo } from '../utils/panelMerge'; import { isOnTheSameGridRow } from './utils'; +import { RefreshEvent, TimeRangeUpdatedEvent } from '@grafana/runtime'; export interface CloneOptions { saveVariables?: boolean; diff --git a/public/app/features/dashboard/state/PanelModel.ts b/public/app/features/dashboard/state/PanelModel.ts index 5756fa021cf..63274fc9534 100644 --- a/public/app/features/dashboard/state/PanelModel.ts +++ b/public/app/features/dashboard/state/PanelModel.ts @@ -2,7 +2,7 @@ import { cloneDeep, defaultsDeep, isArray, isEqual, keys } from 'lodash'; import { v4 as uuidv4 } from 'uuid'; // Utils -import { getTemplateSrv } from '@grafana/runtime'; +import { getTemplateSrv, RefreshEvent } from '@grafana/runtime'; import { getNextRefIdChar } from 'app/core/utils/query'; // Types import { @@ -27,7 +27,6 @@ import { PanelOptionsChangedEvent, PanelQueriesChangedEvent, PanelTransformationsChangedEvent, - RefreshEvent, RenderEvent, } from 'app/types/events'; import { getTimeSrv } from '../services/TimeSrv'; diff --git a/public/app/features/dashboard/utils/panel.ts b/public/app/features/dashboard/utils/panel.ts index 8911ff69dae..2c68b00cd5b 100644 --- a/public/app/features/dashboard/utils/panel.ts +++ b/public/app/features/dashboard/utils/panel.ts @@ -4,7 +4,7 @@ import store from 'app/core/store'; // Models import { DashboardModel } from 'app/features/dashboard/state/DashboardModel'; import { PanelModel } from 'app/features/dashboard/state/PanelModel'; -import { TimeRange, AppEvents, rangeUtil, dateMath } from '@grafana/data'; +import { TimeRange, AppEvents, rangeUtil, dateMath, PanelModel as IPanelModel } from '@grafana/data'; // Utils import { isString as _isString } from 'lodash'; @@ -52,7 +52,7 @@ export const duplicatePanel = (dashboard: DashboardModel, panel: PanelModel) => dashboard.duplicatePanel(panel); }; -export const copyPanel = (panel: PanelModel) => { +export const copyPanel = (panel: IPanelModel) => { let saveModel = panel; if (panel instanceof PanelModel) { saveModel = panel.getSaveModel(); diff --git a/public/app/features/inspector/QueryInspector.tsx b/public/app/features/inspector/QueryInspector.tsx index e2546a0d4dd..226eb1e6941 100644 --- a/public/app/features/inspector/QueryInspector.tsx +++ b/public/app/features/inspector/QueryInspector.tsx @@ -8,11 +8,10 @@ import { CopyToClipboard } from 'app/core/components/CopyToClipboard/CopyToClipb import { PanelModel } from 'app/features/dashboard/state'; import { getPanelInspectorStyles } from './styles'; import { supportsDataQuery } from 'app/features/dashboard/components/PanelEditor/utils'; -import { config } from '@grafana/runtime'; +import { config, RefreshEvent } from '@grafana/runtime'; import { css } from '@emotion/css'; import { Subscription } from 'rxjs'; import { backendSrv } from 'app/core/services/backend_srv'; -import { RefreshEvent } from 'app/types/events'; interface DsQuery { isLoading: boolean; diff --git a/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.ts b/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.ts index cae76d671aa..b7756e6295c 100644 --- a/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.ts +++ b/public/app/features/query/state/DashboardQueryRunner/DashboardQueryRunner.ts @@ -16,7 +16,7 @@ import { AnnotationsWorker } from './AnnotationsWorker'; import { getAnnotationsByPanelId } from './utils'; import { DashboardModel } from '../../../dashboard/state'; import { getTimeSrv, TimeSrv } from '../../../dashboard/services/TimeSrv'; -import { RefreshEvent } from '../../../../types/events'; +import { RefreshEvent } from '@grafana/runtime'; import { config } from 'app/core/config'; import { UnifiedAlertStatesWorker } from './UnifiedAlertStatesWorker'; diff --git a/public/app/routes/GrafanaCtrl.ts b/public/app/routes/GrafanaCtrl.ts index a195b13d4f5..42e26003331 100644 --- a/public/app/routes/GrafanaCtrl.ts +++ b/public/app/routes/GrafanaCtrl.ts @@ -11,6 +11,7 @@ import { setLegacyAngularInjector, setLocationSrv, locationService, + setAppEvents, } from '@grafana/runtime'; import config from 'app/core/config'; import coreModule from 'app/core/core_module'; @@ -56,6 +57,7 @@ export class GrafanaCtrl { datasourceSrv.init(config.datasources, config.defaultDatasource); setLocationSrv(locationService); + setAppEvents(appEvents); initGrafanaLive(); diff --git a/public/app/types/events.ts b/public/app/types/events.ts index 2da73d11ae7..7311feb048f 100644 --- a/public/app/types/events.ts +++ b/public/app/types/events.ts @@ -1,11 +1,4 @@ -import { - AnnotationQuery, - BusEventBase, - BusEventWithPayload, - eventFactory, - GrafanaTheme2, - TimeRange, -} from '@grafana/data'; +import { AnnotationQuery, BusEventBase, BusEventWithPayload, eventFactory } from '@grafana/data'; import { IconName } from '@grafana/ui'; /** @@ -132,10 +125,6 @@ export class DashboardPanelsChangedEvent extends BusEventBase { static type = 'dashboard-panels-changed'; } -export class RefreshEvent extends BusEventBase { - static type = 'refresh'; -} - export class PanelDirectiveReadyEvent extends BusEventBase { static type = 'panel-directive-ready'; } @@ -144,10 +133,6 @@ export class RenderEvent extends BusEventBase { static type = 'render'; } -export class ThemeChangedEvent extends BusEventWithPayload { - static type = 'theme-changed'; -} - export class ZoomOutEvent extends BusEventWithPayload { static type = 'zoom-out'; } @@ -198,10 +183,6 @@ export class AnnotationQueryFinished extends BusEventWithPayload { - static type = 'time-range-updated'; -} - export class PanelEditEnteredEvent extends BusEventWithPayload { static type = 'panel-edit-started'; }