Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SceneCSSGridLayout: Add support for dragging and dropping panels #993

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions packages/scenes/src/components/VizPanel/VizPanelRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export function VizPanelRenderer({ model }: SceneComponentProps<VizPanel>) {
const plugin = model.getPlugin();

const { dragClass, dragClassCancel } = getDragClasses(model);
const dragHooks = getDragHooks(model);
const dataObject = sceneGraph.getData(model);

const rawData = dataObject.useState();
Expand Down Expand Up @@ -192,6 +193,7 @@ export function VizPanelRenderer({ model }: SceneComponentProps<VizPanel>) {
onFocus={setPanelAttention}
onMouseEnter={setPanelAttention}
onMouseMove={debouncedMouseMove}
onDragStart={dragHooks.onDragStart}
collapsible={collapsible}
collapsed={collapsed}
onToggleCollapse={model.onToggleCollapse}
Expand Down Expand Up @@ -257,6 +259,11 @@ function getDragClasses(panel: VizPanel) {
return { dragClass: parentLayout.getDragClass?.(), dragClassCancel: parentLayout?.getDragClassCancel?.() };
}

function getDragHooks(panel: VizPanel) {
const parentLayout = sceneGraph.getLayout(panel);
return { onDragStart: parentLayout?.onPointerDown };
}

/**
* Walks up the parent chain until it hits the layout object, trying to find the closest SceneGridItemLike ancestor.
* It is not always the direct parent, because the VizPanel can be wrapped in other objects.
Expand Down
58 changes: 58 additions & 0 deletions packages/scenes/src/components/layout/CSSGrid/SceneCSSGridItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { css } from '@emotion/css';
import React, { CSSProperties } from 'react';
import { SceneObjectBase } from '../../../core/SceneObjectBase';
import { SceneComponentProps, SceneObject, SceneObjectState } from '../../../core/types';
import { useStyles2 } from '@grafana/ui';
import { GrafanaTheme2 } from '@grafana/data';

export interface SceneCSSGridItemPlacement {
/**
* True when the item should rendered but not visible.
* Useful for conditional display of layout items
*/
isHidden?: boolean;
/**
* Useful for making content span across multiple rows or columns
*/
gridColumn?: CSSProperties['gridColumn'];
gridRow?: CSSProperties['gridRow'];
}

export interface SceneCSSGridItemState extends SceneCSSGridItemPlacement, SceneObjectState {
body?: SceneObject;
}

export interface SceneCSSGridItemRenderProps<T> extends SceneComponentProps<T> {
parentState?: SceneCSSGridItemPlacement;
}

export class SceneCSSGridItem extends SceneObjectBase<SceneCSSGridItemState> {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand doing pocs here (if you need to make changes to VizPanelRenderer esp),

just be aware we have a special class in core for this CSS grid items, https://github.com/grafana/grafana/blob/main/public/app/features/dashboard-scene/scene/layout-responsive-grid/ResponsiveGridItem.tsx#L13

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh this wasn't a POC, I just factored it out from SceneCSSGridLayout

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I understand, just know we are not using it dashboards.

I think a challenge with this work is what logic needs live in scenes vs the core repo implementation (and the ResponsiveGridLayoutManager)

public static Component = SceneCSSGridItemRenderer;
}

function SceneCSSGridItemRenderer({ model, parentState }: SceneCSSGridItemRenderProps<SceneCSSGridItem>) {
if (!parentState) {
throw new Error('SceneCSSGridItem must be a child of SceneCSSGridLayout');
}

const { body, isHidden } = model.useState();
const styles = useStyles2(getStyles, model.state);

if (!body || isHidden) {
return null;
}

return (
<div className={styles.wrapper}>
<body.Component model={body} />
</div>
);
}

const getStyles = (_theme: GrafanaTheme2, state: SceneCSSGridItemState) => ({
wrapper: css({
gridColumn: state.gridColumn || 'unset',
gridRow: state.gridRow || 'unset',
position: 'relative', // Needed for VizPanel
}),
});
Loading
Loading