@electerm/electerm-react 5.3.15 → 5.5.6
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.
- package/README.md +246 -12
- package/client/common/choose-save-folder.js +21 -2
- package/client/common/constants.js +23 -6
- package/client/common/create-title.jsx +6 -0
- package/client/common/default-setting.js +14 -0
- package/client/common/init-setting-item.js +5 -0
- package/client/common/platform.js +24 -0
- package/client/components/ai/agent-tool-call-card.jsx +10 -2
- package/client/components/ai/agent.js +4 -1
- package/client/components/ai/ai-attachments.js +87 -0
- package/client/components/ai/ai-chat-empty.jsx +43 -0
- package/client/components/ai/ai-chat-entry.jsx +13 -4
- package/client/components/ai/ai-chat-history-item.jsx +28 -4
- package/client/components/ai/ai-chat-history.jsx +2 -1
- package/client/components/ai/ai-chat.jsx +104 -13
- package/client/components/ai/ai-config-props.js +4 -130
- package/client/components/ai/ai-config.jsx +135 -15
- package/client/components/ai/ai-presets.js +173 -0
- package/client/components/ai/ai.styl +83 -0
- package/client/components/bg/css-overwrite.jsx +11 -0
- package/client/components/bookmark-form/bookmark-schema.js +4 -0
- package/client/components/bookmark-form/common/fields.jsx +3 -0
- package/client/components/bookmark-form/config/common-fields.js +12 -0
- package/client/components/bookmark-form/config/local.js +3 -2
- package/client/components/bookmark-form/config/serial.js +3 -2
- package/client/components/bookmark-form/config/ssh.js +2 -1
- package/client/components/bookmark-form/config/telnet.js +3 -2
- package/client/components/bookmark-form/index.jsx +10 -8
- package/client/components/common/item-filter.jsx +76 -0
- package/client/components/common/item-filter.styl +54 -0
- package/client/components/common/lazy-boundary.jsx +34 -0
- package/client/components/common/opacity.jsx +3 -1
- package/client/components/footer/footer-entry.jsx +35 -5
- package/client/components/footer/footer.styl +8 -1
- package/client/components/layout/layout.jsx +23 -31
- package/client/components/layout/pixed.js +3 -0
- package/client/components/main/main.jsx +80 -28
- package/client/components/main/term-fullscreen.styl +9 -3
- package/client/components/quick-commands/qm.styl +3 -2
- package/client/components/rdp/file-transfer.js +4 -4
- package/client/components/remote-monitor/monitor-details.jsx +458 -0
- package/client/components/remote-monitor/monitor-details.styl +87 -0
- package/client/components/remote-monitor/monitor-model.js +764 -0
- package/client/components/remote-monitor/remote-monitor-bar-entry.jsx +18 -0
- package/client/components/remote-monitor/remote-monitor-bar.jsx +344 -0
- package/client/components/remote-monitor/remote-monitor-bar.styl +106 -0
- package/client/components/remote-monitor/session-monitor.js +361 -0
- package/client/components/remote-monitor/use-monitor-details.js +10 -0
- package/client/components/remote-monitor/visibility.js +18 -0
- package/client/components/session/session-control.jsx +29 -2
- package/client/components/session/session.jsx +40 -18
- package/client/components/session/sessions.jsx +5 -2
- package/client/components/setting-panel/col.jsx +32 -6
- package/client/components/setting-panel/list.styl +12 -0
- package/client/components/setting-panel/setting-common.jsx +25 -56
- package/client/components/setting-panel/setting-mobile-breadcrumb.jsx +29 -0
- package/client/components/setting-panel/setting-modal.jsx +64 -44
- package/client/components/setting-panel/setting-terminal.jsx +7 -2
- package/client/components/setting-panel/setting-wrap.jsx +0 -3
- package/client/components/setting-panel/setting-wrap.styl +80 -11
- package/client/components/setting-panel/setting.styl +1 -1
- package/client/components/setting-panel/tab-triggers.jsx +71 -0
- package/client/components/sftp/file-compare-modal.jsx +6 -3
- package/client/components/sftp/file-item.jsx +5 -3
- package/client/components/sftp/owner-list.js +11 -2
- package/client/components/side-panel-r/side-panel-r.jsx +2 -2
- package/client/components/sidebar/index.jsx +28 -21
- package/client/components/sidebar/left-sidebar-icons.jsx +1 -1
- package/client/components/sidebar/sidebar.styl +16 -0
- package/client/components/sys-menu/menu-btn.jsx +30 -1
- package/client/components/tabs/index.jsx +2 -2
- package/client/components/tabs/tab-title.jsx +3 -2
- package/client/components/tabs/tab.jsx +5 -1
- package/client/components/tabs/tabs.styl +4 -0
- package/client/components/terminal/attach-addon-custom.js +295 -49
- package/client/components/terminal/automation/index.js +64 -0
- package/client/components/terminal/automation/keys.js +49 -0
- package/client/components/terminal/automation/stream-matcher.js +82 -0
- package/client/components/terminal/automation/strip-ansi.js +19 -0
- package/client/components/terminal/automation/trigger-engine.js +233 -0
- package/client/components/terminal/automation/trigger-presets.js +110 -0
- package/client/components/terminal/command-tracker-addon.js +31 -1
- package/client/components/terminal/mixins/index.js +27 -0
- package/client/components/terminal/mixins/term-attach.js +123 -0
- package/client/components/terminal/mixins/term-config.jsx +84 -0
- package/client/components/terminal/mixins/term-content.js +88 -0
- package/client/components/terminal/mixins/term-context-menu.jsx +291 -0
- package/client/components/terminal/mixins/term-file-drop.js +149 -0
- package/client/components/terminal/mixins/term-init.js +122 -0
- package/client/components/terminal/mixins/term-log.jsx +96 -0
- package/client/components/terminal/mixins/term-resize.js +87 -0
- package/client/components/terminal/mixins/term-socket.js +433 -0
- package/client/components/terminal/mixins/term-suggestions.js +224 -0
- package/client/components/terminal/mixins/term-theme.js +190 -0
- package/client/components/terminal/mixins/term-touch.js +136 -0
- package/client/components/terminal/shell-detect.js +37 -0
- package/client/components/terminal/shell.js +0 -28
- package/client/components/terminal/shortcut-bar-entry.jsx +32 -27
- package/client/components/terminal/shortcut-bar.jsx +4 -6
- package/client/components/terminal/shortcut-bar.styl +4 -0
- package/client/components/terminal/ssh-reload-state.js +56 -0
- package/client/components/terminal/startup-queue.js +379 -0
- package/client/components/terminal/terminal-interactive.jsx +32 -0
- package/client/components/terminal/terminal.jsx +102 -2007
- package/client/components/terminal/transfer-client-base.js +5 -29
- package/client/components/terminal/trzsz-client.js +1 -3
- package/client/components/terminal/xmodem-client.js +1 -3
- package/client/components/terminal/xterm-loader.js +7 -0
- package/client/components/terminal/zmodem-client.js +1 -3
- package/client/components/terminal-info/base.jsx +18 -70
- package/client/components/terminal-info/terminal-info-entry.jsx +13 -5
- package/client/components/terminal-info/terminal-info.jsx +50 -59
- package/client/components/terminal-info/terminal-info.styl +6 -49
- package/client/components/text-editor/open-text-editor.js +30 -0
- package/client/components/text-editor/text-editor-entry.jsx +17 -6
- package/client/components/text-editor/text-editor.jsx +14 -0
- package/client/components/theme/theme-form.jsx +22 -0
- package/client/components/tree-list/bookmark-transport.jsx +7 -31
- package/client/components/tree-list/tree-list.styl +13 -0
- package/client/components/triggers/trigger-editor.jsx +246 -0
- package/client/components/triggers/trigger-form.jsx +200 -0
- package/client/components/triggers/trigger-session-modal.jsx +199 -0
- package/client/components/triggers/trigger-setting-list.jsx +89 -0
- package/client/components/triggers/trigger-transport.jsx +60 -0
- package/client/components/triggers/triggers-field.jsx +19 -0
- package/client/components/widgets/widgets-list.jsx +11 -1
- package/client/css/mobile.styl +9 -1
- package/client/store/common.js +12 -1
- package/client/store/init-state.js +14 -0
- package/client/store/mcp-handler.js +158 -30
- package/client/store/setting.js +20 -0
- package/client/store/sidebar.js +12 -0
- package/client/store/store.js +2 -0
- package/client/store/sync.js +45 -9
- package/client/store/system-menu.js +2 -0
- package/client/store/tab.js +41 -3
- package/client/store/trigger.js +118 -0
- package/client/store/watch.js +13 -5
- package/client/views/index.pug +3 -0
- package/package.json +1 -1
- package/client/components/terminal-info/activity.jsx +0 -57
- package/client/components/terminal-info/data-cols-parser.jsx +0 -54
- package/client/components/terminal-info/disk.jsx +0 -45
- package/client/components/terminal-info/format-disks.js +0 -45
- package/client/components/terminal-info/network.jsx +0 -121
- package/client/components/terminal-info/resource.jsx +0 -99
- package/client/components/terminal-info/run-cmd.jsx +0 -263
- package/client/components/terminal-info/sys-info.jsx +0 -56
- package/client/components/terminal-info/up.jsx +0 -17
|
@@ -4,16 +4,15 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
// import { transferTypeMap } from '../../common/constants.js'
|
|
7
|
-
import {
|
|
7
|
+
import { chooseSaveDirectory } from '../../common/choose-save-folder.js'
|
|
8
8
|
import { getLocalFileInfo } from '../sftp/file-read.js'
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
11
|
* TransferClientBase class - abstract base for file transfer protocols
|
|
12
12
|
*/
|
|
13
13
|
export class TransferClientBase {
|
|
14
|
-
constructor (terminal
|
|
14
|
+
constructor (terminal) {
|
|
15
15
|
this.terminal = terminal
|
|
16
|
-
this.storageKey = storageKey
|
|
17
16
|
this.socket = null
|
|
18
17
|
this.isActive = false
|
|
19
18
|
this.currentTransfer = null
|
|
@@ -233,38 +232,15 @@ export class TransferClientBase {
|
|
|
233
232
|
if (window._apiControlSelectFolder) {
|
|
234
233
|
const folder = window._apiControlSelectFolder
|
|
235
234
|
delete window._apiControlSelectFolder
|
|
236
|
-
if (this.storageKey) {
|
|
237
|
-
setItem(this.storageKey, folder)
|
|
238
|
-
}
|
|
239
235
|
return folder
|
|
240
236
|
}
|
|
241
237
|
|
|
242
|
-
//
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
const savePaths = await window.api.openDialog({
|
|
246
|
-
title: 'Choose a folder to save file(s)',
|
|
247
|
-
message: 'Choose a folder to save file(s)',
|
|
248
|
-
defaultPath: lastPath || undefined,
|
|
249
|
-
properties: [
|
|
250
|
-
'openDirectory',
|
|
251
|
-
'showHiddenFiles',
|
|
252
|
-
'createDirectory',
|
|
253
|
-
'noResolveAliases',
|
|
254
|
-
'treatPackageAsDirectory',
|
|
255
|
-
'dontAddToRecent'
|
|
256
|
-
],
|
|
238
|
+
// Last saved path is remembered by chooseSaveDirectory in localStorage
|
|
239
|
+
const savePath = await chooseSaveDirectory({
|
|
257
240
|
noBrowserTransfer: true
|
|
258
241
|
}).catch(() => false)
|
|
259
242
|
|
|
260
|
-
|
|
261
|
-
return null
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
if (this.storageKey) {
|
|
265
|
-
setItem(this.storageKey, savePaths[0])
|
|
266
|
-
}
|
|
267
|
-
return savePaths[0]
|
|
243
|
+
return savePath || null
|
|
268
244
|
}
|
|
269
245
|
|
|
270
246
|
/**
|
|
@@ -8,14 +8,12 @@ import { filesize } from 'filesize'
|
|
|
8
8
|
import { TransferClientBase } from './transfer-client-base.js'
|
|
9
9
|
import { transferTypeMap } from '../../common/constants.js'
|
|
10
10
|
|
|
11
|
-
const TRZSZ_SAVE_PATH_KEY = 'trzsz-save-path'
|
|
12
|
-
|
|
13
11
|
/**
|
|
14
12
|
* TrzszClient class handles trzsz UI and client-side logic
|
|
15
13
|
*/
|
|
16
14
|
export class TrzszClient extends TransferClientBase {
|
|
17
15
|
constructor (terminal) {
|
|
18
|
-
super(terminal
|
|
16
|
+
super(terminal)
|
|
19
17
|
this.transferStartTime = 0
|
|
20
18
|
this.totalTransferred = 0
|
|
21
19
|
this.totalSpeed = 0
|
|
@@ -9,14 +9,12 @@ import { filesize } from 'filesize'
|
|
|
9
9
|
import { TransferClientBase } from './transfer-client-base.js'
|
|
10
10
|
import { transferTypeMap } from '../../common/constants.js'
|
|
11
11
|
|
|
12
|
-
const XMODEM_SAVE_PATH_KEY = 'xmodem-save-path'
|
|
13
|
-
|
|
14
12
|
/**
|
|
15
13
|
* XmodemClient class handles XMODEM UI and client-side logic
|
|
16
14
|
*/
|
|
17
15
|
export class XmodemClient extends TransferClientBase {
|
|
18
16
|
constructor (terminal) {
|
|
19
|
-
super(terminal
|
|
17
|
+
super(terminal)
|
|
20
18
|
this.transferStartTime = 0
|
|
21
19
|
this.pendingMode = null // 'send' or 'receive' - waiting for user action
|
|
22
20
|
}
|
|
@@ -72,6 +72,13 @@ export async function loadImageAddon () {
|
|
|
72
72
|
return window.xtermAddons.ImageAddon
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
+
export async function loadSerializeAddon () {
|
|
76
|
+
if (window.xtermAddons.SerializeAddon) return window.xtermAddons.SerializeAddon
|
|
77
|
+
const mod = await import('@xterm/addon-serialize')
|
|
78
|
+
window.xtermAddons.SerializeAddon = mod.SerializeAddon
|
|
79
|
+
return window.xtermAddons.SerializeAddon
|
|
80
|
+
}
|
|
81
|
+
|
|
75
82
|
export function getTerminal () {
|
|
76
83
|
return window.xtermAddons.Terminal
|
|
77
84
|
}
|
|
@@ -8,14 +8,12 @@ import { filesize } from 'filesize'
|
|
|
8
8
|
import { TransferClientBase } from './transfer-client-base.js'
|
|
9
9
|
import { transferTypeMap } from '../../common/constants.js'
|
|
10
10
|
|
|
11
|
-
const ZMODEM_SAVE_PATH_KEY = 'zmodem-save-path'
|
|
12
|
-
|
|
13
11
|
/**
|
|
14
12
|
* ZmodemClient class handles zmodem UI and client-side logic
|
|
15
13
|
*/
|
|
16
14
|
export class ZmodemClient extends TransferClientBase {
|
|
17
15
|
constructor (terminal) {
|
|
18
|
-
super(terminal
|
|
16
|
+
super(terminal)
|
|
19
17
|
this.transferStartTime = 0
|
|
20
18
|
}
|
|
21
19
|
|
|
@@ -2,23 +2,10 @@
|
|
|
2
2
|
* show base terminal info, id sessionID
|
|
3
3
|
*/
|
|
4
4
|
import { Component } from 'react'
|
|
5
|
-
import
|
|
6
|
-
Button,
|
|
7
|
-
Dropdown
|
|
8
|
-
} from 'antd'
|
|
5
|
+
import ItemFilter from '../common/item-filter'
|
|
9
6
|
import SwitchLabel from '../common/switch'
|
|
10
|
-
import
|
|
7
|
+
import { INFO_PANEL_ITEM_IDS } from '../remote-monitor/monitor-model'
|
|
11
8
|
import { toggleTerminalLog, toggleTerminalLogTimestamp } from '../terminal/terminal-apis'
|
|
12
|
-
import {
|
|
13
|
-
ClockCircleOutlined,
|
|
14
|
-
BorderlessTableOutlined,
|
|
15
|
-
DatabaseOutlined,
|
|
16
|
-
BarsOutlined,
|
|
17
|
-
ApiOutlined,
|
|
18
|
-
PartitionOutlined,
|
|
19
|
-
FilterOutlined,
|
|
20
|
-
CheckOutlined
|
|
21
|
-
} from '@ant-design/icons'
|
|
22
9
|
import { refs } from '../common/ref'
|
|
23
10
|
import ShowItem from '../common/show-item'
|
|
24
11
|
import { osResolve } from '../../common/resolve'
|
|
@@ -26,15 +13,6 @@ import createDefaultLogPath from '../../common/default-log-path'
|
|
|
26
13
|
|
|
27
14
|
const e = window.translate
|
|
28
15
|
|
|
29
|
-
const mapper = {
|
|
30
|
-
uptime: <ClockCircleOutlined />,
|
|
31
|
-
cpu: <BorderlessTableOutlined />,
|
|
32
|
-
mem: <DatabaseOutlined />,
|
|
33
|
-
activities: <BarsOutlined />,
|
|
34
|
-
network: <ApiOutlined />,
|
|
35
|
-
disks: <PartitionOutlined />
|
|
36
|
-
}
|
|
37
|
-
|
|
38
16
|
export default class TerminalInfoBase extends Component {
|
|
39
17
|
state = {
|
|
40
18
|
saveTerminalLogToFile: false,
|
|
@@ -73,14 +51,14 @@ export default class TerminalInfoBase extends Component {
|
|
|
73
51
|
})
|
|
74
52
|
}
|
|
75
53
|
|
|
76
|
-
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
54
|
+
handleToggleInfo = (id) => {
|
|
55
|
+
const selected = new Set(this.props.terminalInfos || [])
|
|
56
|
+
if (selected.has(id)) {
|
|
57
|
+
selected.delete(id)
|
|
58
|
+
} else {
|
|
59
|
+
selected.add(id)
|
|
60
|
+
}
|
|
61
|
+
window.store.setTerminalInfos(INFO_PANEL_ITEM_IDS.filter(x => selected.has(x)))
|
|
84
62
|
}
|
|
85
63
|
|
|
86
64
|
handleToggle = () => {
|
|
@@ -134,43 +112,13 @@ export default class TerminalInfoBase extends Component {
|
|
|
134
112
|
)
|
|
135
113
|
}
|
|
136
114
|
|
|
137
|
-
|
|
138
|
-
const {
|
|
139
|
-
terminalInfos
|
|
140
|
-
} = this.props
|
|
141
|
-
const items = defaults.terminalInfos.map(f => {
|
|
142
|
-
const checked = terminalInfos.includes(f)
|
|
143
|
-
return {
|
|
144
|
-
key: f,
|
|
145
|
-
label: (
|
|
146
|
-
<span
|
|
147
|
-
className='term-info-filter-label'
|
|
148
|
-
style={{
|
|
149
|
-
display: 'flex',
|
|
150
|
-
alignItems: 'center',
|
|
151
|
-
gap: '6px'
|
|
152
|
-
}}
|
|
153
|
-
>
|
|
154
|
-
<span style={{ width: '14px' }}>{checked ? <CheckOutlined /> : null}</span>
|
|
155
|
-
{mapper[f]} {f}
|
|
156
|
-
</span>
|
|
157
|
-
),
|
|
158
|
-
onClick: () => this.toggleTerminalLogInfo(f)
|
|
159
|
-
}
|
|
160
|
-
})
|
|
115
|
+
renderInfoFilter () {
|
|
161
116
|
return (
|
|
162
|
-
<
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
<Button
|
|
168
|
-
size='small'
|
|
169
|
-
icon={<FilterOutlined />}
|
|
170
|
-
>
|
|
171
|
-
{e('filter')}({terminalInfos.length}/{defaults.terminalInfos.length})
|
|
172
|
-
</Button>
|
|
173
|
-
</Dropdown>
|
|
117
|
+
<ItemFilter
|
|
118
|
+
ids={INFO_PANEL_ITEM_IDS}
|
|
119
|
+
onToggle={this.handleToggleInfo}
|
|
120
|
+
selected={this.props.terminalInfos || []}
|
|
121
|
+
/>
|
|
174
122
|
)
|
|
175
123
|
}
|
|
176
124
|
|
|
@@ -209,9 +157,9 @@ export default class TerminalInfoBase extends Component {
|
|
|
209
157
|
)
|
|
210
158
|
: null
|
|
211
159
|
}
|
|
212
|
-
<div className='
|
|
160
|
+
<div className='terminal-info-filter-wrap'>
|
|
213
161
|
{
|
|
214
|
-
this.
|
|
162
|
+
this.renderInfoFilter()
|
|
215
163
|
}
|
|
216
164
|
</div>
|
|
217
165
|
|
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
import { lazy, Suspense } from 'react'
|
|
2
|
+
import { auto } from 'manate/react'
|
|
3
|
+
import { getRemoteMonitorTab } from '../remote-monitor/visibility'
|
|
4
|
+
import LazyBoundary from '../common/lazy-boundary'
|
|
2
5
|
|
|
3
6
|
const TerminalInfo = lazy(() => import('./terminal-info'))
|
|
4
7
|
|
|
5
|
-
export default function TerminalInfoEntry (props) {
|
|
8
|
+
export default auto(function TerminalInfoEntry (props) {
|
|
9
|
+
const tab = getRemoteMonitorTab(props.store)
|
|
10
|
+
if (props.store.rightPanelTab !== 'info' || props.pid !== tab?.id) return null
|
|
11
|
+
|
|
6
12
|
return (
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
13
|
+
<LazyBoundary>
|
|
14
|
+
<Suspense fallback={null}>
|
|
15
|
+
<TerminalInfo {...props} />
|
|
16
|
+
</Suspense>
|
|
17
|
+
</LazyBoundary>
|
|
10
18
|
)
|
|
11
|
-
}
|
|
19
|
+
})
|
|
@@ -1,65 +1,56 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
import { PureComponent } from 'react'
|
|
1
|
+
import { auto } from 'manate/react'
|
|
2
|
+
import { useEffect, useState } from 'react'
|
|
6
3
|
import TerminalInfoBase from './base'
|
|
7
|
-
import
|
|
8
|
-
import
|
|
9
|
-
import
|
|
10
|
-
import
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import RunCmd from './run-cmd'
|
|
4
|
+
import MonitorDetails from '../remote-monitor/monitor-details'
|
|
5
|
+
import { getInfoPanelItems } from '../remote-monitor/monitor-model'
|
|
6
|
+
import { useMonitorDetails } from '../remote-monitor/use-monitor-details'
|
|
7
|
+
import { createEmptyMonitorSnapshot } from '../remote-monitor/session-monitor'
|
|
8
|
+
import { getRemoteMonitorTab } from '../remote-monitor/visibility'
|
|
9
|
+
import { statusMap } from '../../common/constants'
|
|
14
10
|
import { runCmd } from '../terminal/terminal-apis'
|
|
11
|
+
import resolveLocalInfo from './local-info-resolver'
|
|
15
12
|
import './terminal-info.styl'
|
|
16
13
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
setStateRef = (...args) => {
|
|
30
|
-
this.setState(...args)
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
killProcess = async (id) => {
|
|
34
|
-
const {
|
|
35
|
-
pid
|
|
36
|
-
} = this.props
|
|
37
|
-
const cmd = `kill ${id}`
|
|
38
|
-
runCmd(pid, cmd)
|
|
39
|
-
}
|
|
14
|
+
function LocalSystemInfo ({ pid }) {
|
|
15
|
+
const [info, setInfo] = useState(null)
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
let active = true
|
|
18
|
+
resolveLocalInfo(pid).then(info => { if (active) setInfo(info) })
|
|
19
|
+
return () => { active = false }
|
|
20
|
+
}, [pid])
|
|
21
|
+
if (!info) return null
|
|
22
|
+
const snapshot = createEmptyMonitorSnapshot(pid)
|
|
23
|
+
snapshot.groups.sysinfo = { status: 'ready', data: info }
|
|
24
|
+
return <MonitorDetails id='hostname' snapshot={snapshot} config={{}} tab={{}} />
|
|
25
|
+
}
|
|
40
26
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
{...state}
|
|
57
|
-
killProcess={this.killProcess}
|
|
58
|
-
/>
|
|
59
|
-
<TerminalInfoNetwork {...props} {...state} />
|
|
60
|
-
<TerminalInfoDisk {...props} {...state} />
|
|
61
|
-
<RunCmd {...props} setState={this.setStateRef} />
|
|
62
|
-
</>
|
|
63
|
-
)
|
|
64
|
-
}
|
|
27
|
+
function RemoteInfo ({ tab, config }) {
|
|
28
|
+
const items = getInfoPanelItems(config.terminalInfos)
|
|
29
|
+
const { snapshot, levels } = useMonitorDetails(tab.id, items, tab.status === statusMap.success)
|
|
30
|
+
return items.map(id => (
|
|
31
|
+
<MonitorDetails
|
|
32
|
+
key={id}
|
|
33
|
+
id={id}
|
|
34
|
+
snapshot={snapshot}
|
|
35
|
+
levels={levels}
|
|
36
|
+
tab={tab}
|
|
37
|
+
config={config}
|
|
38
|
+
includeActivity={false}
|
|
39
|
+
onKillProcess={pid => runCmd(tab.id, `kill ${pid}`)}
|
|
40
|
+
/>
|
|
41
|
+
))
|
|
65
42
|
}
|
|
43
|
+
|
|
44
|
+
export default auto(function TerminalInfo ({ store, ...props }) {
|
|
45
|
+
const tab = getRemoteMonitorTab(store)
|
|
46
|
+
if (store.rightPanelTab !== 'info' || props.pid !== tab?.id) return null
|
|
47
|
+
const config = store.config
|
|
48
|
+
return (
|
|
49
|
+
<>
|
|
50
|
+
<TerminalInfoBase {...props} terminalInfos={config.terminalInfos} />
|
|
51
|
+
{props.isRemote
|
|
52
|
+
? <RemoteInfo key={tab.id} tab={tab} config={config} />
|
|
53
|
+
: <LocalSystemInfo key={tab.id} pid={tab.id} />}
|
|
54
|
+
</>
|
|
55
|
+
)
|
|
56
|
+
})
|
|
@@ -2,53 +2,10 @@
|
|
|
2
2
|
color var(--text-dark)
|
|
3
3
|
&:hover
|
|
4
4
|
color var(--text)
|
|
5
|
-
.info-
|
|
6
|
-
|
|
7
|
-
right 0
|
|
8
|
-
top 100px
|
|
9
|
-
bottom 0
|
|
10
|
-
width 500px
|
|
11
|
-
background var(--main)
|
|
12
|
-
border 1px solid var(--main-darker)
|
|
13
|
-
border-radius 5px 0 0 5px
|
|
14
|
-
border-right none
|
|
15
|
-
color var(--text)
|
|
16
|
-
z-index 100
|
|
17
|
-
overflow-y scroll
|
|
18
|
-
|
|
19
|
-
.drag-handle
|
|
20
|
-
left 0
|
|
21
|
-
right auto
|
|
22
|
-
display block
|
|
23
|
-
.terminal-info-section
|
|
5
|
+
.terminal-info-section,
|
|
6
|
+
.right-side-panel-content > .remote-monitor-details
|
|
24
7
|
padding 10px 0
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
flex-direction column
|
|
30
|
-
gap 4px
|
|
31
|
-
.terminal-info-sys-row
|
|
32
|
-
display flex
|
|
33
|
-
gap 8px
|
|
34
|
-
align-items baseline
|
|
35
|
-
font-size 12px
|
|
36
|
-
.terminal-info-sys-key
|
|
37
|
-
flex none
|
|
38
|
-
width 80px
|
|
39
|
-
color var(--text-dark)
|
|
40
|
-
text-transform capitalize
|
|
41
|
-
.terminal-info-sys-val
|
|
42
|
-
flex 1
|
|
43
|
-
overflow hidden
|
|
44
|
-
text-overflow ellipsis
|
|
45
|
-
white-space nowrap
|
|
46
|
-
.activity-item
|
|
47
|
-
max-height 1.6em
|
|
48
|
-
line-height 1.6
|
|
49
|
-
overflow hidden
|
|
50
|
-
&:hover
|
|
51
|
-
max-height none
|
|
52
|
-
.info-panel-wrap-pin
|
|
53
|
-
.toggle-info-panel-wrap
|
|
54
|
-
color var(--success)
|
|
8
|
+
|
|
9
|
+
.terminal-info-filter-wrap
|
|
10
|
+
display flex
|
|
11
|
+
justify-content flex-end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* open the text editor, load/mount it on demand
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { refsStatic } from '../common/ref'
|
|
6
|
+
|
|
7
|
+
let pending = null
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* request to open the text editor with file data,
|
|
11
|
+
* if the editor is not mounted yet, mount it first
|
|
12
|
+
* and keep the data as pending, editor will consume
|
|
13
|
+
* it on mount
|
|
14
|
+
* @param {object} data { id, file }
|
|
15
|
+
*/
|
|
16
|
+
export function openTextEditor (data) {
|
|
17
|
+
const editor = refsStatic.get('text-editor')
|
|
18
|
+
if (editor) {
|
|
19
|
+
editor.openEditor(data)
|
|
20
|
+
return
|
|
21
|
+
}
|
|
22
|
+
pending = data
|
|
23
|
+
window.store.textEditorRequested = true
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function takePendingTextEditorData () {
|
|
27
|
+
const data = pending
|
|
28
|
+
pending = null
|
|
29
|
+
return data
|
|
30
|
+
}
|
|
@@ -1,11 +1,22 @@
|
|
|
1
|
-
import { lazy, Suspense } from 'react'
|
|
2
|
-
|
|
3
|
-
const TextEditor = lazy(() => import('./text-editor'))
|
|
1
|
+
import { lazy, Suspense, useMemo } from 'react'
|
|
2
|
+
import LazyBoundary from '../common/lazy-boundary'
|
|
4
3
|
|
|
5
4
|
export default function TextEditorEntry (props) {
|
|
5
|
+
// one lazy component per mount: the entry is remounted (the mount latch is
|
|
6
|
+
// released by the boundary below) exactly when a previous load failed, and
|
|
7
|
+
// React.lazy caches a rejected import() forever — so a retry has to go
|
|
8
|
+
// through a *new* lazy component
|
|
9
|
+
const TextEditor = useMemo(() => lazy(() => import('./text-editor')), [])
|
|
10
|
+
const onError = () => {
|
|
11
|
+
// release the mount latch so the next "edit file" request mounts a fresh
|
|
12
|
+
// lazy component and retries the fetch
|
|
13
|
+
window.store.textEditorRequested = false
|
|
14
|
+
}
|
|
6
15
|
return (
|
|
7
|
-
<
|
|
8
|
-
<
|
|
9
|
-
|
|
16
|
+
<LazyBoundary onError={onError}>
|
|
17
|
+
<Suspense fallback={null}>
|
|
18
|
+
<TextEditor {...props} />
|
|
19
|
+
</Suspense>
|
|
20
|
+
</LazyBoundary>
|
|
10
21
|
)
|
|
11
22
|
}
|
|
@@ -13,6 +13,7 @@ import Modal from '../common/modal'
|
|
|
13
13
|
import resolve from '../../common/resolve'
|
|
14
14
|
import { safeGetItem } from '../../common/safe-local-storage.js'
|
|
15
15
|
import { refsStatic, refs } from '../common/ref'
|
|
16
|
+
import { takePendingTextEditorData } from './open-text-editor'
|
|
16
17
|
|
|
17
18
|
const e = window.translate
|
|
18
19
|
|
|
@@ -27,6 +28,19 @@ export default class TextEditor extends PureComponent {
|
|
|
27
28
|
|
|
28
29
|
componentDidMount () {
|
|
29
30
|
refsStatic.add('text-editor', this)
|
|
31
|
+
// editor may be mounted by an open request,
|
|
32
|
+
// consume the pending data now
|
|
33
|
+
const data = takePendingTextEditorData()
|
|
34
|
+
if (data) {
|
|
35
|
+
this.openEditor(data)
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
componentWillUnmount () {
|
|
40
|
+
// the entry can be unmounted (a failed chunk load releases the mount
|
|
41
|
+
// latch); without this a later request would find this dead instance and
|
|
42
|
+
// call openEditor on it, so the modal would never show up
|
|
43
|
+
refsStatic.remove('text-editor')
|
|
30
44
|
}
|
|
31
45
|
|
|
32
46
|
setStateProxy = (state, cb) => {
|
|
@@ -40,6 +40,9 @@ export default function ThemeForm (props) {
|
|
|
40
40
|
action.current = 'saveOnly'
|
|
41
41
|
form.submit()
|
|
42
42
|
}
|
|
43
|
+
function applyOnly () {
|
|
44
|
+
props.store.setTheme(props.formData.id)
|
|
45
|
+
}
|
|
43
46
|
// A function to validate the input text
|
|
44
47
|
async function validateInput (_, value) {
|
|
45
48
|
const input = value
|
|
@@ -189,6 +192,25 @@ export default function ThemeForm (props) {
|
|
|
189
192
|
if (!id) {
|
|
190
193
|
return null
|
|
191
194
|
}
|
|
195
|
+
if (readonly) {
|
|
196
|
+
return (
|
|
197
|
+
<FormItem>
|
|
198
|
+
<Button
|
|
199
|
+
type='primary'
|
|
200
|
+
className='mg1r mg1b'
|
|
201
|
+
onClick={applyOnly}
|
|
202
|
+
>
|
|
203
|
+
{e('apply')}
|
|
204
|
+
</Button>
|
|
205
|
+
<Button
|
|
206
|
+
type='dashed'
|
|
207
|
+
onClick={exporter}
|
|
208
|
+
>
|
|
209
|
+
{e('export')}
|
|
210
|
+
</Button>
|
|
211
|
+
</FormItem>
|
|
212
|
+
)
|
|
213
|
+
}
|
|
192
214
|
return (
|
|
193
215
|
<FormItem>
|
|
194
216
|
<Button
|
|
@@ -5,8 +5,7 @@
|
|
|
5
5
|
import { PureComponent } from 'react'
|
|
6
6
|
import {
|
|
7
7
|
ExportOutlined,
|
|
8
|
-
ImportOutlined
|
|
9
|
-
EditOutlined
|
|
8
|
+
ImportOutlined
|
|
10
9
|
} from '@ant-design/icons'
|
|
11
10
|
import { Button, Space } from 'antd'
|
|
12
11
|
import Upload from '../common/upload'
|
|
@@ -19,21 +18,6 @@ export default class BookmarkTransport extends PureComponent {
|
|
|
19
18
|
|
|
20
19
|
handleDownload = () => {}
|
|
21
20
|
|
|
22
|
-
handleToggleEdit = () => {
|
|
23
|
-
window.store.bookmarkSelectMode = true
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
renderEdit () {
|
|
27
|
-
return (
|
|
28
|
-
<Button
|
|
29
|
-
icon={<EditOutlined />}
|
|
30
|
-
onClick={this.handleToggleEdit}
|
|
31
|
-
title={e('edit')}
|
|
32
|
-
key='edit-and-del'
|
|
33
|
-
/>
|
|
34
|
-
)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
21
|
renderExport () {
|
|
38
22
|
return (
|
|
39
23
|
<Button
|
|
@@ -63,19 +47,11 @@ export default class BookmarkTransport extends PureComponent {
|
|
|
63
47
|
}
|
|
64
48
|
|
|
65
49
|
render () {
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
</Space.Compact>
|
|
73
|
-
)
|
|
74
|
-
}
|
|
75
|
-
return [
|
|
76
|
-
edit,
|
|
77
|
-
this.renderExport(),
|
|
78
|
-
this.renderImport()
|
|
79
|
-
]
|
|
50
|
+
return (
|
|
51
|
+
<Space.Compact>
|
|
52
|
+
{this.renderExport()}
|
|
53
|
+
{this.renderImport()}
|
|
54
|
+
</Space.Compact>
|
|
55
|
+
)
|
|
80
56
|
}
|
|
81
57
|
}
|
|
@@ -187,3 +187,16 @@
|
|
|
187
187
|
&.is-active
|
|
188
188
|
opacity 1
|
|
189
189
|
pointer-events auto
|
|
190
|
+
// touch screens have no hover — always reveal the hover-only action icons
|
|
191
|
+
.is-touch-device
|
|
192
|
+
.tree-list-row
|
|
193
|
+
.tree-item-title
|
|
194
|
+
padding-right 60px
|
|
195
|
+
.tree-item-op-wrap
|
|
196
|
+
opacity 1
|
|
197
|
+
pointer-events auto
|
|
198
|
+
.add-menu-wrap
|
|
199
|
+
.sidebar-panel
|
|
200
|
+
.tree-list-row
|
|
201
|
+
.tree-item-title
|
|
202
|
+
padding-right 20px
|