Skip to content

Commit d7d9dde

Browse files
Introduce environment tabs for secrets
Co-authored-by: Saikrishna321 <[email protected]>
1 parent e11408c commit d7d9dde

File tree

11 files changed

+965
-15
lines changed

11 files changed

+965
-15
lines changed

app/common/public/locales/en/translation.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,5 +295,8 @@
295295
"gestureNameCannotBeEmptyError": "Gesture name cannot be empty",
296296
"gestureInvalidJsonError": "Invalid JSON file. Unable to parse the file content",
297297
"gestureImportedFrom": "Gesture imported from '{{fileName}}'",
298-
"invalidSessionFile": "Invalid session file"
298+
"invalidSessionFile": "Invalid session file",
299+
"Environment Variables": "Environment Variables",
300+
"Variable Name": "Variable Name",
301+
"Delete Variable": "Delete Variable"
299302
}

app/common/renderer/actions/Inspector.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,9 @@ export const TOGGLE_SHOW_ATTRIBUTES = 'TOGGLE_SHOW_ATTRIBUTES';
116116
export const TOGGLE_REFRESHING_STATE = 'TOGGLE_REFRESHING_STATE';
117117

118118
export const SET_GESTURE_UPLOAD_ERROR = 'SET_GESTURE_UPLOAD_ERROR';
119+
export const SET_ENVIRONMENT_VARIABLES = 'SET_ENVIRONMENT_VARIABLES';
120+
export const ADD_ENVIRONMENT_VARIABLE = 'ADD_ENVIRONMENT_VARIABLE';
121+
export const DELETE_ENVIRONMENT_VARIABLE = 'DELETE_ENVIRONMENT_VARIABLE';
119122

120123
const KEEP_ALIVE_PING_INTERVAL = 20 * 1000;
121124
const NO_NEW_COMMAND_LIMIT = 24 * 60 * 60 * 1000; // Set timeout to 24 hours
@@ -919,6 +922,24 @@ export function setGestureUploadErrors(errors) {
919922
};
920923
}
921924

925+
export function setEnvironmentVariables(envVars) {
926+
return (dispatch) => {
927+
dispatch({type: SET_ENVIRONMENT_VARIABLES, envVars});
928+
};
929+
}
930+
931+
export function addEnvironmentVariable(key, value) {
932+
return (dispatch) => {
933+
dispatch({type: ADD_ENVIRONMENT_VARIABLE, key, value});
934+
};
935+
}
936+
937+
export function deleteEnvironmentVariable(key) {
938+
return (dispatch) => {
939+
dispatch({type: DELETE_ENVIRONMENT_VARIABLE, key});
940+
};
941+
}
942+
922943
export function uploadGesturesFromFile(fileList) {
923944
return async (dispatch) => {
924945
const gestures = await readTextFromUploadedFiles(fileList);

app/common/renderer/actions/Session.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import {notification} from 'antd';
22
import {includes, isPlainObject, isUndefined, toPairs, union, values, without} from 'lodash';
3+
import {interpolateEnvironmentVariables} from '../utils/env-utils';
34
import moment from 'moment';
45
import {Web2Driver} from 'web2driver';
56

@@ -229,7 +230,12 @@ export function newSession(caps, attachSessId = null) {
229230

230231
dispatch({type: NEW_SESSION_REQUESTED, caps});
231232

233+
// Get environment variables from state
234+
const environmentVariables = getState().inspector.environmentVariables || [];
235+
236+
// Get capabilities and interpolate environment variables
232237
let desiredCapabilities = caps ? getCapsObject(caps) : {};
238+
desiredCapabilities = interpolateEnvironmentVariables(desiredCapabilities, environmentVariables);
233239
let host, port, username, accessKey, https, path, token;
234240
desiredCapabilities = addCustomCaps(desiredCapabilities);
235241

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import {PlusOutlined, DeleteOutlined} from '@ant-design/icons';
2+
import {Button, Input, Space, Table, Tooltip} from 'antd';
3+
import {useState} from 'react';
4+
import {useDispatch, useSelector} from 'react-redux';
5+
import {setEnvironmentVariables, addEnvironmentVariable, deleteEnvironmentVariable} from '../../actions/Inspector';
6+
import styles from './EnvironmentVariables.module.css';
7+
8+
const EnvironmentVariables = ({t}) => {
9+
const dispatch = useDispatch();
10+
const envVars = useSelector(state => state.inspector.environmentVariables || []);
11+
const [newVar, setNewVar] = useState({key: '', value: ''});
12+
13+
const columns = [
14+
{
15+
title: t('Variable Name'),
16+
dataIndex: 'key',
17+
key: 'key',
18+
width: '40%',
19+
},
20+
{
21+
title: t('Value'),
22+
dataIndex: 'value',
23+
key: 'value',
24+
width: '40%',
25+
render: (text) => <Input.Password value={text} readOnly />,
26+
},
27+
{
28+
title: t('Actions'),
29+
key: 'action',
30+
width: '20%',
31+
render: (_, record) => (
32+
<Tooltip title={t('Delete Variable')}>
33+
<Button
34+
type="text"
35+
danger
36+
icon={<DeleteOutlined />}
37+
onClick={() => {
38+
dispatch(deleteEnvironmentVariable(record.key));
39+
}}
40+
/>
41+
</Tooltip>
42+
),
43+
},
44+
];
45+
46+
const handleAddVariable = () => {
47+
if (!newVar.key || !newVar.value) return;
48+
49+
// Check for duplicate keys
50+
if (envVars.some((v) => v.key === newVar.key)) {
51+
return;
52+
}
53+
54+
dispatch(addEnvironmentVariable(newVar.key, newVar.value));
55+
setNewVar({key: '', value: ''});
56+
};
57+
58+
return (
59+
<div className={styles.container}>
60+
<div className={styles.addForm}>
61+
<Space.Compact style={{width: '100%'}}>
62+
<Input
63+
placeholder={t('Variable Name')}
64+
value={newVar.key}
65+
onChange={(e) => setNewVar({...newVar, key: e.target.value})}
66+
/>
67+
<Input.Password
68+
placeholder={t('Value')}
69+
value={newVar.value}
70+
onChange={(e) => setNewVar({...newVar, value: e.target.value})}
71+
/>
72+
<Button
73+
type="primary"
74+
icon={<PlusOutlined />}
75+
onClick={handleAddVariable}
76+
disabled={!newVar.key || !newVar.value}
77+
>
78+
{t('Add')}
79+
</Button>
80+
</Space.Compact>
81+
</div>
82+
<Table
83+
columns={columns}
84+
dataSource={envVars}
85+
pagination={false}
86+
rowKey="key"
87+
size="small"
88+
/>
89+
</div>
90+
);
91+
};
92+
93+
export default EnvironmentVariables;
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.container {
2+
display: flex;
3+
flex-direction: column;
4+
gap: 16px;
5+
}
6+
7+
.addForm {
8+
padding: 8px 0;
9+
}

app/common/renderer/components/Inspector/Inspector.jsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
import {Button, Card, Modal, Space, Spin, Switch, Tabs, Tooltip} from 'antd';
1616
import {debounce} from 'lodash';
1717
import {useEffect, useRef, useState} from 'react';
18+
import styles from './Inspector.module.css';
1819
import {useNavigate} from 'react-router';
1920

2021
import {BUTTON} from '../../constants/antd-types';
@@ -30,7 +31,6 @@ import {downloadFile} from '../../utils/file-handling';
3031
import Commands from './Commands.jsx';
3132
import GestureEditor from './GestureEditor.jsx';
3233
import HeaderButtons from './HeaderButtons.jsx';
33-
import InspectorStyles from './Inspector.module.css';
3434
import Recorder from './Recorder.jsx';
3535
import SavedGestures from './SavedGestures.jsx';
3636
import Screenshot from './Screenshot.jsx';
@@ -221,7 +221,7 @@ const Inspector = (props) => {
221221
}, [showKeepAlivePrompt]);
222222

223223
const screenShotControls = (
224-
<div className={InspectorStyles['screenshot-controls']}>
224+
<div className={styles['screenshot-controls']}>
225225
<Space size="middle">
226226
<Tooltip
227227
title={t(showCentroids ? 'Hide Element Handles' : 'Show Element Handles')}
@@ -263,22 +263,22 @@ const Inspector = (props) => {
263263
);
264264

265265
const main = (
266-
<div className={InspectorStyles['inspector-main']}>
266+
<div className={styles['inspector-main']}>
267267
<div
268268
id="screenshotContainer"
269-
className={InspectorStyles['screenshot-container']}
269+
className={styles['screenshot-container']}
270270
ref={screenshotContainerEl}
271271
>
272272
{screenShotControls}
273273
{showScreenshot && <Screenshot {...props} scaleRatio={scaleRatio} />}
274274
{screenshotError && t('couldNotObtainScreenshot', {screenshotError})}
275275
{!showScreenshot && (
276276
<Spin size="large" spinning={true}>
277-
<div className={InspectorStyles.screenshotBox} />
277+
<div className={styles.screenshotBox} />
278278
</Spin>
279279
)}
280280
</div>
281-
<div id="sourceTreeContainer" className={InspectorStyles['interaction-tab-container']}>
281+
<div id="sourceTreeContainer" className={styles['interaction-tab-container']}>
282282
<Tabs
283283
activeKey={selectedInspectorTab}
284284
size="small"
@@ -331,15 +331,15 @@ const Inspector = (props) => {
331331
</div>
332332
<div
333333
id="selectedElementContainer"
334-
className={`${InspectorStyles['interaction-tab-container']} ${InspectorStyles['element-detail-container']} action-col`}
334+
className={`${styles['interaction-tab-container']} ${styles['element-detail-container']} action-col`}
335335
>
336336
<Card
337337
title={
338338
<span>
339339
<TagOutlined /> {t('selectedElement')}
340340
</span>
341341
}
342-
className={InspectorStyles['selected-element-card']}
342+
className={styles['selected-element-card']}
343343
>
344344
{selectedElement.path && <SelectedElement {...props} />}
345345
{!selectedElement.path && <i>{t('selectElementInSource')}</i>}
@@ -359,7 +359,7 @@ const Inspector = (props) => {
359359
<ThunderboltOutlined /> {t('Execute Commands')}
360360
</span>
361361
}
362-
className={InspectorStyles['interaction-tab-card']}
362+
className={styles['interaction-tab-card']}
363363
>
364364
<Commands {...props} />
365365
</Card>
@@ -376,7 +376,7 @@ const Inspector = (props) => {
376376
<HighlightOutlined /> {t('Gesture Builder')}
377377
</span>
378378
}
379-
className={InspectorStyles['interaction-tab-card']}
379+
className={styles['interaction-tab-card']}
380380
>
381381
<GestureEditor {...props} />
382382
</Card>
@@ -387,7 +387,7 @@ const Inspector = (props) => {
387387
<HighlightOutlined /> {t('Saved Gestures')}
388388
</span>
389389
}
390-
className={InspectorStyles['interaction-tab-card']}
390+
className={styles['interaction-tab-card']}
391391
>
392392
<SavedGestures {...props} />
393393
</Card>
@@ -410,7 +410,7 @@ const Inspector = (props) => {
410410
<InfoCircleOutlined /> {t('Session Information')}
411411
</span>
412412
}
413-
className={InspectorStyles['interaction-tab-card']}
413+
className={styles['interaction-tab-card']}
414414
>
415415
<SessionInfo {...props} />
416416
</Card>
@@ -423,7 +423,7 @@ const Inspector = (props) => {
423423
);
424424

425425
return (
426-
<div className={InspectorStyles['inspector-container']}>
426+
<div className={styles['inspector-container']}>
427427
<HeaderButtons quitCurrentSession={quitCurrentSession} {...props} />
428428
{main}
429429
<Modal

0 commit comments

Comments
 (0)