@electerm/electerm-react 1.39.18 → 1.39.35
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 +7 -3
- package/client/common/create-title.jsx +12 -2
- package/client/common/default-setting.js +7 -1
- package/client/common/init-setting-item.js +6 -0
- package/client/components/bookmark-form/index.jsx +6 -2
- package/client/components/bookmark-form/rdp-form-ui.jsx +1 -1
- package/client/components/bookmark-form/rdp-form.jsx +1 -1
- package/client/components/bookmark-form/render-auth-ssh.jsx +27 -1
- package/client/components/bookmark-form/vnc-form-ui.jsx +179 -0
- package/client/components/bookmark-form/vnc-form.jsx +16 -0
- package/client/components/footer/footer-entry.jsx +1 -0
- package/client/components/main/term-fullscreen.styl +4 -1
- package/client/components/profile/profile-form-elem.jsx +87 -0
- package/client/components/profile/profile-form.jsx +33 -0
- package/client/components/profile/profile-list.jsx +79 -0
- package/client/components/profile/profile-transport-mod.jsx +5 -0
- package/client/components/profile/profile-transport.jsx +12 -0
- package/client/components/quick-commands/quick-command-transport-mod.jsx +13 -14
- package/client/components/rdp/rdp-session.jsx +53 -36
- package/client/components/session/session.jsx +14 -3
- package/client/components/session/session.styl +7 -2
- package/client/components/setting-panel/setting-common.jsx +1 -0
- package/client/components/setting-panel/setting-modal.jsx +14 -0
- package/client/components/setting-panel/setting-terminal.jsx +1 -1
- package/client/components/setting-panel/tab-profiles.jsx +38 -0
- package/client/components/sftp/list-table-ui.jsx +99 -46
- package/client/components/sftp/sftp-entry.jsx +1 -0
- package/client/components/sftp/sftp.styl +4 -1
- package/client/components/sftp/transfer-common.js +1 -1
- package/client/components/terminal/index.jsx +2 -4
- package/client/components/vnc/vnc-form.jsx +66 -0
- package/client/components/vnc/vnc-session.jsx +297 -0
- package/client/store/common.js +21 -0
- package/client/store/index.js +1 -0
- package/client/store/init-state.js +4 -23
- package/client/store/load-data.js +1 -2
- package/package.json +1 -1
|
@@ -68,12 +68,14 @@ export const connectionMap = buildConst([
|
|
|
68
68
|
'serial',
|
|
69
69
|
'local',
|
|
70
70
|
'web',
|
|
71
|
-
'rdp'
|
|
71
|
+
'rdp',
|
|
72
|
+
'vnc'
|
|
72
73
|
])
|
|
73
74
|
|
|
74
75
|
export const authTypeMap = buildConst([
|
|
75
76
|
'password',
|
|
76
|
-
'privateKey'
|
|
77
|
+
'privateKey',
|
|
78
|
+
'profiles'
|
|
77
79
|
])
|
|
78
80
|
|
|
79
81
|
export const footerHeight = 36
|
|
@@ -101,7 +103,8 @@ export const settingMap = buildConst([
|
|
|
101
103
|
'terminalThemes',
|
|
102
104
|
'bookmarkGroups',
|
|
103
105
|
'quickCommands',
|
|
104
|
-
'addressBookmarks'
|
|
106
|
+
'addressBookmarks',
|
|
107
|
+
'profiles'
|
|
105
108
|
])
|
|
106
109
|
|
|
107
110
|
export const infoTabs = buildConst([
|
|
@@ -135,6 +138,7 @@ export const terminalSplitDirectionMap = buildConst([
|
|
|
135
138
|
export const terminalSshConfigType = 'ssh-config'
|
|
136
139
|
export const terminalWebType = 'web'
|
|
137
140
|
export const terminalRdpType = 'rdp'
|
|
141
|
+
export const terminalVncType = 'vnc'
|
|
138
142
|
export const terminalSerialType = 'serial'
|
|
139
143
|
export const terminalTelnetType = 'telnet'
|
|
140
144
|
export const terminalLocalType = 'local'
|
|
@@ -9,7 +9,16 @@ import {
|
|
|
9
9
|
const { prefix } = window
|
|
10
10
|
const p = prefix('sftp')
|
|
11
11
|
|
|
12
|
-
|
|
12
|
+
function maskHost (hostOrIp = '') {
|
|
13
|
+
if (/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(hostOrIp)) {
|
|
14
|
+
const arr = hostOrIp.split('.')
|
|
15
|
+
return arr.slice(0, arr.length - 2).join('.') + '.*.*'
|
|
16
|
+
} else {
|
|
17
|
+
return hostOrIp.replace(/^.{3}/, '***')
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export default function createTitle (res, hide = true) {
|
|
13
22
|
if (!res) {
|
|
14
23
|
return ''
|
|
15
24
|
}
|
|
@@ -17,7 +26,8 @@ export default function createTitle (res) {
|
|
|
17
26
|
host, port, username, title, type,
|
|
18
27
|
path, connectionHoppings, sshTunnels
|
|
19
28
|
} = res
|
|
20
|
-
const
|
|
29
|
+
const h = hide && window.store.config.hideIP ? maskHost(host) : host
|
|
30
|
+
const fixTitle = `${username || ''}@${h}:${port}`
|
|
21
31
|
const extra = host || path ? (path || fixTitle) : ''
|
|
22
32
|
let f = title
|
|
23
33
|
? `${title}` + (extra ? ` - ${extra}` : '')
|
|
@@ -13,6 +13,7 @@ const { prefix } = window
|
|
|
13
13
|
const e = prefix('control')
|
|
14
14
|
const newQuickCommand = 'newQuickCommand'
|
|
15
15
|
const q = prefix('quickCommands')
|
|
16
|
+
const f = prefix('form')
|
|
16
17
|
|
|
17
18
|
export default (arr, tab) => {
|
|
18
19
|
if (tab === settingMap.history) {
|
|
@@ -28,5 +29,10 @@ export default (arr, tab) => {
|
|
|
28
29
|
id: '',
|
|
29
30
|
name: q(newQuickCommand)
|
|
30
31
|
}
|
|
32
|
+
} else if (tab === settingMap.profiles) {
|
|
33
|
+
return {
|
|
34
|
+
id: '',
|
|
35
|
+
name: f(settingMap.profiles)
|
|
36
|
+
}
|
|
31
37
|
}
|
|
32
38
|
}
|
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
terminalSerialType,
|
|
12
12
|
terminalWebType,
|
|
13
13
|
terminalRdpType,
|
|
14
|
+
terminalVncType,
|
|
14
15
|
terminalLocalType,
|
|
15
16
|
terminalTelnetType,
|
|
16
17
|
newBookmarkIdPrefix
|
|
@@ -21,6 +22,7 @@ import LocalForm from './local-form'
|
|
|
21
22
|
import TelnetForm from './telnet-form'
|
|
22
23
|
import WebForm from './web-form'
|
|
23
24
|
import RdpForm from './rdp-form'
|
|
25
|
+
import VncForm from './vnc-form'
|
|
24
26
|
import { createTitleWithTag } from '../../common/create-title'
|
|
25
27
|
import {
|
|
26
28
|
LoadingOutlined,
|
|
@@ -43,7 +45,8 @@ export default class BookmarkIndex extends Component {
|
|
|
43
45
|
terminalWebType,
|
|
44
46
|
terminalLocalType,
|
|
45
47
|
terminalSerialType,
|
|
46
|
-
terminalRdpType
|
|
48
|
+
terminalRdpType,
|
|
49
|
+
terminalVncType
|
|
47
50
|
].includes(initType)
|
|
48
51
|
) {
|
|
49
52
|
initType = connectionMap.ssh
|
|
@@ -72,7 +75,8 @@ export default class BookmarkIndex extends Component {
|
|
|
72
75
|
[connectionMap.serial]: SerialForm,
|
|
73
76
|
[connectionMap.local]: LocalForm,
|
|
74
77
|
[connectionMap.web]: WebForm,
|
|
75
|
-
[connectionMap.rdp]: RdpForm
|
|
78
|
+
[connectionMap.rdp]: RdpForm,
|
|
79
|
+
[connectionMap.vnc]: VncForm
|
|
76
80
|
}
|
|
77
81
|
|
|
78
82
|
handleChange = (e) => {
|
|
@@ -6,7 +6,8 @@ import {
|
|
|
6
6
|
Input,
|
|
7
7
|
Upload,
|
|
8
8
|
AutoComplete,
|
|
9
|
-
Form
|
|
9
|
+
Form,
|
|
10
|
+
Select
|
|
10
11
|
} from 'antd'
|
|
11
12
|
import { formItemLayout } from '../../common/form-layout'
|
|
12
13
|
import { uniqBy } from 'lodash-es'
|
|
@@ -57,6 +58,31 @@ export default function renderAuth (props) {
|
|
|
57
58
|
</FormItem>
|
|
58
59
|
)
|
|
59
60
|
}
|
|
61
|
+
if (authType === 'profiles') {
|
|
62
|
+
const opts = {
|
|
63
|
+
options: store.profiles
|
|
64
|
+
.map(d => {
|
|
65
|
+
return {
|
|
66
|
+
label: d.name,
|
|
67
|
+
value: d.id
|
|
68
|
+
}
|
|
69
|
+
}),
|
|
70
|
+
placeholder: e('profiles'),
|
|
71
|
+
allowClear: false
|
|
72
|
+
}
|
|
73
|
+
return (
|
|
74
|
+
<FormItem
|
|
75
|
+
{...formItemLayout}
|
|
76
|
+
label={e('profiles')}
|
|
77
|
+
name='profile'
|
|
78
|
+
hasFeedback
|
|
79
|
+
>
|
|
80
|
+
<Select
|
|
81
|
+
{...opts}
|
|
82
|
+
/>
|
|
83
|
+
</FormItem>
|
|
84
|
+
)
|
|
85
|
+
}
|
|
60
86
|
return [
|
|
61
87
|
<FormItem
|
|
62
88
|
{...formItemLayout}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* web form
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { useEffect } from 'react'
|
|
6
|
+
import {
|
|
7
|
+
Input,
|
|
8
|
+
Form,
|
|
9
|
+
InputNumber,
|
|
10
|
+
TreeSelect,
|
|
11
|
+
Switch
|
|
12
|
+
} from 'antd'
|
|
13
|
+
import { formItemLayout } from '../../common/form-layout'
|
|
14
|
+
import {
|
|
15
|
+
newBookmarkIdPrefix,
|
|
16
|
+
terminalVncType
|
|
17
|
+
} from '../../common/constants'
|
|
18
|
+
import useSubmit from './use-submit'
|
|
19
|
+
import copy from 'json-deep-copy'
|
|
20
|
+
import { defaults } from 'lodash-es'
|
|
21
|
+
import { ColorPickerItem } from './color-picker-item.jsx'
|
|
22
|
+
import { getRandomDefaultColor } from '../../common/rand-hex-color.js'
|
|
23
|
+
import formatBookmarkGroups from './bookmark-group-tree-format'
|
|
24
|
+
import findBookmarkGroupId from '../../common/find-bookmark-group-id'
|
|
25
|
+
|
|
26
|
+
const FormItem = Form.Item
|
|
27
|
+
const { prefix } = window
|
|
28
|
+
const e = prefix('form')
|
|
29
|
+
const c = prefix('common')
|
|
30
|
+
|
|
31
|
+
export default function VncFormUi (props) {
|
|
32
|
+
const [
|
|
33
|
+
form,
|
|
34
|
+
handleFinish,
|
|
35
|
+
submitUi
|
|
36
|
+
] = useSubmit(props)
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
if (props.formData.id.startsWith(newBookmarkIdPrefix)) {
|
|
39
|
+
form.setFieldsValue({
|
|
40
|
+
category: props.currentBookmarkGroupId
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
}, [props.currentBookmarkGroupId])
|
|
44
|
+
const {
|
|
45
|
+
id = ''
|
|
46
|
+
} = props.formData
|
|
47
|
+
const {
|
|
48
|
+
bookmarkGroups = [],
|
|
49
|
+
currentBookmarkGroupId
|
|
50
|
+
} = props
|
|
51
|
+
let initialValues = copy(props.formData)
|
|
52
|
+
const initBookmarkGroupId = !id.startsWith(newBookmarkIdPrefix)
|
|
53
|
+
? findBookmarkGroupId(bookmarkGroups, id)
|
|
54
|
+
: currentBookmarkGroupId
|
|
55
|
+
const defaultValues = {
|
|
56
|
+
type: terminalVncType,
|
|
57
|
+
port: 5900,
|
|
58
|
+
category: initBookmarkGroupId,
|
|
59
|
+
color: getRandomDefaultColor(),
|
|
60
|
+
viewOnly: false,
|
|
61
|
+
scaleViewport: true
|
|
62
|
+
}
|
|
63
|
+
initialValues = defaults(initialValues, defaultValues)
|
|
64
|
+
function renderCommon () {
|
|
65
|
+
const {
|
|
66
|
+
bookmarkGroups = []
|
|
67
|
+
} = props
|
|
68
|
+
const tree = formatBookmarkGroups(bookmarkGroups)
|
|
69
|
+
return (
|
|
70
|
+
<div className='pd1x'>
|
|
71
|
+
<FormItem
|
|
72
|
+
{...formItemLayout}
|
|
73
|
+
label={e('title')}
|
|
74
|
+
hasFeedback
|
|
75
|
+
>
|
|
76
|
+
<FormItem noStyle name='title'>
|
|
77
|
+
<Input addonBefore={<ColorPickerItem />} />
|
|
78
|
+
</FormItem>
|
|
79
|
+
</FormItem>
|
|
80
|
+
<FormItem
|
|
81
|
+
{...formItemLayout}
|
|
82
|
+
label={e('host')}
|
|
83
|
+
hasFeedback
|
|
84
|
+
name='host'
|
|
85
|
+
required
|
|
86
|
+
>
|
|
87
|
+
<Input />
|
|
88
|
+
</FormItem>
|
|
89
|
+
<FormItem
|
|
90
|
+
{...formItemLayout}
|
|
91
|
+
label={e('port')}
|
|
92
|
+
hasFeedback
|
|
93
|
+
name='port'
|
|
94
|
+
rules={[{
|
|
95
|
+
required: true, message: 'port required'
|
|
96
|
+
}]}
|
|
97
|
+
>
|
|
98
|
+
<InputNumber
|
|
99
|
+
placeholder={e('port')}
|
|
100
|
+
min={1}
|
|
101
|
+
max={65535}
|
|
102
|
+
step={1}
|
|
103
|
+
/>
|
|
104
|
+
</FormItem>
|
|
105
|
+
<FormItem
|
|
106
|
+
{...formItemLayout}
|
|
107
|
+
label={e('viewOnly')}
|
|
108
|
+
name='viewOnly'
|
|
109
|
+
valuePropName='checked'
|
|
110
|
+
>
|
|
111
|
+
<Switch />
|
|
112
|
+
</FormItem>
|
|
113
|
+
<FormItem
|
|
114
|
+
{...formItemLayout}
|
|
115
|
+
label={e('scaleViewport')}
|
|
116
|
+
name='scaleViewport'
|
|
117
|
+
valuePropName='checked'
|
|
118
|
+
>
|
|
119
|
+
<Switch />
|
|
120
|
+
</FormItem>
|
|
121
|
+
<FormItem
|
|
122
|
+
{...formItemLayout}
|
|
123
|
+
label={e('username')}
|
|
124
|
+
hasFeedback
|
|
125
|
+
name='username'
|
|
126
|
+
>
|
|
127
|
+
<Input />
|
|
128
|
+
</FormItem>
|
|
129
|
+
<FormItem
|
|
130
|
+
{...formItemLayout}
|
|
131
|
+
label={e('password')}
|
|
132
|
+
hasFeedback
|
|
133
|
+
name='password'
|
|
134
|
+
>
|
|
135
|
+
<Input.Password />
|
|
136
|
+
</FormItem>
|
|
137
|
+
<FormItem
|
|
138
|
+
{...formItemLayout}
|
|
139
|
+
label={e('description')}
|
|
140
|
+
name='description'
|
|
141
|
+
hasFeedback
|
|
142
|
+
>
|
|
143
|
+
<Input.TextArea rows={1} />
|
|
144
|
+
</FormItem>
|
|
145
|
+
<FormItem
|
|
146
|
+
{...formItemLayout}
|
|
147
|
+
label={c('bookmarkCategory')}
|
|
148
|
+
name='category'
|
|
149
|
+
>
|
|
150
|
+
<TreeSelect
|
|
151
|
+
treeData={tree}
|
|
152
|
+
treeDefaultExpandAll
|
|
153
|
+
showSearch
|
|
154
|
+
/>
|
|
155
|
+
</FormItem>
|
|
156
|
+
<FormItem
|
|
157
|
+
{...formItemLayout}
|
|
158
|
+
label='type'
|
|
159
|
+
name='type'
|
|
160
|
+
className='hide'
|
|
161
|
+
>
|
|
162
|
+
<Input />
|
|
163
|
+
</FormItem>
|
|
164
|
+
</div>
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return (
|
|
169
|
+
<Form
|
|
170
|
+
form={form}
|
|
171
|
+
onFinish={handleFinish}
|
|
172
|
+
initialValues={initialValues}
|
|
173
|
+
name='vnc-form'
|
|
174
|
+
>
|
|
175
|
+
{renderCommon()}
|
|
176
|
+
{submitUi}
|
|
177
|
+
</Form>
|
|
178
|
+
)
|
|
179
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* bookmark form
|
|
3
|
+
*/
|
|
4
|
+
import BookmarkForm from './ssh-form'
|
|
5
|
+
import VncFormUi from './vnc-form-ui'
|
|
6
|
+
|
|
7
|
+
export default class VncForm extends BookmarkForm {
|
|
8
|
+
render () {
|
|
9
|
+
return (
|
|
10
|
+
<VncFormUi
|
|
11
|
+
{...this.props}
|
|
12
|
+
{...this.getProps()}
|
|
13
|
+
/>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
.terminal-control
|
|
6
6
|
.qm-wrap-tooltip
|
|
7
7
|
.main-footer
|
|
8
|
+
.session-v-info
|
|
8
9
|
display none
|
|
9
10
|
.term-fullscreen-control
|
|
10
11
|
display block
|
|
@@ -12,7 +13,9 @@
|
|
|
12
13
|
top 10px
|
|
13
14
|
position fixed
|
|
14
15
|
z-index 100
|
|
16
|
+
background rgba(45, 245, 108, 0.8)
|
|
15
17
|
.term-wrap
|
|
18
|
+
.session-v-wrap
|
|
16
19
|
position fixed
|
|
17
20
|
left 0 !important
|
|
18
21
|
top 0 !important
|
|
@@ -24,4 +27,4 @@
|
|
|
24
27
|
right 10px !important
|
|
25
28
|
bottom 10px !important
|
|
26
29
|
.term-fullscreen-control
|
|
27
|
-
display none
|
|
30
|
+
display none
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import {
|
|
2
|
+
Form,
|
|
3
|
+
message,
|
|
4
|
+
Button
|
|
5
|
+
} from 'antd'
|
|
6
|
+
import generate from '../../common/uid'
|
|
7
|
+
import InputAutoFocus from '../common/input-auto-focus'
|
|
8
|
+
import renderAuth from '../bookmark-form/render-auth-ssh'
|
|
9
|
+
import { formItemLayout } from '../../common/form-layout'
|
|
10
|
+
import {
|
|
11
|
+
settingMap
|
|
12
|
+
} from '../../common/constants'
|
|
13
|
+
const FormItem = Form.Item
|
|
14
|
+
const { prefix } = window
|
|
15
|
+
const e = prefix('form')
|
|
16
|
+
const s = prefix('setting')
|
|
17
|
+
const ss = prefix('sftp')
|
|
18
|
+
|
|
19
|
+
export default function QuickCommandForm (props) {
|
|
20
|
+
const [form] = Form.useForm()
|
|
21
|
+
const { autofocustrigger } = props.store
|
|
22
|
+
async function handleSubmit (res) {
|
|
23
|
+
const { formData } = props
|
|
24
|
+
console.log(res)
|
|
25
|
+
const update1 = {
|
|
26
|
+
...res,
|
|
27
|
+
id: generate()
|
|
28
|
+
}
|
|
29
|
+
if (formData.id) {
|
|
30
|
+
props.store.editItem(formData.id, res, settingMap.profiles)
|
|
31
|
+
} else {
|
|
32
|
+
props.store.addItem(update1, settingMap.profiles)
|
|
33
|
+
props.store.setSettingItem({
|
|
34
|
+
id: '',
|
|
35
|
+
name: e('profile')
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
message.success(s('saved'))
|
|
39
|
+
}
|
|
40
|
+
return (
|
|
41
|
+
<Form
|
|
42
|
+
form={form}
|
|
43
|
+
onFinish={handleSubmit}
|
|
44
|
+
className='form-wrap pd2l'
|
|
45
|
+
layout='vertical'
|
|
46
|
+
initialValues={props.formData}
|
|
47
|
+
>
|
|
48
|
+
<FormItem
|
|
49
|
+
label={e('profileName')}
|
|
50
|
+
{...formItemLayout}
|
|
51
|
+
rules={[{
|
|
52
|
+
max: 60, message: '60 chars max'
|
|
53
|
+
}, {
|
|
54
|
+
required: true, message: 'Name required'
|
|
55
|
+
}]}
|
|
56
|
+
hasFeedback
|
|
57
|
+
name='name'
|
|
58
|
+
>
|
|
59
|
+
<InputAutoFocus
|
|
60
|
+
selectall='yes'
|
|
61
|
+
autofocustrigger={autofocustrigger}
|
|
62
|
+
/>
|
|
63
|
+
</FormItem>
|
|
64
|
+
{
|
|
65
|
+
renderAuth({
|
|
66
|
+
store: props.store,
|
|
67
|
+
form,
|
|
68
|
+
authType: 'password'
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
{
|
|
72
|
+
renderAuth({
|
|
73
|
+
store: props.store,
|
|
74
|
+
form
|
|
75
|
+
})
|
|
76
|
+
}
|
|
77
|
+
<FormItem>
|
|
78
|
+
<Button
|
|
79
|
+
type='primary'
|
|
80
|
+
htmlType='submit'
|
|
81
|
+
>
|
|
82
|
+
{ss('submit')}
|
|
83
|
+
</Button>
|
|
84
|
+
</FormItem>
|
|
85
|
+
</Form>
|
|
86
|
+
)
|
|
87
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { PureComponent } from 'react'
|
|
2
|
+
import ProfileCommandForm from './profile-form-elem'
|
|
3
|
+
import { LoadingOutlined } from '@ant-design/icons'
|
|
4
|
+
|
|
5
|
+
export default class ProfleFormIndex extends PureComponent {
|
|
6
|
+
state = {
|
|
7
|
+
ready: false
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
componentDidMount () {
|
|
11
|
+
this.timer = setTimeout(() => {
|
|
12
|
+
this.setState({
|
|
13
|
+
ready: true
|
|
14
|
+
})
|
|
15
|
+
}, 200)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
componentWillUnmount () {
|
|
19
|
+
clearTimeout(this.timer)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
render () {
|
|
23
|
+
const { ready } = this.state
|
|
24
|
+
if (!ready) {
|
|
25
|
+
return (
|
|
26
|
+
<div className='pd3 aligncenter'>
|
|
27
|
+
<LoadingOutlined />
|
|
28
|
+
</div>
|
|
29
|
+
)
|
|
30
|
+
}
|
|
31
|
+
return <ProfileCommandForm {...this.props} />
|
|
32
|
+
}
|
|
33
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* quick command list render
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import List from '../setting-panel/list'
|
|
6
|
+
import { PlusOutlined } from '@ant-design/icons'
|
|
7
|
+
import classnames from 'classnames'
|
|
8
|
+
import highlight from '../common/highlight'
|
|
9
|
+
import ProfileTransport from './profile-transport'
|
|
10
|
+
import {
|
|
11
|
+
settingMap
|
|
12
|
+
} from '../../common/constants'
|
|
13
|
+
|
|
14
|
+
export default class ProfileList extends List {
|
|
15
|
+
del = (item, e) => {
|
|
16
|
+
e.stopPropagation()
|
|
17
|
+
this.props.store.delItem(item, settingMap.profiles)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
onClickItem = (item) => {
|
|
21
|
+
this.props.onClickItem(item)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
renderItem = (item, i) => {
|
|
25
|
+
if (!item) {
|
|
26
|
+
return null
|
|
27
|
+
}
|
|
28
|
+
const { activeItemId } = this.props
|
|
29
|
+
const { name, id } = item
|
|
30
|
+
const cls = classnames(
|
|
31
|
+
'item-list-unit theme-item',
|
|
32
|
+
{
|
|
33
|
+
active: activeItemId === id
|
|
34
|
+
}
|
|
35
|
+
)
|
|
36
|
+
let title = name
|
|
37
|
+
title = highlight(
|
|
38
|
+
title,
|
|
39
|
+
this.state.keyword
|
|
40
|
+
)
|
|
41
|
+
return (
|
|
42
|
+
<div
|
|
43
|
+
key={i + id}
|
|
44
|
+
className={cls}
|
|
45
|
+
onClick={() => this.onClickItem(item)}
|
|
46
|
+
data-id={id}
|
|
47
|
+
>
|
|
48
|
+
<div className='elli pd1y pd2x' title={name}>
|
|
49
|
+
{
|
|
50
|
+
!id
|
|
51
|
+
? <PlusOutlined className='mg1r' />
|
|
52
|
+
: null
|
|
53
|
+
}
|
|
54
|
+
{title}
|
|
55
|
+
</div>
|
|
56
|
+
{this.renderDelBtn(item)}
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
renderTransport = () => {
|
|
62
|
+
return (
|
|
63
|
+
<ProfileTransport
|
|
64
|
+
store={this.props.store}
|
|
65
|
+
/>
|
|
66
|
+
)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
filter = list => {
|
|
70
|
+
const { keyword } = this.state
|
|
71
|
+
return keyword
|
|
72
|
+
? list.filter((item) => {
|
|
73
|
+
const n = (item.name || '').toLowerCase()
|
|
74
|
+
const k = keyword.toLowerCase()
|
|
75
|
+
return n.includes(k)
|
|
76
|
+
})
|
|
77
|
+
: list
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import ProfileTransportMod from './profile-transport-mod'
|
|
2
|
+
import { Component } from '../common/react-subx'
|
|
3
|
+
|
|
4
|
+
export default class ProfileTransport extends Component {
|
|
5
|
+
render () {
|
|
6
|
+
return (
|
|
7
|
+
<div className='pd1b'>
|
|
8
|
+
<ProfileTransportMod store={this.props.store} />
|
|
9
|
+
</div>
|
|
10
|
+
)
|
|
11
|
+
}
|
|
12
|
+
}
|