@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 { PlusOutlined, QuestionCircleOutlined, MinusCircleFilled, UserOutlined } from '@ant-design/icons'
13
- import { formItemLayout, tailFormItemLayout } from '../../../common/form-layout'
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 [initialValues] = useState({
30
- sshTunnel: 'forwardRemoteToLocal',
31
- sshTunnelLocalPort: 12200,
32
- sshTunnelLocalHost: '127.0.0.1',
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
- data
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('del'),
134
+ title: e('op'),
112
135
  key: 'op',
113
136
  dataIndex: 'id',
114
- render: (id) => {
137
+ render: (id, record) => {
115
138
  return (
116
- <MinusCircleFilled
117
- className='pointer'
118
- onClick={() => remove(id)}
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
- <Form
209
- form={formChild}
210
- onFinish={handleFinish}
181
+ {renderList()}
182
+ <SshTunnelForm
183
+ formChild={formChild}
211
184
  initialValues={initialValues}
212
- component='div'
213
- >
214
- {renderList()}
215
- <FormItem
216
- label={e('sshTunnel')}
217
- name='sshTunnel'
218
- {...formItemLayout}
219
- defaultValue='forwardRemoteToLocal'
220
- required
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
- <Input
282
- placeholder={e('name')}
195
+ <SshTunnelForm
196
+ key={editingItem?.id}
197
+ formChild={editFormChild}
198
+ initialValues={editingItem}
199
+ onFinish={handleEditFinish}
200
+ isEdit
283
201
  />
284
- </FormItem>
285
- <FormItem {...tailFormItemLayout} className='mg60b'>
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
  }
@@ -28,7 +28,8 @@ const {
28
28
  const downloadMirrorList = [
29
29
  'github',
30
30
  'gh-proxy',
31
- 'sourceforge'
31
+ 'sourceforge',
32
+ 'r2'
32
33
  ]
33
34
 
34
35
  export default class Upgrade extends PureComponent {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "3.6.6",
3
+ "version": "3.6.16",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",