Merge pull request #3624 from influxdata/flux/yield-polish

Flux/yield polish
pull/10616/head
Alex Paxton 2018-06-11 13:59:05 -07:00 committed by GitHub
commit f248c57c5c
11 changed files with 246 additions and 145 deletions

View File

@ -37,6 +37,7 @@ class BodyBuilder extends PureComponent<Props> {
funcNames={this.funcNames}
funcs={d.funcs}
declarationsFromBody={this.declarationsFromBody}
isLastBody={this.isLastBody(i)}
/>
</div>
)
@ -57,6 +58,7 @@ class BodyBuilder extends PureComponent<Props> {
funcs={b.funcs}
funcNames={this.funcNames}
declarationsFromBody={this.declarationsFromBody}
isLastBody={this.isLastBody(i)}
/>
</div>
)
@ -80,6 +82,12 @@ class BodyBuilder extends PureComponent<Props> {
)
}
private isLastBody = (bodyIndex: number): boolean => {
const {body} = this.props
return bodyIndex === body.length - 1
}
private get newDeclarationFuncs(): string[] {
const {body} = this.props
const declarationFunctions = [funcNames.FROM]

View File

@ -13,6 +13,7 @@ interface Props {
funcs: Func[]
declarationID?: string
declarationsFromBody: string[]
isLastBody: boolean
}
// an Expression is a group of one or more functions
@ -67,6 +68,7 @@ class ExpressionNode extends PureComponent<Props> {
onChangeArg={onChangeArg}
onDelete={onDeleteFuncNode}
onToggleYield={onToggleYield}
isYielding={this.isNextFuncYield(i)}
declarationID={declarationID}
onGenerateScript={onGenerateScript}
declarationsFromBody={declarationsFromBody}
@ -85,6 +87,26 @@ class ExpressionNode extends PureComponent<Props> {
</FluxContext.Consumer>
)
}
private isNextFuncYield = (funcIndex: number): boolean => {
const {funcs, isLastBody} = this.props
if (funcIndex === funcs.length - 1 && isLastBody) {
return true
}
if (funcIndex === funcs.length - 1) {
return false
}
const nextFunc = funcs[funcIndex + 1]
if (nextFunc.name === 'yield') {
return true
}
return false
}
}
export default ExpressionNode

View File

@ -17,13 +17,13 @@ interface Props {
class FluxGraph extends PureComponent<Props> {
public render() {
const containerStyle = {
width: 'calc(100% - 50px)',
height: 'calc(100% - 70px)',
width: 'calc(100% - 32px)',
height: 'calc(100% - 16px)',
position: 'absolute',
}
return (
<div className="flux-graph" style={{width: '100%', height: '100%'}}>
<div className="yield-node--graph">
<Dygraph
labels={this.labels}
staticLegend={false}

View File

@ -1,4 +1,5 @@
import React, {PureComponent, MouseEvent} from 'react'
import classnames from 'classnames'
import FuncArgs from 'src/flux/components/FuncArgs'
import FuncArgsPreview from 'src/flux/components/FuncArgsPreview'
@ -22,6 +23,7 @@ interface Props {
onChangeArg: OnChangeArg
onGenerateScript: () => void
declarationsFromBody: string[]
isYielding: boolean
}
interface State {
@ -56,7 +58,7 @@ export default class FuncNode extends PureComponent<Props, State> {
return (
<div
className="func-node"
className={this.nodeClassName}
onMouseEnter={this.handleMouseEnter}
onMouseLeave={this.handleMouseLeave}
onClick={this.handleClick}
@ -82,6 +84,11 @@ export default class FuncNode extends PureComponent<Props, State> {
)
}
private get nodeClassName(): string {
const {isYielding} = this.props
return classnames('func-node', {active: isYielding})
}
private handleDelete = (e: MouseEvent<HTMLElement>): void => {
e.stopPropagation()
const {func, bodyID, declarationID} = this.props

View File

@ -1,11 +1,10 @@
import React, {PureComponent, CSSProperties, ChangeEvent} from 'react'
import React, {PureComponent, ChangeEvent} from 'react'
import _ from 'lodash'
import {FluxTable} from 'src/types'
import {ErrorHandling} from 'src/shared/decorators/errors'
import FancyScrollbar from 'src/shared/components/FancyScrollbar'
import TableSidebarItem from 'src/flux/components/TableSidebarItem'
import {vis} from 'src/flux/constants'
interface Props {
data: FluxTable[]
@ -32,26 +31,20 @@ export default class TableSidebar extends PureComponent<Props, State> {
const {searchTerm} = this.state
return (
<div className="time-machine--sidebar">
<div className="yield-node--sidebar">
{!this.isDataEmpty && (
<div
className="time-machine-sidebar--heading"
style={this.headingStyle}
>
Tables
<div className="time-machine-sidebar--filter">
<div className="yield-node--sidebar-heading">
<input
type="text"
className="form-control input-xs"
className="form-control input-xs yield-node--sidebar-filter"
onChange={this.handleSearch}
placeholder="Filter tables"
value={searchTerm}
/>
</div>
</div>
)}
<FancyScrollbar>
<div className="time-machine-vis--sidebar query-builder--list">
<div className="yield-node--tabs">
{this.data.map(({partitionKey, id}) => {
return (
<TableSidebarItem
@ -81,14 +74,6 @@ export default class TableSidebar extends PureComponent<Props, State> {
return data.filter(d => d.name.includes(searchTerm))
}
get headingStyle(): CSSProperties {
return {
height: `${vis.TABLE_ROW_HEADER_HEIGHT + 4}px`,
backgroundColor: '#31313d',
borderBottom: '2px solid #383846', // $g5-pepper
}
}
get isDataEmpty(): boolean {
return _.isEmpty(this.props.data)
}

View File

@ -19,7 +19,7 @@ export default class TableSidebarItem extends PureComponent<Props> {
public render() {
return (
<div
className={`time-machine-sidebar--item ${this.active}`}
className={`yield-node--tab ${this.active}`}
onClick={this.handleClick}
>
{this.name}

View File

@ -50,7 +50,7 @@ export default class TimeMachineTable extends PureComponent<Props, State> {
const {scrollLeft, filteredTable} = this.state
return (
<div style={{flex: '1 1 auto'}}>
<>
<AutoSizer>
{({width}) => (
<ColumnSizer
@ -100,7 +100,7 @@ export default class TimeMachineTable extends PureComponent<Props, State> {
</ColumnSizer>
)}
</AutoSizer>
</div>
</>
)
}

View File

@ -11,6 +11,7 @@ import NoResults from 'src/flux/components/NoResults'
interface Props {
data: FluxTable[]
yieldName: string
}
enum VisType {
@ -44,8 +45,8 @@ class TimeMachineVis extends PureComponent<Props, State> {
const {visType} = this.state
return (
<div className="time-machine-visualization">
<div className="time-machine-visualization--settings">
<>
<div className="yield-node--controls">
<VisHeaderTabs
view={visType}
views={[VisType.Table, VisType.Line]}
@ -53,10 +54,8 @@ class TimeMachineVis extends PureComponent<Props, State> {
onToggleView={this.selectVisType}
/>
</div>
<div className="time-machine-visualization--visualization">
{this.vis}
</div>
</div>
<div className="yield-node--visualization">{this.vis}</div>
</>
)
}
@ -80,7 +79,7 @@ class TimeMachineVis extends PureComponent<Props, State> {
onSelectResult={this.handleSelectResult}
/>
)}
<div className="time-machine--vis">
<div className="yield-node--table">
{this.shouldShowTable && (
<TimeMachineTable table={this.selectedResult} />
)}

View File

@ -44,9 +44,9 @@ class YieldFuncNode extends PureComponent<Props, State> {
const yieldName = _.get(func, 'args.0.value', 'result')
return (
<div style={{width: '1000px', height: '1000px'}}>
<span>{yieldName}</span>
<TimeMachineVis data={data} />
<div className="yield-node">
<div className="func-node--connector" />
<TimeMachineVis data={data} yieldName={yieldName} />
</div>
)
}

View File

@ -10,11 +10,21 @@ $flux-connector-line: 2px;
$flux-node-gap: 30px;
$flux-node-padding: 10px;
$flux-arg-min-width: 120px;
$flux-number-color: $c-neutrino;
$flux-func-color: $c-comet;
$flux-number-color: $c-hydrogen;
$flux-object-color: $c-viridian;
$flux-string-color: $c-honeydew;
$flux-boolean-color: $c-viridian;
$flux-invalid-color: $c-viridian;
$flux-invalid-color: $c-curacao;
$flux-func-hover: $c-moonstone;
$flux-number-hover: $c-neutrino;
$flux-object-hover: $c-rainforest;
$flux-string-hover: $c-wasabi;
$flux-boolean-hover: $c-rainforest;
$flux-invalid-hover: $c-dreamsicle;
// Shared Node styles
%flux-node {
min-height: $flux-node-height;
@ -131,6 +141,25 @@ $flux-invalid-color: $c-viridian;
display: flex;
align-items: center;
margin-left: $flux-node-gap;
&:hover,
&.active {
.func-node--preview {
color: $g20-white;
}
.func-arg--string {
color: $flux-string-hover;
}
.func-arg--boolean {
color: $flux-boolean-hover;
}
.func-arg--number {
color: $flux-number-hover;
}
.func-arg--invalid {
color: $flux-invalid-hover;
}
}
}
.func-node--connector {
@ -140,7 +169,10 @@ $flux-invalid-color: $c-viridian;
top: 0;
left: 0;
transform: translateX(-100%);
z-index: 0; // Connection Lines
z-index: 0;
pointer-events: none;
// Connection Lines
&:before,
&:after {
content: '';
@ -198,9 +230,10 @@ $flux-invalid-color: $c-viridian;
.func-node--name {
height: $flux-node-height;
line-height: $flux-node-height;
color: $c-comet;
.func-node:hover & {
color: $c-potassium;
color: $flux-func-color;
.func-node:hover &,
.func-node.active & {
color: $flux-func-hover;
}
}
@ -303,11 +336,13 @@ $flux-filter-unit: 26px;
$flux-filter-unit-wrapped: 34px;
$flux-filter-expression: $g3-castle;
$flux-filter-parens: $g5-pepper;
%flux-filter-style {
height: $flux-filter-unit;
line-height: $flux-filter-unit;
border-style: solid;
border-width: 0;
transition: background-color 0.25s ease;
}
.flux-filter--key {
@ -357,7 +392,9 @@ $flux-filter-parens: $g5-pepper;
height: $flux-filter-unit-wrapped;
width: ($flux-filter-unit-wrapped - $flux-filter-unit) / 2;
background-color: $flux-filter-parens;
border: (($flux-filter-unit-wrapped - $flux-filter-unit) / 2) solid $flux-filter-expression;
border: (($flux-filter-unit-wrapped - $flux-filter-unit) / 2) solid
$flux-filter-expression;
transition: border-color 0.25s ease;
}
.flux-filter--paren-open {
@ -374,6 +411,8 @@ $flux-filter-parens: $g5-pepper;
position: relative;
z-index: 2;
background-color: $flux-filter-parens;
transition: background-color 0.25s ease;
&:before {
content: '';
width: 100%;
@ -386,6 +425,7 @@ $flux-filter-parens: $g5-pepper;
border-color: $flux-filter-expression;
z-index: -1;
box-sizing: border-box;
transition: border-color 0.25s ease;
}
}
@ -420,3 +460,53 @@ $flux-filter-parens: $g5-pepper;
font-weight: 500;
padding-left: 20px;
}
// Func Node Active State (When node is before a yield)
.func-node.active {
background-color: $c-star;
.func-node--connector:after {
@include gradient-h($g3-castle, $c-star);
}
.flux-filter--value.number {
color: $flux-number-hover;
}
.flux-filter--value.string {
color: $flux-string-hover;
}
.flux-filter--value.boolean {
color: $flux-boolean-hover;
}
.flux-filter--key,
.flux-filter--key + .flux-filter--operator,
.flux-filter--key + .flux-filter--operator + .flux-filter--value {
background-color: $c-amethyst;
}
.flux-filter--paren-open,
.flux-filter--paren-close {
border-color: $c-amethyst;
}
.flux-filter--paren-open+.flux-filter--key,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator+.flux-filter--value,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator+.flux-filter--value {
background-color: $c-star;
&:before {
border-color: $c-amethyst;
}
}
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator,
.flux-filter--paren-open+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator+.flux-filter--key+.flux-filter--operator+.flux-filter--value+.flux-filter--operator {
background-color: $c-amethyst;
}
}

View File

@ -1,124 +1,105 @@
/*
Time Machine Visualization
----------------------------------------------------------------------------
Yield Node Styles
------------------------------------------------------------------------------
*/
.time-machine-visualization {
$flux-builder-vis-height: 550px;
$flux-builder-yield-tabs-min-width: 180px;
$flux-builder-yield-tabs-max-width: 400px;
.yield-node {
position: relative;
display: flex;
align-content: center;
align-items: flex-start;
justify-content: flex-start;
flex-direction: column;
width: 100%;
height: 100%;
padding: 10px;
@include gradient-v($g2-kevlar, $g0-obsidian);
width: calc(100% - #{$flux-node-gap});
height: $flux-builder-vis-height;
margin-bottom: $flux-node-tooltip-gap / 2;
margin-top: $flux-node-tooltip-gap / 2;
margin-left: $flux-node-gap;
// Hide Horizontal Line
& > .func-node--connector:after {
content: none;
}
}
.time-machine-visualization--settings {
margin-bottom: 10px;
}
.time-machine-visualization--visualization {
display: flex;
flex: 1 1 auto;
width: 100%;
height: 100%;
}
.time-machine--sidebar,
.time-machine--vis {
.yield-node--controls {
background-color: $g3-castle;
border-radius: $radius;
padding: $flux-node-padding;
border-radius: $radius $radius 0 0;
}
.yield-node--visualization {
display: flex;
align-items: stretch;
flex-wrap: none;
width: 100%;
height: 100%;
}
// Sidebar
.yield-node--sidebar {
display: flex;
flex-direction: column;
align-items: stretch;
flex-wrap: nowrap;
height: inherit;
width: 25%;
min-width: $flux-builder-yield-tabs-min-width;
max-width: $flux-builder-yield-tabs-max-width;
background-color: $g2-kevlar;
overflow: hidden;
border-radius: $radius 0 0 $radius;
}
.time-machine--sidebar {
flex-basis: 25%;
margin-right: 5px;
.yield-node--sidebar-heading {
padding: $flux-node-padding;
}
.time-machine--vis {
flex-basis: 75%;
flex-grow: 1;
}
.time-machine--graph-header {
height: 56px;
padding: 0 16px;
display: flex;
align-items: center;
justify-content: center
}
.time-machine--graph-header .nav.nav-tablist {
width: 180px;
li {
justify-content: center;
flex: 1 0 0;
white-space: nowrap;
}
}
.time-machine--graph-body {
padding: 0 16px 8px 16px;
flex: 1 0 0;
}
.time-machine-sidebar--heading {
@include no-user-select();
width: 100%;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
font-weight: 600;
color: $query-builder--heading-text;
background-color: $query-builder--heading-bg;
padding: 0 $query-builder--list-gutter;
line-height: $query-builder--heading-height;
> .time-machine-sidebar--filter {
flex: 1 1 100%;
margin-left: 20px;
margin-top: 1px;
input {
.yield-node--sidebar-filter.form-control.input-xs {
font-size: 12px;
}
// Tabs
.yield-node--tabs {
display: flex;
flex-direction: column;
position: relative;
// Shadow
&:before {
content: '';
position: absolute;
top: 0;
right: 0;
width: $flux-node-padding;
height: 100%;
@include gradient-h(fade-out($g2-kevlar, 1), fade-out($g2-kevlar, 0.4));
pointer-events: none;
}
}
.time-machine-sidebar--item {
.yield-node--tab {
@include no-user-select();
background-color: $query-builder--list-item-bg;
color: $query-builder--list-item-text;
height: $query-builder--list-item-height;
list-style-type: none;
cursor: default;
color: $g11-sidewalk;
height: 28px;
display: flex;
align-items: center;
margin: 0;
font-size: 12px;
font-weight: 600;
padding: 0 $query-builder--list-gutter;
padding: 0 $flux-node-padding;
transition: color 0.25s ease, background-color 0.25s ease;
white-space: nowrap;
overflow-x: hidden;
&:hover {
background-color: $query-builder--list-item-bg-hover;
color: $query-builder--list-item-text-hover;
background-color: $g4-onyx;
color: $g15-platinum;
cursor: pointer;
}
&.active {
background-color: $query-builder--list-item-bg-active;
color: $query-builder--list-item-text-active;
background-color: $g5-pepper;
color: $g18-cloud;
}
> span {
@ -136,13 +117,22 @@
}
}
.flux-graph {
background-color: $g3-castle;
position: relative;
padding: 20px;
.dygraph-child {
// Table
.yield-node--table {
border-left: 1px solid $g5-pepper;
flex: 1 0 0;
background-color: $g3-castle;
overflow: hidden;
border-radius: 0 $radius $radius 0;
}
// Line Graph
.yield-node--graph {
position: relative;
width: 100%;
height: 100%;
}
padding: 8px 16px;
background-color: $g3-castle;
border-radius: 0 0 $radius $radius;
}