Make canvas bigger, start in the middle
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import { css } from '@emotion/css';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { TransformComponent, TransformWrapper } from 'react-zoom-pan-pinch';
|
||||
import { ReactZoomPanPinchRef, TransformComponent, TransformWrapper } from 'react-zoom-pan-pinch';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { useStyles2 } from '@grafana/ui';
|
||||
@@ -37,7 +37,7 @@ export function ExploreMapCanvas() {
|
||||
);
|
||||
|
||||
const handleTransformChange = useCallback(
|
||||
(ref: any) => {
|
||||
(ref: ReactZoomPanPinchRef) => {
|
||||
dispatch(
|
||||
updateViewport({
|
||||
zoom: ref.state.scale,
|
||||
@@ -52,7 +52,7 @@ export function ExploreMapCanvas() {
|
||||
return (
|
||||
<div className={styles.canvasWrapper}>
|
||||
<TransformWrapper
|
||||
ref={contextTransformRef as any}
|
||||
ref={contextTransformRef}
|
||||
initialScale={viewport.zoom}
|
||||
initialPositionX={viewport.panX}
|
||||
initialPositionY={viewport.panY}
|
||||
@@ -69,7 +69,18 @@ export function ExploreMapCanvas() {
|
||||
wheel={{ step: 0.1 }}
|
||||
>
|
||||
<TransformComponent wrapperClass={styles.transformWrapper} contentClass={styles.transformContent}>
|
||||
<div ref={canvasRef} className={styles.canvas} onClick={handleCanvasClick}>
|
||||
<div
|
||||
ref={canvasRef}
|
||||
className={styles.canvas}
|
||||
onClick={handleCanvasClick}
|
||||
onKeyDown={(e) => {
|
||||
if (e.key === 'Escape') {
|
||||
dispatch(selectPanel({ panelId: undefined }));
|
||||
}
|
||||
}}
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
>
|
||||
{Object.values(panels).map((panel) => (
|
||||
<ExploreMapPanelContainer key={panel.id} panel={panel} />
|
||||
))}
|
||||
@@ -105,8 +116,8 @@ const getStyles = (theme: GrafanaTheme2) => {
|
||||
}),
|
||||
canvas: css({
|
||||
position: 'relative',
|
||||
width: '5000px',
|
||||
height: '5000px',
|
||||
width: '10000px',
|
||||
height: '10000px',
|
||||
backgroundImage: `
|
||||
linear-gradient(${theme.colors.border.weak} 1px, transparent 1px),
|
||||
linear-gradient(90deg, ${theme.colors.border.weak} 1px, transparent 1px)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { css, cx } from '@emotion/css';
|
||||
import { useCallback, useRef } from 'react';
|
||||
import { DraggableData, Rnd, RndResizeCallback } from 'react-rnd';
|
||||
import { Rnd, RndDragCallback, RndResizeCallback } from 'react-rnd';
|
||||
|
||||
import { GrafanaTheme2 } from '@grafana/data';
|
||||
import { t } from '@grafana/i18n';
|
||||
@@ -32,8 +32,8 @@ export function ExploreMapPanelContainer({ panel }: ExploreMapPanelContainerProp
|
||||
const viewport = useSelector((state) => state.exploreMap.viewport);
|
||||
const isSelected = selectedPanelId === panel.id;
|
||||
|
||||
const handleDragStop = useCallback(
|
||||
(_e: MouseEvent | TouchEvent, data: DraggableData) => {
|
||||
const handleDragStop: RndDragCallback = useCallback(
|
||||
(_e, data) => {
|
||||
dispatch(
|
||||
updatePanelPosition({
|
||||
panelId: panel.id,
|
||||
|
||||
@@ -21,7 +21,12 @@ export function ExploreMapToolbar() {
|
||||
const viewport = useSelector((state) => state.exploreMap.viewport);
|
||||
|
||||
const handleAddPanel = useCallback(() => {
|
||||
dispatch(addPanel({}));
|
||||
dispatch(addPanel({
|
||||
viewportSize: {
|
||||
width: window.innerWidth,
|
||||
height: window.innerHeight
|
||||
}
|
||||
}));
|
||||
}, [dispatch]);
|
||||
|
||||
const handleResetCanvas = useCallback(() => {
|
||||
@@ -47,8 +52,14 @@ export function ExploreMapToolbar() {
|
||||
|
||||
const handleResetZoom = useCallback(() => {
|
||||
if (transformRef?.current) {
|
||||
// Reset both scale and position to initial values
|
||||
transformRef.current.setTransform(0, 0, 1, 200);
|
||||
// Reset to center of canvas (5000, 5000)
|
||||
// Calculate position to center the viewport
|
||||
const viewportWidth = window.innerWidth;
|
||||
const viewportHeight = window.innerHeight;
|
||||
const panX = -(5000 - viewportWidth / 2);
|
||||
const panY = -(5000 - viewportHeight / 2);
|
||||
|
||||
transformRef.current.setTransform(panX, panY, 1, 200);
|
||||
}
|
||||
}, [transformRef]);
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ import { createErrorNotification, createSuccessNotification } from 'app/core/cop
|
||||
import { useDispatch, useSelector } from 'app/types/store';
|
||||
|
||||
import { loadCanvas } from '../state/exploreMapSlice';
|
||||
import { ExploreMapState, SerializedExploreState } from '../state/types';
|
||||
import { ExploreMapState, initialExploreMapState, SerializedExploreState } from '../state/types';
|
||||
|
||||
const STORAGE_KEY = 'grafana.exploreMap.state';
|
||||
|
||||
@@ -73,6 +73,7 @@ export function useCanvasPersistence() {
|
||||
// Enrich with Explore state before exporting
|
||||
const enrichedState: ExploreMapState = {
|
||||
...exploreMapState,
|
||||
viewport: initialExploreMapState.viewport, // Don't export viewport state - use initial centered viewport
|
||||
cursors: {}, // Don't export cursor state - it's ephemeral
|
||||
panels: Object.fromEntries(
|
||||
Object.entries(exploreMapState.panels).map(([panelId, panel]) => {
|
||||
|
||||
@@ -12,18 +12,33 @@ import {
|
||||
UserCursor,
|
||||
} from './types';
|
||||
|
||||
interface AddPanelPayload {
|
||||
position?: Partial<PanelPosition>;
|
||||
viewportSize?: { width: number; height: number };
|
||||
}
|
||||
|
||||
const exploreMapSlice = createSlice({
|
||||
name: 'exploreMap',
|
||||
initialState: initialExploreMapState,
|
||||
reducers: {
|
||||
addPanel: (state, action: PayloadAction<{ position?: Partial<PanelPosition> }>) => {
|
||||
addPanel: (state, action: PayloadAction<AddPanelPayload>) => {
|
||||
const panelId = uuidv4();
|
||||
const exploreId = generateExploreId();
|
||||
|
||||
// Calculate center of current viewport in canvas coordinates
|
||||
const viewportSize = action.payload.viewportSize || { width: 1920, height: 1080 };
|
||||
const canvasCenterX = (-state.viewport.panX + viewportSize.width / 2) / state.viewport.zoom;
|
||||
const canvasCenterY = (-state.viewport.panY + viewportSize.height / 2) / state.viewport.zoom;
|
||||
|
||||
const panelWidth = 600;
|
||||
const panelHeight = 400;
|
||||
const offset = Object.keys(state.panels).length * 30;
|
||||
|
||||
const defaultPosition: PanelPosition = {
|
||||
x: 100 + Object.keys(state.panels).length * 50,
|
||||
y: 100 + Object.keys(state.panels).length * 50,
|
||||
width: 600,
|
||||
height: 400,
|
||||
x: canvasCenterX - panelWidth / 2 + offset,
|
||||
y: canvasCenterY - panelHeight / 2 + offset,
|
||||
width: panelWidth,
|
||||
height: panelHeight,
|
||||
zIndex: state.nextZIndex,
|
||||
};
|
||||
|
||||
|
||||
@@ -50,8 +50,12 @@ export interface ExploreMapState {
|
||||
export const initialExploreMapState: ExploreMapState = {
|
||||
viewport: {
|
||||
zoom: 1,
|
||||
panX: 0,
|
||||
panY: 0,
|
||||
// Center the viewport at canvas center (5000, 5000)
|
||||
// The pan values are offsets, so we need to calculate based on viewport size
|
||||
// At zoom 1, we want canvas position 5000 to be at screen center
|
||||
// Initial position assumes typical viewport of ~1920x1080
|
||||
panX: -4040, // -(5000 - 1920/2) = -4040
|
||||
panY: -4460, // -(5000 - 1080/2) = -4460
|
||||
},
|
||||
panels: {},
|
||||
selectedPanelId: undefined,
|
||||
|
||||
Reference in New Issue
Block a user