From 1f8b120c22bdafda1c9d7abae4af167b791d980b Mon Sep 17 00:00:00 2001 From: Marco polo Date: Thu, 11 Apr 2024 16:52:19 -0400 Subject: [PATCH] Revert "[ui] Refactor SplitPanelContainer (#20909)" This reverts commit c1740a189322cba600fc898a3956433911a7bbd3. --- .../src/components/ConfigEditorWithSchema.tsx | 4 +- .../src/components/SplitPanelContainer.tsx | 259 ++++++++++-------- .../src/asset-graph/AssetGraphExplorer.tsx | 2 - .../LaunchpadConfigExpansionButton.tsx | 52 ---- .../src/launchpad/LaunchpadSession.tsx | 16 +- .../packages/ui-core/src/runs/Run.tsx | 32 ++- 6 files changed, 171 insertions(+), 194 deletions(-) delete mode 100644 js_modules/dagster-ui/packages/ui-core/src/launchpad/LaunchpadConfigExpansionButton.tsx diff --git a/js_modules/dagster-ui/packages/ui-components/src/components/ConfigEditorWithSchema.tsx b/js_modules/dagster-ui/packages/ui-components/src/components/ConfigEditorWithSchema.tsx index 986cc12d607df..97baf799c8482 100644 --- a/js_modules/dagster-ui/packages/ui-components/src/components/ConfigEditorWithSchema.tsx +++ b/js_modules/dagster-ui/packages/ui-components/src/components/ConfigEditorWithSchema.tsx @@ -4,7 +4,7 @@ import {createGlobalStyle} from 'styled-components'; import {Box} from './Box'; import {ConfigEditorHandle, ConfigSchema, NewConfigEditor} from './NewConfigEditor'; import {Spinner} from './Spinner'; -import {SplitPanelContainer, SplitPanelContainerHandle} from './SplitPanelContainer'; +import {SplitPanelContainer} from './SplitPanelContainer'; import {ConfigEditorHelp} from './configeditor/ConfigEditorHelp'; import {isHelpContextEqual} from './configeditor/isHelpContextEqual'; import {ConfigEditorHelpContext} from './configeditor/types/ConfigEditorHelpContext'; @@ -32,7 +32,7 @@ export const ConfigEditorWithSchema = ({ onConfigChange, configSchema, }: Props) => { - const editorSplitPanelContainer = useRef(null); + const editorSplitPanelContainer = useRef(null); const [editorHelpContext, setEditorHelpContext] = useState(null); const editor = useRef(null); diff --git a/js_modules/dagster-ui/packages/ui-components/src/components/SplitPanelContainer.tsx b/js_modules/dagster-ui/packages/ui-components/src/components/SplitPanelContainer.tsx index c0725f9300440..37c27bf55cf93 100644 --- a/js_modules/dagster-ui/packages/ui-components/src/components/SplitPanelContainer.tsx +++ b/js_modules/dagster-ui/packages/ui-components/src/components/SplitPanelContainer.tsx @@ -1,7 +1,9 @@ -import {forwardRef, useCallback, useImperativeHandle, useRef, useState} from 'react'; +import * as React from 'react'; import styled from 'styled-components'; +import {Button} from './Button'; import {Colors} from './Color'; +import {Icon} from './Icon'; const DIVIDER_THICKNESS = 2; @@ -11,124 +13,110 @@ interface SplitPanelContainerProps { first: React.ReactNode; firstInitialPercent: number; firstMinSize?: number; - secondMinSize?: number; second: React.ReactNode | null; // Note: pass null to hide / animate away the second panel } -export type SplitPanelContainerHandle = { - getSize: () => number; - changeSize: (value: number) => void; -}; +interface SplitPanelContainerState { + size: number; + key: string; + resizing: boolean; +} -export const SplitPanelContainer = forwardRef( - (props, ref) => { - const { - axis = 'horizontal', - identifier, - first, - firstInitialPercent, - firstMinSize, - secondMinSize = 0, - second, - } = props; - - const [_, setTrigger] = useState(0); - const [resizing, setResizing] = useState(false); - const key = `dagster.panel-width.${identifier}`; - - const getSize = useCallback(() => { - if (!second) { - return 100; - } - const storedSize = window.localStorage.getItem(key); - const parsed = storedSize === null ? null : parseFloat(storedSize); - return parsed === null || isNaN(parsed) ? firstInitialPercent : parsed; - }, [firstInitialPercent, key, second]); - - const onChangeSize = useCallback( - (newValue: number) => { - window.localStorage.setItem(key, `${newValue}`); - setTrigger((current) => (current ? 0 : 1)); - }, - [key], - ); +export class SplitPanelContainer extends React.Component< + SplitPanelContainerProps, + SplitPanelContainerState +> { + constructor(props: SplitPanelContainerProps) { + super(props); + + const key = `dagster.panel-width.${this.props.identifier}`; + const value = window.localStorage.getItem(key); + let size = Number(value); + if (value === null || isNaN(size)) { + size = this.props.firstInitialPercent; + } + + this.state = {size, key, resizing: false}; + } - useImperativeHandle(ref, () => ({getSize, changeSize: onChangeSize}), [onChangeSize, getSize]); + onChangeSize = (size: number) => { + this.setState({size}); + window.localStorage.setItem(this.state.key, `${size}`); + }; + + getSize = () => { + return this.state.size; + }; - const firstSize = getSize(); + render() { + const {firstMinSize, first, second} = this.props; + const {size: _size, resizing} = this.state; + const axis = this.props.axis || 'horizontal'; const firstPaneStyles: React.CSSProperties = {flexShrink: 0}; + const firstSize = second ? _size : 100; // Note: The divider appears after the first panel, so making the first panel 100% wide // hides the divider offscreen. To prevent this, we subtract the divider depth. if (axis === 'horizontal') { firstPaneStyles.minWidth = firstMinSize; - firstPaneStyles.width = `calc(${firstSize / 100} * (100% - ${ - DIVIDER_THICKNESS + (second ? secondMinSize : 0) - }px))`; + firstPaneStyles.width = `calc(${firstSize}% - ${DIVIDER_THICKNESS}px)`; } else { firstPaneStyles.minHeight = firstMinSize; - firstPaneStyles.height = `calc(${firstSize / 100} * (100% - ${ - DIVIDER_THICKNESS + (second ? secondMinSize : 0) - }px))`; + firstPaneStyles.height = `calc(${firstSize}% - ${DIVIDER_THICKNESS}px)`; } return ( - +
{first}
this.setState({resizing})} + onMove={this.onChangeSize} />
{second}
); - }, -); + } +} interface IDividerProps { axis: 'horizontal' | 'vertical'; resizing: boolean; - secondMinSize: number; onSetResizing: (resizing: boolean) => void; onMove: (vw: number) => void; } -const PanelDivider = (props: IDividerProps) => { - const {axis, resizing, secondMinSize, onSetResizing, onMove} = props; - const ref = useRef(null); +class PanelDivider extends React.Component { + ref = React.createRef(); - const onMouseDown = (e: React.MouseEvent) => { + onMouseDown = (e: React.MouseEvent) => { e.preventDefault(); - onSetResizing(true); + this.props.onSetResizing(true); const onMouseMove = (event: MouseEvent) => { - const parent = ref.current?.closest('.split-panel-container'); + const parent = this.ref.current?.closest('#split-panel-container'); if (!parent) { return; } const parentRect = parent.getBoundingClientRect(); const firstPanelPercent = - axis === 'horizontal' - ? ((event.clientX - parentRect.left) * 100) / - (parentRect.width - secondMinSize - DIVIDER_THICKNESS) - : ((event.clientY - parentRect.top) * 100) / - (parentRect.height - secondMinSize - DIVIDER_THICKNESS); + this.props.axis === 'horizontal' + ? ((event.clientX - parentRect.left) * 100) / parentRect.width + : ((event.clientY - parentRect.top) * 100) / parentRect.height; - onMove(Math.min(100, Math.max(0, firstPanelPercent))); + this.props.onMove(Math.min(100, Math.max(0, firstPanelPercent))); }; const onMouseUp = () => { - onSetResizing(false); + this.props.onSetResizing(false); document.removeEventListener('mousemove', onMouseMove); document.removeEventListener('mouseup', onMouseUp); }; @@ -136,60 +124,109 @@ const PanelDivider = (props: IDividerProps) => { document.addEventListener('mouseup', onMouseUp); }; - const hitArea = - axis === 'horizontal' ? ( - - ) : ( - + render() { + const Wrapper = DividerWrapper[this.props.axis]; + const HitArea = DividerHitArea[this.props.axis]; + return ( + + + ); + } +} - return axis === 'horizontal' ? ( - - {hitArea} - - ) : ( - - {hitArea} - +interface PanelToggleProps { + axis: 'horizontal' | 'vertical'; + container: React.RefObject; +} + +// Todo: This component attempts to sync itself with the container, but it can't +// observe the container's width without a React context or adding a listener, etc. +// If we keep making components that manipulate panel state we may want to move it +// all to a context consumed by both. +// +export const SecondPanelToggle = ({container, axis}: PanelToggleProps) => { + const [prevSize, setPrevSize] = React.useState('unknown'); + const initialIsOpen = (container.current?.state.size || 0) < 100; + + const [open, setOpen] = React.useState(initialIsOpen); + React.useEffect(() => setOpen(initialIsOpen), [initialIsOpen]); + + return ( + - + {pipeline.tags.length || tagsFromSession.length ? ( { ) : null} { /> } - secondMinSize={240} /> diff --git a/js_modules/dagster-ui/packages/ui-core/src/runs/Run.tsx b/js_modules/dagster-ui/packages/ui-core/src/runs/Run.tsx index e3d3cc0df5ec6..9d9d0de7b7fd8 100644 --- a/js_modules/dagster-ui/packages/ui-core/src/runs/Run.tsx +++ b/js_modules/dagster-ui/packages/ui-core/src/runs/Run.tsx @@ -6,7 +6,6 @@ import { Icon, NonIdealState, SplitPanelContainer, - SplitPanelContainerHandle, Tooltip, } from '@dagster-io/ui-components'; import * as React from 'react'; @@ -250,33 +249,35 @@ const RunWithData = ({ onSetSelectionQuery(newSelected.join(', ') || '*'); }; - const [expandedPanel, setExpandedPanel] = React.useState(null); - const containerRef = React.useRef(null); - + const [splitPanelContainer, setSplitPanelContainer] = React.useState( + null, + ); React.useEffect(() => { - if (containerRef.current) { - const size = containerRef.current.getSize(); - if (size === 100) { + const initialSize = splitPanelContainer?.getSize(); + switch (initialSize) { + case 100: setExpandedPanel('top'); - } else if (size === 0) { + return; + case 0: setExpandedPanel('bottom'); - } + return; } - }, []); + }, [splitPanelContainer]); + const [expandedPanel, setExpandedPanel] = React.useState(null); const isTopExpanded = expandedPanel === 'top'; const isBottomExpanded = expandedPanel === 'bottom'; const expandBottomPanel = () => { - containerRef.current?.changeSize(0); + splitPanelContainer?.onChangeSize(0); setExpandedPanel('bottom'); }; const expandTopPanel = () => { - containerRef.current?.changeSize(100); + splitPanelContainer?.onChangeSize(100); setExpandedPanel('top'); }; const resetPanels = () => { - containerRef.current?.changeSize(50); + splitPanelContainer?.onChangeSize(50); setExpandedPanel(null); }; @@ -330,13 +331,14 @@ const RunWithData = ({ return ( <> { + setSplitPanelContainer(container); + }} axis="vertical" identifier="run-gantt" firstInitialPercent={35} firstMinSize={56} first={gantt(metadata)} - secondMinSize={56} second={