Skip to content

Commit

Permalink
Top-down DAG layout with opinionated zoom, jump bar, styled right sid…
Browse files Browse the repository at this point in the history
…ebar (#222)

* Initial pass at vertical DAG

* Update graphQL definitions

* Remove align option to get vertically centered DAG

* Add compact rendering for nodes with > 4 inputs or outputs

* Revert settings.json changes

* Update jest tests

* Center the minified input/output blocks

* Replace panzoom with our own library, basic pan + double click to zoom at two distinct levels

* Distinct zoom levels, nav in top bar, detail view on right side

* Fix the escape hotkey, detection of current text field input

* Clean up React hierarchy, address initial feedback

* More cleanup

* Fix typescript error with new optional config

* Update snapshot tests
  • Loading branch information
bengotow authored Sep 27, 2018
1 parent ad149be commit 9480db5
Show file tree
Hide file tree
Showing 27 changed files with 1,253 additions and 1,020 deletions.
15 changes: 12 additions & 3 deletions python_modules/dagit/dagit/webapp/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
"dependencies": {
"@blueprintjs/core": "^3.0.1",
"@blueprintjs/icons": "^3.0.0",
"@blueprintjs/select": "^3.2.0",
"@types/dagre": "^0.7.40",
"@types/prop-types": "^15.5.4",
"@types/react-router": "^4.0.30",
Expand All @@ -16,11 +17,11 @@
"@vx/responsive": "^0.0.165",
"@vx/scale": "^0.0.165",
"@vx/shape": "^0.0.170",
"amator": "^1.1.0",
"apollo-boost": "^0.1.12",
"d3-hierarchy": "^1.1.6",
"dagre": "^0.8.2",
"graphql-tag": "^2.9.2",
"panzoom": "^6.1.3",
"react": "^16.4.2",
"react-apollo": "^2.1.9",
"react-dom": "^16.4.2",
Expand Down Expand Up @@ -61,12 +62,20 @@
"watch-types": "apollo codegen:generate --queries \"./src/**/*.tsx\" --target typescript types --schema ./src/schema.json --watch"
},
"jest": {
"roots": ["<rootDir>/src"],
"roots": [
"<rootDir>/src"
],
"transform": {
"^.+\\.(ts|tsx)$": "ts-jest",
"\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/jest/fileTransformer.js"
},
"moduleFileExtensions": ["js", "jsx", "json", "ts", "tsx"],
"moduleFileExtensions": [
"js",
"jsx",
"json",
"ts",
"tsx"
],
"testRegex": "/__tests__/.*\\.test\\.(ts|tsx)$",
"testURL": "http://localhost"
}
Expand Down
85 changes: 60 additions & 25 deletions python_modules/dagit/dagit/webapp/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,80 @@ import gql from "graphql-tag";
import { Query, QueryResult } from "react-apollo";
import { Route } from "react-router";
import { BrowserRouter } from "react-router-dom";
import Page from "./Page";
import Loading from "./Loading";
import Pipelines from "./Pipelines";
import PipelineExplorer from "./PipelineExplorer";
import PipelineJumpBar from "./PipelineJumpBar";
import { AppQuery } from "./types/AppQuery";

import { Alignment, Navbar, NonIdealState } from "@blueprintjs/core";
import navBarImage from "./images/nav-logo.png";

export default class App extends React.Component {
public render() {
return (
<BrowserRouter>
<Route path="/:pipeline">
{({ match, history }) => (
<Query query={APP_QUERY}>
{(queryResult: QueryResult<AppQuery, any>) => (
<Page>
<Loading queryResult={queryResult}>
{data => (
<Pipelines
selectedPipeline={match ? match.params.pipeline : ""}
pipelines={data.pipelines}
history={history}
/>
)}
</Loading>
</Page>
)}
</Query>
)}
</Route>
</BrowserRouter>
<Query query={APP_QUERY}>
{(queryResult: QueryResult<AppQuery, any>) => (
<Loading queryResult={queryResult}>
{data => (
<BrowserRouter>
<Route path="/:pipeline/:solid?">
{({ match, history }) => {
const selectedPipeline = data.pipelines.find(
p => (match ? p.name === match.params.pipeline : false)
);
const selectedSolid =
selectedPipeline &&
selectedPipeline.solids.find(
s => (match ? s.name === match.params.solid : false)
);

return (
<>
<Navbar>
<Navbar.Group align={Alignment.LEFT}>
<Navbar.Heading>
<img src={navBarImage} style={{ height: 34 }} />
</Navbar.Heading>
<Navbar.Divider />
<PipelineJumpBar
selectedPipeline={selectedPipeline}
selectedSolid={selectedSolid}
pipelines={data.pipelines}
history={history}
/>
</Navbar.Group>
</Navbar>
{selectedPipeline ? (
<PipelineExplorer
pipeline={selectedPipeline}
solid={selectedSolid}
history={history}
/>
) : (
<NonIdealState
title="No pipeline selected"
description="Select a pipeline in the sidebar on the left"
/>
)}
</>
);
}}
</Route>
</BrowserRouter>
)}
</Loading>
)}
</Query>
);
}
}

export const APP_QUERY = gql`
query AppQuery {
pipelines {
...PipelinesFragment
...PipelineFragment
}
}
${Pipelines.fragments.PipelinesFragment}
${PipelineExplorer.fragments.PipelineFragment}
`;
45 changes: 0 additions & 45 deletions python_modules/dagit/dagit/webapp/src/Breadcrumbs.tsx

This file was deleted.

28 changes: 8 additions & 20 deletions python_modules/dagit/dagit/webapp/src/Config.tsx
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import * as React from "react";
import gql from "graphql-tag";
import styled from "styled-components";
import { UL, H6, Colors } from "@blueprintjs/core";
import SpacedCard from "./SpacedCard";
import { UL, Colors } from "@blueprintjs/core";
import TypeWithTooltip from "./TypeWithTooltip";
import Description from "./Description";
import { ConfigFragment } from "./types/ConfigFragment";

interface ConfigProps {
config: ConfigFragment | null;
config: ConfigFragment;
}

export default class Config extends React.Component<ConfigProps, {}> {
Expand Down Expand Up @@ -61,27 +60,16 @@ export default class Config extends React.Component<ConfigProps, {}> {
}

public render() {
if (this.props.config) {
return (
<ConfigCard elevation={3}>
<H6>Config</H6>
<TypeWithTooltip type={this.props.config.type} />
{this.renderFields(this.props.config)}
</ConfigCard>
);
} else {
return null;
}
return (
<div>
<TypeWithTooltip type={this.props.config.type} />
{this.renderFields(this.props.config)}
</div>
);
}
}

const ConfigCard = styled(SpacedCard)`
width: 400px;
margin-bottom: 10px;
`;

const DescriptionWrapper = styled.div`
max-width: 400px;
margin-top: 10px;
margin-bottom: 10px;
color: ${Colors.GRAY2};
Expand Down
2 changes: 0 additions & 2 deletions python_modules/dagit/dagit/webapp/src/Description.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import * as React from "react";
import gql from "graphql-tag";
import styled from "styled-components";
import { H1, H2, H3, H4, H5, H6, Text, Code, UL, Pre } from "@blueprintjs/core";
import * as ReactMarkdown from "react-markdown";

interface IDescriptionProps {
Expand Down
21 changes: 0 additions & 21 deletions python_modules/dagit/dagit/webapp/src/Page.tsx

This file was deleted.

60 changes: 60 additions & 0 deletions python_modules/dagit/dagit/webapp/src/PanelDivider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
import * as React from "react";
import styled from "styled-components";
import { Colors } from "@blueprintjs/core";

interface IDividerProps {
onMove: (vw: number) => void;
}
interface IDividerState {
down: boolean;
}

export class PanelDivider extends React.Component<
IDividerProps,
IDividerState
> {
state = {
down: false
};

onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
this.setState({ down: true });
const onMouseMove = (event: MouseEvent) => {
let vx = (event.clientX * 100) / window.innerWidth;
this.props.onMove(vx);
};
const onMouseUp = (event: MouseEvent) => {
this.setState({ down: false });
document.removeEventListener("mousemove", onMouseMove);
document.removeEventListener("mouseup", onMouseUp);
};
document.addEventListener("mousemove", onMouseMove);
document.addEventListener("mouseup", onMouseUp);
};

render() {
return (
<DividerWrapper down={this.state.down}>
<DividerHitArea onMouseDown={this.onMouseDown} />
</DividerWrapper>
);
}
}

const DividerWrapper = styled.div<{ down: boolean }>`
width: 4px;
background: ${Colors.WHITE};
border-left: 1px solid ${p => (p.down ? Colors.GRAY5 : Colors.LIGHT_GRAY2)};
border-right: 1px solid ${p => (p.down ? Colors.GRAY3 : Colors.GRAY5)};
overflow: visible;
position: relative;
`;

const DividerHitArea = styled.div`
width: 17px;
height: 100%;
z-index: 2;
cursor: ew-resize;
position: relative;
left: -8px;
`;
Loading

0 comments on commit 9480db5

Please sign in to comment.