@ -2,14 +2,15 @@ import * as H from 'history';
import { NavIndex } from '@grafana/data' ;
import { config , locationService } from '@grafana/runtime' ;
import { SceneObjectBase , SceneObjectState , VizPanel } from '@grafana/scenes' ;
import { SceneGridItem , SceneGridLayout , Scene ObjectBase , SceneObjectState , VizPanel } from '@grafana/scenes' ;
import { getDashboardSceneFor , getPanelIdForVizPanel } from '../utils/utils' ;
import { PanelRepeaterGridItem } from '../scene/PanelRepeaterGridItem' ;
import { getPanelIdForVizPanel , getDashboardSceneFor } from '../utils/utils' ;
import { PanelDataPane } from './PanelDataPane/PanelDataPane' ;
import { PanelEditorRenderer } from './PanelEditorRenderer' ;
import { PanelOptionsPane } from './PanelOptionsPane' ;
import { VizPanelManager } from './VizPanelManager' ;
import { VizPanelManager , VizPanelManagerState } from './VizPanelManager' ;
export interface PanelEditorState extends SceneObjectState {
isDirty? : boolean ;
@ -20,12 +21,21 @@ export interface PanelEditorState extends SceneObjectState {
}
export class PanelEditor extends SceneObjectBase < PanelEditorState > {
private _initialRepeatOptions : Pick < VizPanelManagerState , ' repeat ' | ' repeatDirection ' | ' maxPerRow ' > = { } ;
static Component = PanelEditorRenderer ;
private _discardChanges = false ;
public constructor ( state : PanelEditorState ) {
super ( state ) ;
const { repeat , repeatDirection , maxPerRow } = state . vizManager . state ;
this . _initialRepeatOptions = {
repeat ,
repeatDirection ,
maxPerRow ,
} ;
this . addActivationHandler ( this . _activationHandler . bind ( this ) ) ;
}
@ -88,7 +98,104 @@ export class PanelEditor extends SceneObjectBase<PanelEditorState> {
dashboard . onEnterEditMode ( ) ;
}
this . state . vizManager . commitChanges ( ) ;
const panelManager = this . state . vizManager ;
const sourcePanel = panelManager . state . sourcePanel . resolve ( ) ;
const sourcePanelParent = sourcePanel ! . parent ;
const normalToRepeat = ! this . _initialRepeatOptions . repeat && panelManager . state . repeat ;
const repeatToNormal = this . _initialRepeatOptions . repeat && ! panelManager . state . repeat ;
if ( sourcePanelParent instanceof SceneGridItem ) {
if ( normalToRepeat ) {
this . replaceSceneGridItemWithPanelRepeater ( sourcePanelParent ) ;
} else {
panelManager . commitChanges ( ) ;
}
} else if ( sourcePanelParent instanceof PanelRepeaterGridItem ) {
if ( repeatToNormal ) {
this . replacePanelRepeaterWithGridItem ( sourcePanelParent ) ;
} else {
this . handleRepeatOptionChanges ( sourcePanelParent ) ;
}
} else {
console . error ( 'Unsupported scene object type' ) ;
}
}
private replaceSceneGridItemWithPanelRepeater ( gridItem : SceneGridItem ) {
const gridLayout = gridItem . parent ;
if ( ! ( gridLayout instanceof SceneGridLayout ) ) {
console . error ( 'Expected grandparent to be SceneGridLayout!' ) ;
return ;
}
const panelManager = this . state . vizManager ;
const repeatDirection = panelManager . state . repeatDirection ? ? 'h' ;
const repeater = new PanelRepeaterGridItem ( {
key : gridItem.state.key ,
x : gridItem.state.x ,
y : gridItem.state.y ,
width : repeatDirection === 'h' ? 24 : gridItem.state.width ,
height : gridItem.state.height ,
itemHeight : gridItem.state.height ,
source : panelManager.state.panel.clone ( ) ,
variableName : panelManager.state.repeat ! ,
repeatedPanels : [ ] ,
repeatDirection : panelManager.state.repeatDirection ,
maxPerRow : panelManager.state.maxPerRow ,
} ) ;
gridLayout . setState ( {
children : gridLayout.state.children.map ( ( child ) = > ( child . state . key === gridItem . state . key ? repeater : child ) ) ,
} ) ;
}
private replacePanelRepeaterWithGridItem ( panelRepeater : PanelRepeaterGridItem ) {
const gridLayout = panelRepeater . parent ;
if ( ! ( gridLayout instanceof SceneGridLayout ) ) {
console . error ( 'Expected grandparent to be SceneGridLayout!' ) ;
return ;
}
const panelManager = this . state . vizManager ;
const panelClone = panelManager . state . panel . clone ( ) ;
const gridItem = new SceneGridItem ( {
key : panelRepeater.state.key ,
x : panelRepeater.state.x ,
y : panelRepeater.state.y ,
width : this._initialRepeatOptions.repeatDirection === 'h' ? 8 : panelRepeater.state.width ,
height : this._initialRepeatOptions.repeatDirection === 'v' ? 8 : panelRepeater.state.height ,
body : panelClone ,
} ) ;
gridLayout . setState ( {
children : gridLayout.state.children.map ( ( child ) = >
child . state . key === panelRepeater . state . key ? gridItem : child
) ,
} ) ;
}
private handleRepeatOptionChanges ( panelRepeater : PanelRepeaterGridItem ) {
let width = panelRepeater . state . width ? ? 1 ;
let height = panelRepeater . state . height ;
const panelManager = this . state . vizManager ;
const horizontalToVertical =
this . _initialRepeatOptions . repeatDirection === 'h' && panelManager . state . repeatDirection === 'v' ;
const verticalToHorizontal =
this . _initialRepeatOptions . repeatDirection === 'v' && panelManager . state . repeatDirection === 'h' ;
if ( horizontalToVertical ) {
width = Math . floor ( width / ( panelRepeater . state . maxPerRow ? ? 1 ) ) ;
} else if ( verticalToHorizontal ) {
width = 24 ;
}
panelRepeater . setState ( {
source : panelManager.state.panel.clone ( ) ,
repeatDirection : panelManager.state.repeatDirection ,
variableName : panelManager.state.repeat ,
maxPerRow : panelManager.state.maxPerRow ,
width ,
height ,
} ) ;
}
}