diff --git a/public/app/features/canvas/runtime/scene.tsx b/public/app/features/canvas/runtime/scene.tsx
index ae30613d838..d098ba0b6c3 100644
--- a/public/app/features/canvas/runtime/scene.tsx
+++ b/public/app/features/canvas/runtime/scene.tsx
@@ -43,14 +43,14 @@ export class Scene {
height = 0;
style: CSSProperties = {};
data?: PanelData;
- selecto?: Selecto | null;
+ selecto?: Selecto;
+ div?: HTMLDivElement;
constructor(cfg: CanvasGroupOptions, public onSave: (cfg: CanvasGroupOptions) => void) {
this.root = this.load(cfg);
}
load(cfg: CanvasGroupOptions) {
- console.log('LOAD', cfg, this);
this.root = new RootElement(
cfg ?? {
type: 'group',
@@ -65,6 +65,11 @@ export class Scene {
this.lookup.set(v.UID, v);
});
+ setTimeout(() => {
+ if (this.div) {
+ this.initMoveable();
+ }
+ }, 100);
return this.root;
}
@@ -85,6 +90,11 @@ export class Scene {
this.height = height;
this.style = { width, height };
this.root.updateSize(width, height);
+
+ if (this.selecto?.getSelectedTargets().length) {
+ let event: MouseEvent = new MouseEvent('click');
+ this.selecto.clickTarget(event, this.div);
+ }
}
onChange(uid: number, cfg: CanvasElementOptions) {
@@ -143,19 +153,27 @@ export class Scene {
return this.root.elements.find((element) => element.div === target);
};
- initMoveable = (sceneContainer: HTMLDivElement) => {
+ setRef = (sceneContainer: HTMLDivElement) => {
+ this.div = sceneContainer;
+ };
+
+ initMoveable = () => {
+ if (this.selecto) {
+ this.selecto.destroy();
+ }
+
const targetElements: HTMLDivElement[] = [];
this.root.elements.forEach((element: ElementState) => {
targetElements.push(element.div!);
});
this.selecto = new Selecto({
- container: sceneContainer,
+ container: this.div,
selectableTargets: targetElements,
selectByClick: true,
});
- const moveable = new Moveable(sceneContainer, {
+ const moveable = new Moveable(this.div!, {
draggable: true,
resizable: true,
})
@@ -209,7 +227,6 @@ export class Scene {
if (event.isDragStart) {
event.inputEvent.preventDefault();
-
setTimeout(() => {
moveable.dragStart(event.inputEvent);
});
@@ -219,7 +236,7 @@ export class Scene {
render() {
return (
-
+
{this.root.render()}
);
diff --git a/public/app/features/dashboard/containers/DashboardPage.tsx b/public/app/features/dashboard/containers/DashboardPage.tsx
index fd43c05b66b..47d9ab6c6d8 100644
--- a/public/app/features/dashboard/containers/DashboardPage.tsx
+++ b/public/app/features/dashboard/containers/DashboardPage.tsx
@@ -29,7 +29,7 @@ import { DashboardLoading } from '../components/DashboardLoading/DashboardLoadin
import { DashboardFailed } from '../components/DashboardLoading/DashboardFailed';
import { DashboardPrompt } from '../components/DashboardPrompt/DashboardPrompt';
import classnames from 'classnames';
-import { PanelEditExitedEvent } from 'app/types/events';
+import { PanelEditEnteredEvent, PanelEditExitedEvent } from 'app/types/events';
import { liveTimer } from '../dashgrid/liveTimer';
export interface DashboardPageRouteParams {
@@ -178,6 +178,9 @@ export class UnthemedDashboardPage extends PureComponent
{
// entering edit mode
if (this.state.editPanel && !prevState.editPanel) {
dashboardWatcher.setEditingState(true);
+
+ // Some panels need to be notified when entering edit mode
+ this.props.dashboard?.events.publish(new PanelEditEnteredEvent(this.state.editPanel.id));
}
// leaving edit mode
diff --git a/public/app/plugins/panel/canvas/CanvasPanel.tsx b/public/app/plugins/panel/canvas/CanvasPanel.tsx
index 6b793edcd8a..0aae1c9cd43 100644
--- a/public/app/plugins/panel/canvas/CanvasPanel.tsx
+++ b/public/app/plugins/panel/canvas/CanvasPanel.tsx
@@ -1,8 +1,8 @@
import { Component } from 'react';
-import { CoreApp, PanelProps } from '@grafana/data';
+import { PanelProps } from '@grafana/data';
import { PanelOptions } from './models.gen';
import { Subscription } from 'rxjs';
-import { PanelEditExitedEvent } from 'app/types/events';
+import { PanelEditEnteredEvent, PanelEditExitedEvent } from 'app/types/events';
import { CanvasGroupOptions } from 'app/features/canvas';
import { Scene } from 'app/features/canvas/runtime/scene';
import { PanelContext, PanelContextRoot } from '@grafana/ui';
@@ -41,6 +41,14 @@ export class CanvasPanel extends Component {
this.scene.updateSize(props.width, props.height);
this.scene.updateData(props.data);
+ this.subs.add(
+ this.props.eventBus.subscribe(PanelEditEnteredEvent, (evt) => {
+ // Remove current selection when entering edit mode for any panel in dashboard
+ let event: MouseEvent = new MouseEvent('click');
+ this.scene?.selecto?.clickTarget(event, this.scene?.div);
+ })
+ );
+
this.subs.add(
this.props.eventBus.subscribe(PanelEditExitedEvent, (evt) => {
if (this.props.id === evt.payload) {
@@ -52,7 +60,7 @@ export class CanvasPanel extends Component {
componentDidMount() {
this.panelContext = this.context as PanelContext;
- if (this.panelContext.onInstanceStateChange && this.panelContext.app === CoreApp.PanelEditor) {
+ if (this.panelContext.onInstanceStateChange) {
this.panelContext.onInstanceStateChange({
scene: this.scene,
layer: this.scene.root,
diff --git a/public/app/types/events.ts b/public/app/types/events.ts
index d914aae48cd..2da73d11ae7 100644
--- a/public/app/types/events.ts
+++ b/public/app/types/events.ts
@@ -201,6 +201,11 @@ export class AnnotationQueryFinished extends BusEventWithPayload {
static type = 'time-range-updated';
}
+
+export class PanelEditEnteredEvent extends BusEventWithPayload {
+ static type = 'panel-edit-started';
+}
+
export class PanelEditExitedEvent extends BusEventWithPayload {
static type = 'panel-edit-finished';
}