Skip to content

Commit 712a7d6

Browse files
authored
feat: update naming conventions and saving restrictions (#5584)
1 parent 9c565ac commit 712a7d6

File tree

8 files changed

+202
-69
lines changed

8 files changed

+202
-69
lines changed

cypress/e2e/shared/fluxQueryBuilder.test.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,7 @@ describe('FluxQueryBuilder', () => {
2424
if (!$toggle.hasClass('active')) {
2525
// hasClass is a jQuery function
2626
$toggle.click()
27-
cy.getByTestID('flux-query-builder--menu').contains(
28-
'New Script'
29-
)
27+
cy.getByTestID('flux-query-builder--menu').contains('Clear')
3028
}
3129
})
3230
})

src/dataExplorer/components/DataExplorerPage.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -62,15 +62,20 @@ const DataExplorerPageHeader: FC = () => {
6262
}
6363

6464
let pageTitle = <Page.Title title="Data Explorer" />
65+
6566
if (fluxQueryBuilder && resource?.data?.hasOwnProperty('name')) {
66-
pageTitle = (
67-
<RenamablePageTitle
68-
onRename={handleRename}
69-
name={resource?.data?.name || ''}
70-
placeholder="Untitled Script"
71-
maxLength={100}
72-
/>
73-
)
67+
if (resource?.data?.type === ResourceType.Scripts) {
68+
pageTitle = <Page.Title title={resource?.data?.name ?? ''} />
69+
} else {
70+
pageTitle = (
71+
<RenamablePageTitle
72+
onRename={handleRename}
73+
name={resource?.data?.name || ''}
74+
placeholder="Untitled Script"
75+
maxLength={100}
76+
/>
77+
)
78+
}
7479
}
7580

7681
return (

src/dataExplorer/components/FluxQueryBuilder.tsx

Lines changed: 79 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
import React, {FC, useState, useContext} from 'react'
2+
import {useHistory} from 'react-router-dom'
3+
import {useSelector} from 'react-redux'
24

35
// Components
46
import {
7+
ComponentColor,
58
DraggableResizer,
69
FlexBox,
710
FlexDirection,
@@ -25,10 +28,14 @@ import ResultsPane from 'src/dataExplorer/components/ResultsPane'
2528
import Sidebar from 'src/dataExplorer/components/Sidebar'
2629
import Schema from 'src/dataExplorer/components/Schema'
2730
import SaveAsScript from 'src/dataExplorer/components/SaveAsScript'
31+
import {QueryContext} from 'src/shared/contexts/query'
32+
import {ResultsContext} from 'src/dataExplorer/components/ResultsContext'
33+
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
34+
import {getOrg} from 'src/organizations/selectors'
35+
import {RemoteDataState} from 'src/types'
2836

2937
// Styles
3038
import './FluxQueryBuilder.scss'
31-
import {isFlagEnabled} from 'src/shared/utils/featureFlag'
3239

3340
export enum OverlayType {
3441
NEW = 'new',
@@ -37,28 +44,77 @@ export enum OverlayType {
3744
}
3845

3946
const FluxQueryBuilder: FC = () => {
40-
const {
41-
query,
42-
setQuery,
43-
vertical,
44-
setVertical,
45-
clearSchemaSelection,
46-
} = useContext(PersistanceContext)
47+
const history = useHistory()
48+
const {hasChanged, query, vertical, setVertical} = useContext(
49+
PersistanceContext
50+
)
4751
const [overlayType, setOverlayType] = useState<OverlayType | null>(null)
52+
const [isOverlayVisible, setIsOverlayVisible] = useState(false)
53+
const {cancel} = useContext(QueryContext)
54+
const {setStatus, setResult} = useContext(ResultsContext)
55+
const org = useSelector(getOrg)
56+
57+
const handleClear = () => {
58+
cancel()
59+
setStatus(RemoteDataState.NotStarted)
60+
setResult(null)
61+
62+
history.replace(`/orgs/${org.id}/data-explorer/from/script`)
63+
64+
if (!isFlagEnabled('saveAsScript')) {
65+
setIsOverlayVisible(false)
66+
}
67+
}
68+
69+
const handleNewScript = () => {
70+
if (isFlagEnabled('saveAsScript')) {
71+
if (hasChanged) {
72+
setOverlayType(OverlayType.NEW)
73+
} else {
74+
handleClear()
75+
}
76+
} else {
77+
if (hasChanged) {
78+
setIsOverlayVisible(true)
79+
} else {
80+
handleClear()
81+
}
82+
}
83+
}
4884

4985
return (
5086
<EditorProvider>
5187
<SidebarProvider>
52-
<Overlay visible={overlayType !== null}>
53-
<SaveAsScript
54-
type={overlayType}
55-
onClose={() => setOverlayType(null)}
56-
onClear={() => {
57-
clearSchemaSelection()
58-
setQuery('')
59-
}}
60-
/>
61-
</Overlay>
88+
{isFlagEnabled('saveAsScript') ? (
89+
<Overlay visible={overlayType !== null}>
90+
<SaveAsScript
91+
type={overlayType}
92+
onClose={() => setOverlayType(null)}
93+
/>
94+
</Overlay>
95+
) : (
96+
<Overlay visible={isOverlayVisible}>
97+
<Overlay.Container maxWidth={500}>
98+
<Overlay.Header title="Caution" />
99+
<Overlay.Body>
100+
This operation will wipe out your existing query text. Are you
101+
sure you want to continue clearing your existing query?
102+
</Overlay.Body>
103+
<Overlay.Footer>
104+
<Button
105+
color={ComponentColor.Default}
106+
onClick={() => setIsOverlayVisible(false)}
107+
text="No"
108+
/>
109+
<Button
110+
color={ComponentColor.Primary}
111+
onClick={handleClear}
112+
text="Yes"
113+
/>
114+
</Overlay.Footer>
115+
</Overlay.Container>
116+
</Overlay>
117+
)}
62118
<FlexBox
63119
className="flux-query-builder--container"
64120
direction={FlexDirection.Column}
@@ -70,8 +126,8 @@ const FluxQueryBuilder: FC = () => {
70126
data-testid="flux-query-builder--menu"
71127
>
72128
<Button
73-
onClick={() => setOverlayType(OverlayType.NEW)}
74-
text="New Script"
129+
onClick={handleNewScript}
130+
text={isFlagEnabled('saveAsScript') ? 'New Script' : 'Clear'}
75131
icon={IconFont.Plus_New}
76132
status={
77133
query.length === 0
@@ -92,9 +148,9 @@ const FluxQueryBuilder: FC = () => {
92148
className="flux-query-builder__action-button"
93149
onClick={() => setOverlayType(OverlayType.SAVE)}
94150
status={
95-
query.length === 0
96-
? ComponentStatus.Disabled
97-
: ComponentStatus.Default
151+
hasChanged
152+
? ComponentStatus.Default
153+
: ComponentStatus.Disabled
98154
}
99155
text="Save"
100156
icon={IconFont.Save}

src/dataExplorer/components/OpenScript.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,11 @@ if (CLOUD) {
2525
}
2626

2727
interface Props {
28+
onCancel: () => void
2829
onClose: () => void
2930
}
3031

31-
const OpenScript: FC<Props> = ({onClose}) => {
32+
const OpenScript: FC<Props> = ({onCancel, onClose}) => {
3233
const [scripts, setScripts] = useState([])
3334
const [loading, setLoading] = useState(RemoteDataState.NotStarted)
3435
const [searchTerm, setSearchTerm] = useState('')
@@ -123,7 +124,7 @@ const OpenScript: FC<Props> = ({onClose}) => {
123124
}
124125
return (
125126
<Overlay.Container maxWidth={500}>
126-
<Overlay.Header title="Open Script" onDismiss={onClose} />
127+
<Overlay.Header title="Open Script" onDismiss={onCancel} />
127128
<Overlay.Body>
128129
<Input
129130
className="data-source--search"
@@ -138,14 +139,14 @@ const OpenScript: FC<Props> = ({onClose}) => {
138139
<Overlay.Footer>
139140
<Button
140141
color={ComponentColor.Tertiary}
141-
onClick={onClose}
142+
onClick={onCancel}
142143
text="Cancel"
143144
/>
144145
{CLOUD && (
145146
<Button
146147
color={ComponentColor.Primary}
147148
status={
148-
scripts.length === 0
149+
scripts.length === 0 || Object.keys(selectedScript).length === 0
149150
? ComponentStatus.Disabled
150151
: ComponentStatus.Default
151152
}

src/dataExplorer/components/SaveAsScript.tsx

Lines changed: 54 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -27,19 +27,36 @@ import {getOrg} from 'src/organizations/selectors'
2727
import OpenScript from 'src/dataExplorer/components/OpenScript'
2828

2929
interface Props {
30-
onClear: () => void
3130
onClose: () => void
3231
type: OverlayType | null
3332
}
3433

35-
const SaveAsScript: FC<Props> = ({onClose, onClear, type}) => {
34+
const SaveAsScript: FC<Props> = ({onClose, type}) => {
3635
const dispatch = useDispatch()
3736
const history = useHistory()
38-
const {query, resource, setResource, save} = useContext(PersistanceContext)
37+
const {hasChanged, resource, setResource, save} = useContext(
38+
PersistanceContext
39+
)
3940
const {cancel} = useContext(QueryContext)
4041
const {setStatus, setResult} = useContext(ResultsContext)
4142
const org = useSelector(getOrg)
4243

44+
const handleClose = () => {
45+
if (!resource?.data?.id) {
46+
// clear out any meta data that's been set by the user prior to saving
47+
// if they decide to cancel out of the process and close the modal
48+
delete resource.data?.name
49+
delete resource.data?.description
50+
setResource({
51+
...resource,
52+
data: {
53+
...(resource?.data ?? {}),
54+
},
55+
})
56+
}
57+
onClose()
58+
}
59+
4360
const handleUpdateDescription = (event: ChangeEvent<HTMLInputElement>) => {
4461
setResource({
4562
...resource,
@@ -64,7 +81,6 @@ const SaveAsScript: FC<Props> = ({onClose, onClear, type}) => {
6481
cancel()
6582
setStatus(RemoteDataState.NotStarted)
6683
setResult(null)
67-
onClear()
6884

6985
history.replace(`/orgs/${org.id}/data-explorer/from/script`)
7086
if (type !== OverlayType.OPEN) {
@@ -75,17 +91,13 @@ const SaveAsScript: FC<Props> = ({onClose, onClear, type}) => {
7591
const handleSaveScript = () => {
7692
try {
7793
save().then(() => {
78-
dispatch(
79-
notify(scriptSaveSuccess(resource?.data?.name ?? 'Untitled Script'))
80-
)
94+
dispatch(notify(scriptSaveSuccess(resource?.data?.name ?? '')))
8195
if (type === OverlayType.NEW) {
8296
clear()
8397
}
8498
})
8599
} catch (error) {
86-
dispatch(
87-
notify(scriptSaveFail(resource?.data?.name ?? 'Untitled Script'))
88-
)
100+
dispatch(notify(scriptSaveFail(resource?.data?.name ?? '')))
89101
console.error({error})
90102
} finally {
91103
if (type !== OverlayType.OPEN) {
@@ -104,15 +116,36 @@ const SaveAsScript: FC<Props> = ({onClose, onClear, type}) => {
104116
overlayTitle = 'Do you want to save your Script first?'
105117
}
106118

107-
if (query.length === 0) {
108-
return <OpenScript onClose={onClose} />
119+
if (!hasChanged && type === OverlayType.OPEN) {
120+
return <OpenScript onCancel={handleClose} onClose={onClose} />
121+
}
122+
123+
const displayWarning =
124+
(type === OverlayType.NEW && !resource?.data?.name) ||
125+
(type === OverlayType.OPEN && !resource?.data?.name) ||
126+
(type === OverlayType.OPEN && hasChanged && resource?.data?.id)
127+
128+
let saveText = 'Save'
129+
130+
if (resource?.data?.id) {
131+
if (type === OverlayType.SAVE) {
132+
saveText = 'Update'
133+
} else {
134+
saveText = 'Yes, Update'
135+
}
136+
} else {
137+
if (type === OverlayType.SAVE) {
138+
saveText = 'Save'
139+
} else {
140+
saveText = 'Yes, Save'
141+
}
109142
}
110143

111144
return (
112145
<Overlay.Container maxWidth={500}>
113-
<Overlay.Header title={overlayTitle} onDismiss={onClose} />
146+
<Overlay.Header title={overlayTitle} onDismiss={handleClose} />
114147
<Overlay.Body>
115-
{type !== OverlayType.SAVE && (
148+
{displayWarning && (
116149
<div className="save-script-overlay__warning-text">
117150
"{resource?.data?.name ?? 'Untitled Script'}" will be overwritten by
118151
a new one if you don’t save it.
@@ -127,6 +160,11 @@ const SaveAsScript: FC<Props> = ({onClose, onClear, type}) => {
127160
type={InputType.Text}
128161
value={resource?.data?.name}
129162
onChange={handleUpdateName}
163+
status={
164+
resource?.data?.id
165+
? ComponentStatus.Disabled
166+
: ComponentStatus.Default
167+
}
130168
/>
131169
<InputLabel>Description</InputLabel>
132170
<Input
@@ -141,7 +179,7 @@ const SaveAsScript: FC<Props> = ({onClose, onClear, type}) => {
141179
<Overlay.Footer>
142180
<Button
143181
color={ComponentColor.Tertiary}
144-
onClick={onClose}
182+
onClick={handleClose}
145183
text="Cancel"
146184
/>
147185
{type !== OverlayType.SAVE && (
@@ -161,7 +199,7 @@ const SaveAsScript: FC<Props> = ({onClose, onClear, type}) => {
161199
: ComponentStatus.Default
162200
}
163201
onClick={handleSaveScript}
164-
text={type === OverlayType.SAVE ? 'Save' : 'Yes, Save'}
202+
text={saveText}
165203
/>
166204
)}
167205
</Overlay.Footer>

src/dataExplorer/components/resources/TemplatePage.tsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,12 @@ import {
1212
} from 'src/dataExplorer/context/persistance'
1313

1414
const Template: FC = () => {
15-
const {setQuery, setResource, clearSchemaSelection} = useContext(
16-
PersistanceContext
17-
)
15+
const {
16+
setQuery,
17+
setHasChanged,
18+
setResource,
19+
clearSchemaSelection,
20+
} = useContext(PersistanceContext)
1821
const params = useParams()[0].split('/')
1922
const org = useSelector(getOrg)
2023
const history = useHistory()
@@ -43,6 +46,7 @@ const Template: FC = () => {
4346
setQuery(data.flux)
4447
setResource(data)
4548
history.replace(`/orgs/${org.id}/data-explorer`)
49+
setHasChanged(false)
4650
})
4751
}, [params])
4852

0 commit comments

Comments
 (0)