Skip to content
Permalink
Browse files

Consolidate split panel handling, save divider locations to local sto…

…rage

Summary: Small diff that makes panel widths "sticky", so if you adjust the size of the execution plan, etc. it stays there.

Test Plan: Run snapshot tests

Reviewers: #ft, alangenfeld

Reviewed By: #ft, alangenfeld

Differential Revision: https://dagster.phacility.com/D1216
  • Loading branch information...
bengotow committed Oct 4, 2019
1 parent 5c76546 commit ef23ea3c3aa8b89adb0c92e7bbf1fd3d9684d8e6
@@ -10,7 +10,7 @@ import * as querystring from "query-string";

import { PipelineExplorerFragment } from "./types/PipelineExplorerFragment";
import PipelineGraph from "./graph/PipelineGraph";
import { PanelDivider } from "./PanelDivider";
import { SplitPanelChildren } from "./SplitPanelChildren";
import SidebarTabbedContainer from "./SidebarTabbedContainer";
import { SolidJumpBar } from "./PipelineJumpComponents";
import {
@@ -34,7 +34,6 @@ interface IPipelineExplorerProps {

interface IPipelineExplorerState {
filter: string;
graphVW: number;
}

export type SolidNameOrPath = { name: string } | { path: string[] };
@@ -69,8 +68,7 @@ export default class PipelineExplorer extends React.Component<
};

state = {
filter: "",
graphVW: 70
filter: ""
};

handleAdjustPath = (fn: (solidNames: string[]) => void) => {
@@ -158,7 +156,7 @@ export default class PipelineExplorer extends React.Component<
selectedDefinitionInvocations,
path
} = this.props;
const { filter, graphVW } = this.state;
const { filter } = this.state;

const solids = this.props.handles.map(h => h.solid);

@@ -172,79 +170,86 @@ export default class PipelineExplorer extends React.Component<

return (
<PipelinesContainer>
<PipelinePanel key="graph" style={{ width: `${graphVW}vw` }}>
<PathOverlay style={{ background: backgroundTranslucent }}>
<Link style={{ padding: 3 }} to={`/p/${pipeline.name}/explore`}>
<Icon icon="diagram-tree" />
</Link>
<Icon icon="chevron-right" />
{path.slice(0, path.length - 1).map((name, idx) => (
<React.Fragment key={idx}>
<Link
style={{ padding: 3 }}
to={`/p/${pipeline.name}/explore/${path
.slice(0, idx + 1)
.join("/")}`}
>
{name}
<SplitPanelChildren
identifier="explorer"
leftInitialPercent={70}
left={
<>
<PathOverlay style={{ background: backgroundTranslucent }}>
<Link style={{ padding: 3 }} to={`/p/${pipeline.name}/explore`}>
<Icon icon="diagram-tree" />
</Link>
<Icon icon="chevron-right" />
</React.Fragment>
))}
<SolidJumpBar
solids={solids}
selectedSolid={selectedHandle && selectedHandle.solid}
onItemSelect={solid =>
this.handleClickSolid({ name: solid.name })
}
/>
</PathOverlay>
<SearchOverlay style={{ background: backgroundTranslucent }}>
<SolidSearchInput
type="text"
placeholder="Filter..."
value={filter}
onChange={e => this.setState({ filter: e.target.value })}
/>
</SearchOverlay>
<PipelineGraph
pipelineName={pipeline.name}
backgroundColor={backgroundColor}
solids={solids}
selectedHandleID={selectedHandle && selectedHandle.handleID}
selectedSolid={selectedHandle && selectedHandle.solid}
parentHandleID={parentHandle && parentHandle.handleID}
parentSolid={parentHandle && parentHandle.solid}
onClickSolid={this.handleClickSolid}
onClickBackground={this.handleClickBackground}
onEnterCompositeSolid={this.handleEnterCompositeSolid}
onLeaveCompositeSolid={this.handleLeaveCompositeSolid}
layout={this.getLayout(solids, parentHandle && parentHandle.solid)}
highlightedSolids={solids.filter(
s => filter && s.name.includes(filter)
)}
/>
</PipelinePanel>
<PanelDivider
axis="horizontal"
onMove={(graphVW: number) => this.setState({ graphVW })}
/>
<RightInfoPanel style={{ width: `${100 - graphVW}vw` }}>
<Route
// eslint-disable-next-line react/no-children-prop
children={({ location }: { location: any }) => (
<SidebarTabbedContainer
pipeline={pipeline}
solid={selectedHandle && selectedHandle.solid}
solidDefinitionInvocations={selectedDefinitionInvocations}
{path.slice(0, path.length - 1).map((name, idx) => (
<React.Fragment key={idx}>
<Link
style={{ padding: 3 }}
to={`/p/${pipeline.name}/explore/${path
.slice(0, idx + 1)
.join("/")}`}
>
{name}
</Link>
<Icon icon="chevron-right" />
</React.Fragment>
))}
<SolidJumpBar
solids={solids}
selectedSolid={selectedHandle && selectedHandle.solid}
onItemSelect={solid =>
this.handleClickSolid({ name: solid.name })
}
/>
</PathOverlay>
<SearchOverlay style={{ background: backgroundTranslucent }}>
<SolidSearchInput
type="text"
placeholder="Filter..."
value={filter}
onChange={e => this.setState({ filter: e.target.value })}
/>
</SearchOverlay>
<PipelineGraph
pipelineName={pipeline.name}
backgroundColor={backgroundColor}
solids={solids}
selectedHandleID={selectedHandle && selectedHandle.handleID}
selectedSolid={selectedHandle && selectedHandle.solid}
parentHandleID={parentHandle && parentHandle.handleID}
parentSolid={parentHandle && parentHandle.solid}
onEnterCompositeSolid={this.handleEnterCompositeSolid}
onClickSolid={this.handleClickSolid}
{...querystring.parse(location.search || "")}
onClickBackground={this.handleClickBackground}
onEnterCompositeSolid={this.handleEnterCompositeSolid}
onLeaveCompositeSolid={this.handleLeaveCompositeSolid}
layout={this.getLayout(
solids,
parentHandle && parentHandle.solid
)}
highlightedSolids={solids.filter(
s => filter && s.name.includes(filter)
)}
/>
)}
/>
</RightInfoPanel>
</>
}
right={
<RightInfoPanel>
<Route
// eslint-disable-next-line react/no-children-prop
children={({ location }: { location: any }) => (
<SidebarTabbedContainer
pipeline={pipeline}
solid={selectedHandle && selectedHandle.solid}
solidDefinitionInvocations={selectedDefinitionInvocations}
parentSolid={parentHandle && parentHandle.solid}
onEnterCompositeSolid={this.handleEnterCompositeSolid}
onClickSolid={this.handleClickSolid}
{...querystring.parse(location.search || "")}
/>
)}
/>
</RightInfoPanel>
}
/>
</PipelinesContainer>
);
}
@@ -260,11 +265,6 @@ const PipelinesContainer = styled.div`
padding-top: 50px;
`;

const PipelinePanel = styled.div`
height: 100%;
position: relative;
`;

const RightInfoPanel = styled.div`
// Fixes major perofmance hit. To reproduce, add enough content to
// the sidebar that it scrolls (via overflow-y below) and then try
@@ -143,6 +143,7 @@ const Tabs = styled.div`
justify-content: center;
border-bottom: 1px solid #ccc;
`;

const Tab = styled.div<{ active: boolean }>`
color: ${p => (p.active ? Colors.COBALT3 : Colors.GRAY2)}
border-top: 3px solid transparent;
@@ -10,6 +10,55 @@ interface IDividerState {
down: boolean;
}

interface SplitPanelChildrenProps {
identifier: string;
left: React.ReactNode;
leftInitialPercent: number;
leftMinWidth?: number;
right: React.ReactNode;
}
interface SplitPanelChildrenState {
width: number;
key: string;
}

export class SplitPanelChildren extends React.Component<
SplitPanelChildrenProps,
SplitPanelChildrenState
> {
constructor(props: SplitPanelChildrenProps) {
super(props);

const key = `dagit.panel-width.${this.props.identifier}`;
let width = Number(window.localStorage.getItem(key));
if (width === 0 || isNaN(width)) {
width = this.props.leftInitialPercent;
}

this.state = { width, key };
}

onChangeWidth = (vw: number) => {
this.setState({ width: vw });
window.localStorage.setItem(this.state.key, `${vw}`);
};

render() {
const { leftMinWidth, left, right } = this.props;
const { width } = this.state;

return (
<>
<Split width={width} style={{ flexShrink: 0, minWidth: leftMinWidth }}>
{left}
</Split>
<PanelDivider axis="horizontal" onMove={this.onChangeWidth} />
<Split>{right}</Split>
</>
);
}
}

export class PanelDivider extends React.Component<
IDividerProps,
IDividerState
@@ -84,3 +133,10 @@ const DividerHitArea = {
top: -8px;
`
};

const Split = styled.div<{ width?: number }>`
${props => (props.width ? `width: ${props.width}vw` : `flex: 1`)};
position: relative;
flex-direction: column;
display: flex;
`;

0 comments on commit ef23ea3

Please sign in to comment.
You can’t perform that action at this time.