@electerm/electerm-react 1.38.65 → 1.38.80
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.
- package/client/common/constants.js +6 -3
- package/client/common/create-title.jsx +9 -1
- package/client/common/sftp.js +3 -0
- package/client/components/batch-op/batch-op.jsx +1 -6
- package/client/components/bookmark-form/bookmark-form.styl +3 -1
- package/client/components/bookmark-form/index.jsx +12 -8
- package/client/components/bookmark-form/render-ssh-tunnel.jsx +210 -88
- package/client/components/bookmark-form/ssh-form-ui.jsx +1 -1
- package/client/components/bookmark-form/web-form-ui.jsx +96 -0
- package/client/components/bookmark-form/web-form.jsx +16 -0
- package/client/components/main/main.jsx +14 -0
- package/client/components/quick-commands/qm.styl +1 -1
- package/client/components/session/session.styl +4 -1
- package/client/components/session/sessions.jsx +16 -2
- package/client/components/session/web-session.jsx +20 -0
- package/client/components/sftp/{confirm-modal.jsx → confirm-modal-store.jsx} +81 -50
- package/client/components/sftp/file-item.jsx +2 -0
- package/client/components/sftp/sftp-entry.jsx +27 -37
- package/client/components/sftp/transfer-conflict-store.jsx +291 -0
- package/client/components/sftp/transport-action-store.jsx +430 -0
- package/client/components/sftp/transports-action-store.jsx +102 -0
- package/client/components/sftp/transports-ui-store.jsx +30 -0
- package/client/components/sidebar/transfer-list-control.jsx +5 -14
- package/client/components/sidebar/transport-ui.jsx +2 -12
- package/client/components/tabs/tab.jsx +43 -2
- package/client/components/tabs/tabs.styl +1 -1
- package/client/components/terminal/index.jsx +14 -1
- package/client/components/terminal/terminal-interactive.jsx +15 -0
- package/client/components/terminal-info/disk.jsx +9 -0
- package/client/entry/worker.js +5 -1
- package/client/store/index.js +16 -1
- package/client/store/init-state.js +2 -3
- package/client/store/sync.js +5 -2
- package/client/store/tab.js +1 -1
- package/client/store/transfer-list.js +55 -2
- package/client/store/watch.js +0 -8
- package/package.json +1 -1
- package/client/components/sftp/transfer-conflict.jsx +0 -323
- package/client/components/sftp/transport-action.jsx +0 -412
- package/client/components/sftp/transport-entry.jsx +0 -108
- package/client/components/sftp/transport-types.js +0 -8
- package/client/components/sftp/transports-action.jsx +0 -111
- package/client/components/sftp/transports-ui.jsx +0 -93
|
@@ -38,7 +38,7 @@ export const contextMenuPaddingTop = 10
|
|
|
38
38
|
export const sftpControlHeight = 28 + 42 + 33 + 36
|
|
39
39
|
export const sidebarWidth = 43
|
|
40
40
|
export const maxHistory = 50
|
|
41
|
-
export const maxTransport =
|
|
41
|
+
export const maxTransport = 1
|
|
42
42
|
export const maxSftpHistory = 20
|
|
43
43
|
export const maxZoom = 8
|
|
44
44
|
export const minZoom = 0.5
|
|
@@ -66,7 +66,8 @@ export const connectionMap = buildConst([
|
|
|
66
66
|
'ssh',
|
|
67
67
|
'telnet',
|
|
68
68
|
'serial',
|
|
69
|
-
'local'
|
|
69
|
+
'local',
|
|
70
|
+
'web'
|
|
70
71
|
])
|
|
71
72
|
|
|
72
73
|
export const authTypeMap = buildConst([
|
|
@@ -131,6 +132,7 @@ export const terminalSplitDirectionMap = buildConst([
|
|
|
131
132
|
])
|
|
132
133
|
|
|
133
134
|
export const terminalSshConfigType = 'ssh-config'
|
|
135
|
+
export const terminalWebType = 'web'
|
|
134
136
|
export const terminalSerialType = 'serial'
|
|
135
137
|
export const terminalTelnetType = 'telnet'
|
|
136
138
|
export const terminalLocalType = 'local'
|
|
@@ -278,7 +280,8 @@ export const commonActions = {
|
|
|
278
280
|
closeContextMenu: 'close-context-menu',
|
|
279
281
|
clickContextMenu: 'click-context-menu',
|
|
280
282
|
openContextMenu: 'open-context-menu',
|
|
281
|
-
addTransfer: 'add-transfer'
|
|
283
|
+
addTransfer: 'add-transfer',
|
|
284
|
+
sftpList: 'sftp-list'
|
|
282
285
|
}
|
|
283
286
|
|
|
284
287
|
export const srcsSkipUpgradeCheck = [
|
|
@@ -15,7 +15,7 @@ export default function createTitle (res) {
|
|
|
15
15
|
}
|
|
16
16
|
const {
|
|
17
17
|
host, port, username, title, type,
|
|
18
|
-
path, connectionHoppings
|
|
18
|
+
path, connectionHoppings, sshTunnels
|
|
19
19
|
} = res
|
|
20
20
|
const fixTitle = `${username || ''}@${host}:${port}`
|
|
21
21
|
const extra = host || path ? (path || fixTitle) : ''
|
|
@@ -25,6 +25,14 @@ export default function createTitle (res) {
|
|
|
25
25
|
if (connectionHoppings && connectionHoppings.length) {
|
|
26
26
|
f = `[⋙]${f}`
|
|
27
27
|
}
|
|
28
|
+
if (
|
|
29
|
+
sshTunnels &&
|
|
30
|
+
sshTunnels.length &&
|
|
31
|
+
sshTunnels[0].sshTunnel &&
|
|
32
|
+
sshTunnels[0].sshTunnelRemoteHost
|
|
33
|
+
) {
|
|
34
|
+
f = `[T]${f}`
|
|
35
|
+
}
|
|
28
36
|
if (type) {
|
|
29
37
|
f = `[${type}]${f}`
|
|
30
38
|
}
|
package/client/common/sftp.js
CHANGED
|
@@ -7,6 +7,7 @@ import Transfer from './transfer'
|
|
|
7
7
|
import { transferTypeMap, instSftpKeys as keys } from './constants'
|
|
8
8
|
import initWs from './ws'
|
|
9
9
|
|
|
10
|
+
window.sftps = {}
|
|
10
11
|
const transferKeys = Object.keys(transferTypeMap)
|
|
11
12
|
|
|
12
13
|
class Sftp {
|
|
@@ -56,6 +57,7 @@ class Sftp {
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
async destroy () {
|
|
60
|
+
delete window.sftps[this.sessionId]
|
|
59
61
|
const { ws } = this
|
|
60
62
|
ws.s({
|
|
61
63
|
action: 'sftp-destroy',
|
|
@@ -69,5 +71,6 @@ class Sftp {
|
|
|
69
71
|
export default async (sessionId) => {
|
|
70
72
|
const sftp = new Sftp()
|
|
71
73
|
await sftp.init(sessionId)
|
|
74
|
+
window.sftps[sessionId] = sftp
|
|
72
75
|
return sftp
|
|
73
76
|
}
|
|
@@ -26,7 +26,6 @@ import { autoRun } from 'manate'
|
|
|
26
26
|
import { pick } from 'lodash-es'
|
|
27
27
|
import { runCmd } from '../terminal/terminal-apis'
|
|
28
28
|
import deepCopy from 'json-deep-copy'
|
|
29
|
-
import postMsg from '../../common/post-msg'
|
|
30
29
|
import uid from '../../common/uid'
|
|
31
30
|
import wait from '../../common/wait'
|
|
32
31
|
import { getFolderFromFilePath } from '../sftp/file-read'
|
|
@@ -186,11 +185,7 @@ export default class BatchOp extends Component {
|
|
|
186
185
|
zip: true,
|
|
187
186
|
skipConfirm: true
|
|
188
187
|
}
|
|
189
|
-
|
|
190
|
-
list: [obj],
|
|
191
|
-
action: commonActions.addTransfer,
|
|
192
|
-
sessionId: tab.sessionId
|
|
193
|
-
})
|
|
188
|
+
window.store.addTransferList([obj])
|
|
194
189
|
const { store } = window
|
|
195
190
|
this.tm = setTimeout(() => {
|
|
196
191
|
reject(new Error('timeout'))
|
|
@@ -9,6 +9,7 @@ import {
|
|
|
9
9
|
settingMap,
|
|
10
10
|
connectionMap,
|
|
11
11
|
terminalSerialType,
|
|
12
|
+
terminalWebType,
|
|
12
13
|
terminalLocalType,
|
|
13
14
|
terminalTelnetType,
|
|
14
15
|
newBookmarkIdPrefix
|
|
@@ -17,6 +18,7 @@ import SshForm from './ssh-form'
|
|
|
17
18
|
import SerialForm from './serial-form'
|
|
18
19
|
import LocalForm from './local-form'
|
|
19
20
|
import TelnetForm from './telnet-form'
|
|
21
|
+
import WebForm from './web-form'
|
|
20
22
|
import { createTitleWithTag } from '../../common/create-title'
|
|
21
23
|
import {
|
|
22
24
|
LoadingOutlined,
|
|
@@ -33,13 +35,14 @@ export default class BookmarkIndex extends Component {
|
|
|
33
35
|
constructor (props) {
|
|
34
36
|
super(props)
|
|
35
37
|
let initType = props.formData.type
|
|
36
|
-
if (
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
if (
|
|
39
|
+
![
|
|
40
|
+
terminalTelnetType,
|
|
41
|
+
terminalWebType,
|
|
42
|
+
terminalLocalType,
|
|
43
|
+
terminalSerialType
|
|
44
|
+
].includes(initType)
|
|
45
|
+
) {
|
|
43
46
|
initType = connectionMap.ssh
|
|
44
47
|
}
|
|
45
48
|
this.state = {
|
|
@@ -64,7 +67,8 @@ export default class BookmarkIndex extends Component {
|
|
|
64
67
|
[connectionMap.ssh]: SshForm,
|
|
65
68
|
[connectionMap.telnet]: TelnetForm,
|
|
66
69
|
[connectionMap.serial]: SerialForm,
|
|
67
|
-
[connectionMap.local]: LocalForm
|
|
70
|
+
[connectionMap.local]: LocalForm,
|
|
71
|
+
[connectionMap.web]: WebForm
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
handleChange = (e) => {
|
|
@@ -5,30 +5,154 @@ import {
|
|
|
5
5
|
Radio,
|
|
6
6
|
Space,
|
|
7
7
|
Button,
|
|
8
|
-
Tooltip
|
|
8
|
+
Tooltip,
|
|
9
|
+
Table
|
|
9
10
|
} from 'antd'
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
11
|
+
import { useState } from 'react'
|
|
12
|
+
import { PlusOutlined, QuestionCircleOutlined, MinusCircleFilled } from '@ant-design/icons'
|
|
13
|
+
import { formItemLayout, tailFormItemLayout } from '../../common/form-layout'
|
|
14
|
+
import uid from '../../common/uid'
|
|
12
15
|
|
|
13
16
|
const FormItem = Form.Item
|
|
14
|
-
const FormList = Form.List
|
|
15
17
|
const {
|
|
16
18
|
Button: RadioButton,
|
|
17
19
|
Group: RadioGroup
|
|
18
20
|
} = Radio
|
|
19
21
|
const { prefix } = window
|
|
20
22
|
const e = prefix('ssh')
|
|
23
|
+
const s = prefix('sftp')
|
|
24
|
+
const m = prefix('menu')
|
|
21
25
|
|
|
22
|
-
export default function
|
|
23
|
-
|
|
26
|
+
export default function renderSshTunnels (props) {
|
|
27
|
+
const {
|
|
28
|
+
form,
|
|
29
|
+
formData
|
|
30
|
+
} = props
|
|
31
|
+
const [formChild] = Form.useForm()
|
|
32
|
+
const [initialValues] = useState({
|
|
33
|
+
sshTunnelLocalPort: 12200,
|
|
34
|
+
sshTunnelLocalHost: '127.0.0.1',
|
|
35
|
+
sshTunnelRemotePort: 12300,
|
|
36
|
+
sshTunnelRemoteHost: '127.0.0.1'
|
|
37
|
+
})
|
|
38
|
+
const [list, setList] = useState(formData.sshTunnels || [])
|
|
39
|
+
function onSubmit () {
|
|
40
|
+
formChild.submit()
|
|
41
|
+
}
|
|
42
|
+
function handleFinish (data) {
|
|
43
|
+
const nd = {
|
|
44
|
+
...data,
|
|
45
|
+
id: uid()
|
|
46
|
+
}
|
|
47
|
+
const v = [
|
|
48
|
+
...form.getFieldValue('sshTunnels'),
|
|
49
|
+
nd
|
|
50
|
+
]
|
|
51
|
+
form.setFieldsValue({
|
|
52
|
+
sshTunnels: v
|
|
53
|
+
})
|
|
54
|
+
setList(old => {
|
|
55
|
+
return [
|
|
56
|
+
...old,
|
|
57
|
+
data
|
|
58
|
+
]
|
|
59
|
+
})
|
|
60
|
+
formChild.resetFields()
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function remove (id) {
|
|
64
|
+
setList(old => {
|
|
65
|
+
return old.filter(i => i.id !== id)
|
|
66
|
+
})
|
|
67
|
+
const v = form.getFieldValue('sshTunnels').filter(i => i.id !== id)
|
|
68
|
+
form.setFieldsValue({
|
|
69
|
+
sshTunnels: v
|
|
70
|
+
})
|
|
71
|
+
formChild.resetFields()
|
|
72
|
+
}
|
|
73
|
+
const cols = [
|
|
74
|
+
{
|
|
75
|
+
title: 'NO.',
|
|
76
|
+
dataIndex: 'index',
|
|
77
|
+
key: 'index',
|
|
78
|
+
render: (k) => k
|
|
79
|
+
}, {
|
|
80
|
+
title: e('sshTunnel'),
|
|
81
|
+
key: 'sshTunnel',
|
|
82
|
+
render: (k, item) => {
|
|
83
|
+
// sshTunnel is forwardRemoteToLocal or forwardLocalToRemote
|
|
84
|
+
const {
|
|
85
|
+
sshTunnel,
|
|
86
|
+
sshTunnelRemoteHost = '127.0.0.1',
|
|
87
|
+
sshTunnelRemotePort,
|
|
88
|
+
sshTunnelLocalHost = '127.0.0.1',
|
|
89
|
+
sshTunnelLocalPort,
|
|
90
|
+
name
|
|
91
|
+
} = item
|
|
92
|
+
const to = sshTunnel === 'forwardRemoteToLocal'
|
|
93
|
+
? `${s('local')}:${sshTunnelLocalHost}:${sshTunnelLocalPort}`
|
|
94
|
+
: `${s('remote')}:${sshTunnelRemoteHost}:${sshTunnelRemotePort}`
|
|
95
|
+
const from = sshTunnel === 'forwardRemoteToLocal'
|
|
96
|
+
? `${s('remote')}:${sshTunnelRemoteHost}:${sshTunnelRemotePort}`
|
|
97
|
+
: `${s('local')}:${sshTunnelLocalHost}:${sshTunnelLocalPort}`
|
|
98
|
+
return (
|
|
99
|
+
<span>
|
|
100
|
+
{name ? `[${name}] ` : ''}→ {from} → {to}
|
|
101
|
+
</span>
|
|
102
|
+
)
|
|
103
|
+
}
|
|
104
|
+
}, {
|
|
105
|
+
title: m('del'),
|
|
106
|
+
key: 'op',
|
|
107
|
+
dataIndex: 'id',
|
|
108
|
+
render: (id) => {
|
|
109
|
+
return (
|
|
110
|
+
<MinusCircleFilled
|
|
111
|
+
className='pointer'
|
|
112
|
+
onClick={() => remove(id)}
|
|
113
|
+
/>
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
]
|
|
118
|
+
|
|
119
|
+
function renderList () {
|
|
24
120
|
return (
|
|
25
|
-
<
|
|
26
|
-
|
|
27
|
-
|
|
121
|
+
<FormItem {...tailFormItemLayout}>
|
|
122
|
+
<Table
|
|
123
|
+
columns={cols}
|
|
124
|
+
className='mg3b'
|
|
125
|
+
pagination={false}
|
|
126
|
+
size='small'
|
|
127
|
+
dataSource={list.map((d, i) => {
|
|
128
|
+
return {
|
|
129
|
+
...d,
|
|
130
|
+
index: i + 1
|
|
131
|
+
}
|
|
132
|
+
})}
|
|
133
|
+
/>
|
|
134
|
+
</FormItem>
|
|
135
|
+
)
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return (
|
|
139
|
+
<div>
|
|
140
|
+
<FormItem
|
|
141
|
+
name='sshTunnels'
|
|
142
|
+
className='hide'
|
|
143
|
+
>
|
|
144
|
+
<Input />
|
|
145
|
+
</FormItem>
|
|
146
|
+
<Form
|
|
147
|
+
form={formChild}
|
|
148
|
+
onFinish={handleFinish}
|
|
149
|
+
initialValues={initialValues}
|
|
28
150
|
>
|
|
151
|
+
{renderList()}
|
|
29
152
|
<FormItem
|
|
30
153
|
label={e('sshTunnel')}
|
|
31
|
-
name=
|
|
154
|
+
name='sshTunnel'
|
|
155
|
+
{...formItemLayout}
|
|
32
156
|
required
|
|
33
157
|
>
|
|
34
158
|
<RadioGroup>
|
|
@@ -48,87 +172,85 @@ export default function renderSshTunnel () {
|
|
|
48
172
|
</RadioButton>
|
|
49
173
|
</RadioGroup>
|
|
50
174
|
</FormItem>
|
|
51
|
-
<Space.Compact className='mg2x'>
|
|
52
|
-
<FormItem
|
|
53
|
-
label={e('destination')}
|
|
54
|
-
name={[field.name, 'sshTunnelRemoteHost']}
|
|
55
|
-
initialValue='127.0.0.1'
|
|
56
|
-
required
|
|
57
|
-
>
|
|
58
|
-
<Input
|
|
59
|
-
className='compact-input'
|
|
60
|
-
placeholder={e('host')}
|
|
61
|
-
/>
|
|
62
|
-
</FormItem>
|
|
63
|
-
<FormItem
|
|
64
|
-
label=''
|
|
65
|
-
name={[field.name, 'sshTunnelRemotePort']}
|
|
66
|
-
initialValue={22}
|
|
67
|
-
required
|
|
68
|
-
>
|
|
69
|
-
<InputNumber
|
|
70
|
-
min={1}
|
|
71
|
-
max={65535}
|
|
72
|
-
// addonBefore={e('remotePort')}
|
|
73
|
-
className='compact-input'
|
|
74
|
-
placeholder={e('port')}
|
|
75
|
-
/>
|
|
76
|
-
</FormItem>
|
|
77
|
-
</Space.Compact>
|
|
78
175
|
<FormItem
|
|
79
|
-
label={
|
|
80
|
-
|
|
81
|
-
initialValue={22}
|
|
176
|
+
label={s('remote')}
|
|
177
|
+
{...formItemLayout}
|
|
82
178
|
required
|
|
83
|
-
className='
|
|
179
|
+
className='ssh-tunnels-host'
|
|
84
180
|
>
|
|
85
|
-
<
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
181
|
+
<Space.Compact>
|
|
182
|
+
<FormItem
|
|
183
|
+
name='sshTunnelRemoteHost'
|
|
184
|
+
label=''
|
|
185
|
+
required
|
|
186
|
+
>
|
|
187
|
+
<Input
|
|
188
|
+
placeholder={e('host')}
|
|
189
|
+
/>
|
|
190
|
+
</FormItem>
|
|
191
|
+
<FormItem
|
|
192
|
+
label=''
|
|
193
|
+
name='sshTunnelRemotePort'
|
|
194
|
+
required
|
|
195
|
+
>
|
|
196
|
+
<InputNumber
|
|
197
|
+
min={1}
|
|
198
|
+
max={65535}
|
|
199
|
+
placeholder={e('port')}
|
|
200
|
+
/>
|
|
201
|
+
</FormItem>
|
|
202
|
+
</Space.Compact>
|
|
203
|
+
</FormItem>
|
|
204
|
+
<FormItem
|
|
205
|
+
label={s('local')}
|
|
206
|
+
{...formItemLayout}
|
|
207
|
+
required
|
|
208
|
+
className='ssh-tunnels-host'
|
|
209
|
+
>
|
|
210
|
+
<Space.Compact>
|
|
211
|
+
<FormItem
|
|
212
|
+
name='sshTunnelLocalHost'
|
|
213
|
+
label=''
|
|
214
|
+
required
|
|
215
|
+
>
|
|
216
|
+
<Input
|
|
217
|
+
placeholder={e('host')}
|
|
218
|
+
/>
|
|
219
|
+
</FormItem>
|
|
220
|
+
<FormItem
|
|
221
|
+
label=''
|
|
222
|
+
name='sshTunnelLocalPort'
|
|
223
|
+
required
|
|
224
|
+
>
|
|
225
|
+
<InputNumber
|
|
226
|
+
min={1}
|
|
227
|
+
max={65535}
|
|
228
|
+
// addonBefore={e('localPort')}
|
|
229
|
+
placeholder={e('port')}
|
|
230
|
+
/>
|
|
231
|
+
</FormItem>
|
|
232
|
+
</Space.Compact>
|
|
233
|
+
</FormItem>
|
|
234
|
+
<FormItem
|
|
235
|
+
name='name'
|
|
236
|
+
label={s('name')}
|
|
237
|
+
{...formItemLayout}
|
|
238
|
+
>
|
|
239
|
+
<Input
|
|
240
|
+
placeholder={e('name')}
|
|
91
241
|
/>
|
|
92
242
|
</FormItem>
|
|
93
|
-
<
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
name='sshTunnels'
|
|
107
|
-
key='sshTunnels'
|
|
108
|
-
>
|
|
109
|
-
{
|
|
110
|
-
(fields, { add, remove }, { errors }) => {
|
|
111
|
-
return (
|
|
112
|
-
<div>
|
|
113
|
-
{
|
|
114
|
-
fields.map((field, i) => {
|
|
115
|
-
return renderItem(field, i, add, remove)
|
|
116
|
-
})
|
|
117
|
-
}
|
|
118
|
-
<FormItem>
|
|
119
|
-
<Button
|
|
120
|
-
type='dashed'
|
|
121
|
-
onClick={() => add()}
|
|
122
|
-
block
|
|
123
|
-
icon={<PlusOutlined />}
|
|
124
|
-
>
|
|
125
|
-
{e('sshTunnel')}
|
|
126
|
-
</Button>
|
|
127
|
-
</FormItem>
|
|
128
|
-
</div>
|
|
129
|
-
)
|
|
130
|
-
}
|
|
131
|
-
}
|
|
132
|
-
</FormList>
|
|
133
|
-
]
|
|
243
|
+
<FormItem {...tailFormItemLayout} className='mg60b'>
|
|
244
|
+
<Button
|
|
245
|
+
type='default'
|
|
246
|
+
htmlType='button'
|
|
247
|
+
icon={<PlusOutlined />}
|
|
248
|
+
onClick={onSubmit}
|
|
249
|
+
>
|
|
250
|
+
{e('sshTunnel')}
|
|
251
|
+
</Button>
|
|
252
|
+
</FormItem>
|
|
253
|
+
</Form>
|
|
254
|
+
</div>
|
|
255
|
+
)
|
|
134
256
|
}
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* web form
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useEffect } from 'react'
|
|
6
|
+
import {
|
|
7
|
+
Input,
|
|
8
|
+
Form
|
|
9
|
+
} from 'antd'
|
|
10
|
+
import { formItemLayout } from '../../common/form-layout'
|
|
11
|
+
import {
|
|
12
|
+
newBookmarkIdPrefix,
|
|
13
|
+
terminalWebType
|
|
14
|
+
} from '../../common/constants'
|
|
15
|
+
import useSubmit from './use-submit'
|
|
16
|
+
import copy from 'json-deep-copy'
|
|
17
|
+
import { defaults } from 'lodash-es'
|
|
18
|
+
import { ColorPickerItem } from './color-picker-item.jsx'
|
|
19
|
+
import { getRandomDefaultColor } from '../../common/rand-hex-color.js'
|
|
20
|
+
|
|
21
|
+
const FormItem = Form.Item
|
|
22
|
+
const { prefix } = window
|
|
23
|
+
const e = prefix('form')
|
|
24
|
+
|
|
25
|
+
export default function LocalFormUi (props) {
|
|
26
|
+
const [
|
|
27
|
+
form,
|
|
28
|
+
handleFinish,
|
|
29
|
+
submitUi
|
|
30
|
+
] = useSubmit(props)
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (props.formData.id.startsWith(newBookmarkIdPrefix)) {
|
|
33
|
+
form.setFieldsValue({
|
|
34
|
+
category: props.currentBookmarkGroupId
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
}, [props.currentBookmarkGroupId])
|
|
38
|
+
let initialValues = copy(props.formData)
|
|
39
|
+
const defaultValues = {
|
|
40
|
+
type: terminalWebType,
|
|
41
|
+
color: getRandomDefaultColor()
|
|
42
|
+
}
|
|
43
|
+
initialValues = defaults(initialValues, defaultValues)
|
|
44
|
+
function renderCommon () {
|
|
45
|
+
return (
|
|
46
|
+
<div className='pd1x'>
|
|
47
|
+
<FormItem
|
|
48
|
+
{...formItemLayout}
|
|
49
|
+
label={e('title')}
|
|
50
|
+
hasFeedback
|
|
51
|
+
>
|
|
52
|
+
<FormItem noStyle name='title'>
|
|
53
|
+
<Input addonBefore={<ColorPickerItem />} />
|
|
54
|
+
</FormItem>
|
|
55
|
+
</FormItem>
|
|
56
|
+
<FormItem
|
|
57
|
+
{...formItemLayout}
|
|
58
|
+
label={e('URL')}
|
|
59
|
+
hasFeedback
|
|
60
|
+
name='url'
|
|
61
|
+
required
|
|
62
|
+
>
|
|
63
|
+
<Input addonBefore={<ColorPickerItem />} />
|
|
64
|
+
</FormItem>
|
|
65
|
+
<FormItem
|
|
66
|
+
{...formItemLayout}
|
|
67
|
+
label={e('description')}
|
|
68
|
+
name='description'
|
|
69
|
+
hasFeedback
|
|
70
|
+
>
|
|
71
|
+
<Input.TextArea rows={1} />
|
|
72
|
+
</FormItem>
|
|
73
|
+
<FormItem
|
|
74
|
+
{...formItemLayout}
|
|
75
|
+
label='type'
|
|
76
|
+
name='type'
|
|
77
|
+
className='hide'
|
|
78
|
+
>
|
|
79
|
+
<Input />
|
|
80
|
+
</FormItem>
|
|
81
|
+
</div>
|
|
82
|
+
)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return (
|
|
86
|
+
<Form
|
|
87
|
+
form={form}
|
|
88
|
+
onFinish={handleFinish}
|
|
89
|
+
initialValues={initialValues}
|
|
90
|
+
name='local-form'
|
|
91
|
+
>
|
|
92
|
+
{renderCommon()}
|
|
93
|
+
{submitUi}
|
|
94
|
+
</Form>
|
|
95
|
+
)
|
|
96
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bookmark form
|
|
3
|
+
*/
|
|
4
|
+
import BookmarkForm from './ssh-form'
|
|
5
|
+
import WebFormUi from './web-form-ui'
|
|
6
|
+
|
|
7
|
+
export default class WebForm extends BookmarkForm {
|
|
8
|
+
render () {
|
|
9
|
+
return (
|
|
10
|
+
<WebFormUi
|
|
11
|
+
{...this.props}
|
|
12
|
+
{...this.getProps()}
|
|
13
|
+
/>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -12,6 +12,9 @@ import CssOverwrite from './css-overwrite'
|
|
|
12
12
|
import UiTheme from './ui-theme'
|
|
13
13
|
import CustomCss from './custom-css.jsx'
|
|
14
14
|
import TerminalInteractive from '../terminal/terminal-interactive'
|
|
15
|
+
import ConfirmModalStore from '../sftp/confirm-modal-store.jsx'
|
|
16
|
+
import TransferConflictStore from '../sftp/transfer-conflict-store.jsx'
|
|
17
|
+
import TransportsActionStore from '../sftp/transports-action-store.jsx'
|
|
15
18
|
import classnames from 'classnames'
|
|
16
19
|
import ShortcutControl from '../shortcuts/shortcut-control.jsx'
|
|
17
20
|
import { isMac, isWin } from '../../common/constants'
|
|
@@ -149,6 +152,17 @@ export default class Index extends Component {
|
|
|
149
152
|
/>
|
|
150
153
|
</div>
|
|
151
154
|
<ContextMenu store={store} />
|
|
155
|
+
<ConfirmModalStore
|
|
156
|
+
store={store}
|
|
157
|
+
/>
|
|
158
|
+
<TransferConflictStore
|
|
159
|
+
store={store}
|
|
160
|
+
_fileTransfers={store._fileTransfers}
|
|
161
|
+
/>
|
|
162
|
+
<TransportsActionStore
|
|
163
|
+
store={store}
|
|
164
|
+
_fileTransfers={store._fileTransfers}
|
|
165
|
+
/>
|
|
152
166
|
</div>
|
|
153
167
|
</ConfigProvider>
|
|
154
168
|
)
|