|
|
|
|
@ -8,7 +8,7 @@ import Selecto from 'selecto'; |
|
|
|
|
import { GrafanaTheme2, PanelData } from '@grafana/data'; |
|
|
|
|
import { stylesFactory } from '@grafana/ui'; |
|
|
|
|
import { config } from 'app/core/config'; |
|
|
|
|
import { CanvasGroupOptions, DEFAULT_CANVAS_ELEMENT_CONFIG } from 'app/features/canvas'; |
|
|
|
|
import { CanvasFrameOptions, DEFAULT_CANVAS_ELEMENT_CONFIG } from 'app/features/canvas'; |
|
|
|
|
import { |
|
|
|
|
ColorDimensionConfig, |
|
|
|
|
ResourceDimensionConfig, |
|
|
|
|
@ -29,12 +29,12 @@ import { LayerActionID } from 'app/plugins/panel/canvas/types'; |
|
|
|
|
import { Placement } from '../types'; |
|
|
|
|
|
|
|
|
|
import { ElementState } from './element'; |
|
|
|
|
import { GroupState } from './group'; |
|
|
|
|
import { FrameState } from './frame'; |
|
|
|
|
import { RootElement } from './root'; |
|
|
|
|
|
|
|
|
|
export interface SelectionParams { |
|
|
|
|
targets: Array<HTMLElement | SVGElement>; |
|
|
|
|
group?: GroupState; |
|
|
|
|
frame?: FrameState; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
export class Scene { |
|
|
|
|
@ -53,15 +53,15 @@ export class Scene { |
|
|
|
|
selecto?: Selecto; |
|
|
|
|
moveable?: Moveable; |
|
|
|
|
div?: HTMLDivElement; |
|
|
|
|
currentLayer?: GroupState; |
|
|
|
|
currentLayer?: FrameState; |
|
|
|
|
isEditingEnabled?: boolean; |
|
|
|
|
|
|
|
|
|
constructor(cfg: CanvasGroupOptions, enableEditing: boolean, public onSave: (cfg: CanvasGroupOptions) => void) { |
|
|
|
|
constructor(cfg: CanvasFrameOptions, enableEditing: boolean, public onSave: (cfg: CanvasFrameOptions) => void) { |
|
|
|
|
this.root = this.load(cfg, enableEditing); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
getNextElementName = (isGroup = false) => { |
|
|
|
|
const label = isGroup ? 'Group' : 'Element'; |
|
|
|
|
getNextElementName = (isFrame = false) => { |
|
|
|
|
const label = isFrame ? 'Frame' : 'Element'; |
|
|
|
|
let idx = this.byName.size + 1; |
|
|
|
|
|
|
|
|
|
const max = idx + 100; |
|
|
|
|
@ -79,10 +79,10 @@ export class Scene { |
|
|
|
|
return !this.byName.has(v); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
load(cfg: CanvasGroupOptions, enableEditing: boolean) { |
|
|
|
|
load(cfg: CanvasFrameOptions, enableEditing: boolean) { |
|
|
|
|
this.root = new RootElement( |
|
|
|
|
cfg ?? { |
|
|
|
|
type: 'group', |
|
|
|
|
type: 'frame', |
|
|
|
|
elements: [DEFAULT_CANVAS_ELEMENT_CONFIG], |
|
|
|
|
}, |
|
|
|
|
this, |
|
|
|
|
@ -126,13 +126,13 @@ export class Scene { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
groupSelection() { |
|
|
|
|
frameSelection() { |
|
|
|
|
this.selection.pipe(first()).subscribe((currentSelectedElements) => { |
|
|
|
|
const currentLayer = currentSelectedElements[0].parent!; |
|
|
|
|
|
|
|
|
|
const newLayer = new GroupState( |
|
|
|
|
const newLayer = new FrameState( |
|
|
|
|
{ |
|
|
|
|
type: 'group', |
|
|
|
|
type: 'frame', |
|
|
|
|
name: this.getNextElementName(true), |
|
|
|
|
elements: [], |
|
|
|
|
}, |
|
|
|
|
@ -140,18 +140,18 @@ export class Scene { |
|
|
|
|
currentSelectedElements[0].parent |
|
|
|
|
); |
|
|
|
|
|
|
|
|
|
const groupPlacement = this.generateGroupContainer(currentSelectedElements); |
|
|
|
|
const framePlacement = this.generateFrameContainer(currentSelectedElements); |
|
|
|
|
|
|
|
|
|
newLayer.options.placement = groupPlacement; |
|
|
|
|
newLayer.options.placement = framePlacement; |
|
|
|
|
|
|
|
|
|
currentSelectedElements.forEach((element: ElementState) => { |
|
|
|
|
const elementContainer = element.div?.getBoundingClientRect(); |
|
|
|
|
element.setPlacementFromConstraint(elementContainer, groupPlacement as DOMRect); |
|
|
|
|
element.setPlacementFromConstraint(elementContainer, framePlacement as DOMRect); |
|
|
|
|
currentLayer.doAction(LayerActionID.Delete, element); |
|
|
|
|
newLayer.doAction(LayerActionID.Duplicate, element, false, false); |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
newLayer.setPlacementFromConstraint(groupPlacement as DOMRect, currentLayer.div?.getBoundingClientRect()); |
|
|
|
|
newLayer.setPlacementFromConstraint(framePlacement as DOMRect, currentLayer.div?.getBoundingClientRect()); |
|
|
|
|
|
|
|
|
|
currentLayer.elements.push(newLayer); |
|
|
|
|
|
|
|
|
|
@ -161,7 +161,7 @@ export class Scene { |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private generateGroupContainer = (elements: ElementState[]): Placement => { |
|
|
|
|
private generateFrameContainer = (elements: ElementState[]): Placement => { |
|
|
|
|
let minTop = Infinity; |
|
|
|
|
let minLeft = Infinity; |
|
|
|
|
let maxRight = 0; |
|
|
|
|
@ -204,7 +204,7 @@ export class Scene { |
|
|
|
|
this.selecto?.clickTarget(event, this.div); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
updateCurrentLayer(newLayer: GroupState) { |
|
|
|
|
updateCurrentLayer(newLayer: FrameState) { |
|
|
|
|
this.currentLayer = newLayer; |
|
|
|
|
this.clearCurrentSelection(); |
|
|
|
|
this.save(); |
|
|
|
|
@ -233,7 +233,7 @@ export class Scene { |
|
|
|
|
return currentElement; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const nestedElements = currentElement instanceof GroupState ? currentElement.elements : []; |
|
|
|
|
const nestedElements = currentElement instanceof FrameState ? currentElement.elements : []; |
|
|
|
|
for (const nestedElement of nestedElements) { |
|
|
|
|
stack.unshift(nestedElement); |
|
|
|
|
} |
|
|
|
|
@ -256,8 +256,8 @@ export class Scene { |
|
|
|
|
private updateSelection = (selection: SelectionParams) => { |
|
|
|
|
this.moveable!.target = selection.targets; |
|
|
|
|
|
|
|
|
|
if (selection.group) { |
|
|
|
|
this.selection.next([selection.group]); |
|
|
|
|
if (selection.frame) { |
|
|
|
|
this.selection.next([selection.frame]); |
|
|
|
|
} else { |
|
|
|
|
const s = selection.targets.map((t) => this.findElementByTarget(t)!); |
|
|
|
|
this.selection.next(s); |
|
|
|
|
@ -275,7 +275,7 @@ export class Scene { |
|
|
|
|
targetElements.push(currentElement.div); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
const nestedElements = currentElement instanceof GroupState ? currentElement.elements : []; |
|
|
|
|
const nestedElements = currentElement instanceof FrameState ? currentElement.elements : []; |
|
|
|
|
for (const nestedElement of nestedElements) { |
|
|
|
|
stack.unshift(nestedElement); |
|
|
|
|
} |
|
|
|
|
|