@electerm/electerm-react 1.39.35 → 1.39.47
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/components/bookmark-form/bookmark-group-tree-format.js +25 -24
- package/client/components/bookmark-form/form-ssh-common.jsx +10 -0
- package/client/components/bookmark-form/render-connection-hopping.jsx +21 -20
- package/client/components/bookmark-form/render-ssh-tunnel.jsx +4 -3
- package/client/components/bookmark-form/ssh-form.jsx +2 -1
- package/client/components/bookmark-form/vnc-form-ui.jsx +42 -3
- package/client/components/main/main.jsx +1 -1
- package/client/components/profile/profile-form-elem.jsx +0 -1
- package/client/components/quick-commands/quick-command-transport-mod.jsx +1 -1
- package/client/components/setting-panel/bookmark-tree-list.jsx +1 -1
- package/client/components/setting-panel/list.styl +3 -0
- package/client/components/setting-panel/start-session-select.jsx +4 -3
- package/client/components/sftp/file-item.jsx +3 -3
- package/client/components/sidebar/bookmark-select.jsx +1 -1
- package/client/components/tabs/index.jsx +1 -1
- package/client/components/tabs/tabs.styl +2 -2
- package/client/components/terminal/index.jsx +3 -2
- package/client/components/terminal-theme/theme-list.jsx +2 -2
- package/client/components/tree-list/tree-expander.jsx +36 -0
- package/client/components/tree-list/tree-list-item.jsx +262 -0
- package/client/components/{setting-panel → tree-list}/tree-list.jsx +397 -324
- package/client/components/{setting-panel → tree-list}/tree-list.styl +26 -6
- package/client/store/common.js +15 -1
- package/client/store/index.js +24 -0
- package/package.json +1 -1
- /package/client/components/{setting-panel → tree-list}/bookmark-transport.jsx +0 -0
|
@@ -3,37 +3,38 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
export default (bookmarkGroups = []) => {
|
|
6
|
-
const
|
|
6
|
+
const btree = bookmarkGroups
|
|
7
7
|
.reduce((prev, k) => {
|
|
8
8
|
return {
|
|
9
9
|
...prev,
|
|
10
10
|
[k.id]: k
|
|
11
11
|
}
|
|
12
12
|
}, {})
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
function buildSubCats (id) {
|
|
14
|
+
const x = btree[id]
|
|
15
|
+
if (!x) {
|
|
16
|
+
return ''
|
|
17
|
+
}
|
|
18
|
+
const y = {
|
|
19
|
+
key: x.id,
|
|
20
|
+
value: x.id,
|
|
21
|
+
title: x.title
|
|
22
|
+
}
|
|
23
|
+
y.children = (x.bookmarkGroupIds || []).map(buildSubCats).filter(d => d)
|
|
24
|
+
if (!y.children.length) {
|
|
25
|
+
delete y.children
|
|
26
|
+
}
|
|
27
|
+
return y
|
|
28
|
+
}
|
|
29
|
+
const level1 = bookmarkGroups.filter(d => d.level !== 2)
|
|
30
|
+
.map(d => {
|
|
16
31
|
const r = {
|
|
17
|
-
title:
|
|
18
|
-
value:
|
|
19
|
-
key:
|
|
20
|
-
|
|
21
|
-
if (j.bookmarkGroupIds && j.bookmarkGroupIds.length) {
|
|
22
|
-
r.children = j.bookmarkGroupIds.map(k => {
|
|
23
|
-
const o = dict[k]
|
|
24
|
-
return o
|
|
25
|
-
? {
|
|
26
|
-
title: o.title,
|
|
27
|
-
value: o.id,
|
|
28
|
-
key: o.id
|
|
29
|
-
}
|
|
30
|
-
: null
|
|
31
|
-
})
|
|
32
|
-
r.children = r.children.filter(d => d)
|
|
33
|
-
if (!r.children.length) {
|
|
34
|
-
delete r.children
|
|
35
|
-
}
|
|
32
|
+
title: d.title,
|
|
33
|
+
value: d.id,
|
|
34
|
+
key: d.id,
|
|
35
|
+
children: (d.bookmarkGroupIds || []).map(buildSubCats).filter(d => d)
|
|
36
36
|
}
|
|
37
37
|
return r
|
|
38
|
-
})
|
|
38
|
+
}).filter(d => d)
|
|
39
|
+
return level1
|
|
39
40
|
}
|
|
@@ -192,6 +192,16 @@ export default function renderCommon (props) {
|
|
|
192
192
|
>
|
|
193
193
|
<Input />
|
|
194
194
|
</FormItem>
|
|
195
|
+
<FormItem
|
|
196
|
+
{...formItemLayout}
|
|
197
|
+
label={e('interactiveValues')}
|
|
198
|
+
name='interactiveValues'
|
|
199
|
+
hasFeedback
|
|
200
|
+
>
|
|
201
|
+
<Input.TextArea
|
|
202
|
+
rows={1}
|
|
203
|
+
/>
|
|
204
|
+
</FormItem>
|
|
195
205
|
{renderRunScripts()}
|
|
196
206
|
<FormItem
|
|
197
207
|
{...formItemLayout}
|
|
@@ -37,11 +37,11 @@ export default function renderConnectionHopping (props) {
|
|
|
37
37
|
authType: authTypeMap.password
|
|
38
38
|
})
|
|
39
39
|
const [list, setList] = useState(formData.connectionHoppings || [])
|
|
40
|
-
function onChangeAuthType (
|
|
40
|
+
function onChangeAuthType (e) {
|
|
41
41
|
editState(old => {
|
|
42
42
|
return {
|
|
43
43
|
...old,
|
|
44
|
-
authType
|
|
44
|
+
authType: e.target.value
|
|
45
45
|
}
|
|
46
46
|
})
|
|
47
47
|
}
|
|
@@ -68,7 +68,7 @@ export default function renderConnectionHopping (props) {
|
|
|
68
68
|
})
|
|
69
69
|
formChild.resetFields()
|
|
70
70
|
}
|
|
71
|
-
const authTypes = Object.keys(authTypeMap).map(k => {
|
|
71
|
+
const authTypes = props.authTypes || Object.keys(authTypeMap).map(k => {
|
|
72
72
|
return k
|
|
73
73
|
})
|
|
74
74
|
|
|
@@ -95,7 +95,8 @@ export default function renderConnectionHopping (props) {
|
|
|
95
95
|
const pass = item.password ? ':*****' : ''
|
|
96
96
|
const ph = item.passphase ? '(passphase:*****)' : ''
|
|
97
97
|
const pk = item.privateKey ? '(privateKey:*****)' : ''
|
|
98
|
-
|
|
98
|
+
const useProfile = item.profile ? '[profile] ' : ''
|
|
99
|
+
return <span>{useProfile}{item.username}{pass}@{item.host}:{item.port}{pk}{ph}</span>
|
|
99
100
|
}
|
|
100
101
|
}, {
|
|
101
102
|
title: m('del'),
|
|
@@ -159,6 +160,22 @@ export default function renderConnectionHopping (props) {
|
|
|
159
160
|
>
|
|
160
161
|
<Input />
|
|
161
162
|
</FormItem>
|
|
163
|
+
<FormItem
|
|
164
|
+
{...formItemLayout}
|
|
165
|
+
label={f('port')}
|
|
166
|
+
hasFeedback
|
|
167
|
+
name='port'
|
|
168
|
+
rules={[{
|
|
169
|
+
required: true, message: 'port required'
|
|
170
|
+
}]}
|
|
171
|
+
>
|
|
172
|
+
<InputNumber
|
|
173
|
+
placeholder={f('port')}
|
|
174
|
+
min={1}
|
|
175
|
+
max={65535}
|
|
176
|
+
step={1}
|
|
177
|
+
/>
|
|
178
|
+
</FormItem>
|
|
162
179
|
<FormItem
|
|
163
180
|
{...formItemLayout}
|
|
164
181
|
label={f('username')}
|
|
@@ -192,22 +209,6 @@ export default function renderConnectionHopping (props) {
|
|
|
192
209
|
}
|
|
193
210
|
</RadioGroup>
|
|
194
211
|
</FormItem>
|
|
195
|
-
<FormItem
|
|
196
|
-
{...formItemLayout}
|
|
197
|
-
label={f('port')}
|
|
198
|
-
hasFeedback
|
|
199
|
-
name='port'
|
|
200
|
-
rules={[{
|
|
201
|
-
required: true, message: 'port required'
|
|
202
|
-
}]}
|
|
203
|
-
>
|
|
204
|
-
<InputNumber
|
|
205
|
-
placeholder={f('port')}
|
|
206
|
-
min={1}
|
|
207
|
-
max={65535}
|
|
208
|
-
step={1}
|
|
209
|
-
/>
|
|
210
|
-
</FormItem>
|
|
211
212
|
<RenderAuth
|
|
212
213
|
form={formChild}
|
|
213
214
|
store={store}
|
|
@@ -88,13 +88,14 @@ export default function renderSshTunnels (props) {
|
|
|
88
88
|
const {
|
|
89
89
|
sshTunnel,
|
|
90
90
|
sshTunnelRemoteHost = '127.0.0.1',
|
|
91
|
-
sshTunnelRemotePort,
|
|
91
|
+
sshTunnelRemotePort = '',
|
|
92
92
|
sshTunnelLocalHost = '127.0.0.1',
|
|
93
|
-
sshTunnelLocalPort,
|
|
93
|
+
sshTunnelLocalPort = '',
|
|
94
94
|
name
|
|
95
95
|
} = item
|
|
96
96
|
if (sshTunnel === 'dynamicForward') {
|
|
97
|
-
|
|
97
|
+
const n = name ? `[${name}] ` : ''
|
|
98
|
+
return `${n}socks5://${sshTunnelLocalHost}:${sshTunnelLocalPort}`
|
|
98
99
|
}
|
|
99
100
|
const to = sshTunnel === 'forwardRemoteToLocal'
|
|
100
101
|
? `${s('local')}:${sshTunnelLocalHost}:${sshTunnelLocalPort}`
|
|
@@ -225,7 +225,7 @@ export default class BookmarkForm extends PureComponent {
|
|
|
225
225
|
}
|
|
226
226
|
|
|
227
227
|
test = async (update) => {
|
|
228
|
-
|
|
228
|
+
let options = {
|
|
229
229
|
...this.props.formData,
|
|
230
230
|
...update
|
|
231
231
|
}
|
|
@@ -233,6 +233,7 @@ export default class BookmarkForm extends PureComponent {
|
|
|
233
233
|
this.setState({
|
|
234
234
|
testing: true
|
|
235
235
|
})
|
|
236
|
+
options = window.store.applyProfileToTabs(options)
|
|
236
237
|
const res = await testCon(options)
|
|
237
238
|
.then(r => r)
|
|
238
239
|
.catch((e) => {
|
|
@@ -8,7 +8,8 @@ import {
|
|
|
8
8
|
Form,
|
|
9
9
|
InputNumber,
|
|
10
10
|
TreeSelect,
|
|
11
|
-
Switch
|
|
11
|
+
Switch,
|
|
12
|
+
Tabs
|
|
12
13
|
} from 'antd'
|
|
13
14
|
import { formItemLayout } from '../../common/form-layout'
|
|
14
15
|
import {
|
|
@@ -22,6 +23,8 @@ import { ColorPickerItem } from './color-picker-item.jsx'
|
|
|
22
23
|
import { getRandomDefaultColor } from '../../common/rand-hex-color.js'
|
|
23
24
|
import formatBookmarkGroups from './bookmark-group-tree-format'
|
|
24
25
|
import findBookmarkGroupId from '../../common/find-bookmark-group-id'
|
|
26
|
+
import renderProxy from './proxy'
|
|
27
|
+
import ConnectionHopping from './render-connection-hopping.jsx'
|
|
25
28
|
|
|
26
29
|
const FormItem = Form.Item
|
|
27
30
|
const { prefix } = window
|
|
@@ -58,9 +61,42 @@ export default function VncFormUi (props) {
|
|
|
58
61
|
category: initBookmarkGroupId,
|
|
59
62
|
color: getRandomDefaultColor(),
|
|
60
63
|
viewOnly: false,
|
|
61
|
-
scaleViewport: true
|
|
64
|
+
scaleViewport: true,
|
|
65
|
+
connectionHoppings: []
|
|
62
66
|
}
|
|
63
67
|
initialValues = defaults(initialValues, defaultValues)
|
|
68
|
+
|
|
69
|
+
function renderTabs (props) {
|
|
70
|
+
const items = [
|
|
71
|
+
{
|
|
72
|
+
key: 'auth',
|
|
73
|
+
label: e('auth'),
|
|
74
|
+
forceRender: true,
|
|
75
|
+
children: renderCommon()
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
key: 'connectionHopping',
|
|
79
|
+
label: e('connectionHopping'),
|
|
80
|
+
forceRender: true,
|
|
81
|
+
children: renderHopping()
|
|
82
|
+
}
|
|
83
|
+
]
|
|
84
|
+
return (
|
|
85
|
+
<Tabs
|
|
86
|
+
items={items}
|
|
87
|
+
/>
|
|
88
|
+
)
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function renderHopping () {
|
|
92
|
+
return (
|
|
93
|
+
<ConnectionHopping
|
|
94
|
+
{...props}
|
|
95
|
+
form={form}
|
|
96
|
+
/>
|
|
97
|
+
)
|
|
98
|
+
}
|
|
99
|
+
|
|
64
100
|
function renderCommon () {
|
|
65
101
|
const {
|
|
66
102
|
bookmarkGroups = []
|
|
@@ -153,6 +189,9 @@ export default function VncFormUi (props) {
|
|
|
153
189
|
showSearch
|
|
154
190
|
/>
|
|
155
191
|
</FormItem>
|
|
192
|
+
{
|
|
193
|
+
renderProxy(props)
|
|
194
|
+
}
|
|
156
195
|
<FormItem
|
|
157
196
|
{...formItemLayout}
|
|
158
197
|
label='type'
|
|
@@ -172,7 +211,7 @@ export default function VncFormUi (props) {
|
|
|
172
211
|
initialValues={initialValues}
|
|
173
212
|
name='vnc-form'
|
|
174
213
|
>
|
|
175
|
-
{
|
|
214
|
+
{renderTabs()}
|
|
176
215
|
{submitUi}
|
|
177
216
|
</Form>
|
|
178
217
|
)
|
|
@@ -83,7 +83,7 @@ export default class Index extends Component {
|
|
|
83
83
|
loaded: configLoaded,
|
|
84
84
|
'system-ui': store.config.useSystemTitleBar,
|
|
85
85
|
'not-system-ui': !store.config.useSystemTitleBar,
|
|
86
|
-
'is-mac': isMac,
|
|
86
|
+
'is-mac': isMac && !window.et.isWebApp,
|
|
87
87
|
'is-win': isWin,
|
|
88
88
|
pinned,
|
|
89
89
|
'qm-pinned': pinnedQuickCommandBar,
|
|
@@ -34,9 +34,10 @@ export default class StartSessionSelect extends Component {
|
|
|
34
34
|
value: x.id,
|
|
35
35
|
title: x.title
|
|
36
36
|
}
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
y.children = [
|
|
38
|
+
...(x.bookmarkGroupIds || []).map(buildSubCats),
|
|
39
|
+
...(x.bookmarkIds || []).map(buildLeaf)
|
|
40
|
+
].filter(d => d)
|
|
40
41
|
if (y.children && !y.children.length) {
|
|
41
42
|
delete y.children
|
|
42
43
|
}
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from '@ant-design/icons'
|
|
11
11
|
import classnames from 'classnames'
|
|
12
12
|
import copy from 'json-deep-copy'
|
|
13
|
-
import { pick, some } from 'lodash-es'
|
|
13
|
+
import { pick, some, without } from 'lodash-es'
|
|
14
14
|
import Input from '../common/input-auto-focus'
|
|
15
15
|
import resolve from '../../common/resolve'
|
|
16
16
|
import { addClass, removeClass } from '../../common/class'
|
|
@@ -382,7 +382,7 @@ export default class FileSection extends React.Component {
|
|
|
382
382
|
const { type } = this.props
|
|
383
383
|
window.store.openFileInfoModal({
|
|
384
384
|
file: this.state.file,
|
|
385
|
-
tab: this.props.tab,
|
|
385
|
+
tab: without(this.props.tab, 'terminals'),
|
|
386
386
|
visible: true,
|
|
387
387
|
pid: this.props.pid,
|
|
388
388
|
sessionId: this.props.sessionId,
|
|
@@ -531,7 +531,7 @@ export default class FileSection extends React.Component {
|
|
|
531
531
|
'message', this.changeFileMode
|
|
532
532
|
)
|
|
533
533
|
window.store.openFileModeModal({
|
|
534
|
-
tab: this.props.tab,
|
|
534
|
+
tab: without(this.props.tab, 'terminals'),
|
|
535
535
|
visible: true,
|
|
536
536
|
uidTree: this.props[`${type}UidTree`],
|
|
537
537
|
gidTree: this.props[`${type}GidTree`]
|
|
@@ -256,7 +256,7 @@ export default class Tabs extends React.Component {
|
|
|
256
256
|
const left = overflow
|
|
257
257
|
? '100%'
|
|
258
258
|
: tabsWidthAll
|
|
259
|
-
const w1 = isMacJs ? 30 : windowControlWidth
|
|
259
|
+
const w1 = isMacJs && window.et.isWebApp ? 30 : windowControlWidth
|
|
260
260
|
const style = {
|
|
261
261
|
width: width - w1 - 166
|
|
262
262
|
}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
.tabs-inner
|
|
12
12
|
margin-left 72px
|
|
13
13
|
.tabs-extra
|
|
14
|
-
right
|
|
14
|
+
right 96px
|
|
15
15
|
.tabs-inner
|
|
16
16
|
position relative
|
|
17
17
|
z-index 2
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
position absolute
|
|
138
138
|
height 40px
|
|
139
139
|
top 0
|
|
140
|
-
right
|
|
140
|
+
right 0
|
|
141
141
|
line-height 40px
|
|
142
142
|
z-index 20
|
|
143
143
|
|
|
@@ -1044,7 +1044,8 @@ class Term extends Component {
|
|
|
1044
1044
|
this.attachAddon._sendData(obj.script + '\r')
|
|
1045
1045
|
}
|
|
1046
1046
|
if (delayedScripts.length > 0) {
|
|
1047
|
-
|
|
1047
|
+
const nextDelay = delayedScripts[0].delay || 0
|
|
1048
|
+
this.timers.timerDelay = setTimeout(this.runDelayedScripts, nextDelay)
|
|
1048
1049
|
}
|
|
1049
1050
|
}
|
|
1050
1051
|
}
|
|
@@ -1092,7 +1093,7 @@ class Term extends Component {
|
|
|
1092
1093
|
server = ''
|
|
1093
1094
|
} = config
|
|
1094
1095
|
const { sessionId, terminalIndex, id, logName } = this.props
|
|
1095
|
-
const tab = window.store.
|
|
1096
|
+
const tab = window.store.applyProfileToTabs(deepCopy(this.props.tab || {}))
|
|
1096
1097
|
const {
|
|
1097
1098
|
srcId, from = 'bookmarks',
|
|
1098
1099
|
type,
|
|
@@ -51,7 +51,7 @@ export default class ThemeList extends List {
|
|
|
51
51
|
renderItem = (item, i) => {
|
|
52
52
|
const { activeItemId } = this.props
|
|
53
53
|
const { theme } = this.props
|
|
54
|
-
const { name, id } = item
|
|
54
|
+
const { name, id, type } = item
|
|
55
55
|
const cls = classnames(
|
|
56
56
|
'item-list-unit theme-item',
|
|
57
57
|
{
|
|
@@ -83,7 +83,7 @@ export default class ThemeList extends List {
|
|
|
83
83
|
{title}
|
|
84
84
|
</div>
|
|
85
85
|
{
|
|
86
|
-
id === defaultTheme.id
|
|
86
|
+
id === defaultTheme.id || type === 'iterm'
|
|
87
87
|
? null
|
|
88
88
|
: this.renderDelBtn(item)
|
|
89
89
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CaretDownOutlined,
|
|
3
|
+
CaretRightOutlined
|
|
4
|
+
} from '@ant-design/icons'
|
|
5
|
+
import { memo } from 'react'
|
|
6
|
+
|
|
7
|
+
export default memo(function TreeExpander (props) {
|
|
8
|
+
function onExpand () {
|
|
9
|
+
props.onExpand(group)
|
|
10
|
+
}
|
|
11
|
+
function onUnExpand () {
|
|
12
|
+
props.onUnExpand(group)
|
|
13
|
+
}
|
|
14
|
+
const { group } = props
|
|
15
|
+
if (
|
|
16
|
+
!group?.bookmarkIds?.length &&
|
|
17
|
+
!group?.bookmarkGroupIds?.length
|
|
18
|
+
) {
|
|
19
|
+
return null
|
|
20
|
+
}
|
|
21
|
+
const shouldOpen = props.keyword || props.expandedKeys.includes(group.id)
|
|
22
|
+
const Icon = shouldOpen
|
|
23
|
+
? CaretDownOutlined
|
|
24
|
+
: CaretRightOutlined
|
|
25
|
+
const func = shouldOpen
|
|
26
|
+
? onUnExpand
|
|
27
|
+
: onExpand
|
|
28
|
+
return (
|
|
29
|
+
<div
|
|
30
|
+
className='tree-expander pointer'
|
|
31
|
+
onClick={func}
|
|
32
|
+
>
|
|
33
|
+
<Icon />
|
|
34
|
+
</div>
|
|
35
|
+
)
|
|
36
|
+
})
|