@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.
Files changed (37) hide show
  1. package/client/common/constants.js +7 -3
  2. package/client/common/create-title.jsx +12 -2
  3. package/client/common/default-setting.js +7 -1
  4. package/client/common/init-setting-item.js +6 -0
  5. package/client/components/bookmark-form/index.jsx +6 -2
  6. package/client/components/bookmark-form/rdp-form-ui.jsx +1 -1
  7. package/client/components/bookmark-form/rdp-form.jsx +1 -1
  8. package/client/components/bookmark-form/render-auth-ssh.jsx +27 -1
  9. package/client/components/bookmark-form/vnc-form-ui.jsx +179 -0
  10. package/client/components/bookmark-form/vnc-form.jsx +16 -0
  11. package/client/components/footer/footer-entry.jsx +1 -0
  12. package/client/components/main/term-fullscreen.styl +4 -1
  13. package/client/components/profile/profile-form-elem.jsx +87 -0
  14. package/client/components/profile/profile-form.jsx +33 -0
  15. package/client/components/profile/profile-list.jsx +79 -0
  16. package/client/components/profile/profile-transport-mod.jsx +5 -0
  17. package/client/components/profile/profile-transport.jsx +12 -0
  18. package/client/components/quick-commands/quick-command-transport-mod.jsx +13 -14
  19. package/client/components/rdp/rdp-session.jsx +53 -36
  20. package/client/components/session/session.jsx +14 -3
  21. package/client/components/session/session.styl +7 -2
  22. package/client/components/setting-panel/setting-common.jsx +1 -0
  23. package/client/components/setting-panel/setting-modal.jsx +14 -0
  24. package/client/components/setting-panel/setting-terminal.jsx +1 -1
  25. package/client/components/setting-panel/tab-profiles.jsx +38 -0
  26. package/client/components/sftp/list-table-ui.jsx +99 -46
  27. package/client/components/sftp/sftp-entry.jsx +1 -0
  28. package/client/components/sftp/sftp.styl +4 -1
  29. package/client/components/sftp/transfer-common.js +1 -1
  30. package/client/components/terminal/index.jsx +2 -4
  31. package/client/components/vnc/vnc-form.jsx +66 -0
  32. package/client/components/vnc/vnc-session.jsx +297 -0
  33. package/client/store/common.js +21 -0
  34. package/client/store/index.js +1 -0
  35. package/client/store/init-state.js +4 -23
  36. package/client/store/load-data.js +1 -2
  37. package/package.json +1 -1
@@ -0,0 +1,66 @@
1
+ /**
2
+ * web form
3
+ */
4
+
5
+ import {
6
+ Input,
7
+ Form,
8
+ Button
9
+ } from 'antd'
10
+ import { formItemLayout, tailFormItemLayout } from '../../common/form-layout'
11
+
12
+ const FormItem = Form.Item
13
+ const { prefix } = window
14
+ const e = prefix('form')
15
+ const s = prefix('sftp')
16
+
17
+ export default function VncForm (props) {
18
+ const [form] = Form.useForm()
19
+
20
+ const initialValues = props.types.reduce((acc, cur) => {
21
+ acc[cur] = ''
22
+ return acc
23
+ }, {})
24
+ function renderCommon () {
25
+ const {
26
+ types
27
+ } = props
28
+ return types.map((type, index) => {
29
+ const Elem = type === 'password' ? Input.Password : Input
30
+ return (
31
+ <FormItem
32
+ {...formItemLayout}
33
+ label={e(type)}
34
+ name={type}
35
+ key={type}
36
+ autoFocus={index === 0}
37
+ >
38
+ <Elem />
39
+ </FormItem>
40
+ )
41
+ })
42
+ }
43
+
44
+ return (
45
+ <Form
46
+ form={form}
47
+ onFinish={props.handleFinish}
48
+ initialValues={initialValues}
49
+ name='vnc-form'
50
+ >
51
+ <div className='pd3t pd1b'>
52
+ {renderCommon()}
53
+ <FormItem
54
+ {...tailFormItemLayout}
55
+ >
56
+ <Button
57
+ type='primary'
58
+ htmlType='submit'
59
+ >
60
+ {s('submit')}
61
+ </Button>
62
+ </FormItem>
63
+ </div>
64
+ </Form>
65
+ )
66
+ }
@@ -0,0 +1,297 @@
1
+ import RdpSession from '../rdp/rdp-session'
2
+ import { createTerm } from '../terminal/terminal-apis'
3
+ import deepCopy from 'json-deep-copy'
4
+ import clone from '../../common/to-simple-obj'
5
+ import { handleErr } from '../../common/fetch'
6
+ import {
7
+ statusMap
8
+ } from '../../common/constants'
9
+ import {
10
+ Spin,
11
+ message,
12
+ Modal,
13
+ Tag
14
+ } from 'antd'
15
+ import * as ls from '../../common/safe-local-storage'
16
+ import { copy } from '../../common/clipboard'
17
+ import resolutions from '../rdp/resolutions'
18
+ import RFB from '@novnc/novnc/core/rfb'
19
+ import VncForm from './vnc-form'
20
+
21
+ const { prefix } = window
22
+ const e = prefix('form')
23
+
24
+ export default class VncSession extends RdpSession {
25
+ constructor (props) {
26
+ const id = `vnc-reso-${props.tab.host}`
27
+ const resObj = ls.getItemJSON(id, resolutions[0])
28
+ super(props)
29
+ this.state = {
30
+ types: [],
31
+ showConfirm: false,
32
+ loading: false,
33
+ aspectRatio: 4 / 3,
34
+ name: '',
35
+ ...resObj
36
+ }
37
+ }
38
+
39
+ componentDidMount () {
40
+ this.remoteInit()
41
+ }
42
+
43
+ componentWillUnmount () {
44
+ this.rfb && this.rfb.disconnect()
45
+ delete this.rfb
46
+ }
47
+
48
+ // computeProps = () => {
49
+ // const {
50
+ // height,
51
+ // width,
52
+ // tabsHeight,
53
+ // leftSidebarWidth,
54
+ // pinned,
55
+ // openedSideBar
56
+ // } = this.props
57
+ // return {
58
+ // width: width - (pinned && openedSideBar ? leftSidebarWidth : 0),
59
+ // height: height - tabsHeight
60
+ // }
61
+ // }
62
+
63
+ remoteInit = async (term = this.term) => {
64
+ this.setState({
65
+ loading: true
66
+ })
67
+ const { config } = this.props
68
+ const {
69
+ host,
70
+ port,
71
+ tokenElecterm,
72
+ server = ''
73
+ } = config
74
+ const { sessionId, id } = this.props
75
+ const tab = deepCopy(this.props.tab || {})
76
+ const {
77
+ type,
78
+ term: terminalType,
79
+ viewOnly = false,
80
+ scaleViewport = true,
81
+ username,
82
+ password
83
+ } = tab
84
+ const opts = clone({
85
+ term: terminalType || config.terminalType,
86
+ sessionId,
87
+ tabId: id,
88
+ srcTabId: tab.id,
89
+ termType: type,
90
+ ...tab
91
+ })
92
+ let pid = await createTerm(opts)
93
+ .catch(err => {
94
+ const text = err.message
95
+ handleErr({ message: text })
96
+ })
97
+ pid = pid || ''
98
+ this.setState({
99
+ loading: false
100
+ })
101
+ if (!pid) {
102
+ this.setStatus(statusMap.error)
103
+ return
104
+ }
105
+ this.setStatus(statusMap.success)
106
+ this.pid = pid
107
+ const hs = server
108
+ ? server.replace(/https?:\/\//, '')
109
+ : `${host}:${port}`
110
+ const pre = server.startsWith('https') ? 'wss' : 'ws'
111
+ const { width, height } = this.state
112
+ const wsUrl = `${pre}://${hs}/vnc/${pid}?sessionId=${sessionId}&token=${tokenElecterm}&width=${width}&height=${height}`
113
+ const vncOpts = {
114
+ scaleViewport,
115
+ viewOnly,
116
+ style: {
117
+ width: width + 'px',
118
+ height: height + 'px',
119
+ overflow: 'scroll'
120
+ },
121
+ credentials: {}
122
+ }
123
+ if (username) {
124
+ vncOpts.credentials.username = username
125
+ }
126
+ if (password) {
127
+ vncOpts.credentials.password = password
128
+ }
129
+ const rfb = new RFB(
130
+ this.getDom(),
131
+ wsUrl,
132
+ vncOpts
133
+ )
134
+ const events = [
135
+ 'connect',
136
+ 'disconnect',
137
+ 'credentialsrequired',
138
+ 'securityfailure',
139
+ 'clipboard',
140
+ 'bell',
141
+ 'desktopname',
142
+ 'capabilities'
143
+ ]
144
+ for (const event of events) {
145
+ rfb.addEventListener(event, this[`on${window.capitalizeFirstLetter(event)}`])
146
+ }
147
+ this.rfb = rfb
148
+ }
149
+
150
+ onConnect = (event) => {
151
+ // console.log('onConnect', event)
152
+ this.setStatus(statusMap.success)
153
+ this.setState({
154
+ loading: false
155
+ })
156
+ }
157
+
158
+ onDisconnect = () => {
159
+ this.setStatus(statusMap.error)
160
+ }
161
+
162
+ onSecurityfailure = (event) => {
163
+ // console.log('onSecurityFailure', event)
164
+ message.error('Security Failure: ' + event.detail?.reason)
165
+ }
166
+
167
+ onOk = (res) => {
168
+ this.setState({
169
+ showConfirm: false
170
+ })
171
+ this.rfb?.sendCredentials(res)
172
+ }
173
+
174
+ onCredentialsrequired = (event) => {
175
+ this.setState({
176
+ types: event.detail?.types || [],
177
+ showConfirm: true
178
+ })
179
+ }
180
+
181
+ renderForm (types = this.state.types) {
182
+ return (
183
+ <VncForm
184
+ types={types}
185
+ handleFinish={this.onOk}
186
+ />
187
+ )
188
+ }
189
+
190
+ onClipboard = (event) => {
191
+ // console.log('onClipboard', event)
192
+ copy(event.detail.text)
193
+ }
194
+
195
+ onBell = (event) => {
196
+ // console.log('Bell', event)
197
+ message.warning('Bell')
198
+ }
199
+
200
+ onDesktopname = (event) => {
201
+ this.setState({
202
+ name: event?.detail?.name || ''
203
+ })
204
+ }
205
+
206
+ onCapabilities = (capabilities) => {
207
+ console.log('onCapabilities', capabilities)
208
+ }
209
+
210
+ getDom = () => {
211
+ const id = 'canvas_' + this.props.tab.id
212
+ return document.getElementById(id)
213
+ }
214
+
215
+ handleReInit = () => {
216
+ this.rfb?.disconnect()
217
+ delete this.rfb
218
+ this.remoteInit()
219
+ }
220
+
221
+ renderInfo () {
222
+ const {
223
+ name
224
+ } = this.state
225
+ const {
226
+ host,
227
+ port,
228
+ username
229
+ } = this.props.tab
230
+ return (
231
+ <span className='mg2l mg2r'>
232
+ <b>{name}</b> {username}@{host}:{port}
233
+ </span>
234
+ )
235
+ }
236
+
237
+ renderHelp = () => {
238
+ return (
239
+ <Tag color='red' className='mg1l'>Beta</Tag>
240
+ )
241
+ }
242
+
243
+ renderConfirm () {
244
+ const {
245
+ showConfirm
246
+ } = this.state
247
+ if (!showConfirm) {
248
+ return null
249
+ }
250
+ const confirmProps = {
251
+ title: e('credentialsRequired'),
252
+ content: this.renderForm(['password']),
253
+ footer: null,
254
+ visible: true
255
+ }
256
+ return (
257
+ <Modal
258
+ {...confirmProps}
259
+ >
260
+ {this.renderForm()}
261
+ </Modal>
262
+ )
263
+ }
264
+
265
+ render () {
266
+ const { width: w, height: h } = this.computeProps()
267
+ const vncProps = {
268
+ style: {
269
+ width: w + 'px',
270
+ height: h + 'px'
271
+ }
272
+ }
273
+ const { width, height, loading } = this.state
274
+ const divProps = {
275
+ style: {
276
+ width: width + 'px',
277
+ height: height + 'px'
278
+ }
279
+ }
280
+ return (
281
+ <Spin spinning={loading}>
282
+ <div
283
+ {...vncProps}
284
+ className='rdp-session-wrap pd1'
285
+ >
286
+ {this.renderControl()}
287
+ <div
288
+ {...divProps}
289
+ className='vnc-session-wrap session-v-wrap'
290
+ id={'canvas_' + this.props.tab.id}
291
+ />
292
+ {this.renderConfirm()}
293
+ </div>
294
+ </Spin>
295
+ )
296
+ }
297
+ }
@@ -211,4 +211,25 @@ export default Store => {
211
211
  terminalInfos: arr
212
212
  })
213
213
  }
214
+
215
+ Store.prototype.applyProfile = function (tab) {
216
+ const {
217
+ authType,
218
+ profile
219
+ } = tab
220
+ if (authType !== 'profiles') {
221
+ return tab
222
+ }
223
+ const p = window.store.profiles.find(x => x.id === profile)
224
+ if (!p) {
225
+ return tab
226
+ }
227
+ // delete tab.password
228
+ // delete tab.privateKey
229
+ // delete tab.passphrase
230
+ return {
231
+ ...tab,
232
+ ...p
233
+ }
234
+ }
214
235
  }
@@ -282,6 +282,7 @@ const getterProps = [
282
282
  'history',
283
283
  'bookmarks',
284
284
  'bookmarkGroups',
285
+ 'profiles',
285
286
  'tabs',
286
287
  'fileTransfers',
287
288
  'transferHistory',
@@ -5,7 +5,6 @@
5
5
  import {
6
6
  settingMap,
7
7
  defaultBookmarkGroupId,
8
- newBookmarkIdPrefix,
9
8
  fileOperationsMap,
10
9
  syncTypes,
11
10
  infoTabs,
@@ -22,14 +21,12 @@ import {
22
21
  qmSortByFrequencyKey,
23
22
  resolutionsLsKey
24
23
  } from '../common/constants'
25
- import { buildDefaultThemes, buildNewTheme } from '../common/terminal-theme'
24
+ import { buildDefaultThemes } from '../common/terminal-theme'
26
25
  import * as ls from '../common/safe-local-storage'
26
+ import initSettingItem from '../common/init-setting-item'
27
27
 
28
28
  const { prefix } = window
29
29
  const t = prefix('terminalThemes')
30
- const e = prefix('common')
31
- const newQuickCommand = 'newQuickCommand'
32
- const q = prefix('quickCommands')
33
30
 
34
31
  function getDefaultBookmarkGroups (bookmarks) {
35
32
  return [
@@ -41,23 +38,6 @@ function getDefaultBookmarkGroups (bookmarks) {
41
38
  ]
42
39
  }
43
40
 
44
- export const getInitItem = (arr, tab) => {
45
- if (tab === settingMap.history) {
46
- return arr[0] || {}
47
- } else if (tab === settingMap.bookmarks) {
48
- return { id: newBookmarkIdPrefix + ':' + (Date.now()), title: '' }
49
- } else if (tab === settingMap.setting) {
50
- return { id: '', title: e('common') }
51
- } else if (tab === settingMap.terminalThemes) {
52
- return buildNewTheme()
53
- } else if (tab === settingMap.quickCommands) {
54
- return {
55
- id: '',
56
- name: q(newQuickCommand)
57
- }
58
- }
59
- }
60
-
61
41
  export default () => {
62
42
  return {
63
43
  // common
@@ -70,6 +50,7 @@ export default () => {
70
50
  termFocused: false,
71
51
  _history: '[]',
72
52
  _bookmarks: '[]',
53
+ _profiles: '[]',
73
54
  _bookmarkGroups: JSON.stringify(
74
55
  getDefaultBookmarkGroups([])
75
56
  ),
@@ -113,7 +94,7 @@ export default () => {
113
94
 
114
95
  // for settings related
115
96
  _setting: '',
116
- _settingItem: JSON.stringify(getInitItem([], settingMap.bookmarks)),
97
+ _settingItem: JSON.stringify(initSettingItem([], settingMap.bookmarks)),
117
98
  settingTab: settingMap.bookmarks, // setting tab
118
99
  autofocustrigger: Date.now(),
119
100
  bookmarkId: undefined,
@@ -80,7 +80,6 @@ export async function addTabFromCommandLine (store, opts) {
80
80
  conf.privateKey = await fs.readFile(options.privateKeyPath)
81
81
  }
82
82
  log.debug('command line opts', conf)
83
- console.log(options.initFolder, !(store.config.onStartSessions || []).length, store.config.initDefaultTabOnStart)
84
83
  if (conf.username && conf.host) {
85
84
  store.addTab(conf)
86
85
  } else if (
@@ -178,7 +177,7 @@ export default (Store) => {
178
177
  await Promise.all(all)
179
178
  .then(arr => {
180
179
  for (const { name, data } of arr) {
181
- ext['_' + name] = data
180
+ ext['_' + name] = data || '[]'
182
181
  }
183
182
  })
184
183
  ext.lastDataUpdateTime = await getData('lastDataUpdateTime') || 0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.39.18",
3
+ "version": "1.39.35",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",