Skip to content

Commit 0844ee3

Browse files
authored
feat: add edit and delete functionality (#6127)
* feat: add edit and delete functionality * chore: make suggested design and PR changes * chore: clear results and cancel the query
1 parent d486e6c commit 0844ee3

File tree

5 files changed

+139
-6
lines changed

5 files changed

+139
-6
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import React, {FC, useContext} from 'react'
2+
import {Button, ComponentColor, IconFont, Overlay} from '@influxdata/clockface'
3+
import './SaveAsScript.scss'
4+
import {CLOUD} from 'src/shared/constants'
5+
import {PersistanceContext} from 'src/dataExplorer/context/persistance'
6+
import {useHistory} from 'react-router-dom'
7+
import {useSelector, useDispatch} from 'react-redux'
8+
import {getOrg} from 'src/organizations/selectors'
9+
import {notify} from 'src/shared/actions/notifications'
10+
import {deleteScriptFail} from 'src/shared/copy/notifications/categories/scripts'
11+
import {ResultsContext} from 'src/dataExplorer/components/ResultsContext'
12+
import {RemoteDataState} from 'src/types'
13+
import {QueryContext} from 'src/shared/contexts/query'
14+
15+
let deleteScript
16+
17+
if (CLOUD) {
18+
deleteScript = require('src/client/scriptsRoutes').deleteScript
19+
}
20+
21+
interface Props {
22+
onBack: () => void
23+
onClose: () => void
24+
}
25+
26+
const DeleteScript: FC<Props> = ({onBack, onClose}) => {
27+
const {resource} = useContext(PersistanceContext)
28+
const {cancel} = useContext(QueryContext)
29+
const {setStatus, setResult} = useContext(ResultsContext)
30+
const history = useHistory()
31+
const dispatch = useDispatch()
32+
const org = useSelector(getOrg)
33+
34+
const handleDeleteScript = async () => {
35+
if (resource.data?.id) {
36+
try {
37+
const resp = await deleteScript({scriptID: resource.data.id})
38+
39+
if (resp.status !== 204) {
40+
throw new Error(resp.data.message)
41+
}
42+
43+
setStatus(RemoteDataState.NotStarted)
44+
setResult(null)
45+
cancel()
46+
history.replace(`/orgs/${org.id}/data-explorer/from/script/`)
47+
onClose()
48+
} catch (error) {
49+
dispatch(notify(deleteScriptFail(resource.data?.name)))
50+
}
51+
}
52+
}
53+
return (
54+
<Overlay.Container maxWidth={500}>
55+
<Overlay.Header
56+
title="Are you sure you want to delete?"
57+
onDismiss={onClose}
58+
/>
59+
<Overlay.Body>
60+
"{resource.data?.name}" will be deleted. Once deleted, this action
61+
cannot be undone.
62+
</Overlay.Body>
63+
<Overlay.Footer>
64+
<Button
65+
color={ComponentColor.Tertiary}
66+
onClick={onClose}
67+
text="cancel"
68+
/>
69+
<Button color={ComponentColor.Secondary} onClick={onBack} text="back" />
70+
<Button
71+
color={ComponentColor.Danger}
72+
onClick={handleDeleteScript}
73+
text="delete"
74+
icon={IconFont.Trash_New}
75+
/>
76+
</Overlay.Footer>
77+
</Overlay.Container>
78+
)
79+
}
80+
81+
export {DeleteScript}

src/dataExplorer/components/FluxQueryBuilder.tsx

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,17 @@ import {RemoteDataState} from 'src/types'
3838
import './FluxQueryBuilder.scss'
3939

4040
export enum OverlayType {
41+
DELETE = 'delete',
42+
EDIT = 'edit',
4143
NEW = 'new',
4244
OPEN = 'open',
4345
SAVE = 'save',
4446
}
4547

4648
const FluxQueryBuilder: FC = () => {
4749
const history = useHistory()
48-
const {hasChanged, vertical, setVertical} = useContext(PersistanceContext)
50+
const {hasChanged, resource, vertical, setVertical} =
51+
useContext(PersistanceContext)
4952
const [overlayType, setOverlayType] = useState<OverlayType | null>(null)
5053
const [isOverlayVisible, setIsOverlayVisible] = useState(false)
5154
const {cancel} = useContext(QueryContext)
@@ -93,6 +96,7 @@ const FluxQueryBuilder: FC = () => {
9396
<Overlay visible={overlayType !== null}>
9497
<SaveAsScript
9598
type={overlayType}
99+
setOverlayType={setOverlayType}
96100
onClose={() => setOverlayType(null)}
97101
/>
98102
</Overlay>
@@ -162,6 +166,15 @@ const FluxQueryBuilder: FC = () => {
162166
icon={IconFont.SaveOutline}
163167
/>
164168
)}
169+
{isFlagEnabled('saveAsScript') && resource?.data?.id && (
170+
<Button
171+
className="flux-query-builder__action-button"
172+
onClick={() => setOverlayType(OverlayType.EDIT)}
173+
status={ComponentStatus.Default}
174+
text="Edit"
175+
icon={IconFont.Pencil}
176+
/>
177+
)}
165178
</div>
166179
{isFlagEnabled('userFeedback') && (
167180
<button

src/dataExplorer/components/SaveAsScript.scss

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,7 @@
66
display: block;
77
margin: -10px 0 12px 0;
88
}
9+
10+
.edit-overlay__delete-script {
11+
margin-top: 16px;
12+
}

src/dataExplorer/components/SaveAsScript.tsx

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
ComponentColor,
55
ComponentStatus,
66
Form,
7+
IconFont,
78
Input,
89
InputLabel,
910
InputType,
@@ -25,16 +26,18 @@ import {
2526
} from 'src/shared/copy/notifications/categories/scripts'
2627
import {getOrg} from 'src/organizations/selectors'
2728
import OpenScript from 'src/dataExplorer/components/OpenScript'
29+
import {DeleteScript} from 'src/dataExplorer/components/DeleteScript'
2830

2931
interface Props {
3032
onClose: () => void
33+
setOverlayType: (type: OverlayType) => void
3134
type: OverlayType | null
3235
}
3336

34-
const SaveAsScript: FC<Props> = ({onClose, type}) => {
37+
const SaveAsScript: FC<Props> = ({onClose, setOverlayType, type}) => {
3538
const dispatch = useDispatch()
3639
const history = useHistory()
37-
const {hasChanged, resource, setResource, clearCompositionSelection, save} =
40+
const {hasChanged, resource, setResource, save} =
3841
useContext(PersistanceContext)
3942
const {cancel} = useContext(QueryContext)
4043
const {setStatus, setResult} = useContext(ResultsContext)
@@ -67,6 +70,10 @@ const SaveAsScript: FC<Props> = ({onClose, type}) => {
6770
})
6871
}
6972

73+
const handleBackClick = () => {
74+
setOverlayType(OverlayType.EDIT)
75+
}
76+
7077
const handleUpdateName = (event: ChangeEvent<HTMLInputElement>) => {
7178
setResource({
7279
...resource,
@@ -80,14 +87,13 @@ const SaveAsScript: FC<Props> = ({onClose, type}) => {
8087
const clear = useCallback(() => {
8188
cancel()
8289
setStatus(RemoteDataState.NotStarted)
83-
clearCompositionSelection()
8490
setResult(null)
8591

8692
history.replace(`/orgs/${org.id}/data-explorer/from/script`)
8793
if (type !== OverlayType.OPEN) {
8894
onClose()
8995
}
90-
}, [onClose, setStatus, setResult, cancel, history, org?.id])
96+
}, [onClose, setStatus, setResult, cancel, history, org?.id, type])
9197

9298
const handleSaveScript = () => {
9399
save()
@@ -108,6 +114,10 @@ const SaveAsScript: FC<Props> = ({onClose, type}) => {
108114
})
109115
}
110116

117+
const handleDeleteScript = () => {
118+
setOverlayType(OverlayType.DELETE)
119+
}
120+
111121
if (type == null) {
112122
return null
113123
}
@@ -121,6 +131,13 @@ const SaveAsScript: FC<Props> = ({onClose, type}) => {
121131
overlayTitle = 'Do you want to save your script first?'
122132
}
123133
}
134+
if (type === OverlayType.EDIT) {
135+
overlayTitle = 'Edit Script Details'
136+
}
137+
138+
if (type === OverlayType.DELETE) {
139+
return <DeleteScript onBack={handleBackClick} onClose={onClose} />
140+
}
124141

125142
if (!hasChanged && type === OverlayType.OPEN) {
126143
return <OpenScript onCancel={handleClose} onClose={onClose} />
@@ -141,6 +158,9 @@ const SaveAsScript: FC<Props> = ({onClose, type}) => {
141158
saveText = 'Yes, Save'
142159
}
143160
}
161+
if (type === OverlayType.EDIT) {
162+
saveText = 'Update'
163+
}
144164

145165
return (
146166
<Overlay.Container maxWidth={540}>
@@ -170,6 +190,16 @@ const SaveAsScript: FC<Props> = ({onClose, type}) => {
170190
value={resource?.data?.description}
171191
onChange={handleUpdateDescription}
172192
/>
193+
{type === OverlayType.EDIT && (
194+
<Button
195+
icon={IconFont.Trash_New}
196+
className="edit-overlay__delete-script"
197+
color={ComponentColor.Danger}
198+
onClick={handleDeleteScript}
199+
text="Delete Script"
200+
testID="flux-query-builder--no-save"
201+
/>
202+
)}
173203
</Form>
174204
</Overlay.Body>
175205
<Overlay.Footer>
@@ -178,7 +208,7 @@ const SaveAsScript: FC<Props> = ({onClose, type}) => {
178208
onClick={handleClose}
179209
text="Cancel"
180210
/>
181-
{type !== OverlayType.SAVE && (
211+
{(type === OverlayType.NEW || type === OverlayType.OPEN) && (
182212
<Button
183213
color={ComponentColor.Default}
184214
onClick={clear}

src/shared/copy/notifications/categories/scripts.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,8 @@ export const scriptSaveSuccess = (scriptName: string): Notification => ({
1515
...defaultSuccessNotification,
1616
message: `${scriptName} has been saved`,
1717
})
18+
19+
export const deleteScriptFail = (scriptName: string): Notification => ({
20+
...defaultErrorNotification,
21+
message: `${scriptName} failed to delete`,
22+
})

0 commit comments

Comments
 (0)