Canvas: Improve enter / exit editor UX (#40591)

This commit is contained in:
Nathan Marrs 2021-10-18 13:10:07 -07:00 committed by GitHub
parent 9c2d70ce0f
commit 7e59b92c8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 44 additions and 11 deletions

View File

@ -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 (
<div key={this.revId} className={this.styles.wrap} style={this.style} ref={this.initMoveable}>
<div key={this.revId} className={this.styles.wrap} style={this.style} ref={this.setRef}>
{this.root.render()}
</div>
);

View File

@ -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<Props, State> {
// 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

View File

@ -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<Props, State> {
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<Props, State> {
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,

View File

@ -201,6 +201,11 @@ export class AnnotationQueryFinished extends BusEventWithPayload<AnnotationQuery
export class TimeRangeUpdatedEvent extends BusEventWithPayload<TimeRange> {
static type = 'time-range-updated';
}
export class PanelEditEnteredEvent extends BusEventWithPayload<number> {
static type = 'panel-edit-started';
}
export class PanelEditExitedEvent extends BusEventWithPayload<number> {
static type = 'panel-edit-finished';
}