mirror of
https://github.com/grafana/grafana.git
synced 2025-02-25 18:55:37 -06:00
197 lines
4.9 KiB
TypeScript
197 lines
4.9 KiB
TypeScript
import { SetPanelAttentionEvent } from '@grafana/data';
|
|
import { locationService } from '@grafana/runtime';
|
|
import { sceneGraph, VizPanel } from '@grafana/scenes';
|
|
import appEvents from 'app/core/app_events';
|
|
import { KeybindingSet } from 'app/core/services/KeybindingSet';
|
|
|
|
import { ShareModal } from '../sharing/ShareModal';
|
|
import { dashboardSceneGraph } from '../utils/dashboardSceneGraph';
|
|
import { getEditPanelUrl, getInspectUrl, getViewPanelUrl, tryGetExploreUrlForPanel } from '../utils/urlBuilders';
|
|
import { getPanelIdForVizPanel } from '../utils/utils';
|
|
|
|
import { DashboardScene } from './DashboardScene';
|
|
import { onRemovePanel, toggleVizPanelLegend } from './PanelMenuBehavior';
|
|
|
|
export function setupKeyboardShortcuts(scene: DashboardScene) {
|
|
const keybindings = new KeybindingSet();
|
|
let vizPanelKey: string | null = null;
|
|
|
|
const panelAttentionSubscription = appEvents.subscribe(SetPanelAttentionEvent, (event) => {
|
|
if (typeof event.payload.panelId === 'string') {
|
|
vizPanelKey = event.payload.panelId;
|
|
}
|
|
});
|
|
|
|
function withFocusedPanel(scene: DashboardScene, fn: (vizPanel: VizPanel) => void) {
|
|
return () => {
|
|
const vizPanel = sceneGraph.findObject(scene, (o) => o.state.key === vizPanelKey);
|
|
if (vizPanel && vizPanel instanceof VizPanel) {
|
|
fn(vizPanel);
|
|
return;
|
|
}
|
|
};
|
|
}
|
|
|
|
// View panel
|
|
keybindings.addBinding({
|
|
key: 'v',
|
|
onTrigger: withFocusedPanel(scene, (vizPanel: VizPanel) => {
|
|
if (!scene.state.viewPanelScene) {
|
|
locationService.push(getViewPanelUrl(vizPanel));
|
|
}
|
|
}),
|
|
});
|
|
|
|
// Panel edit
|
|
keybindings.addBinding({
|
|
key: 'e',
|
|
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
|
const sceneRoot = vizPanel.getRoot();
|
|
if (sceneRoot instanceof DashboardScene) {
|
|
const panelId = getPanelIdForVizPanel(vizPanel);
|
|
if (!scene.state.editPanel) {
|
|
locationService.push(getEditPanelUrl(panelId));
|
|
}
|
|
}
|
|
}),
|
|
});
|
|
|
|
// Panel share
|
|
keybindings.addBinding({
|
|
key: 'p s',
|
|
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
|
scene.showModal(new ShareModal({ panelRef: vizPanel.getRef() }));
|
|
}),
|
|
});
|
|
|
|
// Panel inspect
|
|
keybindings.addBinding({
|
|
key: 'i',
|
|
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
|
locationService.push(getInspectUrl(vizPanel));
|
|
}),
|
|
});
|
|
|
|
// Got to Explore for panel
|
|
keybindings.addBinding({
|
|
key: 'p x',
|
|
onTrigger: withFocusedPanel(scene, async (vizPanel: VizPanel) => {
|
|
const url = await tryGetExploreUrlForPanel(vizPanel);
|
|
if (url) {
|
|
locationService.push(url);
|
|
}
|
|
}),
|
|
});
|
|
|
|
// Toggle legend
|
|
keybindings.addBinding({
|
|
key: 'p l',
|
|
onTrigger: withFocusedPanel(scene, toggleVizPanelLegend),
|
|
});
|
|
|
|
// Refresh
|
|
keybindings.addBinding({
|
|
key: 'd r',
|
|
onTrigger: () => sceneGraph.getTimeRange(scene).onRefresh(),
|
|
});
|
|
|
|
// Zoom out
|
|
keybindings.addBinding({
|
|
key: 't z',
|
|
onTrigger: () => {
|
|
handleZoomOut(scene);
|
|
},
|
|
});
|
|
|
|
keybindings.addBinding({
|
|
key: 'ctrl+z',
|
|
onTrigger: () => {
|
|
handleZoomOut(scene);
|
|
},
|
|
});
|
|
|
|
// Relative -> Absolute time range
|
|
keybindings.addBinding({
|
|
key: 't a',
|
|
onTrigger: () => {
|
|
const timePicker = dashboardSceneGraph.getTimePicker(scene);
|
|
timePicker?.toAbsolute();
|
|
},
|
|
});
|
|
|
|
keybindings.addBinding({
|
|
key: 't left',
|
|
onTrigger: () => {
|
|
handleTimeRangeShift(scene, 'left');
|
|
},
|
|
});
|
|
|
|
keybindings.addBinding({
|
|
key: 't right',
|
|
onTrigger: () => {
|
|
handleTimeRangeShift(scene, 'right');
|
|
},
|
|
});
|
|
|
|
// Dashboard settings
|
|
keybindings.addBinding({
|
|
key: 'd s',
|
|
onTrigger: scene.onOpenSettings,
|
|
});
|
|
|
|
keybindings.addBinding({
|
|
key: 'mod+s',
|
|
onTrigger: () => scene.openSaveDrawer({}),
|
|
});
|
|
|
|
// toggle all panel legends (TODO)
|
|
// delete panel
|
|
keybindings.addBinding({
|
|
key: 'p r',
|
|
onTrigger: withFocusedPanel(scene, (vizPanel: VizPanel) => {
|
|
if (scene.state.isEditing) {
|
|
onRemovePanel(scene, vizPanel);
|
|
}
|
|
}),
|
|
});
|
|
|
|
// duplicate panel
|
|
keybindings.addBinding({
|
|
key: 'p d',
|
|
onTrigger: withFocusedPanel(scene, (vizPanel: VizPanel) => {
|
|
if (scene.state.isEditing) {
|
|
scene.duplicatePanel(vizPanel);
|
|
}
|
|
}),
|
|
});
|
|
|
|
// toggle all exemplars (TODO)
|
|
// collapse all rows (TODO)
|
|
// expand all rows (TODO)
|
|
|
|
return () => {
|
|
keybindings.removeAll();
|
|
panelAttentionSubscription.unsubscribe();
|
|
};
|
|
}
|
|
|
|
function handleZoomOut(scene: DashboardScene) {
|
|
const timePicker = dashboardSceneGraph.getTimePicker(scene);
|
|
timePicker?.onZoom();
|
|
}
|
|
|
|
function handleTimeRangeShift(scene: DashboardScene, direction: 'left' | 'right') {
|
|
const timePicker = dashboardSceneGraph.getTimePicker(scene);
|
|
|
|
if (!timePicker) {
|
|
return;
|
|
}
|
|
|
|
if (direction === 'left') {
|
|
timePicker.onMoveBackward();
|
|
}
|
|
if (direction === 'right') {
|
|
timePicker.onMoveForward();
|
|
}
|
|
}
|