diff --git a/dashboard/src/app.tsx b/dashboard/src/app.tsx
index a6227455c0..3f5d7fe46d 100644
--- a/dashboard/src/app.tsx
+++ b/dashboard/src/app.tsx
@@ -24,6 +24,15 @@ import "flexboxgrid/dist/flexboxgrid.min.css"
import "./styles/padding-margin-mixin.scss"
import { EventProvider } from "./context/events"
import { DataProvider } from "./context/data"
+import { NavLink } from "./components/links"
+
+import logo from "./assets/logo.png"
+
+// Style and align properly
+const Logo = styled.img`
+ height: auto;
+ width: 80%;
+`
const SidebarWrapper = styled.div`
border-right: 1px solid ${colors.border};
@@ -44,6 +53,11 @@ const App = () => (
overflow-y: hidden;
`}>
+
+
+
+
+
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+import React, { ChangeEvent } from "react"
+
+interface Props {
+ name: string
+ checked?: boolean
+ onChange: (event: ChangeEvent
) => void
+}
+
+const CheckBox: React.SFC = ({ name, onChange, checked = false }) => {
+ return (
+
+ )
+}
+
+export default CheckBox
diff --git a/dashboard/src/components/graph/graph.scss b/dashboard/src/components/graph/graph.scss
index 4e19d7eff6..7d4e16e04b 100644
--- a/dashboard/src/components/graph/graph.scss
+++ b/dashboard/src/components/graph/graph.scss
@@ -2,6 +2,13 @@
g.taskPending > rect {
stroke: #f17fcd;
stroke-dasharray: 8;
+ animation: dash 15s linear infinite;
+ }
+
+ @keyframes dash {
+ to {
+ stroke-dashoffset: 1000;
+ }
}
g.taskComplete > rect {
@@ -27,4 +34,17 @@
stroke: rgba(0,0,0,0.32);
stroke-width: 1.5px;
}
+
+ div.label-wrap {
+ text-align: center;
+
+ span.name {
+ font-weight: bold;
+ }
+ span.type {
+ display: inline-block;
+ margin-top: 0.5em
+ }
+ }
+
}
diff --git a/dashboard/src/components/graph/index.tsx b/dashboard/src/components/graph/index.tsx
index a4c7247c6a..b1391cce0b 100644
--- a/dashboard/src/components/graph/index.tsx
+++ b/dashboard/src/components/graph/index.tsx
@@ -8,8 +8,9 @@
import cls from "classnames"
import { css } from "emotion/macro"
-import React, { Component } from "react"
+import React, { Component, ChangeEvent } from "react"
import styled from "@emotion/styled/macro"
+import { capitalize, uniq } from "lodash"
import * as d3 from "d3"
import dagreD3 from "dagre-d3"
@@ -59,6 +60,7 @@ function drawChart(graph: Graph, width: number, height: number) {
label: node.label,
class: "",
id: node.id,
+ labelType: "html",
})
}
@@ -129,6 +131,7 @@ interface Props {
}
interface State {
+ filters: { [key: string]: boolean }
nodes: Node[]
edges: Edge[]
}
@@ -146,13 +149,15 @@ const getIdFromTaskKey = (key: string) => {
return makeId(name, type)
}
+// Renders as HTML
const makeLabel = (name: string, type: string) => {
const nameParts = name.split(".")
// test names look like: name.test-name.type
if (type === "test") {
type += ` (${nameParts[1]})`
}
- return `${nameParts[0]}\n${type}`
+ return "" +
+ nameParts[0] + "
" + type + "
"
}
const Span = styled.span`
@@ -175,17 +180,34 @@ class Chart extends Component {
_edges: Edge[]
_chartRef: React.RefObject
+ state = {
+ nodes: [],
+ edges: [],
+ filters: {},
+ }
+
constructor(props) {
super(props)
this._chartRef = React.createRef()
+ this.onCheckboxChange = this.onCheckboxChange.bind(this)
+
+ const taskTypes = uniq(this.props.graph.nodes.map(n => n.type))
+ const filters = taskTypes.reduce((acc, type) => {
+ acc[type] = false
+ return acc
+ }, {})
+ this.state = {
+ ...this.state,
+ filters,
+ }
}
componentDidMount() {
this.drawChart()
// Re-draw graph on **end** of window resize event (hence the timer)
- let resizeTimer
+ let resizeTimer: NodeJS.Timeout
window.onresize = () => {
clearTimeout(resizeTimer)
resizeTimer = setTimeout(() => {
@@ -194,6 +216,12 @@ class Chart extends Component {
}
}
+ onCheckboxChange({ target }: ChangeEvent) {
+ this.setState({
+ filters: { ...this.state.filters, [target.name]: !target.checked },
+ })
+ }
+
drawChart() {
const graph = this.makeGraph()
this._nodes = graph.nodes
@@ -204,30 +232,38 @@ class Chart extends Component {
}
makeGraph() {
- const nodes: Node[] = this.props.graph.nodes.map(n => {
- return {
- id: makeId(n.name, n.type),
- name: n.name,
- label: makeLabel(n.name, n.type),
- }
- })
- const edges: Edge[] = this.props.graph.relationships.map(r => {
- const source = r.dependency
- const target = r.dependant
- return {
- source: makeId(source.name, source.type),
- target: makeId(target.name, target.type),
- type: source.type,
- }
- })
+ const { filters } = this.state
+ const nodes: Node[] = this.props.graph.nodes
+ .filter(n => !filters[n.type])
+ .map(n => {
+ return {
+ id: makeId(n.name, n.type),
+ name: n.name,
+ label: makeLabel(n.name, n.type),
+ }
+ })
+ const edges: Edge[] = this.props.graph.relationships
+ .filter(n => !filters[n.dependant.type] && !filters[n.dependency.type])
+ .map(r => {
+ const source = r.dependency
+ const target = r.dependant
+ return {
+ source: makeId(source.name, source.type),
+ target: makeId(target.name, target.type),
+ type: source.type,
+ }
+ })
return { edges, nodes }
}
- componentDidUpdate(_prevProps: Props) {
- const { message } = this.props
+ componentDidUpdate(_prevProps, prevState: State) {
+ const message = this.props.message
if (message && message.type === "event") {
this.updateNodeClass(message)
}
+ if (prevState.filters !== this.state.filters) {
+ this.drawChart()
+ }
}
clearClasses(el: HTMLElement) {
@@ -256,13 +292,16 @@ class Chart extends Component {
render() {
const { message } = this.props
+ const taskTypes = uniq(this.props.graph.nodes.map(n => n.type))
const chartHeightEstimate = `100vh - 15rem`
+
let spinner = null
let status = "Ready"
if (message && message.name !== "taskGraphComplete") {
status = "Processing..."
spinner =
}
+
return (
+ height: calc(${chartHeightEstimate});
+ `} ref={this._chartRef} id="chart">
+ display: flex;
+ `, "ml-1 pb-1")}>
{status}
{spinner}
diff --git a/dashboard/src/components/sidebar.tsx b/dashboard/src/components/sidebar.tsx
index 1ffc963416..69e37cfcc8 100644
--- a/dashboard/src/components/sidebar.tsx
+++ b/dashboard/src/components/sidebar.tsx
@@ -14,7 +14,6 @@ import { NavLink } from "./links"
import { Page } from "../containers/sidebar"
import { colors, fontMedium } from "../styles/variables"
-import logo from "../assets/logo.png"
interface Props {
pages: Page[]
@@ -48,12 +47,6 @@ const linkStyle = `
const A = styled.a(linkStyle)
const Link = styled(NavLink)(linkStyle)
-// Style and align properly
-const Logo = styled.img`
- height: auto;
- width: 80%;
-`
-
class Sidebar extends Component {
constructor(props) {
@@ -68,11 +61,6 @@ class Sidebar extends Component {
render() {
return (
-
-
-
-
-