@electerm/electerm-react 1.39.56 → 1.39.76

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.
@@ -22,6 +22,7 @@ import {
22
22
  modals
23
23
  } from '../../common/constants'
24
24
  import HelpIcon from '../common/help-icon'
25
+ import download from '../../common/download'
25
26
  import { autoRun } from 'manate'
26
27
  import { pick } from 'lodash-es'
27
28
  import { runCmd } from '../terminal/terminal-apis'
@@ -48,6 +49,45 @@ export default class BatchOp extends Component {
48
49
  tab: 'tasks'
49
50
  }
50
51
 
52
+ exampleColumns = [
53
+ { title: f('host'), dataIndex: 'host', key: 'host' },
54
+ { title: f('port'), dataIndex: 'port', key: 'port', responsive: ['md'] },
55
+ { title: f('username'), dataIndex: 'username', key: 'username', responsive: ['lg'] },
56
+ { title: f('password'), dataIndex: 'password', key: 'password', responsive: ['xl'] },
57
+ { title: 'Command', dataIndex: 'command', key: 'command', responsive: ['lg'] },
58
+ { title: t('localPath'), dataIndex: 'localPath', key: 'localPath', responsive: ['xl'] },
59
+ { title: t('remotePath'), dataIndex: 'remotePath', key: 'remotePath', responsive: ['xl'] },
60
+ { title: 'Action', dataIndex: 'action', key: 'action', responsive: ['md'] },
61
+ { title: 'Command After', dataIndex: 'commandAfter', key: 'commandAfter', responsive: ['xl'] }
62
+ ]
63
+
64
+ exampleData = [
65
+ {
66
+ key: '1',
67
+ host: '192.168.1.3',
68
+ port: '22',
69
+ username: 'username',
70
+ password: 'password',
71
+ command: 'touch yy.js && ls -al',
72
+ localPath: '/home/user/some_local_file_or_folder_to_upload',
73
+ remotePath: '/server/some_server_folder_for_upload',
74
+ action: 'upload',
75
+ commandAfter: 'touch yy1.js && ls -al'
76
+ },
77
+ {
78
+ key: '2',
79
+ host: '192.168.1.3',
80
+ port: '22',
81
+ username: 'username',
82
+ password: 'password',
83
+ command: 'ls -al',
84
+ localPath: '/home/user/some_local_folder_for_download',
85
+ remotePath: '/server/some_server_file_or_folder',
86
+ action: 'download',
87
+ commandAfter: 'ls'
88
+ }
89
+ ]
90
+
51
91
  componentDidMount () {
52
92
  this.watch()
53
93
  }
@@ -64,6 +104,15 @@ export default class BatchOp extends Component {
64
104
  window.removeEventListener('message', this.handleEvent)
65
105
  }
66
106
 
107
+ handleDownloadExample = () => {
108
+ const csvText = this.exampleData.map(d => {
109
+ return Object.keys(d).filter(d => d !== 'key').map(k => {
110
+ return d[k]
111
+ }).join(',')
112
+ }).join('\n')
113
+ download('batch-op-example.csv', csvText)
114
+ }
115
+
67
116
  handleEvent = e => {
68
117
  if (e && e.data && e.data.action === commonActions.batchOp) {
69
118
  const {
@@ -448,6 +497,14 @@ export default class BatchOp extends Component {
448
497
  working
449
498
  } = this.state
450
499
  const disabled = loading || working
500
+ const exampleTableProps = {
501
+ dataSource: this.exampleData,
502
+ columns: this.exampleColumns,
503
+ pagination: false,
504
+ size: 'small',
505
+ rowKey: 'key'
506
+ }
507
+
451
508
  return (
452
509
  <div>
453
510
  <div className='pd1y'>
@@ -458,12 +515,25 @@ export default class BatchOp extends Component {
458
515
  />
459
516
  </h2>
460
517
  <div className='pd1y'>{c('examples')}:</div>
461
- <pre>
462
- <code>"192.168.1.3","22","username","password","touch yy.js && ls -al","/home/user/some_local_file_or_folder_to_upload","/server/some_server_folder_for_upload","upload","touch yy1.js && ls -al"</code>
463
- </pre>
464
- <pre>
465
- <code>"192.168.1.3","22","username","password","ls -al","/home/user/some_local_folder_for_download","/server/some_server_file_or_folder","download","ls"</code>
466
- </pre>
518
+ <Table
519
+ {...exampleTableProps}
520
+ />
521
+ <div className='pd1t pd2b'>
522
+ <Button
523
+ onClick={this.handleDownloadExample}
524
+ type='dashed'
525
+ >
526
+ Download example csv
527
+ </Button>
528
+ </div>
529
+ <div className='pd2y'>
530
+ <pre>
531
+ <code>"192.168.1.3","22","username","password","touch yy.js && ls -al","/home/user/some_local_file_or_folder_to_upload","/server/some_server_folder_for_upload","upload","touch yy1.js && ls -al"</code>
532
+ </pre>
533
+ <pre>
534
+ <code>"192.168.1.3","22","username","password","ls -al","/home/user/some_local_folder_for_download","/server/some_server_file_or_folder","download","ls"</code>
535
+ </pre>
536
+ </div>
467
537
  </div>
468
538
  {this.renderErrors()}
469
539
  <div className='pd1y'>
@@ -24,6 +24,13 @@ export default function renderAuth (props) {
24
24
  form,
25
25
  authType
26
26
  } = props
27
+ const beforeUpload = async (file) => {
28
+ const privateKey = await window.fs.readFile(file.path)
29
+ form.setFieldsValue({
30
+ privateKey
31
+ })
32
+ return false
33
+ }
27
34
  if (authType === 'password') {
28
35
  const opts = {
29
36
  options: uniqBy(
@@ -101,7 +108,7 @@ export default function renderAuth (props) {
101
108
  />
102
109
  </FormItem>
103
110
  <Upload
104
- beforeUpload={file => props.beforeUpload(file, form)}
111
+ beforeUpload={beforeUpload}
105
112
  fileList={[]}
106
113
  >
107
114
  <Button
@@ -307,17 +307,8 @@ export default class BookmarkForm extends PureComponent {
307
307
  }
308
308
  }
309
309
 
310
- beforeUpload = async (file, form) => {
311
- const privateKey = await window.fs.readFile(file.path)
312
- form.setFieldsValue({
313
- privateKey
314
- })
315
- return false
316
- }
317
-
318
310
  getProps = () => {
319
311
  const funcs = pick(this, [
320
- 'beforeUpload',
321
312
  'handleFinish',
322
313
  'testConnection',
323
314
  'connect',
@@ -17,7 +17,7 @@ const {
17
17
  const { prefix } = window
18
18
  const f = prefix('form')
19
19
 
20
- export default class SystemMenu extends Component {
20
+ export default class FooterEntry extends Component {
21
21
  handleInfoPanel = () => {
22
22
  const { activeTerminalId } = this.props.store
23
23
  postMessage({
@@ -18,7 +18,7 @@ export default class QuickCommandsItem extends PureComponent {
18
18
  }
19
19
 
20
20
  render () {
21
- const { name, id, nameMatch, labelMatch } = this.props.item
21
+ const { name, id, nameMatch, labelMatch, shortcut } = this.props.item
22
22
  const {
23
23
  draggable,
24
24
  handleDragOver,
@@ -29,16 +29,20 @@ export default class QuickCommandsItem extends PureComponent {
29
29
  'name-match': nameMatch,
30
30
  'label-match': labelMatch
31
31
  })
32
+ const btnProps = {
33
+ className: cls,
34
+ onClick: this.handleSelect,
35
+ 'data-id': id,
36
+ title: shortcut,
37
+ draggable,
38
+ onDragOver: handleDragOver,
39
+ onDragStart: handleDragStart,
40
+ onDrop: handleDrop
41
+ }
32
42
  return (
33
43
  <Button
34
44
  key={id}
35
- className={cls}
36
- onClick={this.handleSelect}
37
- data-id={id}
38
- draggable={draggable}
39
- onDragOver={handleDragOver}
40
- onDragStart={handleDragStart}
41
- onDrop={handleDrop}
45
+ {...btnProps}
42
46
  >
43
47
  {name}
44
48
  </Button>
@@ -3,13 +3,11 @@
3
3
  */
4
4
 
5
5
  import { Component } from '../common/react-subx'
6
- import { isWin, quickCommandLabelsLsKey } from '../../common/constants'
7
- import { find, sortBy } from 'lodash-es'
6
+ import { quickCommandLabelsLsKey } from '../../common/constants'
7
+ import { sortBy } from 'lodash-es'
8
8
  import { Button, Input, Select, Space } from 'antd'
9
9
  import * as ls from '../../common/safe-local-storage'
10
- import generate from '../../common/uid'
11
10
  import CmdItem from './quick-command-item'
12
- import delay from '../../common/wait'
13
11
  import {
14
12
  EditOutlined,
15
13
  CloseCircleOutlined,
@@ -54,33 +52,7 @@ export default class QuickCommandsFooterBox extends Component {
54
52
  if (id === addQuickCommands) {
55
53
  store.handleOpenQuickCommandsSetting()
56
54
  } else {
57
- const qm = find(
58
- this.props.store.currentQuickCommands,
59
- a => a.id === id
60
- )
61
- const { runQuickCommand } = this.props.store
62
- const qms = qm && qm.commands
63
- ? qm.commands
64
- : (qm && qm.command
65
- ? [
66
- {
67
- command: qm.command,
68
- id: generate(),
69
- delay: 100
70
- }
71
- ]
72
- : []
73
- )
74
- for (const q of qms) {
75
- const realCmd = isWin
76
- ? q.command.replace(/\n/g, '\n\r')
77
- : q.command
78
- await delay(q.delay || 100)
79
- runQuickCommand(realCmd, qm.inputOnly)
80
- store.editQuickCommand(qm.id, {
81
- clickCount: ((qm.clickCount || 0) + 1)
82
- })
83
- }
55
+ store.runQuickCommandItem(id)
84
56
  }
85
57
  }
86
58
 
@@ -195,7 +167,9 @@ export default class QuickCommandsFooterBox extends Component {
195
167
  openQuickCommandBar,
196
168
  pinnedQuickCommandBar,
197
169
  qmSortByFrequency,
198
- inActiveTerminal
170
+ inActiveTerminal,
171
+ leftSidebarWidth,
172
+ openedSideBar
199
173
  } = this.props.store
200
174
  if ((!openQuickCommandBar && !pinnedQuickCommandBar) || !inActiveTerminal) {
201
175
  return null
@@ -233,11 +207,18 @@ export default class QuickCommandsFooterBox extends Component {
233
207
  { 'fil-keyword': !!keyword }
234
208
  )
235
209
  const type = qmSortByFrequency ? 'primary' : 'default'
210
+ const w = openedSideBar ? 43 + leftSidebarWidth : 43
211
+ const qmProps = {
212
+ className: 'qm-wrap-tooltip',
213
+ style: {
214
+ left: w
215
+ },
216
+ onMouseLeave: this.handleMouseLeave,
217
+ onMouseEnter: this.handleMouseEnter
218
+ }
236
219
  return (
237
220
  <div
238
- className='qm-wrap-tooltip'
239
- onMouseLeave={this.handleMouseLeave}
240
- onMouseEnter={this.handleMouseEnter}
221
+ {...qmProps}
241
222
  >
242
223
  <div className='pd2'>
243
224
  <div className='pd2b fix'>
@@ -1,48 +1,118 @@
1
- import { Button, Switch, Form, message, Select } from 'antd'
2
- import copy from 'json-deep-copy'
1
+ import {
2
+ Button,
3
+ Switch,
4
+ Form,
5
+ message,
6
+ Select,
7
+ Input
8
+ } from 'antd'
9
+ import { useState } from 'react'
3
10
  import generate from '../../common/uid'
4
11
  import InputAutoFocus from '../common/input-auto-focus'
5
12
  import renderQm from './quick-commands-list-form'
13
+ import ShortcutEdit from '../shortcuts/shortcut-editor'
14
+ import shortcutsDefaultsGen from '../shortcuts/shortcuts-defaults'
15
+ import deepCopy from 'json-deep-copy'
16
+ import {
17
+ isMacJs as isMac
18
+ } from '../../common/constants.js'
19
+
6
20
  const FormItem = Form.Item
7
21
  const { Option } = Select
8
22
  const { prefix } = window
9
23
  const e = prefix('form')
10
24
  const t = prefix('quickCommands')
11
25
  const s = prefix('setting')
26
+ const shortcutsDefaults = shortcutsDefaultsGen()
12
27
 
13
28
  export default function QuickCommandForm (props) {
14
29
  const [form] = Form.useForm()
15
- const { autofocustrigger, quickCommandTags = [] } = props.store
30
+ const { store, formData } = props
31
+ const { autofocustrigger, quickCommandTags = [] } = store
32
+ const [shortcut, setShortcut] = useState(formData.shortcut || '')
33
+ const uid = formData.id || generate()
34
+ const updateConfig = (name, value) => {
35
+ form.setFieldsValue({
36
+ shortcut: value
37
+ })
38
+ setShortcut(value)
39
+ }
40
+ const handleClear = () => {
41
+ console.log('handleClear')
42
+ form.setFieldsValue({
43
+ shortcut: ''
44
+ })
45
+ setShortcut('')
46
+ }
47
+ const getKeysTakenData = () => {
48
+ const { shortcuts = {} } = store.config
49
+ const { quickCommands = [] } = store
50
+
51
+ // Gather system shortcuts
52
+ const systemShortcuts = shortcutsDefaults.reduce((p, k) => {
53
+ const propName = isMac ? 'shortcutMac' : 'shortcut'
54
+ const name = k.name + '_' + propName
55
+ const vv = k.readonly ? k[propName] : (shortcuts[name] || k[propName])
56
+ const v = vv
57
+ .split(',')
58
+ .map(f => f.trim())
59
+ .reduce((p, k) => ({
60
+ ...p,
61
+ [k]: true
62
+ }), {})
63
+ return {
64
+ ...p,
65
+ ...v
66
+ }
67
+ }, {})
68
+
69
+ // Gather quick command shortcuts
70
+ const quickCommandShortcuts = quickCommands.reduce((acc, command) => {
71
+ if (command.shortcut) {
72
+ acc[command.shortcut] = true
73
+ }
74
+ return acc
75
+ }, {})
76
+
77
+ // Combine system shortcuts and quick command shortcuts
78
+ return {
79
+ ...systemShortcuts,
80
+ ...quickCommandShortcuts
81
+ }
82
+ }
83
+
16
84
  async function handleSubmit (res) {
17
85
  const { formData } = props
18
86
  const {
19
87
  name,
20
88
  commands,
21
89
  inputOnly,
22
- labels
90
+ labels,
91
+ shortcut
23
92
  } = res
24
- const update = copy({
93
+ const update = deepCopy({
25
94
  name,
26
95
  commands,
27
96
  inputOnly,
28
- labels
97
+ labels,
98
+ shortcut
29
99
  })
30
100
  const update1 = {
31
101
  ...update,
32
- id: generate()
102
+ id: uid
33
103
  }
34
104
  if (formData.id) {
35
- props.store.editQuickCommand(formData.id, update)
105
+ store.editQuickCommand(formData.id, update)
36
106
  } else {
37
- props.store.addQuickCommand(update1)
38
- props.store.setSettingItem({
107
+ store.addQuickCommand(update1)
108
+ store.setSettingItem({
39
109
  id: '',
40
110
  name: t('newQuickCommand')
41
111
  })
42
112
  }
43
113
  message.success(s('saved'))
44
114
  }
45
- const initialValues = props.formData
115
+ const initialValues = formData
46
116
  if (!initialValues.labels) {
47
117
  initialValues.labels = []
48
118
  }
@@ -53,6 +123,18 @@ export default function QuickCommandForm (props) {
53
123
  delay: 100
54
124
  }]
55
125
  }
126
+ console.log('initialValues', initialValues, formData)
127
+ const editorProps = {
128
+ data: {
129
+ name: uid,
130
+ shortcut
131
+ },
132
+ keysTaken: getKeysTakenData(),
133
+ store,
134
+ updateConfig,
135
+ handleClear,
136
+ renderClear: true
137
+ }
56
138
  return (
57
139
  <Form
58
140
  form={form}
@@ -95,6 +177,17 @@ export default function QuickCommandForm (props) {
95
177
  }
96
178
  </Select>
97
179
  </FormItem>
180
+ <FormItem
181
+ label={s('settingShortcuts')}
182
+ name='shortcut'
183
+ >
184
+ <div>
185
+ <Input className='hide' />
186
+ <ShortcutEdit
187
+ {...editorProps}
188
+ />
189
+ </div>
190
+ </FormItem>
98
191
  <FormItem
99
192
  label={t('inputOnly')}
100
193
  name='inputOnly'
@@ -26,6 +26,10 @@ export default function KeywordForm (props) {
26
26
  formChild.submit()
27
27
  }
28
28
 
29
+ function handleChange (e) {
30
+ formChild.submit()
31
+ }
32
+
29
33
  function handleFinish (data) {
30
34
  props.submit(data)
31
35
  }
@@ -34,7 +38,7 @@ export default function KeywordForm (props) {
34
38
  try {
35
39
  return Promise.resolve(!!new RegExp(`(${value})`, 'gi'))
36
40
  } catch (e) {
37
- console.log(e)
41
+ console.log(e, 'check keyword error')
38
42
  return Promise.reject(e)
39
43
  }
40
44
  }
@@ -57,6 +61,7 @@ export default function KeywordForm (props) {
57
61
  >
58
62
  <Input
59
63
  addonBefore={renderBefore(field.name)}
64
+ onChange={handleChange}
60
65
  />
61
66
  </FormItem>
62
67
  </FormItem>
@@ -121,7 +126,9 @@ export default function KeywordForm (props) {
121
126
  <FormItem>
122
127
  <Button
123
128
  type='dashed'
124
- onClick={() => add()}
129
+ onClick={() => add({
130
+ color: 'red'
131
+ })}
125
132
  icon={<PlusOutlined />}
126
133
  >
127
134
  {f('keyword')}
@@ -143,16 +143,30 @@ export default class ShortcutEdit extends PureComponent {
143
143
  return (
144
144
  <Button
145
145
  className='edit-shortcut-button'
146
- onClick={this.handleEditClick}
147
146
  >
148
147
  <span>{shortcut}</span>
149
148
  <EditFilled
150
149
  className='shortcut-edit-icon pointer mg1l'
150
+ onClick={this.handleEditClick}
151
151
  />
152
+ {
153
+ this.renderClear()
154
+ }
152
155
  </Button>
153
156
  )
154
157
  }
155
158
 
159
+ renderClear () {
160
+ if (this.props.renderClear && this.props.data.shortcut) {
161
+ return (
162
+ <CloseOutlined
163
+ className='pointer mg1l'
164
+ onClick={this.props.handleClear}
165
+ />
166
+ )
167
+ }
168
+ }
169
+
156
170
  renderAfter () {
157
171
  const {
158
172
  shortcut
@@ -102,6 +102,14 @@ export function shortcutExtend (Cls) {
102
102
  const shortcutsConfig = buildConfig(this.props.config, d => !d.hidden)
103
103
  const keys = Object.keys(shortcutsConfig)
104
104
  const len = keys.length
105
+ if (this.term) {
106
+ const qmMatch = window.store.quickCommands.find(d => d.shortcut === r)
107
+ if (qmMatch) {
108
+ window.store.runQuickCommandItem(
109
+ qmMatch.id
110
+ )
111
+ }
112
+ }
105
113
  for (let i = 0; i < len; i++) {
106
114
  const k = keys[i]
107
115
  const conf = shortcutsConfig[k]
@@ -51,26 +51,41 @@ export default class Shortcuts extends Component {
51
51
  }
52
52
 
53
53
  getKeysTakenData = () => {
54
- const { shortcuts = {} } = this.props.store.config
55
- return shortcutsDefaults
56
- .reduce((p, k) => {
57
- const propName = isMac ? 'shortcutMac' : 'shortcut'
58
- const name = k.name + '_' + propName
59
- const vv = k.readonly ? k[propName] : (shortcuts[name] || k[propName])
60
- const v = vv
61
- .split(',')
62
- .map(f => f.trim())
63
- .reduce((p, k, i) => {
64
- return {
65
- ...p,
66
- [k]: true
67
- }
68
- }, {})
69
- return {
54
+ const { store } = this.props
55
+ const { shortcuts = {} } = store.config
56
+ const { quickCommands = [] } = store
57
+
58
+ // Gather system shortcuts
59
+ const systemShortcuts = shortcutsDefaults.reduce((p, k) => {
60
+ const propName = isMac ? 'shortcutMac' : 'shortcut'
61
+ const name = k.name + '_' + propName
62
+ const vv = k.readonly ? k[propName] : (shortcuts[name] || k[propName])
63
+ const v = vv
64
+ .split(',')
65
+ .map(f => f.trim())
66
+ .reduce((p, k) => ({
70
67
  ...p,
71
- ...v
72
- }
73
- }, {})
68
+ [k]: true
69
+ }), {})
70
+ return {
71
+ ...p,
72
+ ...v
73
+ }
74
+ }, {})
75
+
76
+ // Gather quick command shortcuts
77
+ const quickCommandShortcuts = quickCommands.reduce((acc, command) => {
78
+ if (command.shortcut) {
79
+ acc[command.shortcut] = true
80
+ }
81
+ return acc
82
+ }, {})
83
+
84
+ // Combine system shortcuts and quick command shortcuts
85
+ return {
86
+ ...systemShortcuts,
87
+ ...quickCommandShortcuts
88
+ }
74
89
  }
75
90
 
76
91
  render () {
@@ -113,7 +128,7 @@ export default class Shortcuts extends Component {
113
128
  }
114
129
  },
115
130
  {
116
- title: s('shortcut'),
131
+ title: s('settingShortcuts'),
117
132
  dataIndex: 'shortcut',
118
133
  key: 'shortcut',
119
134
  render: (shortcut, inst) => {
@@ -19,6 +19,7 @@ import {
19
19
  PushpinOutlined
20
20
  } from '@ant-design/icons'
21
21
  import classNames from 'classnames'
22
+ import './terminal-info.styl'
22
23
 
23
24
  export default class TerminalInfoContent extends PureComponent {
24
25
  state = {
@@ -997,7 +997,8 @@ export default class ItemListTree extends Component {
997
997
  bookmarkGroupIds = [],
998
998
  id
999
999
  } = group
1000
- if (!this.state.expandedKeys.includes(id)) {
1000
+ const shouldRender = this.state.keyword || this.state.expandedKeys.includes(id)
1001
+ if (!shouldRender) {
1001
1002
  return null
1002
1003
  }
1003
1004
  return [
@@ -5,8 +5,11 @@
5
5
  import {
6
6
  settingMap,
7
7
  qmSortByFrequencyKey,
8
- terminalActions
8
+ terminalActions,
9
+ isWin
9
10
  } from '../common/constants'
11
+ import delay from '../common/wait'
12
+ import generate from '../common/uid'
10
13
  import postMessage from '../common/post-msg'
11
14
  import * as ls from '../common/safe-local-storage'
12
15
 
@@ -39,6 +42,39 @@ export default Store => {
39
42
  })
40
43
  }
41
44
 
45
+ Store.prototype.runQuickCommandItem = async (id) => {
46
+ const {
47
+ store
48
+ } = window
49
+
50
+ const qm = store.currentQuickCommands.find(
51
+ a => a.id === id
52
+ )
53
+ const { runQuickCommand } = store
54
+ const qms = qm && qm.commands
55
+ ? qm.commands
56
+ : (qm && qm.command
57
+ ? [
58
+ {
59
+ command: qm.command,
60
+ id: generate(),
61
+ delay: 100
62
+ }
63
+ ]
64
+ : []
65
+ )
66
+ for (const q of qms) {
67
+ const realCmd = isWin
68
+ ? q.command.replace(/\n/g, '\n\r')
69
+ : q.command
70
+ await delay(q.delay || 100)
71
+ runQuickCommand(realCmd, qm.inputOnly)
72
+ store.editQuickCommand(qm.id, {
73
+ clickCount: ((qm.clickCount || 0) + 1)
74
+ })
75
+ }
76
+ }
77
+
42
78
  Store.prototype.setQmSortByFrequency = function (v) {
43
79
  window.store.qmSortByFrequency = v
44
80
  ls.setItem(qmSortByFrequencyKey, v ? 'yes' : 'no')
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@electerm/electerm-react",
3
- "version": "1.39.56",
3
+ "version": "1.39.76",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",