From 4537b373c19128f56b84a15a0f085de04a32379a Mon Sep 17 00:00:00 2001 From: Delmer Reed Date: Wed, 13 Jun 2018 12:29:23 -0700 Subject: [PATCH 01/27] Add cancelable promise wrapper Co-authored-by: Jared Scheib --- ui/src/shared/apis/flux/metaQueries.ts | 50 ++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/ui/src/shared/apis/flux/metaQueries.ts b/ui/src/shared/apis/flux/metaQueries.ts index af326241c..ec479de7e 100644 --- a/ui/src/shared/apis/flux/metaQueries.ts +++ b/ui/src/shared/apis/flux/metaQueries.ts @@ -113,6 +113,56 @@ const tagsetFilter = (filter: SchemaFilter[]): string => { return `|> filter(fn: (r) => ${predicates.join(' and ')} )` } +interface CanceledResolvedValue { + isCanceled: boolean + value: T | null +} + +interface CanceledRejectedValue { + isCanceled: boolean + error: Error | null +} + +type PossiblyCanceledValue = CanceledResolvedValue | CanceledRejectedValue + +interface WrappedCancelablePromise { + promise: Promise> + cancel: () => void +} + +export const makeCancelable = ( + promise: Promise +): WrappedCancelablePromise => { + let isCanceled = false + + const wrappedPromise = new Promise>( + async (resolve, reject) => { + try { + const value = await promise + + if (isCanceled) { + reject({isCanceled, value: null}) + } else { + resolve({isCanceled, value}) + } + } catch (error) { + if (isCanceled) { + reject({isCanceled, error: null}) + } else { + reject({isCanceled, error}) + } + } + } + ) + + return { + promise: wrappedPromise, + cancel() { + isCanceled = true + }, + } +} + const proxy = async (service: Service, script: string) => { const and = encodeURIComponent('&') const mark = encodeURIComponent('?') From 2b48c44779da920d4f27982dc3fd21db2adcfec5 Mon Sep 17 00:00:00 2001 From: Delmer Reed Date: Wed, 13 Jun 2018 14:15:53 -0700 Subject: [PATCH 02/27] Refactor cancelable promise result into union type Instead of returning objects with a boolean isCanceled property we preferred to introduce a new custom error type for canceled promises. Co-authored-by: Jared Scheib --- ui/src/shared/apis/flux/metaQueries.ts | 30 +++++++++++--------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/ui/src/shared/apis/flux/metaQueries.ts b/ui/src/shared/apis/flux/metaQueries.ts index ec479de7e..5b4d46111 100644 --- a/ui/src/shared/apis/flux/metaQueries.ts +++ b/ui/src/shared/apis/flux/metaQueries.ts @@ -113,43 +113,39 @@ const tagsetFilter = (filter: SchemaFilter[]): string => { return `|> filter(fn: (r) => ${predicates.join(' and ')} )` } -interface CanceledResolvedValue { - isCanceled: boolean - value: T | null -} - -interface CanceledRejectedValue { - isCanceled: boolean - error: Error | null -} - -type PossiblyCanceledValue = CanceledResolvedValue | CanceledRejectedValue +type CancelablePromiseResult = T | CanceledPromiseError | Error interface WrappedCancelablePromise { - promise: Promise> + promise: Promise> cancel: () => void } +class CanceledPromiseError extends Error { + constructor() { + super('Canceled Promise') + } +} + export const makeCancelable = ( promise: Promise ): WrappedCancelablePromise => { let isCanceled = false - const wrappedPromise = new Promise>( + const wrappedPromise = new Promise>( async (resolve, reject) => { try { const value = await promise if (isCanceled) { - reject({isCanceled, value: null}) + reject(new CanceledPromiseError()) } else { - resolve({isCanceled, value}) + resolve(value) } } catch (error) { if (isCanceled) { - reject({isCanceled, error: null}) + reject(new CanceledPromiseError()) } else { - reject({isCanceled, error}) + reject(error) } } } From 2de09469c2cb40c4e2a79d5f06c9a73ad1521d4b Mon Sep 17 00:00:00 2001 From: Delmer Reed Date: Wed, 13 Jun 2018 15:56:20 -0700 Subject: [PATCH 03/27] Extract types and utils for canceling promises Simplifies canceled promise generic type to utilize a single parameter. Reject messages for promises can be type any. Co-authored-by: Jared Scheib --- ui/src/shared/apis/flux/metaQueries.ts | 46 -------------------------- ui/src/types/promises.ts | 4 +++ ui/src/utils/promises.ts | 32 ++++++++++++++++++ 3 files changed, 36 insertions(+), 46 deletions(-) create mode 100644 ui/src/types/promises.ts create mode 100644 ui/src/utils/promises.ts diff --git a/ui/src/shared/apis/flux/metaQueries.ts b/ui/src/shared/apis/flux/metaQueries.ts index 5b4d46111..af326241c 100644 --- a/ui/src/shared/apis/flux/metaQueries.ts +++ b/ui/src/shared/apis/flux/metaQueries.ts @@ -113,52 +113,6 @@ const tagsetFilter = (filter: SchemaFilter[]): string => { return `|> filter(fn: (r) => ${predicates.join(' and ')} )` } -type CancelablePromiseResult = T | CanceledPromiseError | Error - -interface WrappedCancelablePromise { - promise: Promise> - cancel: () => void -} - -class CanceledPromiseError extends Error { - constructor() { - super('Canceled Promise') - } -} - -export const makeCancelable = ( - promise: Promise -): WrappedCancelablePromise => { - let isCanceled = false - - const wrappedPromise = new Promise>( - async (resolve, reject) => { - try { - const value = await promise - - if (isCanceled) { - reject(new CanceledPromiseError()) - } else { - resolve(value) - } - } catch (error) { - if (isCanceled) { - reject(new CanceledPromiseError()) - } else { - reject(error) - } - } - } - ) - - return { - promise: wrappedPromise, - cancel() { - isCanceled = true - }, - } -} - const proxy = async (service: Service, script: string) => { const and = encodeURIComponent('&') const mark = encodeURIComponent('?') diff --git a/ui/src/types/promises.ts b/ui/src/types/promises.ts new file mode 100644 index 000000000..765e1e388 --- /dev/null +++ b/ui/src/types/promises.ts @@ -0,0 +1,4 @@ +export interface WrappedCancelablePromise { + promise: Promise + cancel: () => void +} diff --git a/ui/src/utils/promises.ts b/ui/src/utils/promises.ts new file mode 100644 index 000000000..4987984ad --- /dev/null +++ b/ui/src/utils/promises.ts @@ -0,0 +1,32 @@ +import {WrappedCancelablePromise} from 'src/types/promises' + +export const makeCancelable = ( + promise: Promise +): WrappedCancelablePromise => { + let isCanceled = false + + const wrappedPromise = new Promise(async (resolve, reject) => { + try { + const value = await promise + + if (isCanceled) { + reject({isCanceled}) + } else { + resolve(value) + } + } catch (error) { + if (isCanceled) { + reject({isCanceled}) + } else { + reject(error) + } + } + }) + + return { + promise: wrappedPromise, + cancel() { + isCanceled = true + }, + } +} From 6804bbcb4c11a3302065541dc10bf8e0e68cf791 Mon Sep 17 00:00:00 2001 From: Delmer Reed Date: Wed, 13 Jun 2018 16:04:25 -0700 Subject: [PATCH 04/27] Cancel fetch response promise on FilterArgs unmount Co-authored-by: Jared Scheib --- ui/src/flux/components/FilterArgs.tsx | 31 ++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/ui/src/flux/components/FilterArgs.tsx b/ui/src/flux/components/FilterArgs.tsx index 65b281c35..2dcf81924 100644 --- a/ui/src/flux/components/FilterArgs.tsx +++ b/ui/src/flux/components/FilterArgs.tsx @@ -5,9 +5,11 @@ import {tagKeys as fetchTagKeys} from 'src/shared/apis/flux/metaQueries' import parseValuesColumn from 'src/shared/parsing/flux/values' import FilterTagList from 'src/flux/components/FilterTagList' import Walker from 'src/flux/ast/walker' +import {makeCancelable} from 'src/utils/promises' import {Service} from 'src/types' import {Links, OnChangeArg, Func, FilterNode} from 'src/types/flux' +import {WrappedCancelablePromise} from 'src/types/promises' interface Props { links: Links @@ -28,6 +30,8 @@ interface State { } class FilterArgs extends PureComponent { + private fetchTagKeysResponse?: WrappedCancelablePromise + constructor(props) { super(props) this.state = { @@ -52,15 +56,24 @@ class FilterArgs extends PureComponent { } public async componentDidMount() { - const {db, service} = this.props - try { this.convertStringToNodes() - const response = await fetchTagKeys(service, db, []) + const response = await this.getTagKeys() const tagKeys = parseValuesColumn(response) - this.setState({tagKeys}) + + this.setState({ + tagKeys, + }) } catch (error) { - console.error(error) + if (!error.isCanceled) { + console.error(error) + } + } + } + + public componentWillUnmount() { + if (this.fetchTagKeysResponse) { + this.fetchTagKeysResponse.cancel() } } @@ -91,6 +104,14 @@ class FilterArgs extends PureComponent { /> ) } + + private getTagKeys(): Promise { + const {db, service} = this.props + + this.fetchTagKeysResponse = makeCancelable(fetchTagKeys(service, db, [])) + + return this.fetchTagKeysResponse.promise + } } const mapStateToProps = ({links}) => { From bea25481240338a27364f7633689664377f7a9c9 Mon Sep 17 00:00:00 2001 From: Andrew Watkins Date: Fri, 15 Jun 2018 09:18:52 -0700 Subject: [PATCH 05/27] Introduce delete body --- ui/src/flux/components/BodyBuilder.tsx | 13 ++++++++++-- ui/src/flux/components/BodyDelete.tsx | 22 ++++++++++++++++++++ ui/src/flux/components/TimeMachine.tsx | 12 ++++++++++- ui/src/flux/constants/ast.ts | 16 ++++++++++++++ ui/src/flux/constants/index.ts | 3 ++- ui/src/flux/containers/FluxPage.tsx | 13 ++++++++++-- ui/src/types/flux.ts | 1 + ui/test/flux/components/TimeMachine.test.tsx | 1 + 8 files changed, 75 insertions(+), 6 deletions(-) create mode 100644 ui/src/flux/components/BodyDelete.tsx diff --git a/ui/src/flux/components/BodyBuilder.tsx b/ui/src/flux/components/BodyBuilder.tsx index f182dd9f6..612fcb936 100644 --- a/ui/src/flux/components/BodyBuilder.tsx +++ b/ui/src/flux/components/BodyBuilder.tsx @@ -5,6 +5,7 @@ import FancyScrollbar from 'src/shared/components/FancyScrollbar' import ExpressionNode from 'src/flux/components/ExpressionNode' import VariableName from 'src/flux/components/VariableName' import FuncSelector from 'src/flux/components/FuncSelector' +import BodyDelete from 'src/flux/components/BodyDelete' import {funcNames} from 'src/flux/constants' import {Service} from 'src/types' @@ -16,6 +17,7 @@ interface Props { suggestions: Suggestion[] onAppendFrom: () => void onAppendJoin: () => void + onDeleteBody: (bodyID: string) => void } interface Body extends FlatBody { @@ -24,12 +26,17 @@ interface Body extends FlatBody { class BodyBuilder extends PureComponent { public render() { - const bodybuilder = this.props.body.map((b, i) => { + const {body, onDeleteBody} = this.props + + const bodybuilder = body.map((b, i) => { if (b.declarations.length) { - return b.declarations.map(d => { + return b.declarations.map((d, dIndex) => { if (d.funcs) { return (
+ {!dIndex && ( + + )} { return (
+
) @@ -53,6 +61,7 @@ class BodyBuilder extends PureComponent { return (
+ void +} + +class BodyDelete extends PureComponent { + public render() { + return ( + + ) + } + + private handleDelete = (): void => { + this.props.onDeleteBody(this.props.bodyID) + } +} + +export default BodyDelete diff --git a/ui/src/flux/components/TimeMachine.tsx b/ui/src/flux/components/TimeMachine.tsx index b92368654..45556135f 100644 --- a/ui/src/flux/components/TimeMachine.tsx +++ b/ui/src/flux/components/TimeMachine.tsx @@ -7,6 +7,7 @@ import { Suggestion, OnChangeScript, OnSubmitScript, + OnDeleteBody, FlatBody, ScriptStatus, } from 'src/types/flux' @@ -22,6 +23,7 @@ interface Props { status: ScriptStatus suggestions: Suggestion[] onChangeScript: OnChangeScript + onDeleteBody: OnDeleteBody onSubmitScript: OnSubmitScript onAppendFrom: () => void onAppendJoin: () => void @@ -63,7 +65,14 @@ class TimeMachine extends PureComponent { } private get builder() { - const {body, service, suggestions, onAppendFrom, onAppendJoin} = this.props + const { + body, + service, + suggestions, + onAppendFrom, + onDeleteBody, + onAppendJoin, + } = this.props return { name: 'Build', @@ -75,6 +84,7 @@ class TimeMachine extends PureComponent { body={body} service={service} suggestions={suggestions} + onDeleteBody={onDeleteBody} onAppendFrom={onAppendFrom} onAppendJoin={onAppendJoin} /> diff --git a/ui/src/flux/constants/ast.ts b/ui/src/flux/constants/ast.ts index e542d8b43..30822212a 100644 --- a/ui/src/flux/constants/ast.ts +++ b/ui/src/flux/constants/ast.ts @@ -1,3 +1,19 @@ +export const emptyAST = { + type: 'Program', + location: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 1, + }, + source: '', + }, + body: [], +} + export const ast = { type: 'File', start: 0, diff --git a/ui/src/flux/constants/index.ts b/ui/src/flux/constants/index.ts index 81695e650..b81ebaa08 100644 --- a/ui/src/flux/constants/index.ts +++ b/ui/src/flux/constants/index.ts @@ -1,4 +1,4 @@ -import {ast} from 'src/flux/constants/ast' +import {ast, emptyAST} from 'src/flux/constants/ast' import * as editor from 'src/flux/constants/editor' import * as argTypes from 'src/flux/constants/argumentTypes' import * as funcNames from 'src/flux/constants/funcNames' @@ -10,6 +10,7 @@ const MAX_RESPONSE_BYTES = 1e7 // 10 MB export { ast, + emptyAST, funcNames, argTypes, editor, diff --git a/ui/src/flux/containers/FluxPage.tsx b/ui/src/flux/containers/FluxPage.tsx index 11b9ded99..24be29632 100644 --- a/ui/src/flux/containers/FluxPage.tsx +++ b/ui/src/flux/containers/FluxPage.tsx @@ -15,7 +15,7 @@ import {UpdateScript} from 'src/flux/actions' import {bodyNodes} from 'src/flux/helpers' import {getSuggestions, getAST, getTimeSeries} from 'src/flux/apis' -import {builder, argTypes} from 'src/flux/constants' +import {builder, argTypes, emptyAST} from 'src/flux/constants' import {Source, Service, Notification, FluxTable} from 'src/types' import { @@ -114,6 +114,7 @@ export class FluxPage extends PureComponent { onAppendJoin={this.handleAppendJoin} onChangeScript={this.handleChangeScript} onSubmitScript={this.handleSubmitScript} + onDeleteBody={this.handleDeleteBody} />
@@ -331,6 +332,13 @@ export class FluxPage extends PureComponent { this.getASTResponse(script) } + private handleDeleteBody = (bodyID: string): void => { + const newBody = this.state.body.filter(b => b.id !== bodyID) + const script = this.getBodyToScript(newBody) + + this.getASTResponse(script) + } + private handleScriptUpToYield = ( bodyID: string, declarationID: string, @@ -601,7 +609,8 @@ export class FluxPage extends PureComponent { const {links} = this.props if (!script) { - return + this.props.updateScript(script) + return this.setState({ast: emptyAST, body: []}) } try { diff --git a/ui/src/types/flux.ts b/ui/src/types/flux.ts index 88014180c..d1756c6c6 100644 --- a/ui/src/types/flux.ts +++ b/ui/src/types/flux.ts @@ -21,6 +21,7 @@ export type ScriptUpToYield = ( yieldNodeIndex: number, isYieldable: boolean ) => string +export type OnDeleteBody = (bodyID: string) => void export interface ScriptStatus { type: string diff --git a/ui/test/flux/components/TimeMachine.test.tsx b/ui/test/flux/components/TimeMachine.test.tsx index f701c5cfa..2fa66c20a 100644 --- a/ui/test/flux/components/TimeMachine.test.tsx +++ b/ui/test/flux/components/TimeMachine.test.tsx @@ -15,6 +15,7 @@ const setup = () => { onValidate: () => {}, onAppendFrom: () => {}, onAppendJoin: () => {}, + onDeleteBody: () => {}, status: {type: '', text: ''}, } From b9d1424b9dee2ddaee5b30b167f025ef9464a064 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 15:24:27 -0700 Subject: [PATCH 06/27] Add optional prop for tooltip position --- ui/src/shared/components/ConfirmButton.tsx | 42 ++++++++++++---------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/ui/src/shared/components/ConfirmButton.tsx b/ui/src/shared/components/ConfirmButton.tsx index c211b3990..36549ab4c 100644 --- a/ui/src/shared/components/ConfirmButton.tsx +++ b/ui/src/shared/components/ConfirmButton.tsx @@ -2,6 +2,8 @@ import React, {PureComponent} from 'react' import {ClickOutside} from 'src/shared/components/ClickOutside' import {ErrorHandling} from 'src/shared/decorators/errors' +type Position = 'top' | 'bottom' | 'left' | 'right' + interface Props { text?: string confirmText?: string @@ -12,6 +14,7 @@ interface Props { icon?: string disabled?: boolean customClass?: string + position?: Position } interface State { @@ -47,10 +50,11 @@ class ConfirmButton extends PureComponent { className={this.className} onClick={this.handleButtonClick} ref={r => (this.buttonDiv = r)} + title={confirmText} > {icon && } {text && text} -
+
{ ) } - private get className() { - const {type, size, square, disabled, customClass} = this.props - const {expanded} = this.state - - const customClassString = customClass ? ` ${customClass}` : '' - const squareString = square ? ' btn-square' : '' - const expandedString = expanded ? ' active' : '' - const disabledString = disabled ? ' disabled' : '' - - return `confirm-button btn ${type} ${size}${customClassString}${squareString}${expandedString}${disabledString}` - } - private handleButtonClick = () => { if (this.props.disabled) { return @@ -92,9 +84,23 @@ class ConfirmButton extends PureComponent { this.setState({expanded: false}) } - private get calculatedPosition() { - if (!this.buttonDiv || !this.tooltipDiv) { - return '' + private get className(): string { + const {type, size, square, disabled, customClass} = this.props + const {expanded} = this.state + + const customClassString = customClass ? ` ${customClass}` : '' + const squareString = square ? ' btn-square' : '' + const expandedString = expanded ? ' active' : '' + const disabledString = disabled ? ' disabled' : '' + + return `confirm-button btn ${type} ${size}${customClassString}${squareString}${expandedString}${disabledString}` + } + + private get tooltipClassName(): string { + const {position} = this.props + + if (position) { + return `confirm-button--tooltip ${position}` } const windowWidth = window.innerWidth @@ -104,10 +110,10 @@ class ConfirmButton extends PureComponent { const rightGap = windowWidth - buttonRect.right if (tooltipRect.width / 2 > rightGap) { - return 'left' + return 'confirm-button--tooltip left' } - return 'bottom' + return 'confirm-button--tooltip bottom' } } From fe3babb9f472cb55fef00c834aaec733345e6d57 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 15:25:46 -0700 Subject: [PATCH 07/27] Use ConfirmButton instead of regular delete if func is from --- ui/src/flux/components/FuncNode.tsx | 41 ++++++++++++++----- .../components/time-machine/flux-builder.scss | 3 +- 2 files changed, 33 insertions(+), 11 deletions(-) diff --git a/ui/src/flux/components/FuncNode.tsx b/ui/src/flux/components/FuncNode.tsx index 84594a233..2b339f538 100644 --- a/ui/src/flux/components/FuncNode.tsx +++ b/ui/src/flux/components/FuncNode.tsx @@ -2,6 +2,7 @@ import React, {PureComponent, MouseEvent} from 'react' import classnames from 'classnames' import _ from 'lodash' +import ConfirmButton from 'src/shared/components/ConfirmButton' import FuncArgs from 'src/flux/components/FuncArgs' import FuncArgsPreview from 'src/flux/components/FuncArgsPreview' import { @@ -103,13 +104,7 @@ export default class FuncNode extends PureComponent { return (
{this.yieldToggleButton} - + {this.deleteButton}
) } @@ -140,6 +135,32 @@ export default class FuncNode extends PureComponent { ) } + private get deleteButton(): JSX.Element { + const {name} = this.props.func + + if (name === 'from') { + return ( + + ) + } + + return ( + + ) + } + private get nodeClassName(): string { const {isYielding} = this.props const {editing} = this.state @@ -147,14 +168,14 @@ export default class FuncNode extends PureComponent { return classnames('func-node', {active: isYielding || editing}) } - private handleDelete = (e: MouseEvent): void => { - e.stopPropagation() + private handleDelete = (): void => { const {func, bodyID, declarationID} = this.props this.props.onDelete({funcID: func.id, bodyID, declarationID}) } - private handleToggleEdit = (): void => { + private handleToggleEdit = (e: MouseEvent): void => { + e.stopPropagation() this.setState({editing: !this.state.editing}) } diff --git a/ui/src/style/components/time-machine/flux-builder.scss b/ui/src/style/components/time-machine/flux-builder.scss index 6e7e2925c..f5bac9c86 100644 --- a/ui/src/style/components/time-machine/flux-builder.scss +++ b/ui/src/style/components/time-machine/flux-builder.scss @@ -258,7 +258,8 @@ $flux-invalid-hover: $c-dreamsicle; opacity: 0; transition: opacity 0.25s ease; - > button.btn { + > button.btn, + > .confirm-button { margin-left: 4px; } } From 9f150011acbfd6d605775704f2e9a0ee032f67c7 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 15:38:45 -0700 Subject: [PATCH 08/27] Guard against unrendered button or tooltip --- ui/src/shared/components/ConfirmButton.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ui/src/shared/components/ConfirmButton.tsx b/ui/src/shared/components/ConfirmButton.tsx index 36549ab4c..f3b506e92 100644 --- a/ui/src/shared/components/ConfirmButton.tsx +++ b/ui/src/shared/components/ConfirmButton.tsx @@ -103,6 +103,10 @@ class ConfirmButton extends PureComponent { return `confirm-button--tooltip ${position}` } + if (!this.buttonDiv || !this.tooltipDiv) { + return 'confirm-button--tooltip bottom' + } + const windowWidth = window.innerWidth const buttonRect = this.buttonDiv.getBoundingClientRect() const tooltipRect = this.tooltipDiv.getBoundingClientRect() From 20843e762be47deb5f6c5ff2fcbd9fb705a2d6ad Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 15:39:09 -0700 Subject: [PATCH 09/27] Add styles for confirm button tooltip positions --- ui/src/style/components/confirm-button.scss | 65 ++++++++++++--------- 1 file changed, 38 insertions(+), 27 deletions(-) diff --git a/ui/src/style/components/confirm-button.scss b/ui/src/style/components/confirm-button.scss index 74bc7a193..a2b1280b0 100644 --- a/ui/src/style/components/confirm-button.scss +++ b/ui/src/style/components/confirm-button.scss @@ -11,18 +11,26 @@ position: absolute; z-index: 1; - + &.top { + bottom: calc(100% + 4px); + left: 50%; + transform: translateX(-50%); + } &.bottom { top: calc(100% + 4px); left: 50%; transform: translateX(-50%); } - &.left { top: 50%; right: calc(100% + 4px); transform: translateY(-50%); } + &.right { + top: 50%; + left: calc(100% + 4px); + transform: translateY(-50%); + } } } .confirm-button--confirmation { @@ -43,11 +51,7 @@ &:after { content: ''; border: 8px solid transparent; - border-bottom-color: $c-curacao; position: absolute; - bottom: 100%; - left: 50%; - transform: translateX(-50%); transition: border-color 0.25s ease; z-index: 100; } @@ -56,28 +60,35 @@ background-color: $c-dreamsicle; cursor: pointer; } - &:hover:after { - border-bottom-color: $c-dreamsicle; - } -} -.confirm-button--tooltip.bottom .confirm-button--confirmation:after { - bottom: 100%; - left: 50%; - border-bottom-color: $c-curacao; - transform: translateX(-50%); -} -.confirm-button--tooltip.bottom .confirm-button--confirmation:hover:after { - border-bottom-color: $c-dreamsicle; -} -.confirm-button--tooltip.left .confirm-button--confirmation:after { - left: 100%; - top: 50%; - border-left-color: $c-curacao; - transform: translateY(-50%); -} -.confirm-button--tooltip.left .confirm-button--confirmation:hover:after { - border-left-color: $c-dreamsicle; + .top &:after { + top: 100%; + left: 50%; + transform: translateX(-50%); + border-top-color: $c-curacao; + } + .top &:hover:after {border-top-color: $c-dreamsicle;} + .bottom &:after { + bottom: 100%; + left: 50%; + transform: translateX(-50%); + border-bottom-color: $c-curacao; + } + .bottom &:hover:after {border-bottom-color: $c-dreamsicle;} + .left &:after { + top: 50%; + left: 100%; + transform: translateY(-50%); + border-left-color: $c-curacao; + } + .left &:hover:after {border-left-color: $c-dreamsicle;} + .right &:after { + top: 50%; + right: 100%; + transform: translateY(-50%); + border-right-color: $c-curacao; + } + .right &:hover:after {border-right-color: $c-dreamsicle;} } .confirm-button.active { From 69d669a05338c8417f14a6b59234601d447d9669 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 15:50:10 -0700 Subject: [PATCH 10/27] Use ConfirmButton in BodyDelete --- ui/src/flux/components/BodyDelete.tsx | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/ui/src/flux/components/BodyDelete.tsx b/ui/src/flux/components/BodyDelete.tsx index 46bf07b78..a358fa5b7 100644 --- a/ui/src/flux/components/BodyDelete.tsx +++ b/ui/src/flux/components/BodyDelete.tsx @@ -1,4 +1,5 @@ import React, {PureComponent} from 'react' +import ConfirmButton from 'src/shared/components/ConfirmButton' interface Props { bodyID: string @@ -8,9 +9,14 @@ interface Props { class BodyDelete extends PureComponent { public render() { return ( - + ) } From bdb833225d161b43292622c2997719f6ad05701b Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 15:50:27 -0700 Subject: [PATCH 11/27] Separate hover interactions between func node and func node menu --- ui/src/flux/components/FuncNode.tsx | 19 +++++++++++-------- .../components/time-machine/flux-builder.scss | 19 +++++++++++-------- 2 files changed, 22 insertions(+), 16 deletions(-) diff --git a/ui/src/flux/components/FuncNode.tsx b/ui/src/flux/components/FuncNode.tsx index 2b339f538..79ae66c07 100644 --- a/ui/src/flux/components/FuncNode.tsx +++ b/ui/src/flux/components/FuncNode.tsx @@ -54,14 +54,16 @@ export default class FuncNode extends PureComponent { return ( <> -
-
-
{func.name}
- +
+
+
+
{func.name}
+ +
{this.funcMenu}
{this.funcArgs} @@ -146,6 +148,7 @@ export default class FuncNode extends PureComponent { confirmText="Delete this query" square={true} confirmAction={this.handleDelete} + position="right" /> ) } diff --git a/ui/src/style/components/time-machine/flux-builder.scss b/ui/src/style/components/time-machine/flux-builder.scss index f5bac9c86..7866f92c3 100644 --- a/ui/src/style/components/time-machine/flux-builder.scss +++ b/ui/src/style/components/time-machine/flux-builder.scss @@ -144,6 +144,8 @@ $flux-invalid-hover: $c-dreamsicle; &:hover, &.active { + cursor: pointer !important; + .func-node--preview { color: $g20-white; } @@ -196,7 +198,7 @@ $flux-invalid-hover: $c-dreamsicle; } // When a query exists unassigned to a variable -.func-node:first-child { +.func-node--wrapper:first-child .func-node { margin-left: 0; padding-left: $flux-node-gap; .func-node--connector { @@ -248,13 +250,14 @@ $flux-invalid-hover: $c-dreamsicle; } } +.func-node--wrapper { + display: flex; + align-items: center; +} + .func-node--menu { display: flex; align-items: center; - position: absolute; - top: 50%; - right: 0; - transform: translate(100%, -50%); opacity: 0; transition: opacity 0.25s ease; @@ -264,9 +267,9 @@ $flux-invalid-hover: $c-dreamsicle; } } -.func-node:hover .func-node--menu, -.func-node.editing .func-node--menu, -.func-node.active .func-node--menu { +.func-node--wrapper:hover .func-node--menu, +.func-node.editing + .func-node--menu, +.func-node.active + .func-node--menu { opacity: 1; } From 3cc963d067af34ea175660286998c852d2f51f81 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 16:06:15 -0700 Subject: [PATCH 12/27] Allow for optional "type" for body delete Used in the confirmation dialog to refer correctly to the object being deleted --- ui/src/flux/components/BodyDelete.tsx | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/ui/src/flux/components/BodyDelete.tsx b/ui/src/flux/components/BodyDelete.tsx index a358fa5b7..156df3920 100644 --- a/ui/src/flux/components/BodyDelete.tsx +++ b/ui/src/flux/components/BodyDelete.tsx @@ -1,18 +1,25 @@ import React, {PureComponent} from 'react' import ConfirmButton from 'src/shared/components/ConfirmButton' +type BodyType = 'variable' | 'query' + interface Props { bodyID: string + type?: BodyType onDeleteBody: (bodyID: string) => void } class BodyDelete extends PureComponent { + public static defaultProps: Partial = { + type: 'query', + } + public render() { return ( { private handleDelete = (): void => { this.props.onDeleteBody(this.props.bodyID) } + + private get confirmText(): string { + const {type} = this.props + + return `Delete this ${type}` + } } export default BodyDelete From 0e7d66838388421b0ee8196cfac3aefb9757017e Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 16:06:35 -0700 Subject: [PATCH 13/27] Move Body type into shared flux types --- ui/src/flux/components/BodyBuilder.tsx | 6 +----- ui/src/types/flux.ts | 3 +++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ui/src/flux/components/BodyBuilder.tsx b/ui/src/flux/components/BodyBuilder.tsx index 612fcb936..9a1848f40 100644 --- a/ui/src/flux/components/BodyBuilder.tsx +++ b/ui/src/flux/components/BodyBuilder.tsx @@ -9,7 +9,7 @@ import BodyDelete from 'src/flux/components/BodyDelete' import {funcNames} from 'src/flux/constants' import {Service} from 'src/types' -import {FlatBody, Suggestion} from 'src/types/flux' +import {Body, Suggestion} from 'src/types/flux' interface Props { service: Service @@ -20,10 +20,6 @@ interface Props { onDeleteBody: (bodyID: string) => void } -interface Body extends FlatBody { - id: string -} - class BodyBuilder extends PureComponent { public render() { const {body, onDeleteBody} = this.props diff --git a/ui/src/types/flux.ts b/ui/src/types/flux.ts index d1756c6c6..ccfae353f 100644 --- a/ui/src/types/flux.ts +++ b/ui/src/types/flux.ts @@ -106,6 +106,9 @@ export interface FlatBody { funcs?: Func[] declarations?: FlatDeclaration[] } +export interface Body extends FlatBody { + id: string +} export interface Func { type: string From 98fc7878231fb1e03bc13063ae3d8264a844b810 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 16:07:01 -0700 Subject: [PATCH 14/27] Style BodyDelete when used on a variable --- ui/src/flux/components/BodyBuilder.tsx | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/ui/src/flux/components/BodyBuilder.tsx b/ui/src/flux/components/BodyBuilder.tsx index 9a1848f40..09cdd60d2 100644 --- a/ui/src/flux/components/BodyBuilder.tsx +++ b/ui/src/flux/components/BodyBuilder.tsx @@ -48,8 +48,16 @@ class BodyBuilder extends PureComponent { return (
- - +
+ +
+ +
+
) }) From a910c3b21b3c1e57d4b0988b24c3ea901dffae14 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 16:11:08 -0700 Subject: [PATCH 15/27] Rename component to be consistent --- ui/src/flux/components/BodyBuilder.tsx | 6 +++--- .../flux/components/{VariableName.tsx => VariableNode.tsx} | 0 2 files changed, 3 insertions(+), 3 deletions(-) rename ui/src/flux/components/{VariableName.tsx => VariableNode.tsx} (100%) diff --git a/ui/src/flux/components/BodyBuilder.tsx b/ui/src/flux/components/BodyBuilder.tsx index 09cdd60d2..436dac535 100644 --- a/ui/src/flux/components/BodyBuilder.tsx +++ b/ui/src/flux/components/BodyBuilder.tsx @@ -3,7 +3,7 @@ import _ from 'lodash' import FancyScrollbar from 'src/shared/components/FancyScrollbar' import ExpressionNode from 'src/flux/components/ExpressionNode' -import VariableName from 'src/flux/components/VariableName' +import VariableNode from 'src/flux/components/VariableNode' import FuncSelector from 'src/flux/components/FuncSelector' import BodyDelete from 'src/flux/components/BodyDelete' import {funcNames} from 'src/flux/constants' @@ -33,7 +33,7 @@ class BodyBuilder extends PureComponent { {!dIndex && ( )} - + { return (
- +
Date: Fri, 15 Jun 2018 16:23:11 -0700 Subject: [PATCH 16/27] Shorten copy --- ui/src/flux/components/BodyDelete.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/flux/components/BodyDelete.tsx b/ui/src/flux/components/BodyDelete.tsx index 156df3920..29bcd2fee 100644 --- a/ui/src/flux/components/BodyDelete.tsx +++ b/ui/src/flux/components/BodyDelete.tsx @@ -34,7 +34,7 @@ class BodyDelete extends PureComponent { private get confirmText(): string { const {type} = this.props - return `Delete this ${type}` + return `Delete ${type}` } } From 339f55c8c22b19e11339669470dfcb17409f6991 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 16:24:37 -0700 Subject: [PATCH 17/27] Move BodyDelete into func node menu --- ui/src/flux/components/BodyBuilder.tsx | 8 +++----- ui/src/flux/components/ExpressionNode.tsx | 4 ++++ ui/src/flux/components/FuncNode.tsx | 18 +++++------------- 3 files changed, 12 insertions(+), 18 deletions(-) diff --git a/ui/src/flux/components/BodyBuilder.tsx b/ui/src/flux/components/BodyBuilder.tsx index 436dac535..9e50b1afc 100644 --- a/ui/src/flux/components/BodyBuilder.tsx +++ b/ui/src/flux/components/BodyBuilder.tsx @@ -26,13 +26,10 @@ class BodyBuilder extends PureComponent { const bodybuilder = body.map((b, i) => { if (b.declarations.length) { - return b.declarations.map((d, dIndex) => { + return b.declarations.map(d => { if (d.funcs) { return (
- {!dIndex && ( - - )} { funcs={d.funcs} declarationsFromBody={this.declarationsFromBody} isLastBody={this.isLastBody(i)} + onDeleteBody={onDeleteBody} />
) @@ -65,13 +63,13 @@ class BodyBuilder extends PureComponent { return (
-
) diff --git a/ui/src/flux/components/ExpressionNode.tsx b/ui/src/flux/components/ExpressionNode.tsx index b70d4f4aa..8275fd6cf 100644 --- a/ui/src/flux/components/ExpressionNode.tsx +++ b/ui/src/flux/components/ExpressionNode.tsx @@ -15,6 +15,7 @@ interface Props { declarationID?: string declarationsFromBody: string[] isLastBody: boolean + onDeleteBody: (bodyID: string) => void } interface State { @@ -42,6 +43,7 @@ class ExpressionNode extends PureComponent { funcNames, funcs, declarationsFromBody, + onDeleteBody, } = this.props const {nonYieldableIndexesToggled} = this.state @@ -106,6 +108,7 @@ class ExpressionNode extends PureComponent { onGenerateScript={onGenerateScript} declarationsFromBody={declarationsFromBody} onToggleYieldWithLast={this.handleToggleYieldWithLast} + onDeleteBody={onDeleteBody} /> ) @@ -152,6 +155,7 @@ class ExpressionNode extends PureComponent { onGenerateScript={onGenerateScript} declarationsFromBody={declarationsFromBody} onToggleYieldWithLast={this.handleToggleYieldWithLast} + onDeleteBody={onDeleteBody} /> void } interface State { @@ -138,19 +139,10 @@ export default class FuncNode extends PureComponent { } private get deleteButton(): JSX.Element { - const {name} = this.props.func + const {func, bodyID, onDeleteBody} = this.props - if (name === 'from') { - return ( - - ) + if (func.name === 'from') { + return } return ( From 8e4eb72575025468d85f23e975623bf4c8614d96 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 16:37:01 -0700 Subject: [PATCH 18/27] Don't ask for confirmation when deleting a variable --- ui/src/flux/components/BodyDelete.tsx | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) diff --git a/ui/src/flux/components/BodyDelete.tsx b/ui/src/flux/components/BodyDelete.tsx index 29bcd2fee..d5f6c0461 100644 --- a/ui/src/flux/components/BodyDelete.tsx +++ b/ui/src/flux/components/BodyDelete.tsx @@ -15,11 +15,25 @@ class BodyDelete extends PureComponent { } public render() { + const {type} = this.props + + if (type === 'variable') { + return ( + + ) + } + return ( { private handleDelete = (): void => { this.props.onDeleteBody(this.props.bodyID) } - - private get confirmText(): string { - const {type} = this.props - - return `Delete ${type}` - } } export default BodyDelete From a00a82ef3b34540b621efa3eac27d5ff4d03b709 Mon Sep 17 00:00:00 2001 From: Alex P Date: Fri, 15 Jun 2018 16:50:56 -0700 Subject: [PATCH 19/27] Add ability to delete a query assigned to a var from the var --- ui/src/flux/components/BodyBuilder.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ui/src/flux/components/BodyBuilder.tsx b/ui/src/flux/components/BodyBuilder.tsx index 9e50b1afc..faa31eb32 100644 --- a/ui/src/flux/components/BodyBuilder.tsx +++ b/ui/src/flux/components/BodyBuilder.tsx @@ -30,7 +30,12 @@ class BodyBuilder extends PureComponent { if (d.funcs) { return (
- +
+ +
+ +
+
Date: Mon, 18 Jun 2018 09:23:57 -0700 Subject: [PATCH 20/27] Add back erroneously removed handleClickOutside functions to annotation components --- ui/src/shared/components/AnnotationInput.tsx | 4 ++++ ui/src/shared/components/NewAnnotation.tsx | 7 +++++++ 2 files changed, 11 insertions(+) diff --git a/ui/src/shared/components/AnnotationInput.tsx b/ui/src/shared/components/AnnotationInput.tsx index 8d8129048..58e766ca7 100644 --- a/ui/src/shared/components/AnnotationInput.tsx +++ b/ui/src/shared/components/AnnotationInput.tsx @@ -45,6 +45,10 @@ class AnnotationInput extends Component {
) } + public handleClickOutside = () => { + this.props.onConfirmUpdate() + this.setState({isEditing: false}) + } private handleInputClick = () => { this.setState({isEditing: true}) diff --git a/ui/src/shared/components/NewAnnotation.tsx b/ui/src/shared/components/NewAnnotation.tsx index a06e4dda6..f1436eac5 100644 --- a/ui/src/shared/components/NewAnnotation.tsx +++ b/ui/src/shared/components/NewAnnotation.tsx @@ -112,6 +112,13 @@ class NewAnnotation extends Component { ) } + public handleClickOutside = () => { + const {onDismissAddingAnnotation, isTempHovering} = this.props + if (!isTempHovering) { + onDismissAddingAnnotation() + } + } + private clampWithinGraphTimerange = (timestamp: number): number => { const [xRangeStart] = this.props.dygraph.xAxisRange() return Math.max(xRangeStart, timestamp) From fe89912a570758e6af7db405f209031f960636b7 Mon Sep 17 00:00:00 2001 From: Christopher Henn Date: Mon, 18 Jun 2018 09:52:36 -0700 Subject: [PATCH 21/27] Fix template variables null property bug --- ui/src/tempVars/constants/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/ui/src/tempVars/constants/index.ts b/ui/src/tempVars/constants/index.ts index 909cf8e0e..6fe11741c 100644 --- a/ui/src/tempVars/constants/index.ts +++ b/ui/src/tempVars/constants/index.ts @@ -97,6 +97,7 @@ export const DEFAULT_TEMPLATES: DefaultTemplates = { values: [], type: TemplateType.CSV, label: '', + query: {}, } }, [TemplateType.TagKeys]: () => { From 3ecafecf4233309bc9d280a8786a2b90c3f7831e Mon Sep 17 00:00:00 2001 From: Alirie Gray Date: Mon, 18 Jun 2018 11:32:36 -0700 Subject: [PATCH 22/27] Fix misimported template variables constants Co-authored-by: Chris Henn Co-authored-by: Alirie Gray --- ui/src/dashboards/components/QueryTextArea.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/dashboards/components/QueryTextArea.js b/ui/src/dashboards/components/QueryTextArea.js index ea152f8cd..655ef51e8 100644 --- a/ui/src/dashboards/components/QueryTextArea.js +++ b/ui/src/dashboards/components/QueryTextArea.js @@ -12,7 +12,7 @@ import { applyMasks, insertTempVar, unMask, -} from 'src/dashboards/constants' +} from 'src/tempVars/constants' @ErrorHandling class QueryTextArea extends Component { From acdd7a19b52fc7af4e83e80d94d8421e5265b254 Mon Sep 17 00:00:00 2001 From: Ricardo N Feliciano Date: Mon, 18 Jun 2018 17:56:17 -0400 Subject: [PATCH 23/27] CircleCI 2.0 (#3710) * Migrate to CircleCI 2.0. * Comment out filters to test all jobs. * Restore deploy job filters. --- .circleci/config.yml | 138 +++++++++++++++++++++++++++++++++++++++++++ circle.yml | 91 ---------------------------- 2 files changed, 138 insertions(+), 91 deletions(-) create mode 100644 .circleci/config.yml delete mode 100644 circle.yml diff --git a/.circleci/config.yml b/.circleci/config.yml new file mode 100644 index 000000000..f05cf6f5e --- /dev/null +++ b/.circleci/config.yml @@ -0,0 +1,138 @@ +workflows: + version: 2 + main: + jobs: + - build + - deploy-nightly: + requires: + - build + filters: + branches: + only: master + - deploy-pre-release: + requires: + - build + filters: + branches: + ignore: /.*/ + tags: + only: /^[0-9]+(\.[0-9]+)*(\S*)([a|rc|beta]([0-9]+))+$/ + - deploy-release: + requires: + - build + filters: + branches: + ignore: /.*/ + tags: + only: /^[0-9]+(\.[0-9]+)*$/ + + +version: 2 +jobs: + build: + environment: + DOCKER_TAG: chronograf-20180327 + machine: true + steps: + - checkout + - run: | + ls -lah + pwd + - run: ./etc/scripts/docker/pull.sh + - run: + name: "Run Tests" + command: > + ./etc/scripts/docker/run.sh + --debug + --test + --no-build + - persist_to_workspace: + root: /home/circleci + paths: + - project + + deploy-nightly: + environment: + DOCKER_TAG: chronograf-20180327 + machine: true + steps: + - attach_workspace: + at: /home/circleci + - run: | + ./etc/scripts/docker/run.sh \ + --debug \ + --clean \ + --package \ + --platform all \ + --arch all \ + --upload \ + --nightly \ + --bucket=dl.influxdata.com/chronograf/releases + cp build/linux/static_amd64/chronograf . + cp build/linux/static_amd64/chronoctl . + docker build -t chronograf . + docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io + docker tag chronograf quay.io/influxdb/chronograf:nightly + docker push quay.io/influxdb/chronograf:nightly + - store_artifacts: + path: ./build/ + + deploy-pre-release: + environment: + DOCKER_TAG: chronograf-20180327 + machine: true + steps: + - attach_workspace: + at: /home/circleci + - run: | + ./etc/scripts/docker/run.sh \ + --clean \ + --debug \ + --release \ + --package \ + --platform all \ + --arch all \ + --upload-overwrite \ + --upload \ + --bucket dl.influxdata.com/chronograf/releases + cp build/linux/static_amd64/chronograf . + cp build/linux/static_amd64/chronoctl . + docker build -t chronograf . + docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io + docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} + docker push quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} + docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_TAG} + docker push quay.io/influxdb/chronograf:${CIRCLE_TAG} + - store_artifacts: + path: ./build/ + + deploy-release: + environment: + DOCKER_TAG: chronograf-20180327 + machine: true + steps: + - attach_workspace: + at: /home/circleci + - run: | + ./etc/scripts/docker/run.sh \ + --clean \ + --debug \ + --release \ + --package \ + --platform all \ + --arch all \ + --upload-overwrite \ + --upload \ + --bucket dl.influxdata.com/chronograf/releases + cp build/linux/static_amd64/chronograf . + cp build/linux/static_amd64/chronoctl . + docker build -t chronograf . + docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io + docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} + docker push quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} + docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_TAG} + docker push quay.io/influxdb/chronograf:${CIRCLE_TAG} + docker tag chronograf quay.io/influxdb/chronograf:latest + docker push quay.io/influxdb/chronograf:latest + - store_artifacts: + path: ./build/ diff --git a/circle.yml b/circle.yml deleted file mode 100644 index 279d238e8..000000000 --- a/circle.yml +++ /dev/null @@ -1,91 +0,0 @@ ---- -machine: - services: - - docker - environment: - DOCKER_TAG: chronograf-20180327 - -dependencies: - override: - - ./etc/scripts/docker/pull.sh - -test: - override: - - > - ./etc/scripts/docker/run.sh - --debug - --test - --no-build - -deployment: - master: - branch: master - commands: - - > - ./etc/scripts/docker/run.sh - --debug - --clean - --package - --platform all - --arch all - --upload - --nightly - --bucket=dl.influxdata.com/chronograf/releases - - sudo chown -R ubuntu:ubuntu /home/ubuntu - - cp build/linux/static_amd64/chronograf . - - cp build/linux/static_amd64/chronoctl . - - docker build -t chronograf . - - docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io - - docker tag chronograf quay.io/influxdb/chronograf:nightly - - docker push quay.io/influxdb/chronograf:nightly - - mv ./build/* $CIRCLE_ARTIFACTS - pre-release: - tag: /^[0-9]+(\.[0-9]+)*(\S*)([a|rc|beta]([0-9]+))+$/ - commands: - - > - ./etc/scripts/docker/run.sh - --clean - --debug - --release - --package - --platform all - --arch all - --upload-overwrite - --upload - --bucket dl.influxdata.com/chronograf/releases - - sudo chown -R ubuntu:ubuntu /home/ubuntu - - cp build/linux/static_amd64/chronograf . - - cp build/linux/static_amd64/chronoctl . - - docker build -t chronograf . - - docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io - - docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} - - docker push quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} - - docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_TAG} - - docker push quay.io/influxdb/chronograf:${CIRCLE_TAG} - - mv ./build/* $CIRCLE_ARTIFACTS - release: - tag: /^[0-9]+(\.[0-9]+)*$/ - commands: - - > - ./etc/scripts/docker/run.sh - --clean - --debug - --release - --package - --platform all - --arch all - --upload-overwrite - --upload - --bucket dl.influxdata.com/chronograf/releases - - sudo chown -R ubuntu:ubuntu /home/ubuntu - - cp build/linux/static_amd64/chronograf . - - cp build/linux/static_amd64/chronoctl . - - docker build -t chronograf . - - docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io - - docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} - - docker push quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} - - docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_TAG} - - docker push quay.io/influxdb/chronograf:${CIRCLE_TAG} - - docker tag chronograf quay.io/influxdb/chronograf:latest - - docker push quay.io/influxdb/chronograf:latest - - mv ./build/* $CIRCLE_ARTIFACTS From 65210b4c2c4cd19c73a61224ba357b8a97c69ac4 Mon Sep 17 00:00:00 2001 From: Luke Morris Date: Mon, 18 Jun 2018 16:06:34 -0700 Subject: [PATCH 24/27] Remove deprecated email flag --- .circleci/config.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index f05cf6f5e..56c4969b9 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -71,7 +71,7 @@ jobs: cp build/linux/static_amd64/chronograf . cp build/linux/static_amd64/chronoctl . docker build -t chronograf . - docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io + docker login -u "$QUAY_USER" -p $QUAY_PASS quay.io docker tag chronograf quay.io/influxdb/chronograf:nightly docker push quay.io/influxdb/chronograf:nightly - store_artifacts: @@ -98,7 +98,7 @@ jobs: cp build/linux/static_amd64/chronograf . cp build/linux/static_amd64/chronoctl . docker build -t chronograf . - docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io + docker login -u "$QUAY_USER" -p $QUAY_PASS quay.io docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} docker push quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_TAG} @@ -127,7 +127,7 @@ jobs: cp build/linux/static_amd64/chronograf . cp build/linux/static_amd64/chronoctl . docker build -t chronograf . - docker login -e $QUAY_EMAIL -u "$QUAY_USER" -p $QUAY_PASS quay.io + docker login -u "$QUAY_USER" -p $QUAY_PASS quay.io docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} docker push quay.io/influxdb/chronograf:${CIRCLE_SHA1:0:7} docker tag chronograf quay.io/influxdb/chronograf:${CIRCLE_TAG} From 3fdb6a1f3a537d0e598ea6e674a8772a13625780 Mon Sep 17 00:00:00 2001 From: Iris Scholten Date: Mon, 18 Jun 2018 16:41:51 -0700 Subject: [PATCH 25/27] Fix type error when temp vars have no values --- ui/src/dashboards/utils/tempVars.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ui/src/dashboards/utils/tempVars.ts b/ui/src/dashboards/utils/tempVars.ts index d122b8aed..1bb1544b8 100644 --- a/ui/src/dashboards/utils/tempVars.ts +++ b/ui/src/dashboards/utils/tempVars.ts @@ -32,7 +32,7 @@ export const generateURLQueryParamsFromTempVars = ( const selected = values.find(value => value.selected === true) const strippedTempVar = stripTempVar(tempVar) - urlQueryParams[strippedTempVar] = selected.value + urlQueryParams[strippedTempVar] = _.get(selected, 'value', '') }) return urlQueryParams From c6587f36be69691c2e4454215b2db9bbb7e8fcdc Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 18 Jun 2018 18:47:39 -0700 Subject: [PATCH 26/27] Refactor confirm button to use classnames instead of ternaries --- ui/src/shared/components/ConfirmButton.tsx | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/ui/src/shared/components/ConfirmButton.tsx b/ui/src/shared/components/ConfirmButton.tsx index f3b506e92..4674697be 100644 --- a/ui/src/shared/components/ConfirmButton.tsx +++ b/ui/src/shared/components/ConfirmButton.tsx @@ -1,4 +1,5 @@ import React, {PureComponent} from 'react' +import classnames from 'classnames' import {ClickOutside} from 'src/shared/components/ClickOutside' import {ErrorHandling} from 'src/shared/decorators/errors' @@ -88,12 +89,12 @@ class ConfirmButton extends PureComponent { const {type, size, square, disabled, customClass} = this.props const {expanded} = this.state - const customClassString = customClass ? ` ${customClass}` : '' - const squareString = square ? ' btn-square' : '' - const expandedString = expanded ? ' active' : '' - const disabledString = disabled ? ' disabled' : '' - - return `confirm-button btn ${type} ${size}${customClassString}${squareString}${expandedString}${disabledString}` + return classnames(`confirm-button btn ${type} ${size}`, { + [customClass]: customClass, + 'btn-square': square, + active: expanded, + disabled, + }) } private get tooltipClassName(): string { From 28bbdbf3cd4c9f197a27998b6743ec24a28bf898 Mon Sep 17 00:00:00 2001 From: Alex P Date: Mon, 18 Jun 2018 18:50:14 -0700 Subject: [PATCH 27/27] Updoot changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e01e7e5cc..213a92d53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ 1. [#3474](https://github.com/influxdata/chronograf/pull/3474): Sort task table on Manage Alert page alphabetically 1. [#3590](https://github.com/influxdata/chronograf/pull/3590): Redesign icons in side navigation +1. [#3696](https://github.com/influxdata/chronograf/pull/3696): Add ability to delete entire queries in Flux Editor ### Bug Fixes