Scenes: Implement drag and drop support for SceneCSSGridLayout (#99386)

* Draft: Move css grid stuff to main

* Scenes: Implement drag and drop support for SceneCSSGridLayout

* Fix some nits

* WIP Refactor

* Added a comment

* Add orchestrator to v2schema and fix error (#100964)

* Add orchestrator to v2schema and fix error

* Display placeholder directly when starting to drag

---------

Co-authored-by: kay delaney <kay@grafana.com>

* Fix merge issue

* Fix panel drag offset and remove console.logs

* Fix small nit

* Fix issue where layout options weren't refreshed on changing layout

* Return empty array from useEditPaneOptions if dashboard body isn't LayoutOrchestrator

* Expect layoutOrchestrator when serializing scene

* Fix tests to expect orchestrator instead of layoutManager

* Fix tests in transformSaveModelSchemaV2ToScene.test.ts

* Fix tests in transformSceneToSaveModelSchemaV2.test.ts

* More test fixes

* fix lint issues

* Small fixes

* default to adding layout orchestrator?

* Empty commit

* delete artifactspage.go

* remove artifactspage.tmpl.html

* betterer

* WIP refactor, not ready for review

* Slightly fix placeholder behavior. still broken though

* Fixed some visual glitches. Still very buggy

* Fix layout bugginess when initiating dragging

* more WIP

* Fix some broken logic

* clean up

* Move LayoutOrchestrator to dashboard state

* More cleanup

* Fix misaligned placeholders after changing layout options or resizing browser

* Fix issue with dragging vs selection

* Fix scroll position jumping when dragging in vertically-oriented grid

* Fix import order errors

* Remove '!' from layoutOrchestrator references

* Add LazyLoader support

* Dynamic Dashboards: Responsive Grid drag and drop minor fixes (#102430)

Changes

---------

Co-authored-by: Oscar Kilhed <oscar.kilhed@grafana.com>
Co-authored-by: Bogdan Matei <bogdan.matei@grafana.com>
This commit is contained in:
kay delaney
2025-03-19 11:53:58 +00:00
committed by GitHub
parent 0c58d39e76
commit 4eab2ea9d3
19 changed files with 788 additions and 67 deletions

View File

@ -143,6 +143,7 @@ export function PanelChrome({
onFocus,
onMouseMove,
onMouseEnter,
onDragStart,
showMenuAlways = false,
}: PanelChromeProps) {
const theme = useTheme2();
@ -150,7 +151,7 @@ export function PanelChrome({
const panelContentId = useId();
const panelTitleId = useId().replace(/:/g, '_');
const { isSelected, onSelect, isSelectable } = useElementSelection(selectionId);
const pointerDownPos = useRef<{ screenX: number; screenY: number }>({ screenX: 0, screenY: 0 });
const pointerDownEvt = useRef<React.PointerEvent | undefined>();
const hasHeader = !hoverHeader;
@ -201,11 +202,13 @@ export function PanelChrome({
const onPointerUp = (evt: React.PointerEvent) => {
evt.stopPropagation();
const distance = Math.sqrt(
Math.pow(pointerDownPos.current.screenX - evt.screenX, 2) +
Math.pow(pointerDownPos.current.screenY - evt.screenY, 2)
const distance = Math.hypot(
pointerDownEvt.current?.screenX ?? 0 - evt.screenX,
pointerDownEvt.current?.screenY ?? 0 - evt.screenY
);
pointerDownEvt.current = undefined;
// If we are dragging some distance or clicking on elements that should cancel dragging (panel menu, etc)
if (
distance > 10 ||
@ -219,7 +222,7 @@ export function PanelChrome({
const onPointerDown = (evt: React.PointerEvent) => {
evt.stopPropagation();
pointerDownPos.current = { screenX: evt.screenX, screenY: evt.screenY };
pointerDownEvt.current = evt;
};
const headerContent = (
@ -347,6 +350,11 @@ export function PanelChrome({
className={cx(styles.headerContainer, dragClass)}
style={headerStyles}
data-testid="header-container"
onPointerMove={() => {
if (pointerDownEvt.current) {
onDragStart?.(pointerDownEvt.current);
}
}}
onPointerDown={onPointerDown}
onMouseEnter={isSelectable ? onHeaderEnter : undefined}
onMouseLeave={isSelectable ? onHeaderLeave : undefined}

View File

@ -19,6 +19,13 @@ export function getDashboardGridStyles(theme: GrafanaTheme2) {
},
},
'.dragging-active': {
'*': {
cursor: 'move',
userSelect: 'none',
},
},
[theme.breakpoints.down('md')]: {
'.react-grid-layout': {
height: 'unset !important',