@electerm/electerm-react 1.38.70 → 1.38.81

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.
@@ -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'
@@ -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 (initType === terminalTelnetType) {
37
- initType = terminalTelnetType
38
- } else if (initType === terminalSerialType) {
39
- initType = terminalSerialType
40
- } else if (initType === terminalLocalType) {
41
- initType = terminalLocalType
42
- } else {
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) => {
@@ -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
+ }
@@ -8,7 +8,7 @@
8
8
  left 43px
9
9
  right 0
10
10
  color text
11
- z-index 200
11
+ z-index 89
12
12
  height auto
13
13
  bottom 36px
14
14
  background alpha(main-dark, .9)
@@ -55,4 +55,7 @@
55
55
  .no-sessions
56
56
  background main-dark
57
57
  text-align center
58
- padding 50px 0
58
+ padding 50px 0
59
+ .web-session-wrap
60
+ height 100vh
61
+ background main
@@ -1,5 +1,6 @@
1
1
  import { Component } from '../common/react-subx'
2
2
  import Session from './session'
3
+ import WebSession from './web-session'
3
4
  import { findIndex, pick } from 'lodash-es'
4
5
  import classNames from 'classnames'
5
6
  import generate from '../../common/uid'
@@ -11,7 +12,8 @@ import {
11
12
  tabActions,
12
13
  termInitId,
13
14
  paneMap,
14
- statusMap
15
+ statusMap,
16
+ terminalWebType
15
17
  } from '../../common/constants'
16
18
  import newTerm, { updateCount } from '../../common/new-terminal'
17
19
  import postMsg from '../../common/post-msg'
@@ -336,7 +338,7 @@ class Sessions extends Component {
336
338
  return this.renderNoSession()
337
339
  }
338
340
  return tabs.map((tab) => {
339
- const { id } = tab
341
+ const { id, type } = tab
340
342
  const cls = classNames(
341
343
  `session-wrap session-${id}`,
342
344
  {
@@ -372,6 +374,18 @@ class Sessions extends Component {
372
374
  'editTab'
373
375
  ])
374
376
  }
377
+ if (type === terminalWebType) {
378
+ const webProps = {
379
+ tab
380
+ }
381
+ return (
382
+ <div className={cls} key={id}>
383
+ <WebSession
384
+ {...webProps}
385
+ />
386
+ </div>
387
+ )
388
+ }
375
389
  return (
376
390
  <div className={cls} key={id}>
377
391
  <Session
@@ -0,0 +1,20 @@
1
+ import { useEffect } from 'react'
2
+ import Link from '../common/external-link'
3
+
4
+ export default function WebSession (props) {
5
+ const {
6
+ tab
7
+ } = props
8
+ useEffect(() => {
9
+ tab.url && window.openLink(tab.url)
10
+ }, [])
11
+ return (
12
+ <div className='web-session-wrap'>
13
+ <div className='pd3 aligncenter'>
14
+ <h1>{tab.title}</h1>
15
+ <p>{tab.description}</p>
16
+ <Link to={tab.url}>{tab.url}</Link>
17
+ </div>
18
+ </div>
19
+ )
20
+ }
@@ -138,9 +138,13 @@ class Term extends Component {
138
138
  clearTimeout(this.timers[k])
139
139
  })
140
140
  this.onClose = true
141
- this.socket && this.socket.close()
141
+ if (this.socket) {
142
+ this.socket.close()
143
+ delete this.socket
144
+ }
142
145
  if (this.term) {
143
146
  this.term.dispose()
147
+ delete this.term
144
148
  }
145
149
  window.removeEventListener(
146
150
  'resize',
@@ -149,6 +153,13 @@ class Term extends Component {
149
153
  window.removeEventListener('message', this.handleEvent)
150
154
  this.dom.removeEventListener('contextmenu', this.onContextMenu)
151
155
  window.removeEventListener('message', this.onContextAction)
156
+ delete this.dom
157
+ delete this.attachAddon
158
+ delete this.fitAddon
159
+ delete this.zmodemAddon
160
+ delete this.searchAddon
161
+ delete this.serializeAddon
162
+ delete this.fitAddon
152
163
  }
153
164
 
154
165
  terminalConfigProps = [
@@ -1226,6 +1237,7 @@ class Term extends Component {
1226
1237
  this.socketCloseWarning = notification.warning({
1227
1238
  key,
1228
1239
  message: e('socketCloseTip'),
1240
+ duration: 30,
1229
1241
  description: (
1230
1242
  <div className='pd2y'>
1231
1243
  <Button
@@ -16,7 +16,11 @@ function createWs (
16
16
  const wsUrl = `ws://${host}:${port}/${type}/${id}?sessionId=${sessionId}&sftpId=${sftpId}&token=${tokenElecterm}`
17
17
  const ws = new WebSocket(wsUrl)
18
18
  ws.s = msg => {
19
- ws.send(JSON.stringify(msg))
19
+ try {
20
+ ws.send(JSON.stringify(msg))
21
+ } catch (e) {
22
+ console.error('ws send error', e)
23
+ }
20
24
  }
21
25
  ws.id = id
22
26
  ws.once = (callack, id) => {
@@ -63,7 +63,18 @@ function expandShorthandColor (color) {
63
63
  if (color.length === 4) {
64
64
  return '#' + color[1] + color[1] + color[2] + color[2] + color[3] + color[3]
65
65
  }
66
- return color
66
+ if (color.length === 7) {
67
+ return color
68
+ }
69
+ if (color.length < 7) {
70
+ return expandShorthandColor(color + 'f')
71
+ }
72
+ if (color.length > 7) {
73
+ return expandShorthandColor(color.slice(0, 7))
74
+ }
75
+ if (!/^#[A-Fa-f0-9]{6}$/.test(color)) {
76
+ return '#141314'
77
+ }
67
78
  }
68
79
 
69
80
  function isColorDark (_color) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.38.70",
3
+ "version": "1.38.81",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",