@electerm/electerm-react 1.39.47 → 1.39.68

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'>
@@ -81,9 +81,11 @@ export default class Index extends Component {
81
81
  } = store
82
82
  const cls = classnames({
83
83
  loaded: configLoaded,
84
+ 'not-webapp': !window.et.isWebApp,
84
85
  'system-ui': store.config.useSystemTitleBar,
85
86
  'not-system-ui': !store.config.useSystemTitleBar,
86
- 'is-mac': isMac && !window.et.isWebApp,
87
+ 'is-mac': isMac,
88
+ 'not-mac': !isMac,
87
89
  'is-win': isWin,
88
90
  pinned,
89
91
  'qm-pinned': pinnedQuickCommandBar,
@@ -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
 
@@ -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) => {
@@ -7,9 +7,10 @@
7
7
  ::-webkit-scrollbar
8
8
  width 0
9
9
  display none
10
- .not-system-ui.is-mac
10
+ .not-system-ui.is-mac.not-webapp
11
11
  .tabs-inner
12
12
  margin-left 72px
13
+ .not-system-ui.not-mac.not-webapp
13
14
  .tabs-extra
14
15
  right 96px
15
16
  .tabs-inner
@@ -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 = {
@@ -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.47",
3
+ "version": "1.39.68",
4
4
  "description": "react components src for electerm",
5
5
  "main": "./client/components/main/main.jsx",
6
6
  "license": "MIT",