Merge pull request #5895 from influxdata/5890/builder_warns_before_overwrite
feat(ui/flux): warn before overriding the existing Flux Editor script1.9.x
commit
37c8f425b4
|
@ -15,6 +15,7 @@
|
|||
1. [#5856](https://github.com/influxdata/chronograf/pull/5856): Add alert rule options to not send alert on state recovery and send regardless of state change.
|
||||
1. [#5893](https://github.com/influxdata/chronograf/pull/5893): Make aggregation function selection optional.
|
||||
1. [#5894](https://github.com/influxdata/chronograf/pull/5894): Autocomplete builtin `v` object in Flux editor.
|
||||
1. [#5895](https://github.com/influxdata/chronograf/pull/5895): Warn before overriding the existing Flux Editor script.
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
|
|
@ -172,6 +172,7 @@ class FluxQueryMaker extends PureComponent<Props, State> {
|
|||
|
||||
return (
|
||||
<FluxQueryBuilder
|
||||
script={draftScript}
|
||||
source={source}
|
||||
timeRange={timeRange}
|
||||
onSubmit={this.handleSubmitBuilderScript}
|
||||
|
|
|
@ -185,6 +185,9 @@ $flux-form-control-checkbox-gap: 20px;
|
|||
margin-right: 4px;
|
||||
&:last-child {
|
||||
flex-grow: 1;
|
||||
.fqb--submit {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -208,3 +211,42 @@ button.flux-query-builder--add-card-button {
|
|||
font-size: 13px;
|
||||
margin-left: 4px;
|
||||
}
|
||||
|
||||
.fqb--confirm-popup {
|
||||
position: fixed;
|
||||
align-items: center;
|
||||
width: 350px;
|
||||
user-select: none;
|
||||
padding: 8px;
|
||||
background-color: #202028;
|
||||
border-color: #ff8564;
|
||||
border-style: solid;
|
||||
border-width: 2px;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 0 5px 0 #dc4e58;
|
||||
font-size: 1.1em;
|
||||
display: flex;
|
||||
z-index: 5000;
|
||||
|
||||
.fqb--confirm-label {
|
||||
margin: 0 8px
|
||||
}
|
||||
> button {
|
||||
color: #fff;
|
||||
background: #bf3d5e;
|
||||
background-image: linear-gradient(45deg, rgb(191, 61, 94) 0%, rgb(249, 95, 83) 100%)
|
||||
}
|
||||
}
|
||||
.fqb--confirm-caret {
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
position: fixed;
|
||||
border-top: 6px solid transparent;
|
||||
border-bottom: 6px solid #ff8564;
|
||||
border-left: 6px solid transparent;
|
||||
border-right: 6px solid transparent;
|
||||
margin-top: -12px;
|
||||
margin-left: -3px;
|
||||
z-index: 9999;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ import FancyScrollbar from '../../FancyScrollbar'
|
|||
import {
|
||||
Button,
|
||||
ButtonShape,
|
||||
ComponentColor,
|
||||
ComponentSize,
|
||||
ComponentStatus,
|
||||
IconFont,
|
||||
|
@ -18,7 +17,6 @@ import AggregationSelector from './AggregationSelector'
|
|||
import TagSelector from './TagSelector'
|
||||
import {notify as notifyActionCreator} from 'src/shared/actions/notifications'
|
||||
import {
|
||||
fluxWizardError,
|
||||
notifyCopyToClipboardFailed,
|
||||
notifyCopyToClipboardSuccess,
|
||||
} from 'src/shared/copy/notifications'
|
||||
|
@ -28,11 +26,12 @@ import timeRangeWindowPeriod from './util/timeRangeWindowPeriod'
|
|||
import {RemoteDataState, TimeZones} from 'src/types'
|
||||
import {buildQuery} from './util/generateFlux'
|
||||
import {timeRangeLabel} from '../../TimeRangeLabel'
|
||||
import FluxQueryBuilderSubmit from './FluxQueryBuilderSubmit'
|
||||
|
||||
interface OwnProps extends TimeMachineQueryProps {
|
||||
onSubmit: (script: string) => void
|
||||
onShowEditor: () => void
|
||||
isRunnable: boolean
|
||||
script: string
|
||||
}
|
||||
|
||||
type Props = OwnProps & typeof mdtp & ReturnType<typeof mstp>
|
||||
|
@ -48,6 +47,7 @@ const FluxQueryBuilder = ({
|
|||
onSubmit,
|
||||
onShowEditor,
|
||||
onAddTagSelector,
|
||||
script: editorScript,
|
||||
}: Props) => {
|
||||
const [defaultPeriod, timeRangeText] = useMemo(
|
||||
() => [
|
||||
|
@ -97,7 +97,7 @@ const FluxQueryBuilder = ({
|
|||
<Button
|
||||
shape={ButtonShape.Square}
|
||||
size={ComponentSize.ExtraSmall}
|
||||
titleText="Copy builder query to clipboard"
|
||||
titleText="Copy builder script to clipboard"
|
||||
icon={IconFont.Duplicate}
|
||||
status={
|
||||
isRunnable ? ComponentStatus.Default : ComponentStatus.Disabled
|
||||
|
@ -115,12 +115,12 @@ const FluxQueryBuilder = ({
|
|||
success
|
||||
? notifyCopyToClipboardSuccess(
|
||||
null,
|
||||
'Query builder flux script has been copied to clipboard.',
|
||||
'Builder script has been copied to clipboard.',
|
||||
''
|
||||
)
|
||||
: notifyCopyToClipboardFailed(
|
||||
null,
|
||||
'Query builder flux script was not copied to clipboard.',
|
||||
'Builder script was not copied to clipboard.',
|
||||
''
|
||||
)
|
||||
)
|
||||
|
@ -128,26 +128,12 @@ const FluxQueryBuilder = ({
|
|||
e.preventDefault()
|
||||
}}
|
||||
/>
|
||||
<Button
|
||||
size={ComponentSize.ExtraSmall}
|
||||
color={ComponentColor.Primary}
|
||||
onClick={() => {
|
||||
try {
|
||||
const script = buildQuery(builderState)
|
||||
onSubmit(script)
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
notify(
|
||||
fluxWizardError(
|
||||
'Unable to build flux script: ' + ex.message
|
||||
)
|
||||
)
|
||||
}
|
||||
}}
|
||||
status={
|
||||
isRunnable ? ComponentStatus.Default : ComponentStatus.Disabled
|
||||
}
|
||||
text="Submit"
|
||||
<FluxQueryBuilderSubmit
|
||||
isRunnable={isRunnable}
|
||||
builderState={builderState}
|
||||
editorScript={editorScript}
|
||||
notify={notify}
|
||||
onSubmit={onSubmit}
|
||||
/>
|
||||
</div>
|
||||
</AggregationSelector>
|
||||
|
|
|
@ -0,0 +1,146 @@
|
|||
// Libraries
|
||||
import React, {useMemo, useRef, useState} from 'react'
|
||||
import {
|
||||
Button,
|
||||
ComponentColor,
|
||||
ComponentSize,
|
||||
ComponentStatus,
|
||||
} from 'src/reusable_ui'
|
||||
import {fluxWizardError} from 'src/shared/copy/notifications'
|
||||
import {PublishNotificationActionCreator} from 'src/types/actions/notifications'
|
||||
import {ClickOutside} from '../../ClickOutside'
|
||||
import {QueryBuilderState} from './types'
|
||||
import {buildQuery} from './util/generateFlux'
|
||||
|
||||
interface Props {
|
||||
isRunnable: boolean
|
||||
onSubmit: (s: string) => void
|
||||
editorScript: string
|
||||
builderState: QueryBuilderState
|
||||
notify: PublishNotificationActionCreator
|
||||
}
|
||||
const EMPTY_FN = () => {}
|
||||
|
||||
const FluxQueryBuilderSubmit = ({
|
||||
builderState,
|
||||
isRunnable,
|
||||
editorScript,
|
||||
onSubmit,
|
||||
notify,
|
||||
}: Props) => {
|
||||
if (!isRunnable) {
|
||||
return (
|
||||
<Button
|
||||
size={ComponentSize.ExtraSmall}
|
||||
color={ComponentColor.Primary}
|
||||
onClick={EMPTY_FN}
|
||||
status={ComponentStatus.Disabled}
|
||||
text="Submit"
|
||||
customClass="fqb--submit"
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
const [showConfirm, setShowConfirm] = useState(false)
|
||||
const buttonRef = useRef<HTMLDivElement>()
|
||||
const lastConfirmedBuilderState = useMemo(() => {
|
||||
return builderState
|
||||
}, [editorScript])
|
||||
|
||||
return (
|
||||
<div ref={buttonRef}>
|
||||
{!showConfirm ? (
|
||||
<Button
|
||||
size={ComponentSize.ExtraSmall}
|
||||
color={ComponentColor.Primary}
|
||||
onClick={() => {
|
||||
try {
|
||||
const script = buildQuery(builderState)
|
||||
const lastScript = buildQuery(lastConfirmedBuilderState)
|
||||
// submit directly if editor is empty, the generated query is the same as the editor query
|
||||
// or if the builder was used to generate the new script
|
||||
if (
|
||||
!editorScript ||
|
||||
script === editorScript ||
|
||||
editorScript === lastScript
|
||||
) {
|
||||
onSubmit(script)
|
||||
} else {
|
||||
setShowConfirm(true)
|
||||
}
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
notify(
|
||||
fluxWizardError('Unable to build flux script: ' + ex.message)
|
||||
)
|
||||
}
|
||||
}}
|
||||
status={ComponentStatus.Default}
|
||||
text="Submit"
|
||||
customClass="fqb--submit"
|
||||
/>
|
||||
) : (
|
||||
<>
|
||||
<Button
|
||||
size={ComponentSize.ExtraSmall}
|
||||
color={ComponentColor.Primary}
|
||||
onClick={EMPTY_FN}
|
||||
status={
|
||||
isRunnable ? ComponentStatus.Default : ComponentStatus.Disabled
|
||||
}
|
||||
text="Submit"
|
||||
customClass="fqb--submit"
|
||||
/>
|
||||
<div
|
||||
className="fqb--confirm-popup"
|
||||
style={{
|
||||
left: `${
|
||||
buttonRef.current.getBoundingClientRect().right - 350
|
||||
}px`,
|
||||
}}
|
||||
>
|
||||
<span className="fqb--confirm-label">
|
||||
Submitting the Script Builder will overwrite the existing Flux
|
||||
script, any changes you have made using Flux will be discarded.
|
||||
This cannot be recovered.
|
||||
</span>
|
||||
<ClickOutside onClickOutside={() => setShowConfirm(false)}>
|
||||
<Button
|
||||
size={ComponentSize.ExtraSmall}
|
||||
color={ComponentColor.Danger}
|
||||
onClick={() => {
|
||||
try {
|
||||
const script = buildQuery(builderState)
|
||||
setShowConfirm(false)
|
||||
onSubmit(script)
|
||||
} catch (ex) {
|
||||
console.error(ex)
|
||||
notify(
|
||||
fluxWizardError(
|
||||
'Unable to build flux script: ' + ex.message
|
||||
)
|
||||
)
|
||||
}
|
||||
}}
|
||||
status={ComponentStatus.Default}
|
||||
text="OK"
|
||||
/>
|
||||
</ClickOutside>
|
||||
</div>
|
||||
<span
|
||||
className="fqb--confirm-caret"
|
||||
style={{
|
||||
left: `${
|
||||
buttonRef.current.getBoundingClientRect().left +
|
||||
buttonRef.current.getBoundingClientRect().width / 2
|
||||
}px`,
|
||||
top: `${buttonRef.current.getBoundingClientRect().bottom}px`,
|
||||
}}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default FluxQueryBuilderSubmit
|
Loading…
Reference in New Issue