@electerm/electerm-react 1.34.30

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 (273) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +31 -0
  3. package/client/common/auto-complete-data-mapper.js +6 -0
  4. package/client/common/byte-format.js +14 -0
  5. package/client/common/class.js +52 -0
  6. package/client/common/clipboard.js +49 -0
  7. package/client/common/constants.js +308 -0
  8. package/client/common/create-lang-edit-link.js +7 -0
  9. package/client/common/create-title.js +29 -0
  10. package/client/common/db-fix.js +24 -0
  11. package/client/common/db.js +155 -0
  12. package/client/common/download-mirrors.js +10 -0
  13. package/client/common/download.js +16 -0
  14. package/client/common/error-handler.jsx +27 -0
  15. package/client/common/fetch-from-server.js +47 -0
  16. package/client/common/fetch.jsx +71 -0
  17. package/client/common/find-bookmark-group-id.js +15 -0
  18. package/client/common/find-parent.js +30 -0
  19. package/client/common/form-layout.js +27 -0
  20. package/client/common/fs.js +21 -0
  21. package/client/common/get-proxy.js +8 -0
  22. package/client/common/id-with-stamp.js +10 -0
  23. package/client/common/index-sorter.js +4 -0
  24. package/client/common/init-setting-item.js +32 -0
  25. package/client/common/is-absolute-path.js +3 -0
  26. package/client/common/is-ip.js +16 -0
  27. package/client/common/is-valid-path.js +7 -0
  28. package/client/common/key-control-pressed.js +13 -0
  29. package/client/common/key-pressed.js +13 -0
  30. package/client/common/key-shift-pressed.js +7 -0
  31. package/client/common/mode2permission.js +81 -0
  32. package/client/common/new-terminal.js +31 -0
  33. package/client/common/parse-int10.js +3 -0
  34. package/client/common/parse-json-safe.js +11 -0
  35. package/client/common/pass-enc.js +25 -0
  36. package/client/common/post-msg.js +3 -0
  37. package/client/common/pre.js +156 -0
  38. package/client/common/promise-timeout.js +27 -0
  39. package/client/common/resolve.js +31 -0
  40. package/client/common/run-idle.js +1 -0
  41. package/client/common/safe-local-storage.js +35 -0
  42. package/client/common/safe-name.js +19 -0
  43. package/client/common/sftp.js +74 -0
  44. package/client/common/terminal-theme.js +158 -0
  45. package/client/common/test-connection.js +12 -0
  46. package/client/common/time.js +30 -0
  47. package/client/common/to-simple-obj.js +5 -0
  48. package/client/common/track.js +7 -0
  49. package/client/common/transfer.js +76 -0
  50. package/client/common/trzsz.js +62 -0
  51. package/client/common/ui-theme.js +44 -0
  52. package/client/common/uid.js +5 -0
  53. package/client/common/update-check.js +79 -0
  54. package/client/common/upgrade.js +68 -0
  55. package/client/common/wait.js +8 -0
  56. package/client/common/ws.js +161 -0
  57. package/client/components/batch-op/batch-op.jsx +650 -0
  58. package/client/components/bookmark-form/bookmark-form.styl +8 -0
  59. package/client/components/bookmark-form/bookmark-group-tree-format.js +39 -0
  60. package/client/components/bookmark-form/encodes.js +44 -0
  61. package/client/components/bookmark-form/form-ssh-common.jsx +208 -0
  62. package/client/components/bookmark-form/form-tabs.jsx +69 -0
  63. package/client/components/bookmark-form/index.jsx +159 -0
  64. package/client/components/bookmark-form/local-form-ui.jsx +152 -0
  65. package/client/components/bookmark-form/local-form.jsx +16 -0
  66. package/client/components/bookmark-form/proxy.jsx +49 -0
  67. package/client/components/bookmark-form/quick-command-list.jsx +31 -0
  68. package/client/components/bookmark-form/quick-command.jsx +228 -0
  69. package/client/components/bookmark-form/render-auth-ssh.jsx +104 -0
  70. package/client/components/bookmark-form/render-connection-hopping.jsx +229 -0
  71. package/client/components/bookmark-form/render-delayed-scripts.jsx +88 -0
  72. package/client/components/bookmark-form/render-ssh-tunnel.jsx +116 -0
  73. package/client/components/bookmark-form/serial-form-ui.jsx +311 -0
  74. package/client/components/bookmark-form/serial-form.jsx +20 -0
  75. package/client/components/bookmark-form/sftp-enable.jsx +33 -0
  76. package/client/components/bookmark-form/ssh-form-ui.jsx +100 -0
  77. package/client/components/bookmark-form/ssh-form.jsx +348 -0
  78. package/client/components/bookmark-form/telnet-form-ui.jsx +154 -0
  79. package/client/components/bookmark-form/telnet-form.jsx +16 -0
  80. package/client/components/bookmark-form/tree-delete.jsx +87 -0
  81. package/client/components/bookmark-form/use-form-funcs.jsx +50 -0
  82. package/client/components/bookmark-form/use-quick-commands.jsx +83 -0
  83. package/client/components/bookmark-form/use-submit.jsx +77 -0
  84. package/client/components/bookmark-form/use-ui.jsx +82 -0
  85. package/client/components/bookmark-form/x11.jsx +23 -0
  86. package/client/components/common/animate-text.jsx +37 -0
  87. package/client/components/common/animate-text.styl +54 -0
  88. package/client/components/common/external-link.jsx +28 -0
  89. package/client/components/common/help-icon.jsx +25 -0
  90. package/client/components/common/highlight.jsx +23 -0
  91. package/client/components/common/highlight.styl +3 -0
  92. package/client/components/common/input-auto-focus.jsx +68 -0
  93. package/client/components/common/input-confirm.jsx +66 -0
  94. package/client/components/common/logo-elem.jsx +22 -0
  95. package/client/components/common/markdown.jsx +27 -0
  96. package/client/components/common/react-subx.jsx +1 -0
  97. package/client/components/common/resize-wrap.jsx +222 -0
  98. package/client/components/common/resize-wrap.styl +9 -0
  99. package/client/components/common/search.jsx +9 -0
  100. package/client/components/common/show-item.jsx +27 -0
  101. package/client/components/context-menu/boomarks.jsx +15 -0
  102. package/client/components/context-menu/context-menu.jsx +340 -0
  103. package/client/components/context-menu/context-menu.styl +90 -0
  104. package/client/components/context-menu/history.jsx +27 -0
  105. package/client/components/context-menu/icon-holder.jsx +5 -0
  106. package/client/components/context-menu/menu-btn.jsx +224 -0
  107. package/client/components/context-menu/sub-tab-menu.jsx +23 -0
  108. package/client/components/context-menu/tabs.jsx +22 -0
  109. package/client/components/context-menu/zoom.jsx +40 -0
  110. package/client/components/footer/batch-input.jsx +177 -0
  111. package/client/components/footer/footer-entry.jsx +141 -0
  112. package/client/components/footer/footer.styl +47 -0
  113. package/client/components/icons/match-case.jsx +10 -0
  114. package/client/components/icons/match-whole-word.jsx +13 -0
  115. package/client/components/icons/regular-exp.jsx +10 -0
  116. package/client/components/main/css-overwrite.jsx +92 -0
  117. package/client/components/main/error-wrapper.jsx +59 -0
  118. package/client/components/main/index.jsx +11 -0
  119. package/client/components/main/loading.jsx +25 -0
  120. package/client/components/main/main.jsx +149 -0
  121. package/client/components/main/term-fullscreen-control.jsx +21 -0
  122. package/client/components/main/term-fullscreen.styl +27 -0
  123. package/client/components/main/ui-theme.jsx +31 -0
  124. package/client/components/main/upgrade.jsx +351 -0
  125. package/client/components/main/upgrade.styl +27 -0
  126. package/client/components/main/wrapper.styl +41 -0
  127. package/client/components/quick-commands/qm.styl +29 -0
  128. package/client/components/quick-commands/quick-command-item.jsx +36 -0
  129. package/client/components/quick-commands/quick-command-transport-mod.jsx +54 -0
  130. package/client/components/quick-commands/quick-command-transport.jsx +12 -0
  131. package/client/components/quick-commands/quick-commands-box.jsx +233 -0
  132. package/client/components/quick-commands/quick-commands-form-elem.jsx +119 -0
  133. package/client/components/quick-commands/quick-commands-form.jsx +33 -0
  134. package/client/components/quick-commands/quick-commands-list.jsx +128 -0
  135. package/client/components/quick-commands/quick-commands-select.jsx +38 -0
  136. package/client/components/session/session.jsx +533 -0
  137. package/client/components/session/session.styl +53 -0
  138. package/client/components/session/sessions.jsx +445 -0
  139. package/client/components/setting-panel/bookmark-transport.jsx +148 -0
  140. package/client/components/setting-panel/bookmark-tree-list.jsx +14 -0
  141. package/client/components/setting-panel/col.jsx +18 -0
  142. package/client/components/setting-panel/list.jsx +186 -0
  143. package/client/components/setting-panel/list.styl +33 -0
  144. package/client/components/setting-panel/on-tree-drop.js +222 -0
  145. package/client/components/setting-panel/setting-modal.jsx +163 -0
  146. package/client/components/setting-panel/setting-wrap.jsx +37 -0
  147. package/client/components/setting-panel/setting-wrap.styl +52 -0
  148. package/client/components/setting-panel/setting.jsx +858 -0
  149. package/client/components/setting-panel/setting.styl +4 -0
  150. package/client/components/setting-panel/start-session-select.jsx +91 -0
  151. package/client/components/setting-panel/tab-bookmarks.jsx +37 -0
  152. package/client/components/setting-panel/tab-history.jsx +44 -0
  153. package/client/components/setting-panel/tab-quick-commands.jsx +38 -0
  154. package/client/components/setting-panel/tab-settings.jsx +42 -0
  155. package/client/components/setting-panel/tab-themes.jsx +34 -0
  156. package/client/components/setting-panel/tree-list.jsx +978 -0
  157. package/client/components/setting-panel/tree-list.styl +57 -0
  158. package/client/components/setting-sync/data-import.jsx +65 -0
  159. package/client/components/setting-sync/setting-sync-form.jsx +271 -0
  160. package/client/components/setting-sync/setting-sync.jsx +81 -0
  161. package/client/components/setting-sync/sync.styl +7 -0
  162. package/client/components/sftp/address-bar.jsx +139 -0
  163. package/client/components/sftp/address-bookmark-item.jsx +47 -0
  164. package/client/components/sftp/address-bookmark.jsx +81 -0
  165. package/client/components/sftp/address-bookmark.styl +8 -0
  166. package/client/components/sftp/confirm-modal.jsx +184 -0
  167. package/client/components/sftp/file-icon.jsx +22 -0
  168. package/client/components/sftp/file-item.jsx +1226 -0
  169. package/client/components/sftp/file-mode-modal.jsx +205 -0
  170. package/client/components/sftp/file-props-modal.jsx +211 -0
  171. package/client/components/sftp/file-read.js +81 -0
  172. package/client/components/sftp/list-table-ui.jsx +547 -0
  173. package/client/components/sftp/owner-list.js +97 -0
  174. package/client/components/sftp/paged-list.jsx +60 -0
  175. package/client/components/sftp/permission-render.jsx +42 -0
  176. package/client/components/sftp/sftp-entry.jsx +1069 -0
  177. package/client/components/sftp/sftp.styl +217 -0
  178. package/client/components/sftp/transfer-common.js +9 -0
  179. package/client/components/sftp/transfer-conflict.jsx +315 -0
  180. package/client/components/sftp/transfer-speed-format.js +60 -0
  181. package/client/components/sftp/transfer-tag.jsx +40 -0
  182. package/client/components/sftp/transfer-tag.styl +11 -0
  183. package/client/components/sftp/transfer.styl +55 -0
  184. package/client/components/sftp/transport-action.jsx +410 -0
  185. package/client/components/sftp/transport-entry.jsx +108 -0
  186. package/client/components/sftp/transport-types.js +8 -0
  187. package/client/components/sftp/transports-action.jsx +111 -0
  188. package/client/components/sftp/transports-ui.jsx +93 -0
  189. package/client/components/sftp/zip.js +42 -0
  190. package/client/components/sidebar/bookmark-select.jsx +48 -0
  191. package/client/components/sidebar/bookmark.jsx +82 -0
  192. package/client/components/sidebar/history.jsx +66 -0
  193. package/client/components/sidebar/index.jsx +230 -0
  194. package/client/components/sidebar/info-modal.jsx +250 -0
  195. package/client/components/sidebar/info.styl +27 -0
  196. package/client/components/sidebar/side-icon.jsx +25 -0
  197. package/client/components/sidebar/sidebar.styl +128 -0
  198. package/client/components/sidebar/transfer-history-modal.jsx +110 -0
  199. package/client/components/sidebar/transfer-history.styl +3 -0
  200. package/client/components/sidebar/transfer-list-control.jsx +205 -0
  201. package/client/components/sidebar/transfer-list.jsx +55 -0
  202. package/client/components/sidebar/transfer-modal.jsx +76 -0
  203. package/client/components/sidebar/transfer.styl +8 -0
  204. package/client/components/sidebar/transport-ui.jsx +109 -0
  205. package/client/components/tabs/index.jsx +320 -0
  206. package/client/components/tabs/tab.jsx +427 -0
  207. package/client/components/tabs/tabs.styl +220 -0
  208. package/client/components/tabs/window-control.jsx +55 -0
  209. package/client/components/terminal/attach-addon-custom.js +70 -0
  210. package/client/components/terminal/build-ls-term-id.js +5 -0
  211. package/client/components/terminal/index.jsx +1358 -0
  212. package/client/components/terminal/normal-buffer.jsx +33 -0
  213. package/client/components/terminal/term-search.jsx +224 -0
  214. package/client/components/terminal/term-search.styl +15 -0
  215. package/client/components/terminal/terminal-apis.js +31 -0
  216. package/client/components/terminal/terminal-interactive.jsx +148 -0
  217. package/client/components/terminal/terminal.styl +96 -0
  218. package/client/components/terminal/xterm-zmodem.js +48 -0
  219. package/client/components/terminal/zmodem-transfer.jsx +98 -0
  220. package/client/components/terminal/zmodem.styl +14 -0
  221. package/client/components/terminal-info/activity.jsx +54 -0
  222. package/client/components/terminal-info/base.jsx +25 -0
  223. package/client/components/terminal-info/content.jsx +101 -0
  224. package/client/components/terminal-info/data-cols-parser.jsx +50 -0
  225. package/client/components/terminal-info/disk.jsx +29 -0
  226. package/client/components/terminal-info/index.jsx +25 -0
  227. package/client/components/terminal-info/network.jsx +114 -0
  228. package/client/components/terminal-info/resource.jsx +80 -0
  229. package/client/components/terminal-info/run-cmd.jsx +273 -0
  230. package/client/components/terminal-info/terminal-info.styl +29 -0
  231. package/client/components/terminal-info/up.jsx +15 -0
  232. package/client/components/terminal-theme/index.jsx +264 -0
  233. package/client/components/terminal-theme/terminal-theme-list.styl +3 -0
  234. package/client/components/terminal-theme/theme-list.jsx +146 -0
  235. package/client/components/text-editor/text-editor-form.jsx +97 -0
  236. package/client/components/text-editor/text-editor.jsx +182 -0
  237. package/client/css/antd-overwrite.styl +14 -0
  238. package/client/css/basic.styl +38 -0
  239. package/client/css/includes/box.styl +154 -0
  240. package/client/css/includes/font-size.styl +6 -0
  241. package/client/css/includes/index.styl +3 -0
  242. package/client/css/includes/text.styl +31 -0
  243. package/client/css/includes/theme-default.styl +20 -0
  244. package/client/entry/basic.js +58 -0
  245. package/client/entry/index.jsx +15 -0
  246. package/client/entry/worker.js +137 -0
  247. package/client/store/address-bookmark.js +25 -0
  248. package/client/store/app-upgrade.js +23 -0
  249. package/client/store/batch-input-history.js +26 -0
  250. package/client/store/bookmark-group.js +128 -0
  251. package/client/store/bookmark.js +22 -0
  252. package/client/store/common.js +140 -0
  253. package/client/store/context-menu.js +23 -0
  254. package/client/store/db-upgrade.js +43 -0
  255. package/client/store/event.js +70 -0
  256. package/client/store/index.js +335 -0
  257. package/client/store/init-state.js +191 -0
  258. package/client/store/item.js +120 -0
  259. package/client/store/load-data.js +198 -0
  260. package/client/store/quick-command.js +43 -0
  261. package/client/store/session.js +54 -0
  262. package/client/store/setting.js +208 -0
  263. package/client/store/sidebar.js +48 -0
  264. package/client/store/sync.js +390 -0
  265. package/client/store/system-menu.js +120 -0
  266. package/client/store/tab.js +74 -0
  267. package/client/store/terminal-theme.js +116 -0
  268. package/client/store/transfer-history.js +27 -0
  269. package/client/store/transfer-list.js +20 -0
  270. package/client/store/ui-theme.js +71 -0
  271. package/client/store/watch.js +116 -0
  272. package/client/views/index.pug +58 -0
  273. package/package.json +34 -0
@@ -0,0 +1,650 @@
1
+ /**
2
+ * settings page
3
+ */
4
+
5
+ import { Component } from '../common/react-subx'
6
+ import {
7
+ CloseCircleOutlined
8
+ } from '@ant-design/icons'
9
+ import {
10
+ Upload,
11
+ Input,
12
+ Button,
13
+ Table,
14
+ Drawer,
15
+ Tabs
16
+ } from 'antd'
17
+ import {
18
+ sidebarWidth,
19
+ statusMap,
20
+ commonActions,
21
+ batchOpHelpLink,
22
+ modals
23
+ } from '../../common/constants'
24
+ import HelpIcon from '../common/help-icon'
25
+ import { autoRun } from 'manate'
26
+ import { pick } from 'lodash-es'
27
+ import { runCmd } from '../terminal/terminal-apis'
28
+ import deepCopy from 'json-deep-copy'
29
+ import postMsg from '../../common/post-msg'
30
+ import uid from '../../common/uid'
31
+ import wait from '../../common/wait'
32
+ import { getFolderFromFilePath } from '../sftp/file-read'
33
+ import resolveFilePath from '../../common/resolve'
34
+
35
+ const { prefix } = window
36
+ const f = prefix('form')
37
+ const t = prefix('transferHistory')
38
+ const c = prefix('common')
39
+ const m = prefix('menu')
40
+
41
+ export default class BatchOp extends Component {
42
+ state = {
43
+ text: '',
44
+ loading: false,
45
+ tasks: [],
46
+ errors: [],
47
+ history: [],
48
+ working: false,
49
+ tab: 'tasks'
50
+ }
51
+
52
+ componentDidMount () {
53
+ this.watch()
54
+ }
55
+
56
+ componentWillUnmount () {
57
+ this.unwatch()
58
+ }
59
+
60
+ watch () {
61
+ window.addEventListener('message', this.handleEvent)
62
+ }
63
+
64
+ unwatch () {
65
+ window.removeEventListener('message', this.handleEvent)
66
+ }
67
+
68
+ handleEvent = e => {
69
+ if (e && e.data && e.data.action === commonActions.batchOp) {
70
+ const {
71
+ func,
72
+ args
73
+ } = e.data.batchOp
74
+ this[func](...args)
75
+ }
76
+ }
77
+
78
+ handleCancel = () => {
79
+ this.props.store.toggleBatchOp()
80
+ }
81
+
82
+ handleChangeTab = tab => {
83
+ this.setState({
84
+ tab
85
+ })
86
+ }
87
+
88
+ handleDel = rec => {
89
+ this.setState(old => {
90
+ return {
91
+ tasks: old.tasks.filter(t => {
92
+ return t.id !== rec.id
93
+ })
94
+ }
95
+ })
96
+ }
97
+
98
+ handleExec = async () => {
99
+ this.setState({
100
+ working: true
101
+ })
102
+ const { tasks } = this.state
103
+ const len = tasks.length
104
+ for (let i = 0; i < len; i++) {
105
+ await this.run(tasks[i], i)
106
+ }
107
+ this.setState(old => {
108
+ return {
109
+ working: false,
110
+ history: [
111
+ ...old.history,
112
+ ...old.tasks
113
+ ],
114
+ tasks: []
115
+ }
116
+ })
117
+ }
118
+
119
+ updateState = (str, index) => {
120
+ this.setState(old => {
121
+ const arr = deepCopy(old.tasks)
122
+ arr[index].state = str
123
+ return {
124
+ tasks: arr
125
+ }
126
+ })
127
+ }
128
+
129
+ run = async (conf, index) => {
130
+ this.updateState('working', index)
131
+ let tab = await this.createTab(conf)
132
+ .then(r => r)
133
+ .catch(err => {
134
+ return 'Error: ' + err.message
135
+ })
136
+ if (!tab || !tab.pid) {
137
+ return this.updateState(tab, index)
138
+ }
139
+
140
+ this.updateState('tab created', index)
141
+ if (conf.cmd) {
142
+ this.updateState('running cmd', index)
143
+ await runCmd(tab.pid, tab.sessionId, conf.cmd)
144
+ this.updateState('running cmd done', index)
145
+ }
146
+ if (conf.remotePath) {
147
+ this.updateState('creating sftp', index)
148
+ tab = await this.createSftp(tab)
149
+ if (!tab || !tab.pid) {
150
+ return this.updateState('Error: ' + tab, index)
151
+ }
152
+ this.updateState('sftp created', index)
153
+ this.updateState('transferring file', index)
154
+ await this.doTransfer(tab, conf)
155
+ this.updateState('done: transferring file', index)
156
+ }
157
+ if (conf.cmdAfterTransfer) {
158
+ this.updateState('run cmd2', index)
159
+ document.querySelector('.session-current .type-tab.ssh').click()
160
+ await wait(200)
161
+ await runCmd(tab.pid, tab.sessionId, conf.cmdAfterTransfer)
162
+ this.updateState('run cmd2 done', index)
163
+ }
164
+ this.updateState(c('finished'), index)
165
+ document.querySelector('.tabs .tab.active .tab-close .anticon').click()
166
+ }
167
+
168
+ doTransfer = (tab, conf) => {
169
+ return new Promise((resolve, reject) => {
170
+ const isDown = conf.action === 'download'
171
+ const fp = isDown ? conf.remotePath : conf.localPath
172
+ const {
173
+ name
174
+ } = getFolderFromFilePath(fp)
175
+ const obj = {
176
+ fromPath: fp,
177
+ id: uid(),
178
+ operation: '',
179
+ sessionId: tab.sessionId,
180
+ tabId: tab.id,
181
+ title: 'batch operation',
182
+ toPath: resolveFilePath(isDown ? conf.localPath : conf.remotePath, name),
183
+ typeFrom: isDown ? 'remote' : 'local',
184
+ typeTo: isDown ? 'local' : 'remote',
185
+ skipConfirm: true
186
+ }
187
+ postMsg({
188
+ list: [obj],
189
+ action: commonActions.addTransfer,
190
+ sessionId: tab.sessionId
191
+ })
192
+ const { store } = window
193
+ this.tm = setTimeout(() => {
194
+ reject(new Error('timeout'))
195
+ }, 1000 * 60 * 60)
196
+ this.ref1 = autoRun(store, () => {
197
+ const { transferHistory } = store
198
+ const first = transferHistory.find(t => t.id === obj.id)
199
+ if (first && first.sessionId === tab.sessionId) {
200
+ this.ref1 && this.ref1.stop()
201
+ delete this.ref1
202
+ clearTimeout(this.tm)
203
+ resolve()
204
+ }
205
+ return store.transferHistory
206
+ })
207
+ this.ref1.start()
208
+ })
209
+ }
210
+
211
+ createSftp = (tab) => {
212
+ return new Promise((resolve, reject) => {
213
+ document.querySelector('.session-current .type-tab.sftp').click()
214
+ const { store } = window
215
+ this.ref2 = autoRun(store, () => {
216
+ const { tabs } = store
217
+ const last = tabs.find(t => t.id === tab.id)
218
+ if (
219
+ last &&
220
+ last.id === tab.id &&
221
+ last.sftpCreated === true
222
+ ) {
223
+ this.ref2 && this.ref2.stop()
224
+ delete this.ref2
225
+ resolve(last)
226
+ } else if (
227
+ last &&
228
+ last.id === tab.id &&
229
+ last.sftpCreated === false
230
+ ) {
231
+ reject(new Error('failed to create sftp connection'))
232
+ }
233
+ return store.tabs
234
+ })
235
+ this.ref2.start()
236
+ })
237
+ }
238
+
239
+ createTab = conf => {
240
+ return new Promise((resolve, reject) => {
241
+ const tab = {
242
+ ...pick(conf, [
243
+ 'host',
244
+ 'port',
245
+ 'username',
246
+ 'password'
247
+ ]),
248
+ authType: 'password',
249
+ enableSftp: true,
250
+ enableSsh: true,
251
+ encode: 'utf-8',
252
+ envLang: 'en_US.UTF-8',
253
+ id: uid(),
254
+ title: 'batch operation',
255
+ pane: 'terminal',
256
+ status: 'processing',
257
+ term: 'xterm-256color',
258
+ x11: false
259
+ }
260
+ const { store } = window
261
+ store.addTab(tab)
262
+ this.ref = autoRun(store, () => {
263
+ const { tabs } = store
264
+ const len = tabs.length
265
+ const last = tabs[len - 1]
266
+ if (
267
+ last &&
268
+ last.pid &&
269
+ last.id === tab.id &&
270
+ last.status === statusMap.success
271
+ ) {
272
+ this.ref && this.ref.stop()
273
+ delete this.ref
274
+ resolve(last)
275
+ } else if (last.status === statusMap.error) {
276
+ reject(new Error('failed to create connection'))
277
+ }
278
+ return store.tabs
279
+ })
280
+ this.ref.start()
281
+ })
282
+ }
283
+
284
+ handleClick = () => {
285
+ this.setState({
286
+ errors: [],
287
+ working: false,
288
+ loading: true
289
+ })
290
+ const reg = /,(?=(?:[^"]*"[^"]*")*[^"]*$)/g
291
+ const errors = []
292
+ const tasks = this.state.text
293
+ .split('\n')
294
+ .filter(d => d)
295
+ .map(r => {
296
+ const [
297
+ host,
298
+ port,
299
+ username,
300
+ password,
301
+ cmd,
302
+ localPath,
303
+ remotePath,
304
+ action,
305
+ cmdAfterTransfer
306
+ ] = r.split(reg).map(g => {
307
+ return g.trim().replace(/^["](.*)["]$/, '$1')
308
+ })
309
+ if (!host || !port || !username || !password) {
310
+ errors.push({
311
+ text: r,
312
+ msg: 'host, port, username, password required'
313
+ })
314
+ return ''
315
+ }
316
+ const res = {
317
+ host,
318
+ port,
319
+ username,
320
+ password
321
+ }
322
+ if (cmd) {
323
+ res.cmd = cmd
324
+ }
325
+ if (cmdAfterTransfer) {
326
+ res.cmdAfterTransfer = cmdAfterTransfer
327
+ }
328
+ if (
329
+ localPath &&
330
+ remotePath &&
331
+ action
332
+ ) {
333
+ Object.assign(res, {
334
+ localPath,
335
+ remotePath,
336
+ action
337
+ })
338
+ }
339
+ if (action && !['upload', 'download'].includes(action)) {
340
+ errors.push({
341
+ text: r,
342
+ msg: 'action can only be download or upload'
343
+ })
344
+ return ''
345
+ } else if (!res.cmd && !res.transfer && !res.cmdAfterTransfer) {
346
+ errors.push({
347
+ text: r,
348
+ msg: 'must have cmd or transfer'
349
+ })
350
+ return ''
351
+ }
352
+ res.id = uid()
353
+ return res
354
+ })
355
+ .filter(d => d)
356
+ this.setState(old => {
357
+ return {
358
+ errors,
359
+ tasks: [
360
+ ...old.tasks,
361
+ ...tasks
362
+ ],
363
+ loading: false,
364
+ text: errors.length ? this.state.text : ''
365
+ }
366
+ })
367
+ }
368
+
369
+ handleChange = (e) => {
370
+ this.setState({
371
+ text: e.target.value
372
+ })
373
+ }
374
+
375
+ beforeUpload = async (file) => {
376
+ const text = await window.fs.readFile(file.path)
377
+ this.setState({
378
+ text
379
+ })
380
+ }
381
+
382
+ renderError (err, i) {
383
+ return (
384
+ <div key={'batch-txt' + i}>
385
+ <pre><code>{err.text}</code></pre>
386
+ <div>{err.msg}</div>
387
+ </div>
388
+ )
389
+ }
390
+
391
+ renderErrors () {
392
+ const {
393
+ errors
394
+ } = this.state
395
+ if (!errors.length) {
396
+ return null
397
+ }
398
+ return (
399
+ <div className='pd1y'>
400
+ {
401
+ errors.map(this.renderError)
402
+ }
403
+ </div>
404
+ )
405
+ }
406
+
407
+ renderExec () {
408
+ const { length } = this.state.tasks
409
+ if (!length) {
410
+ return null
411
+ }
412
+ return (
413
+ <div className='pd1b'>
414
+ <Button
415
+ onClick={this.handleExec}
416
+ loading={this.state.working}
417
+ >{c('execute')}
418
+ </Button>
419
+ </div>
420
+ )
421
+ }
422
+
423
+ translate = k => {
424
+ if (k === 'index') {
425
+ return 'NO.'
426
+ } else if (
427
+ [
428
+ 'host',
429
+ 'port',
430
+ 'username',
431
+ 'password'
432
+ ].includes(k)
433
+ ) {
434
+ return f(k)
435
+ } else if (
436
+ k.includes('Path')
437
+ ) {
438
+ return t(k)
439
+ } else {
440
+ return c(k)
441
+ }
442
+ }
443
+
444
+ renderContent () {
445
+ const {
446
+ text,
447
+ loading,
448
+ tasks,
449
+ working
450
+ } = this.state
451
+ const disabled = loading || working
452
+ return (
453
+ <div>
454
+ <div className='pd1y'>
455
+ <h2>
456
+ {c('batchOperation')}
457
+ <HelpIcon
458
+ link={batchOpHelpLink}
459
+ />
460
+ </h2>
461
+ <div className='pd1y'>{c('examples')}:</div>
462
+ <pre>
463
+ <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>
464
+ </pre>
465
+ <pre>
466
+ <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>
467
+ </pre>
468
+ </div>
469
+ {this.renderErrors()}
470
+ <div className='pd1y'>
471
+ <Upload
472
+ beforeUpload={this.beforeUpload}
473
+ fileList={[]}
474
+ disabled={disabled}
475
+ >
476
+ <Button
477
+ type='dashed'
478
+ disabled={disabled}
479
+ >
480
+ {c('importFromCSV')}
481
+ </Button>
482
+ </Upload>
483
+ </div>
484
+ <div className='pd1y'>
485
+ <Input.TextArea
486
+ value={text}
487
+ disabled={disabled}
488
+ rows={10}
489
+ onChange={this.handleChange}
490
+ />
491
+ </div>
492
+ <div className='pd1b fix'>
493
+ <div className='fleft'>
494
+ <Button
495
+ onClick={this.handleClick}
496
+ loading={loading}
497
+ disabled={disabled}
498
+ htmlType='button'
499
+ >{c('addToQueue')}
500
+ </Button>
501
+ </div>
502
+ <div className='fright'>
503
+ <Button
504
+ onClick={this.handleExec}
505
+ loading={loading}
506
+ disabled={disabled || !tasks.length}
507
+ type='primary'
508
+ htmlType='button'
509
+ >{c('execute')}
510
+ </Button>
511
+ </div>
512
+ </div>
513
+ <div className='pd1y'>
514
+ {this.renderTables()}
515
+ </div>
516
+ </div>
517
+ )
518
+ }
519
+
520
+ renderTables () {
521
+ const {
522
+ tab
523
+ } = this.state
524
+ return (
525
+ <Tabs
526
+ activeKey={tab}
527
+ onChange={this.handleChangeTab}
528
+ items={this.renderItems()}
529
+ />
530
+ )
531
+ }
532
+
533
+ renderItems = () => {
534
+ return ['tasks', 'history'].map(this.renderTab)
535
+ }
536
+
537
+ renderTab = (tab) => {
538
+ const data = this.state[tab]
539
+ const columns = [
540
+ 'index',
541
+ 'host',
542
+ 'port',
543
+ 'username',
544
+ 'password',
545
+ 'cmd',
546
+ 'localPath',
547
+ 'remotePath',
548
+ 'cmdAfterTransfer',
549
+ 'state'
550
+ ].map(k => {
551
+ return {
552
+ title: this.translate(k),
553
+ dataIndex: k,
554
+ key: k,
555
+ render: (k) => k || ''
556
+ }
557
+ })
558
+ if (tab === 'tasks') {
559
+ columns.push({
560
+ title: m('del'),
561
+ dataIndex: 'op',
562
+ key: 'op',
563
+ render: (k, rec) => {
564
+ if (this.state.loading || this.state.working) {
565
+ return null
566
+ }
567
+ return (
568
+ <span
569
+ className='act-del pointer'
570
+ onClick={() => this.handleDel(rec)}
571
+ >
572
+ {m('del')}
573
+ </span>
574
+ )
575
+ }
576
+ })
577
+ }
578
+ const src = data.map((t, i) => {
579
+ return {
580
+ index: i + 1,
581
+ ...t
582
+ }
583
+ })
584
+ const len = data.length
585
+ const title = `${c(tab)}(${len})`
586
+ return {
587
+ key: tab,
588
+ label: title,
589
+ children: (
590
+ <Table
591
+ dataSource={src}
592
+ columns={columns}
593
+ bordered
594
+ pagination={false}
595
+ size='small'
596
+ rowKey='id'
597
+ />
598
+ )
599
+ }
600
+ }
601
+
602
+ renderClose () {
603
+ const {
604
+ loading,
605
+ working
606
+ } = this.state
607
+ if (loading || working) {
608
+ return null
609
+ }
610
+ return (
611
+ <CloseCircleOutlined
612
+ className='close-setting-wrap'
613
+ onClick={this.handleCancel}
614
+ />
615
+ )
616
+ }
617
+
618
+ render () {
619
+ const {
620
+ showModal,
621
+ innerWidth
622
+ } = this.props.store
623
+ const showBatchOp = showModal === modals.batchOps
624
+ const pops = {
625
+ open: showBatchOp,
626
+ onClose: this.handleCancel,
627
+ className: 'setting-wrap',
628
+ width: innerWidth - sidebarWidth,
629
+ zIndex: 888,
630
+ placement: 'left',
631
+ headerStyle: {
632
+ display: 'none'
633
+ }
634
+ }
635
+ return (
636
+ <Drawer
637
+ {...pops}
638
+ >
639
+ <div id='batch-op-wrap'>
640
+ {this.renderClose()}
641
+ <div className='setting-wrap-content'>
642
+ <div className='pd3 setting-wrap-inner'>
643
+ {showBatchOp ? this.renderContent() : null}
644
+ </div>
645
+ </div>
646
+ </div>
647
+ </Drawer>
648
+ )
649
+ }
650
+ }
@@ -0,0 +1,8 @@
1
+ .dns-section
2
+ line-height 34px
3
+ .mg24b
4
+ margin-bottom 24px
5
+ .mg60b
6
+ margin-bottom 60px
7
+ .compact-input input
8
+ width 80px !important
@@ -0,0 +1,39 @@
1
+ /**
2
+ * create bookmark group tree data
3
+ */
4
+
5
+ export default (bookmarkGroups = []) => {
6
+ const dict = bookmarkGroups
7
+ .reduce((prev, k) => {
8
+ return {
9
+ ...prev,
10
+ [k.id]: k
11
+ }
12
+ }, {})
13
+ return bookmarkGroups
14
+ .filter(d => d.level !== 2)
15
+ .map(j => {
16
+ const r = {
17
+ title: j.title,
18
+ value: j.id,
19
+ key: j.id
20
+ }
21
+ if (j.bookmarkGroupIds && j.bookmarkGroupIds.length) {
22
+ r.children = j.bookmarkGroupIds.map(k => {
23
+ const o = dict[k]
24
+ return o
25
+ ? {
26
+ title: o.title,
27
+ value: o.id,
28
+ key: o.id
29
+ }
30
+ : null
31
+ })
32
+ r.children = r.children.filter(d => d)
33
+ if (!r.children.length) {
34
+ delete r.children
35
+ }
36
+ }
37
+ return r
38
+ })
39
+ }