@electerm/electerm-react 3.6.6 → 3.6.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Form,
|
|
3
|
+
Input,
|
|
4
|
+
InputNumber,
|
|
5
|
+
Radio,
|
|
6
|
+
Space,
|
|
7
|
+
Button,
|
|
8
|
+
Tooltip
|
|
9
|
+
} from 'antd'
|
|
10
|
+
import {
|
|
11
|
+
PlusOutlined,
|
|
12
|
+
QuestionCircleOutlined,
|
|
13
|
+
SaveOutlined,
|
|
14
|
+
UserOutlined
|
|
15
|
+
} from '@ant-design/icons'
|
|
16
|
+
import { formItemLayout, tailFormItemLayout } from '../../../common/form-layout'
|
|
17
|
+
import { useState } from 'react'
|
|
18
|
+
|
|
19
|
+
const FormItem = Form.Item
|
|
20
|
+
const {
|
|
21
|
+
Button: RadioButton,
|
|
22
|
+
Group: RadioGroup
|
|
23
|
+
} = Radio
|
|
24
|
+
const e = window.translate
|
|
25
|
+
|
|
26
|
+
export default function SshTunnelForm (props) {
|
|
27
|
+
const {
|
|
28
|
+
formChild,
|
|
29
|
+
initialValues,
|
|
30
|
+
onFinish,
|
|
31
|
+
isEdit
|
|
32
|
+
} = props
|
|
33
|
+
|
|
34
|
+
const [isDynamic, setIsDynamic] = useState(
|
|
35
|
+
(initialValues?.sshTunnel || 'forwardRemoteToLocal') === 'dynamicForward'
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
function onChange (ev) {
|
|
39
|
+
setIsDynamic(ev.target.value === 'dynamicForward')
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function onSubmit () {
|
|
43
|
+
formChild.submit()
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function renderSshTunnelFlow (direction) {
|
|
47
|
+
const localToRemote = direction === 'localToRemote'
|
|
48
|
+
const middle = localToRemote ? e('local') : e('remote')
|
|
49
|
+
const last = localToRemote ? e('remote') : e('local')
|
|
50
|
+
return (
|
|
51
|
+
<div>
|
|
52
|
+
<p>{e(direction)}</p>
|
|
53
|
+
<p><UserOutlined /> → {middle} → {last}</p>
|
|
54
|
+
</div>
|
|
55
|
+
)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function renderDynamicForward () {
|
|
59
|
+
return (
|
|
60
|
+
<p><UserOutlined /> → socks proxy → url</p>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function renderRemote () {
|
|
65
|
+
if (isDynamic) {
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
return (
|
|
69
|
+
<FormItem
|
|
70
|
+
label={e('remote')}
|
|
71
|
+
{...formItemLayout}
|
|
72
|
+
required
|
|
73
|
+
className='ssh-tunnels-host'
|
|
74
|
+
>
|
|
75
|
+
<Space.Compact>
|
|
76
|
+
<FormItem
|
|
77
|
+
name='sshTunnelRemoteHost'
|
|
78
|
+
label=''
|
|
79
|
+
required
|
|
80
|
+
>
|
|
81
|
+
<Input
|
|
82
|
+
placeholder={e('host')}
|
|
83
|
+
/>
|
|
84
|
+
</FormItem>
|
|
85
|
+
<FormItem
|
|
86
|
+
label=''
|
|
87
|
+
name='sshTunnelRemotePort'
|
|
88
|
+
required
|
|
89
|
+
>
|
|
90
|
+
<InputNumber
|
|
91
|
+
min={1}
|
|
92
|
+
max={65535}
|
|
93
|
+
placeholder={e('port')}
|
|
94
|
+
/>
|
|
95
|
+
</FormItem>
|
|
96
|
+
</Space.Compact>
|
|
97
|
+
</FormItem>
|
|
98
|
+
)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return (
|
|
102
|
+
<Form
|
|
103
|
+
form={formChild}
|
|
104
|
+
onFinish={onFinish}
|
|
105
|
+
initialValues={initialValues}
|
|
106
|
+
component='div'
|
|
107
|
+
>
|
|
108
|
+
<FormItem
|
|
109
|
+
label={e('sshTunnel')}
|
|
110
|
+
name='sshTunnel'
|
|
111
|
+
{...formItemLayout}
|
|
112
|
+
required
|
|
113
|
+
>
|
|
114
|
+
<RadioGroup onChange={onChange}>
|
|
115
|
+
<RadioButton value='forwardRemoteToLocal'>
|
|
116
|
+
<Tooltip title={renderSshTunnelFlow('remoteToLocal')}>
|
|
117
|
+
<span>R→L <QuestionCircleOutlined /></span>
|
|
118
|
+
</Tooltip>
|
|
119
|
+
</RadioButton>
|
|
120
|
+
<RadioButton value='forwardLocalToRemote'>
|
|
121
|
+
<Tooltip title={renderSshTunnelFlow('localToRemote')}>
|
|
122
|
+
<span>L→R <QuestionCircleOutlined /></span>
|
|
123
|
+
</Tooltip>
|
|
124
|
+
</RadioButton>
|
|
125
|
+
<RadioButton value='dynamicForward'>
|
|
126
|
+
<Tooltip title={renderDynamicForward()}>
|
|
127
|
+
<span>{e('dynamicForward')}(socks proxy) <QuestionCircleOutlined /></span>
|
|
128
|
+
</Tooltip>
|
|
129
|
+
</RadioButton>
|
|
130
|
+
</RadioGroup>
|
|
131
|
+
</FormItem>
|
|
132
|
+
{renderRemote()}
|
|
133
|
+
<FormItem
|
|
134
|
+
label={e('local')}
|
|
135
|
+
{...formItemLayout}
|
|
136
|
+
required
|
|
137
|
+
className='ssh-tunnels-host'
|
|
138
|
+
>
|
|
139
|
+
<Space.Compact>
|
|
140
|
+
<FormItem
|
|
141
|
+
name='sshTunnelLocalHost'
|
|
142
|
+
label=''
|
|
143
|
+
required
|
|
144
|
+
>
|
|
145
|
+
<Input
|
|
146
|
+
placeholder={e('host')}
|
|
147
|
+
/>
|
|
148
|
+
</FormItem>
|
|
149
|
+
<FormItem
|
|
150
|
+
label=''
|
|
151
|
+
name='sshTunnelLocalPort'
|
|
152
|
+
required
|
|
153
|
+
>
|
|
154
|
+
<InputNumber
|
|
155
|
+
min={1}
|
|
156
|
+
max={65535}
|
|
157
|
+
placeholder={e('port')}
|
|
158
|
+
/>
|
|
159
|
+
</FormItem>
|
|
160
|
+
</Space.Compact>
|
|
161
|
+
</FormItem>
|
|
162
|
+
<FormItem
|
|
163
|
+
name='name'
|
|
164
|
+
label={e('name')}
|
|
165
|
+
{...formItemLayout}
|
|
166
|
+
>
|
|
167
|
+
<Input
|
|
168
|
+
placeholder={e('name')}
|
|
169
|
+
/>
|
|
170
|
+
</FormItem>
|
|
171
|
+
<FormItem {...tailFormItemLayout} className='mg60b'>
|
|
172
|
+
<Button
|
|
173
|
+
type='default'
|
|
174
|
+
htmlType='button'
|
|
175
|
+
icon={isEdit ? <SaveOutlined /> : <PlusOutlined />}
|
|
176
|
+
onClick={onSubmit}
|
|
177
|
+
>
|
|
178
|
+
{isEdit ? e('save') : e('sshTunnel')}
|
|
179
|
+
</Button>
|
|
180
|
+
</FormItem>
|
|
181
|
+
</Form>
|
|
182
|
+
)
|
|
183
|
+
}
|
|
@@ -1,46 +1,37 @@
|
|
|
1
1
|
import {
|
|
2
2
|
Form,
|
|
3
3
|
Input,
|
|
4
|
-
InputNumber,
|
|
5
|
-
Radio,
|
|
6
|
-
Space,
|
|
7
|
-
Button,
|
|
8
|
-
Tooltip,
|
|
9
4
|
Table
|
|
10
5
|
} from 'antd'
|
|
11
6
|
import { useState } from 'react'
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
7
|
+
import { MinusCircleFilled, EditOutlined } from '@ant-design/icons'
|
|
8
|
+
import { tailFormItemLayout } from '../../../common/form-layout'
|
|
14
9
|
import uid from '../../../common/uid'
|
|
10
|
+
import Modal from '../../common/modal'
|
|
11
|
+
import SshTunnelForm from './ssh-tunnel-form'
|
|
15
12
|
|
|
16
13
|
const FormItem = Form.Item
|
|
17
|
-
const {
|
|
18
|
-
Button: RadioButton,
|
|
19
|
-
Group: RadioGroup
|
|
20
|
-
} = Radio
|
|
21
14
|
const e = window.translate
|
|
22
15
|
|
|
16
|
+
const defaultInitialValues = {
|
|
17
|
+
sshTunnel: 'forwardRemoteToLocal',
|
|
18
|
+
sshTunnelLocalPort: 12200,
|
|
19
|
+
sshTunnelLocalHost: '127.0.0.1',
|
|
20
|
+
sshTunnelRemotePort: 12300,
|
|
21
|
+
sshTunnelRemoteHost: '127.0.0.1'
|
|
22
|
+
}
|
|
23
|
+
|
|
23
24
|
export default function renderSshTunnels (props) {
|
|
24
25
|
const {
|
|
25
26
|
form,
|
|
26
27
|
formData
|
|
27
28
|
} = props
|
|
28
29
|
const [formChild] = Form.useForm()
|
|
29
|
-
const [
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
sshTunnelRemotePort: 12300,
|
|
34
|
-
sshTunnelRemoteHost: '127.0.0.1'
|
|
35
|
-
})
|
|
36
|
-
const [isDynamic, setter] = useState(formData.sshTunnel === 'dynamicForward')
|
|
30
|
+
const [editFormChild] = Form.useForm()
|
|
31
|
+
const [initialValues] = useState(defaultInitialValues)
|
|
32
|
+
const [editModalVisible, setEditModalVisible] = useState(false)
|
|
33
|
+
const [editingItem, setEditingItem] = useState(null)
|
|
37
34
|
const [list, setList] = useState(formData.sshTunnels || [])
|
|
38
|
-
function onSubmit () {
|
|
39
|
-
formChild.submit()
|
|
40
|
-
}
|
|
41
|
-
function onChange (e) {
|
|
42
|
-
setter(e.target.value === 'dynamicForward')
|
|
43
|
-
}
|
|
44
35
|
function handleFinish (data) {
|
|
45
36
|
const nd = {
|
|
46
37
|
...data,
|
|
@@ -56,7 +47,7 @@ export default function renderSshTunnels (props) {
|
|
|
56
47
|
setList(old => {
|
|
57
48
|
return [
|
|
58
49
|
...old,
|
|
59
|
-
|
|
50
|
+
nd
|
|
60
51
|
]
|
|
61
52
|
})
|
|
62
53
|
formChild.resetFields()
|
|
@@ -72,6 +63,38 @@ export default function renderSshTunnels (props) {
|
|
|
72
63
|
})
|
|
73
64
|
formChild.resetFields()
|
|
74
65
|
}
|
|
66
|
+
|
|
67
|
+
function openEdit (record) {
|
|
68
|
+
setEditingItem(record)
|
|
69
|
+
setEditModalVisible(true)
|
|
70
|
+
setTimeout(() => {
|
|
71
|
+
editFormChild.setFieldsValue(record)
|
|
72
|
+
}, 100)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function handleEditFinish (data) {
|
|
76
|
+
const updatedItem = {
|
|
77
|
+
...data,
|
|
78
|
+
id: editingItem.id
|
|
79
|
+
}
|
|
80
|
+
setList(old => old.map(item => item.id === editingItem.id ? updatedItem : item))
|
|
81
|
+
const v = (form.getFieldValue('sshTunnels') || []).map(
|
|
82
|
+
item => item.id === editingItem.id ? updatedItem : item
|
|
83
|
+
)
|
|
84
|
+
form.setFieldsValue({
|
|
85
|
+
sshTunnels: v
|
|
86
|
+
})
|
|
87
|
+
setEditModalVisible(false)
|
|
88
|
+
setEditingItem(null)
|
|
89
|
+
editFormChild.resetFields()
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function closeEditModal () {
|
|
93
|
+
setEditModalVisible(false)
|
|
94
|
+
setEditingItem(null)
|
|
95
|
+
editFormChild.resetFields()
|
|
96
|
+
}
|
|
97
|
+
|
|
75
98
|
const cols = [
|
|
76
99
|
{
|
|
77
100
|
title: 'NO.',
|
|
@@ -108,15 +131,21 @@ export default function renderSshTunnels (props) {
|
|
|
108
131
|
)
|
|
109
132
|
}
|
|
110
133
|
}, {
|
|
111
|
-
title: e('
|
|
134
|
+
title: e('op'),
|
|
112
135
|
key: 'op',
|
|
113
136
|
dataIndex: 'id',
|
|
114
|
-
render: (id) => {
|
|
137
|
+
render: (id, record) => {
|
|
115
138
|
return (
|
|
116
|
-
<
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
139
|
+
<span>
|
|
140
|
+
<EditOutlined
|
|
141
|
+
className='pointer mg1r'
|
|
142
|
+
onClick={() => openEdit(record)}
|
|
143
|
+
/>
|
|
144
|
+
<MinusCircleFilled
|
|
145
|
+
className='pointer'
|
|
146
|
+
onClick={() => remove(id)}
|
|
147
|
+
/>
|
|
148
|
+
</span>
|
|
120
149
|
)
|
|
121
150
|
}
|
|
122
151
|
}
|
|
@@ -141,62 +170,6 @@ export default function renderSshTunnels (props) {
|
|
|
141
170
|
)
|
|
142
171
|
}
|
|
143
172
|
|
|
144
|
-
// direction = localToRemote or remoteToLocal, should render user, remote port, local port visit directions connected with arrows accordingly
|
|
145
|
-
function renderSshTunnelFlow (direction) {
|
|
146
|
-
const localToRemote = direction === 'localToRemote'
|
|
147
|
-
const middle = localToRemote ? e('local') : e('remote')
|
|
148
|
-
const last = localToRemote ? e('remote') : e('local')
|
|
149
|
-
return (
|
|
150
|
-
<div>
|
|
151
|
-
<p>{e(direction)}</p>
|
|
152
|
-
<p><UserOutlined /> → {middle} → {last}</p>
|
|
153
|
-
</div>
|
|
154
|
-
)
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
function renderDynamicForward () {
|
|
158
|
-
return (
|
|
159
|
-
<p><UserOutlined /> → socks proxy → url</p>
|
|
160
|
-
)
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
function renderRemote () {
|
|
164
|
-
if (isDynamic) {
|
|
165
|
-
return null
|
|
166
|
-
}
|
|
167
|
-
return (
|
|
168
|
-
<FormItem
|
|
169
|
-
label={e('remote')}
|
|
170
|
-
{...formItemLayout}
|
|
171
|
-
required
|
|
172
|
-
className='ssh-tunnels-host'
|
|
173
|
-
>
|
|
174
|
-
<Space.Compact>
|
|
175
|
-
<FormItem
|
|
176
|
-
name='sshTunnelRemoteHost'
|
|
177
|
-
label=''
|
|
178
|
-
required
|
|
179
|
-
>
|
|
180
|
-
<Input
|
|
181
|
-
placeholder={e('host')}
|
|
182
|
-
/>
|
|
183
|
-
</FormItem>
|
|
184
|
-
<FormItem
|
|
185
|
-
label=''
|
|
186
|
-
name='sshTunnelRemotePort'
|
|
187
|
-
required
|
|
188
|
-
>
|
|
189
|
-
<InputNumber
|
|
190
|
-
min={1}
|
|
191
|
-
max={65535}
|
|
192
|
-
placeholder={e('port')}
|
|
193
|
-
/>
|
|
194
|
-
</FormItem>
|
|
195
|
-
</Space.Compact>
|
|
196
|
-
</FormItem>
|
|
197
|
-
)
|
|
198
|
-
}
|
|
199
|
-
|
|
200
173
|
return (
|
|
201
174
|
<>
|
|
202
175
|
<FormItem
|
|
@@ -205,94 +178,29 @@ export default function renderSshTunnels (props) {
|
|
|
205
178
|
>
|
|
206
179
|
<Input />
|
|
207
180
|
</FormItem>
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
181
|
+
{renderList()}
|
|
182
|
+
<SshTunnelForm
|
|
183
|
+
formChild={formChild}
|
|
211
184
|
initialValues={initialValues}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
<
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
{
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
>
|
|
222
|
-
<RadioGroup onChange={onChange}>
|
|
223
|
-
<RadioButton
|
|
224
|
-
value='forwardRemoteToLocal'
|
|
225
|
-
>
|
|
226
|
-
<Tooltip title={renderSshTunnelFlow('remoteToLocal')}>
|
|
227
|
-
<span>R→L <QuestionCircleOutlined /></span>
|
|
228
|
-
</Tooltip>
|
|
229
|
-
</RadioButton>
|
|
230
|
-
<RadioButton
|
|
231
|
-
value='forwardLocalToRemote'
|
|
232
|
-
>
|
|
233
|
-
<Tooltip title={renderSshTunnelFlow('localToRemote')}>
|
|
234
|
-
<span>L→R <QuestionCircleOutlined /></span>
|
|
235
|
-
</Tooltip>
|
|
236
|
-
</RadioButton>
|
|
237
|
-
<RadioButton
|
|
238
|
-
value='dynamicForward'
|
|
239
|
-
>
|
|
240
|
-
<Tooltip title={renderDynamicForward()}>
|
|
241
|
-
<span>{e('dynamicForward')}(socks proxy) <QuestionCircleOutlined /></span>
|
|
242
|
-
</Tooltip>
|
|
243
|
-
</RadioButton>
|
|
244
|
-
</RadioGroup>
|
|
245
|
-
</FormItem>
|
|
246
|
-
{renderRemote()}
|
|
247
|
-
<FormItem
|
|
248
|
-
label={e('local')}
|
|
249
|
-
{...formItemLayout}
|
|
250
|
-
required
|
|
251
|
-
className='ssh-tunnels-host'
|
|
252
|
-
>
|
|
253
|
-
<Space.Compact>
|
|
254
|
-
<FormItem
|
|
255
|
-
name='sshTunnelLocalHost'
|
|
256
|
-
label=''
|
|
257
|
-
required
|
|
258
|
-
>
|
|
259
|
-
<Input
|
|
260
|
-
placeholder={e('host')}
|
|
261
|
-
/>
|
|
262
|
-
</FormItem>
|
|
263
|
-
<FormItem
|
|
264
|
-
label=''
|
|
265
|
-
name='sshTunnelLocalPort'
|
|
266
|
-
required
|
|
267
|
-
>
|
|
268
|
-
<InputNumber
|
|
269
|
-
min={1}
|
|
270
|
-
max={65535}
|
|
271
|
-
placeholder={e('port')}
|
|
272
|
-
/>
|
|
273
|
-
</FormItem>
|
|
274
|
-
</Space.Compact>
|
|
275
|
-
</FormItem>
|
|
276
|
-
<FormItem
|
|
277
|
-
name='name'
|
|
278
|
-
label={e('name')}
|
|
279
|
-
{...formItemLayout}
|
|
185
|
+
onFinish={handleFinish}
|
|
186
|
+
/>
|
|
187
|
+
{editModalVisible && (
|
|
188
|
+
<Modal
|
|
189
|
+
open={editModalVisible}
|
|
190
|
+
onCancel={closeEditModal}
|
|
191
|
+
footer={null}
|
|
192
|
+
title={e('edit') + ' ' + e('sshTunnel')}
|
|
193
|
+
width={600}
|
|
280
194
|
>
|
|
281
|
-
<
|
|
282
|
-
|
|
195
|
+
<SshTunnelForm
|
|
196
|
+
key={editingItem?.id}
|
|
197
|
+
formChild={editFormChild}
|
|
198
|
+
initialValues={editingItem}
|
|
199
|
+
onFinish={handleEditFinish}
|
|
200
|
+
isEdit
|
|
283
201
|
/>
|
|
284
|
-
</
|
|
285
|
-
|
|
286
|
-
<Button
|
|
287
|
-
type='default'
|
|
288
|
-
htmlType='button'
|
|
289
|
-
icon={<PlusOutlined />}
|
|
290
|
-
onClick={onSubmit}
|
|
291
|
-
>
|
|
292
|
-
{e('sshTunnel')}
|
|
293
|
-
</Button>
|
|
294
|
-
</FormItem>
|
|
295
|
-
</Form>
|
|
202
|
+
</Modal>
|
|
203
|
+
)}
|
|
296
204
|
</>
|
|
297
205
|
)
|
|
298
206
|
}
|