Skip to content

Commit e2573b4

Browse files
committed
use autocomplete in json request body also
1 parent 6018948 commit e2573b4

2 files changed

Lines changed: 65 additions & 2 deletions

File tree

src/components/atoms/Editor.js

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,58 @@
11
import React, { useRef, useEffect, useState } from 'react';
22

33
import { basicSetup } from 'codemirror';
4-
import { EditorState, Prec } from '@codemirror/state';
5-
import { EditorView, keymap, lineNumbers } from '@codemirror/view';
4+
import { EditorState, Compartment } from '@codemirror/state';
5+
import { EditorView, keymap, lineNumbers, tooltips } from '@codemirror/view';
66
import { indentWithTab, history } from '@codemirror/commands';
77
import { json } from '@codemirror/lang-json';
88
import { defaultKeymap } from '@codemirror/commands';
99
import { syntaxHighlighting, defaultHighlightStyle } from '@codemirror/language';
10+
import { isEqual } from 'lodash';
11+
import { autocompletion, CompletionContext } from '@codemirror/autocomplete';
12+
13+
// Function to dynamically generate autocomplete options
14+
const createAutocompleteSource = (options) => {
15+
return (context) => {
16+
let word = context.matchBefore(/\{\{\w*$/);
17+
if (!word) return null;
18+
19+
return {
20+
from: word.from,
21+
options: options.map((option) => ({ label: `{{${option}}}`, type: 'keyword' })),
22+
};
23+
};
24+
};
25+
26+
// Create a Compartment for autocomplete
27+
const autocompleteCompartment = new Compartment();
28+
29+
// Function to update autocomplete options
30+
const updateAutocompleteOptions = (view, newOptions) => {
31+
view.dispatch({
32+
effects: autocompleteCompartment.reconfigure(autocompletion({ override: [createAutocompleteSource(newOptions)] })),
33+
});
34+
};
35+
36+
// Custom styles to hide scrollbar
37+
const hideScrollbar = EditorView.theme({
38+
'.cm-scroller': {
39+
overflowX: 'auto',
40+
overflowY: 'hidden',
41+
whiteSpace: 'nowrap',
42+
scrollbarWidth: 'none' /* For Firefox */,
43+
},
44+
});
1045

1146
export const Editor = ({ ...props }) => {
1247
const editor = useRef();
1348
const [view, setView] = useState(null);
49+
const [dynamicOptions, setDynamicOptions] = useState([]);
1450

1551
if (view) {
52+
if (!isEqual(dynamicOptions, props.completionOptions)) {
53+
updateAutocompleteOptions(view, props.completionOptions);
54+
setDynamicOptions(props.completionOptions);
55+
}
1656
if (props.value != view.state.doc.toString()) {
1757
view.dispatch({ changes: { from: 0, to: view.state.doc.length, insert: props.value } });
1858
}
@@ -35,6 +75,11 @@ export const Editor = ({ ...props }) => {
3575
onUpdate,
3676
EditorState.readOnly.of(props.readOnly || false),
3777
history(),
78+
hideScrollbar,
79+
autocompleteCompartment.of(autocompletion({ override: [createAutocompleteSource(dynamicOptions)] })),
80+
tooltips({
81+
parent: document.body,
82+
}),
3883
],
3984
});
4085

src/components/molecules/flow/nodes/RequestBody.js

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@ import NodeHorizontalDivider from 'components/atoms/flow/NodeHorizontalDivider';
1010
import TextInputWithLabel from 'components/atoms/common/TextInputWithLabel';
1111
import Button from 'components/atoms/common/Button';
1212
import { BUTTON_TYPES } from 'constants/Common';
13+
import useCollectionStore from 'stores/CollectionStore';
14+
import { useTabStore } from 'stores/TabStore';
15+
import { cloneDeep } from 'lodash';
1316

1417
const requestBodyTypeOptions = ['None', 'form-data', 'raw-json'];
1518

@@ -91,6 +94,20 @@ const RequestBody = ({ nodeId, nodeData }) => {
9194
}
9295
};
9396

97+
const getActiveVariables = () => {
98+
const collectionId = useCanvasStore.getState().collectionId;
99+
if (collectionId) {
100+
const activeEnv = useCollectionStore
101+
.getState()
102+
.collections.find((c) => c.id === collectionId)
103+
?.environments.find((e) => e.name === useTabStore.getState().selectedEnv);
104+
if (activeEnv) {
105+
return Object.keys(cloneDeep(activeEnv.variables));
106+
}
107+
}
108+
return [];
109+
};
110+
94111
return (
95112
<>
96113
<div className='flex items-center justify-between p-4 bg-background'>
@@ -137,6 +154,7 @@ const RequestBody = ({ nodeId, nodeData }) => {
137154
onChange={(e) => handleRawJson(e)}
138155
value={nodeData.requestBody.body}
139156
classes={'w-full max-h-96'}
157+
completionOptions={getActiveVariables()}
140158
/>
141159
</div>
142160
<Button

0 commit comments

Comments
 (0)