@electerm/electerm-react 1.60.18 → 1.60.32
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/client/common/clipboard.js +1 -14
- package/client/common/constants.js +0 -43
- package/client/common/data-compare.js +55 -0
- package/client/common/default-setting.js +2 -10
- package/client/common/resolve.js +18 -22
- package/client/common/sftp.js +0 -3
- package/client/components/ai/ai-chat.jsx +30 -6
- package/client/components/ai/ai-config.jsx +17 -6
- package/client/components/batch-op/batch-op.jsx +3 -24
- package/client/components/bookmark-form/bookmark-group-tree-format.js +7 -9
- package/client/components/bookmark-form/form-ssh-common.jsx +0 -2
- package/client/components/bookmark-form/ssh-form.jsx +8 -41
- package/client/components/bookmark-form/tree-delete.jsx +1 -13
- package/client/components/common/animate-text.jsx +3 -4
- package/client/components/common/drag-handle.jsx +59 -45
- package/client/components/common/drag-handle.styl +2 -1
- package/client/components/common/input-auto-focus.jsx +29 -63
- package/client/components/common/ref.js +24 -0
- package/client/components/footer/batch-input.jsx +1 -6
- package/client/components/footer/footer-entry.jsx +13 -16
- package/client/components/footer/footer.styl +0 -5
- package/client/components/icons/ai-icon.jsx +17 -0
- package/client/components/icons/ai-icon.styl +3 -0
- package/client/components/layout/layout-item.jsx +14 -0
- package/client/components/main/main.jsx +8 -19
- package/client/components/main/upgrade.jsx +13 -25
- package/client/components/profile/profile-form-elem.jsx +1 -2
- package/client/components/quick-commands/on-drop.js +1 -12
- package/client/components/quick-commands/quick-command-transport-mod.jsx +3 -13
- package/client/components/quick-commands/quick-commands-form-elem.jsx +1 -2
- package/client/components/rdp/rdp-session.jsx +4 -4
- package/client/components/session/session.jsx +9 -11
- package/client/components/setting-panel/on-tree-drop.js +4 -35
- package/client/components/setting-panel/setting-common.jsx +4 -1
- package/client/components/setting-panel/setting-modal.jsx +7 -5
- package/client/components/setting-panel/tab-settings.jsx +0 -1
- package/client/components/setting-sync/setting-sync.jsx +0 -1
- package/client/components/sftp/address-bookmark-item.jsx +1 -15
- package/client/components/sftp/confirm-modal-store.jsx +2 -2
- package/client/components/sftp/{file-mode-modal.jsx → file-info-modal.jsx} +137 -37
- package/client/components/sftp/file-item.jsx +156 -192
- package/client/components/sftp/file-table-header.jsx +98 -0
- package/client/components/sftp/list-table-ui.jsx +125 -416
- package/client/components/sftp/sftp-entry.jsx +102 -128
- package/client/components/sftp/sftp.styl +6 -22
- package/client/components/sftp/transfer-conflict-store.jsx +8 -12
- package/client/components/sftp/transport-action-store.jsx +7 -15
- package/client/components/shortcuts/shortcut-control.jsx +72 -3
- package/client/components/shortcuts/shortcut-handler.js +0 -1
- package/client/components/side-panel-r/side-panel-r.jsx +7 -4
- package/client/components/sidebar/bookmark-select.jsx +5 -3
- package/client/components/sidebar/history.jsx +3 -0
- package/client/components/sidebar/index.jsx +1 -1
- package/client/components/sidebar/info-modal.jsx +3 -0
- package/client/components/sidebar/side-panel.jsx +7 -4
- package/client/components/sidebar/sidebar-panel.jsx +1 -1
- package/client/components/sidebar/sidebar.styl +3 -3
- package/client/components/sys-menu/icons-map.jsx +52 -0
- package/client/components/{context-menu → sys-menu}/menu-btn.jsx +33 -45
- package/client/components/sys-menu/sys-menu.jsx +163 -0
- package/client/components/{context-menu/context-menu.styl → sys-menu/sys-menu.styl} +2 -11
- package/client/components/tabs/index.jsx +5 -97
- package/client/components/tabs/tab.jsx +121 -73
- package/client/components/tabs/tabs.styl +4 -1
- package/client/components/terminal/term-search.jsx +16 -28
- package/client/components/terminal/terminal-interactive.jsx +0 -2
- package/client/components/terminal/{index.jsx → terminal.jsx} +110 -240
- package/client/components/terminal-info/base.jsx +21 -46
- package/client/components/terminal-info/terminal-info.jsx +3 -0
- package/client/components/text-editor/text-editor.jsx +38 -53
- package/client/components/theme/theme-form.jsx +0 -2
- package/client/components/tree-list/bookmark-toolbar.jsx +23 -47
- package/client/components/tree-list/bookmark-transport.jsx +2 -90
- package/client/components/tree-list/move-item-modal.jsx +101 -0
- package/client/components/tree-list/tree-expander.jsx +2 -3
- package/client/components/tree-list/tree-list-item.jsx +8 -11
- package/client/components/tree-list/tree-list.jsx +75 -296
- package/client/components/vnc/vnc-session.jsx +5 -3
- package/client/store/app-upgrade.js +2 -5
- package/client/store/bookmark-group.js +116 -51
- package/client/store/common.js +36 -54
- package/client/store/event.js +4 -37
- package/client/store/init-state.js +9 -12
- package/client/store/item.js +34 -39
- package/client/store/load-data.js +5 -1
- package/client/store/quick-command.js +2 -12
- package/client/store/session.js +6 -7
- package/client/store/setting.js +3 -7
- package/client/store/sidebar.js +2 -8
- package/client/store/store.js +0 -20
- package/client/store/system-menu.js +1 -2
- package/client/store/tab.js +29 -1
- package/client/store/terminal-theme.js +0 -4
- package/client/store/watch.js +26 -4
- package/package.json +1 -1
- package/client/common/post-msg.js +0 -3
- package/client/components/common/native-input.jsx +0 -30
- package/client/components/context-menu/context-menu.jsx +0 -339
- package/client/components/sftp/file-props-modal.jsx +0 -210
- package/client/store/context-menu.js +0 -23
- /package/client/components/{context-menu → sys-menu}/boomarks.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/history.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/icon-holder.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/sub-tab-menu.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/tabs.jsx +0 -0
- /package/client/components/{context-menu → sys-menu}/zoom.jsx +0 -0
|
@@ -3,9 +3,6 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import { message } from 'antd'
|
|
6
|
-
import {
|
|
7
|
-
copyBookmarkItemPrefix
|
|
8
|
-
} from './constants'
|
|
9
6
|
|
|
10
7
|
const fileRegWin = /^(remote:)?\w:\\.+/
|
|
11
8
|
const fileReg = /^(remote:)?\/.+/
|
|
@@ -24,7 +21,7 @@ export const readClipboardAsync = () => {
|
|
|
24
21
|
|
|
25
22
|
export const copy = (str) => {
|
|
26
23
|
message.success({
|
|
27
|
-
content: '
|
|
24
|
+
content: window.translate('copied'),
|
|
28
25
|
duation: 2,
|
|
29
26
|
key: 'copy-message'
|
|
30
27
|
})
|
|
@@ -45,13 +42,3 @@ export const hasFileInClipboardText = (
|
|
|
45
42
|
(fileReg.test(t) || fileRegWin.test(t))
|
|
46
43
|
}, true)
|
|
47
44
|
}
|
|
48
|
-
|
|
49
|
-
export const hasBookmarkOrGroupInClipboardText = (
|
|
50
|
-
text = readClipboard()
|
|
51
|
-
) => {
|
|
52
|
-
const arr = text.split('\n')
|
|
53
|
-
return arr.reduce((prev, t = '') => {
|
|
54
|
-
return prev &&
|
|
55
|
-
t.startsWith(copyBookmarkItemPrefix)
|
|
56
|
-
}, true)
|
|
57
|
-
}
|
|
@@ -171,10 +171,6 @@ export const defaultTheme = {
|
|
|
171
171
|
uiThemeConfig: getUiThemeConfig(window.et.stylus)
|
|
172
172
|
}
|
|
173
173
|
|
|
174
|
-
export const eventTypes = {
|
|
175
|
-
resetFileListTable: 'reset-file-list-table'
|
|
176
|
-
}
|
|
177
|
-
|
|
178
174
|
export const commonBaudRates = [
|
|
179
175
|
110,
|
|
180
176
|
300,
|
|
@@ -229,17 +225,6 @@ const defaultThemeLightConf = _get(
|
|
|
229
225
|
)
|
|
230
226
|
defaultThemeLightConf.id = defaultThemeLightConf._id
|
|
231
227
|
export const defaultThemeLight = defaultThemeLightConf
|
|
232
|
-
export const terminalActions = {
|
|
233
|
-
showInfoPanel: 'show-info-panel',
|
|
234
|
-
changeEncode: 'change-encode',
|
|
235
|
-
batchInput: 'batch-input',
|
|
236
|
-
quickCommand: 'quick-command',
|
|
237
|
-
openTerminalSearch: 'open-terminal-search',
|
|
238
|
-
doSearchNext: 'do-search-next',
|
|
239
|
-
doSearchPrev: 'do-search-prev',
|
|
240
|
-
clearSearch: 'clear-search',
|
|
241
|
-
zoom: 'zoom-terminal'
|
|
242
|
-
}
|
|
243
228
|
export const fileActions = {
|
|
244
229
|
cancel: 'cancel',
|
|
245
230
|
skip: 'skip',
|
|
@@ -250,32 +235,6 @@ export const fileActions = {
|
|
|
250
235
|
renameAll: 'renameAll'
|
|
251
236
|
}
|
|
252
237
|
|
|
253
|
-
export const commonActions = {
|
|
254
|
-
returnTermLogState: 'return-term-log-state',
|
|
255
|
-
getTermLogState: 'get-term-log-state',
|
|
256
|
-
setTermLogState: 'set-term-log-state',
|
|
257
|
-
batchOp: 'batch-op',
|
|
258
|
-
updateStore: 'update-store',
|
|
259
|
-
editWithSystemEditorDone: 'edit-with-system-editor-done',
|
|
260
|
-
editWithSystemEditor: 'edit-with-system-editor',
|
|
261
|
-
onCloseTextEditor: 'on-close-text-editor',
|
|
262
|
-
submitTextEditorText: 'submit-text-editor-text',
|
|
263
|
-
fetchTextEditorText: 'fetch-text-editor-text',
|
|
264
|
-
loadTextEditorText: 'load-text-editor-text',
|
|
265
|
-
openTextEditor: 'open-text-editor',
|
|
266
|
-
submitFileModeEdit: 'submit-file-mode-edit',
|
|
267
|
-
submitFileModeClose: 'submit-file-mode-close',
|
|
268
|
-
showFileModeModal: 'show-file-mode-modal',
|
|
269
|
-
showFileInfoModal: 'show-file-info-modal',
|
|
270
|
-
appUpdateCheck: 'check-app-update',
|
|
271
|
-
closeContextMenu: 'close-context-menu',
|
|
272
|
-
closeContextMenuAfter: 'close-context-menu-after',
|
|
273
|
-
clickContextMenu: 'click-context-menu',
|
|
274
|
-
openContextMenu: 'open-context-menu',
|
|
275
|
-
addTransfer: 'add-transfer',
|
|
276
|
-
sftpList: 'sftp-list'
|
|
277
|
-
}
|
|
278
|
-
|
|
279
238
|
export const srcsSkipUpgradeCheck = [
|
|
280
239
|
'.appx',
|
|
281
240
|
'.snap',
|
|
@@ -283,8 +242,6 @@ export const srcsSkipUpgradeCheck = [
|
|
|
283
242
|
]
|
|
284
243
|
export const termLSPrefix = 'term:sess:'
|
|
285
244
|
export const batchInputLsKey = 'batch-inputs'
|
|
286
|
-
export const copyBookmarkItemPrefix = 'bookmark:'
|
|
287
|
-
export const copyBookmarkGroupItemPrefix = 'bookmarkGroup:'
|
|
288
245
|
export const rendererTypes = {
|
|
289
246
|
dom: 'dom',
|
|
290
247
|
canvas: 'canvas',
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare two arrays of objects and return differences
|
|
3
|
+
* @param {Array} oldArr - Original array of objects
|
|
4
|
+
* @param {Array} newArr - New array of objects to compare against
|
|
5
|
+
* @returns {Object} Object containing arrays of items to update, add, and remove
|
|
6
|
+
*/
|
|
7
|
+
export default function compare (oldArr, newArr) {
|
|
8
|
+
if (!oldArr || !newArr) {
|
|
9
|
+
return {
|
|
10
|
+
updated: [],
|
|
11
|
+
added: [],
|
|
12
|
+
removed: []
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// Create maps for faster lookup
|
|
16
|
+
const oldMap = new Map(
|
|
17
|
+
oldArr.map(item => [item.id, item])
|
|
18
|
+
)
|
|
19
|
+
const newMap = new Map(
|
|
20
|
+
newArr.map(item => [item.id, item])
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
const updated = []
|
|
24
|
+
const added = []
|
|
25
|
+
const removed = []
|
|
26
|
+
|
|
27
|
+
// Find items to update or add
|
|
28
|
+
for (const item of newArr) {
|
|
29
|
+
const oldItem = oldMap.get(item.id)
|
|
30
|
+
if (!oldItem) {
|
|
31
|
+
// Item doesn't exist in old array - need to add
|
|
32
|
+
added.push(item)
|
|
33
|
+
} else {
|
|
34
|
+
// Item exists - check if it needs updating
|
|
35
|
+
// Convert to JSON strings for deep comparison
|
|
36
|
+
const oldStr = JSON.stringify(oldItem)
|
|
37
|
+
const newStr = JSON.stringify(item)
|
|
38
|
+
if (oldStr !== newStr) {
|
|
39
|
+
updated.push(item)
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Find items to remove
|
|
45
|
+
for (const item of oldArr) {
|
|
46
|
+
if (!newMap.has(item.id)) {
|
|
47
|
+
removed.push(item)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
return {
|
|
51
|
+
updated,
|
|
52
|
+
added,
|
|
53
|
+
removed
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -16,7 +16,7 @@ export default {
|
|
|
16
16
|
execMacArgs: [],
|
|
17
17
|
execLinuxArgs: [],
|
|
18
18
|
enableGlobalProxy: false,
|
|
19
|
-
|
|
19
|
+
disableConnectionHistory: false,
|
|
20
20
|
disableTransferHistory: false,
|
|
21
21
|
terminalBackgroundImagePath: '',
|
|
22
22
|
terminalBackgroundFilterOpacity: 1,
|
|
@@ -61,13 +61,5 @@ export default {
|
|
|
61
61
|
dataSyncSelected: 'all',
|
|
62
62
|
baseURLAI: 'https://api.deepseek.com',
|
|
63
63
|
modelAI: 'deepseek-chat',
|
|
64
|
-
roleAI:
|
|
65
|
-
- Provide clear, safe, and efficient shell commands
|
|
66
|
-
- Always explain what each command does
|
|
67
|
-
- Warn about potentially dangerous operations
|
|
68
|
-
- Format command output with markdown code blocks
|
|
69
|
-
- If multiple steps are needed, number them
|
|
70
|
-
- Mention any prerequisites or dependencies
|
|
71
|
-
- Include common flags and options
|
|
72
|
-
- Specify which OS (Linux/Mac/Windows) the command is for`
|
|
64
|
+
roleAI: '终端专家,提供不同系统下安全命令,解释用法及风险,用markdown格式'
|
|
73
65
|
}
|
package/client/common/resolve.js
CHANGED
|
@@ -6,31 +6,27 @@
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
export default (basePath, nameOrDot) => {
|
|
9
|
-
const
|
|
10
|
-
basePath.includes('
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
)
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
const hasWinDrive = (path) => /^[a-zA-Z]:/.test(path)
|
|
10
|
+
const isWin = basePath.includes('\\') || nameOrDot.includes('\\') || hasWinDrive(basePath) || hasWinDrive(nameOrDot)
|
|
11
|
+
const sep = isWin ? '\\' : '/'
|
|
12
|
+
// Handle Windows drive letters (with or without initial slash)
|
|
13
|
+
if (/^[a-zA-Z]:/.test(nameOrDot)) {
|
|
14
|
+
return nameOrDot.replace(/^\//, '').replace(/\//g, sep)
|
|
15
|
+
}
|
|
16
|
+
// Handle absolute paths
|
|
17
|
+
if (nameOrDot.startsWith('/')) {
|
|
18
|
+
return nameOrDot.replace(/\\/g, sep)
|
|
19
|
+
}
|
|
16
20
|
if (nameOrDot === '..') {
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
return '/'
|
|
21
|
+
const parts = basePath.split(sep)
|
|
22
|
+
if (parts.length > 1) {
|
|
23
|
+
parts.pop()
|
|
24
|
+
return isWin && parts.length === 1 ? '/' : parts.join(sep) || '/'
|
|
21
25
|
}
|
|
22
|
-
|
|
23
|
-
return res || '/'
|
|
24
|
-
}
|
|
25
|
-
const pre = (nameOrDot.includes(':\\') || /^[a-z]+:$/i.test(nameOrDot)) && basePath === '/'
|
|
26
|
-
? ''
|
|
27
|
-
: basePath
|
|
28
|
-
const mid = (basePath.endsWith(sep) ? '' : sep)
|
|
29
|
-
let ff = pre + mid + nameOrDot
|
|
30
|
-
if (/^\\[a-z]+:$/i.test(ff)) {
|
|
31
|
-
ff = ff.slice(1)
|
|
26
|
+
return '/'
|
|
32
27
|
}
|
|
33
|
-
|
|
28
|
+
const result = basePath.endsWith(sep) ? basePath + nameOrDot : basePath + sep + nameOrDot
|
|
29
|
+
return isWin && result.length === 3 && result.endsWith(':\\') ? '/' : result
|
|
34
30
|
}
|
|
35
31
|
|
|
36
32
|
export const osResolve = (...args) => {
|
package/client/common/sftp.js
CHANGED
|
@@ -7,7 +7,6 @@ import Transfer from './transfer'
|
|
|
7
7
|
import { transferTypeMap, instSftpKeys as keys } from './constants'
|
|
8
8
|
import initWs from './ws'
|
|
9
9
|
|
|
10
|
-
window.sftps = {}
|
|
11
10
|
const transferKeys = Object.keys(transferTypeMap)
|
|
12
11
|
|
|
13
12
|
class Sftp {
|
|
@@ -57,7 +56,6 @@ class Sftp {
|
|
|
57
56
|
}
|
|
58
57
|
|
|
59
58
|
async destroy () {
|
|
60
|
-
delete window.sftps[this.sessionId]
|
|
61
59
|
const { ws } = this
|
|
62
60
|
ws.s({
|
|
63
61
|
action: 'sftp-destroy',
|
|
@@ -71,6 +69,5 @@ class Sftp {
|
|
|
71
69
|
export default async (sessionId) => {
|
|
72
70
|
const sftp = new Sftp()
|
|
73
71
|
await sftp.init(sessionId)
|
|
74
|
-
window.sftps[sessionId] = sftp
|
|
75
72
|
return sftp
|
|
76
73
|
}
|
|
@@ -15,6 +15,7 @@ import {
|
|
|
15
15
|
aiConfigWikiLink
|
|
16
16
|
} from '../../common/constants'
|
|
17
17
|
import HelpIcon from '../common/help-icon'
|
|
18
|
+
import { refsStatic } from '../common/ref'
|
|
18
19
|
import './ai.styl'
|
|
19
20
|
|
|
20
21
|
const { TextArea } = Input
|
|
@@ -34,7 +35,12 @@ export default function AIChat (props) {
|
|
|
34
35
|
setPrompt(e.target.value)
|
|
35
36
|
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
+
function buildRole () {
|
|
39
|
+
const lang = props.config.languageAI || window.store.getLangName()
|
|
40
|
+
return props.config.roleAI + `;用[${lang}]回复`
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
const handleSubmit = useCallback(async function () {
|
|
38
44
|
if (aiConfigMissing()) {
|
|
39
45
|
window.store.toggleAIConfig()
|
|
40
46
|
}
|
|
@@ -44,7 +50,7 @@ export default function AIChat (props) {
|
|
|
44
50
|
'AIchat',
|
|
45
51
|
prompt,
|
|
46
52
|
props.config.modelAI,
|
|
47
|
-
|
|
53
|
+
buildRole(),
|
|
48
54
|
props.config.baseURLAI,
|
|
49
55
|
props.config.apiKeyAI
|
|
50
56
|
).catch(
|
|
@@ -72,19 +78,26 @@ export default function AIChat (props) {
|
|
|
72
78
|
}
|
|
73
79
|
setPrompt('')
|
|
74
80
|
setIsLoading(false)
|
|
75
|
-
}
|
|
81
|
+
}, [prompt, isLoading, props.config])
|
|
76
82
|
|
|
77
83
|
function handleConfigSubmit (values) {
|
|
78
84
|
window.store.updateConfig(values)
|
|
79
85
|
message.success('Saved')
|
|
80
86
|
}
|
|
81
87
|
|
|
88
|
+
function getInitialValues () {
|
|
89
|
+
const res = pick(props.config, aiConfigsArr)
|
|
90
|
+
if (!res.languageAI) {
|
|
91
|
+
res.languageAI = window.store.getLangName()
|
|
92
|
+
}
|
|
93
|
+
return res
|
|
94
|
+
}
|
|
95
|
+
|
|
82
96
|
const renderConfig = useCallback(() => {
|
|
83
97
|
if (!props.showAIConfig) return null
|
|
84
|
-
const aiConfigs = pick(props.config, aiConfigsArr)
|
|
85
98
|
return (
|
|
86
99
|
<AIConfigForm
|
|
87
|
-
initialValues={
|
|
100
|
+
initialValues={getInitialValues()}
|
|
88
101
|
onSubmit={handleConfigSubmit}
|
|
89
102
|
showAIConfig={props.showAIConfig}
|
|
90
103
|
/>
|
|
@@ -124,10 +137,21 @@ export default function AIChat (props) {
|
|
|
124
137
|
}
|
|
125
138
|
|
|
126
139
|
useEffect(() => {
|
|
140
|
+
refsStatic.add('AIChat', {
|
|
141
|
+
setPrompt,
|
|
142
|
+
handleSubmit
|
|
143
|
+
})
|
|
127
144
|
if (aiConfigMissing()) {
|
|
128
145
|
window.store.toggleAIConfig()
|
|
129
146
|
}
|
|
130
|
-
|
|
147
|
+
return () => {
|
|
148
|
+
refsStatic.remove('AIChat')
|
|
149
|
+
}
|
|
150
|
+
}, [handleSubmit])
|
|
151
|
+
|
|
152
|
+
if (props.rightPanelTab !== 'ai') {
|
|
153
|
+
return null
|
|
154
|
+
}
|
|
131
155
|
|
|
132
156
|
return (
|
|
133
157
|
<Flex vertical className='ai-chat-container'>
|
|
@@ -16,6 +16,14 @@ import {
|
|
|
16
16
|
import providers from './providers'
|
|
17
17
|
|
|
18
18
|
const e = window.translate
|
|
19
|
+
const defaultRoles = [
|
|
20
|
+
{
|
|
21
|
+
value: 'Terminal expert, provide safe commands for different OS, explain usage and risks, use markdown format'
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
value: '终端专家,提供不同系统下安全命令,解释用法及风险,用markdown格式'
|
|
25
|
+
}
|
|
26
|
+
]
|
|
19
27
|
|
|
20
28
|
export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig }) {
|
|
21
29
|
const [form] = Form.useForm()
|
|
@@ -86,6 +94,7 @@ export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig })
|
|
|
86
94
|
form={form}
|
|
87
95
|
onFinish={handleSubmit}
|
|
88
96
|
initialValues={initialValues}
|
|
97
|
+
layout='vertical'
|
|
89
98
|
>
|
|
90
99
|
<Form.Item
|
|
91
100
|
label='API URL'
|
|
@@ -105,7 +114,7 @@ export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig })
|
|
|
105
114
|
</Form.Item>
|
|
106
115
|
|
|
107
116
|
<Form.Item
|
|
108
|
-
label='
|
|
117
|
+
label={e('modelAi')}
|
|
109
118
|
name='modelAI'
|
|
110
119
|
rules={[{ required: true, message: 'Please input or select a model!' }]}
|
|
111
120
|
>
|
|
@@ -124,14 +133,16 @@ export default function AIConfigForm ({ initialValues, onSubmit, showAIConfig })
|
|
|
124
133
|
</Form.Item>
|
|
125
134
|
|
|
126
135
|
<Form.Item
|
|
127
|
-
label='
|
|
136
|
+
label={e('roleAI')}
|
|
128
137
|
name='roleAI'
|
|
129
138
|
rules={[{ required: true, message: 'Please input the AI role!' }]}
|
|
130
139
|
>
|
|
131
|
-
<
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
140
|
+
<AutoComplete options={defaultRoles} placement='topLeft'>
|
|
141
|
+
<Input.TextArea
|
|
142
|
+
placeholder='Enter AI role/system prompt'
|
|
143
|
+
rows={1}
|
|
144
|
+
/>
|
|
145
|
+
</AutoComplete>
|
|
135
146
|
</Form.Item>
|
|
136
147
|
|
|
137
148
|
<Form.Item>
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
import {
|
|
18
18
|
sidebarWidth,
|
|
19
19
|
statusMap,
|
|
20
|
-
commonActions,
|
|
21
20
|
batchOpHelpLink,
|
|
22
21
|
modals
|
|
23
22
|
} from '../../common/constants'
|
|
@@ -31,6 +30,7 @@ import uid from '../../common/uid'
|
|
|
31
30
|
import wait from '../../common/wait'
|
|
32
31
|
import { getFolderFromFilePath } from '../sftp/file-read'
|
|
33
32
|
import resolveFilePath from '../../common/resolve'
|
|
33
|
+
import { refsStatic } from '../common/ref'
|
|
34
34
|
|
|
35
35
|
const e = window.translate
|
|
36
36
|
|
|
@@ -85,19 +85,8 @@ export default class BatchOp extends PureComponent {
|
|
|
85
85
|
]
|
|
86
86
|
|
|
87
87
|
componentDidMount () {
|
|
88
|
-
this.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
componentWillUnmount () {
|
|
92
|
-
this.unwatch()
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
watch () {
|
|
96
|
-
window.addEventListener('message', this.handleEvent)
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
unwatch () {
|
|
100
|
-
window.removeEventListener('message', this.handleEvent)
|
|
88
|
+
this.id = 'batch-op'
|
|
89
|
+
refsStatic.add(this.id, this)
|
|
101
90
|
}
|
|
102
91
|
|
|
103
92
|
handleDownloadExample = () => {
|
|
@@ -109,16 +98,6 @@ export default class BatchOp extends PureComponent {
|
|
|
109
98
|
download('batch-op-example.csv', csvText)
|
|
110
99
|
}
|
|
111
100
|
|
|
112
|
-
handleEvent = e => {
|
|
113
|
-
if (e && e.data && e.data.action === commonActions.batchOp) {
|
|
114
|
-
const {
|
|
115
|
-
func,
|
|
116
|
-
args
|
|
117
|
-
} = e.data.batchOp
|
|
118
|
-
this[func](...args)
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
101
|
handleCancel = () => {
|
|
123
102
|
window.store.toggleBatchOp()
|
|
124
103
|
}
|
|
@@ -2,16 +2,10 @@
|
|
|
2
2
|
* create bookmark group tree data
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
|
-
export default (bookmarkGroups = []) => {
|
|
6
|
-
const btree = bookmarkGroups
|
|
7
|
-
.reduce((prev, k) => {
|
|
8
|
-
return {
|
|
9
|
-
...prev,
|
|
10
|
-
[k.id]: k
|
|
11
|
-
}
|
|
12
|
-
}, {})
|
|
5
|
+
export default (bookmarkGroups = [], disabledId = '', returnMap = false) => {
|
|
6
|
+
const btree = new Map(bookmarkGroups.map(d => [d.id, d]))
|
|
13
7
|
function buildSubCats (id) {
|
|
14
|
-
const x = btree
|
|
8
|
+
const x = btree.get(id)
|
|
15
9
|
if (!x) {
|
|
16
10
|
return ''
|
|
17
11
|
}
|
|
@@ -32,9 +26,13 @@ export default (bookmarkGroups = []) => {
|
|
|
32
26
|
title: d.title,
|
|
33
27
|
value: d.id,
|
|
34
28
|
key: d.id,
|
|
29
|
+
disabled: d.id === disabledId,
|
|
35
30
|
children: (d.bookmarkGroupIds || []).map(buildSubCats).filter(d => d)
|
|
36
31
|
}
|
|
37
32
|
return r
|
|
38
33
|
}).filter(d => d)
|
|
34
|
+
if (returnMap) {
|
|
35
|
+
return [level1, btree]
|
|
36
|
+
}
|
|
39
37
|
return level1
|
|
40
38
|
}
|
|
@@ -32,7 +32,6 @@ const e = window.translate
|
|
|
32
32
|
|
|
33
33
|
export default function renderCommon (props) {
|
|
34
34
|
const {
|
|
35
|
-
autofocustrigger,
|
|
36
35
|
bookmarkGroups = [],
|
|
37
36
|
ips,
|
|
38
37
|
form,
|
|
@@ -85,7 +84,6 @@ export default function renderCommon (props) {
|
|
|
85
84
|
}
|
|
86
85
|
<FormItem noStyle name='host'>
|
|
87
86
|
<InputAutoFocus
|
|
88
|
-
autofocustrigger={autofocustrigger}
|
|
89
87
|
selectall='yes'
|
|
90
88
|
name='host'
|
|
91
89
|
onBlur={props.onBlur}
|
|
@@ -5,7 +5,7 @@ import { PureComponent } from 'react'
|
|
|
5
5
|
import {
|
|
6
6
|
message
|
|
7
7
|
} from 'antd'
|
|
8
|
-
import { uniq,
|
|
8
|
+
import { uniq, pick } from 'lodash-es'
|
|
9
9
|
import copy from 'json-deep-copy'
|
|
10
10
|
import generate from '../../common/uid'
|
|
11
11
|
import {
|
|
@@ -20,6 +20,7 @@ import testCon from '../../common/test-connection'
|
|
|
20
20
|
import FormUi from './ssh-form-ui'
|
|
21
21
|
import findBookmarkGroupId from '../../common/find-bookmark-group-id'
|
|
22
22
|
import newTerm from '../../common/new-terminal'
|
|
23
|
+
import { action } from 'manate'
|
|
23
24
|
|
|
24
25
|
export default class BookmarkForm extends PureComponent {
|
|
25
26
|
state = {
|
|
@@ -95,7 +96,10 @@ export default class BookmarkForm extends PureComponent {
|
|
|
95
96
|
: currentBookmarkGroupId
|
|
96
97
|
}
|
|
97
98
|
|
|
98
|
-
updateBookmarkGroups = (
|
|
99
|
+
updateBookmarkGroups = action((bookmark, categoryId) => {
|
|
100
|
+
const {
|
|
101
|
+
bookmarkGroups
|
|
102
|
+
} = window.store
|
|
99
103
|
let index = bookmarkGroups.findIndex(
|
|
100
104
|
bg => bg.id === categoryId
|
|
101
105
|
)
|
|
@@ -106,50 +110,21 @@ export default class BookmarkForm extends PureComponent {
|
|
|
106
110
|
}
|
|
107
111
|
const bid = bookmark.id
|
|
108
112
|
const bg = bookmarkGroups[index]
|
|
109
|
-
const updates = []
|
|
110
|
-
const old = copy(bg.bookmarkIds)
|
|
111
113
|
if (!bg.bookmarkIds.includes(bid)) {
|
|
112
114
|
bg.bookmarkIds.unshift(bid)
|
|
113
115
|
}
|
|
114
116
|
bg.bookmarkIds = uniq(bg.bookmarkIds)
|
|
115
|
-
|
|
116
|
-
updates.push({
|
|
117
|
-
id: bg.id,
|
|
118
|
-
db: 'bookmarkGroups',
|
|
119
|
-
update: {
|
|
120
|
-
bookmarkIds: bg.bookmarkIds
|
|
121
|
-
}
|
|
122
|
-
})
|
|
123
|
-
}
|
|
124
|
-
bookmarkGroups = bookmarkGroups.map((bg, i) => {
|
|
117
|
+
bookmarkGroups.forEach((bg, i) => {
|
|
125
118
|
if (i === index) {
|
|
126
119
|
return bg
|
|
127
120
|
}
|
|
128
|
-
const olde = copy(bg.bookmarkIds)
|
|
129
121
|
bg.bookmarkIds = bg.bookmarkIds.filter(
|
|
130
122
|
g => g !== bid
|
|
131
123
|
)
|
|
132
|
-
if (!isEqual(bg.bookmarkIds, olde)) {
|
|
133
|
-
updates.push({
|
|
134
|
-
id: bg.id,
|
|
135
|
-
db: 'bookmarkGroups',
|
|
136
|
-
update: {
|
|
137
|
-
bookmarkIds: bg.bookmarkIds
|
|
138
|
-
}
|
|
139
|
-
})
|
|
140
|
-
}
|
|
141
124
|
return bg
|
|
142
125
|
})
|
|
143
|
-
runIdle(() => {
|
|
144
|
-
this.props.store.setBookmarkGroups(
|
|
145
|
-
bookmarkGroups
|
|
146
|
-
)
|
|
147
|
-
})
|
|
148
|
-
runIdle(() => {
|
|
149
|
-
this.props.store.batchDbUpdate(updates)
|
|
150
|
-
})
|
|
151
126
|
message.success('OK', 3)
|
|
152
|
-
}
|
|
127
|
+
})
|
|
153
128
|
|
|
154
129
|
submit = (evt, item, type = this.props.type) => {
|
|
155
130
|
if (item.host) {
|
|
@@ -162,9 +137,6 @@ export default class BookmarkForm extends PureComponent {
|
|
|
162
137
|
const { addItem, editItem } = this.props.store
|
|
163
138
|
const categoryId = obj.category
|
|
164
139
|
delete obj.category
|
|
165
|
-
const bookmarkGroups = copy(
|
|
166
|
-
this.props.bookmarkGroups
|
|
167
|
-
)
|
|
168
140
|
if (!obj.id.startsWith(newBookmarkIdPrefix)) {
|
|
169
141
|
const tar = copy(obj)
|
|
170
142
|
delete tar.id
|
|
@@ -172,7 +144,6 @@ export default class BookmarkForm extends PureComponent {
|
|
|
172
144
|
editItem(obj.id, tar, settingMap.bookmarks)
|
|
173
145
|
})
|
|
174
146
|
this.updateBookmarkGroups(
|
|
175
|
-
bookmarkGroups,
|
|
176
147
|
obj,
|
|
177
148
|
categoryId
|
|
178
149
|
)
|
|
@@ -185,7 +156,6 @@ export default class BookmarkForm extends PureComponent {
|
|
|
185
156
|
addItem(obj, settingMap.bookmarks)
|
|
186
157
|
})
|
|
187
158
|
this.updateBookmarkGroups(
|
|
188
|
-
bookmarkGroups,
|
|
189
159
|
obj,
|
|
190
160
|
categoryId
|
|
191
161
|
)
|
|
@@ -200,9 +170,6 @@ export default class BookmarkForm extends PureComponent {
|
|
|
200
170
|
settingItem = getInitItem([], settingMap.bookmarks)
|
|
201
171
|
) => {
|
|
202
172
|
const { store } = this.props
|
|
203
|
-
this.props.store.storeAssign({
|
|
204
|
-
autofocustrigger: Date.now()
|
|
205
|
-
})
|
|
206
173
|
store.setSettingItem(settingItem)
|
|
207
174
|
}
|
|
208
175
|
|
|
@@ -20,20 +20,8 @@ export default class BookmarkTreeDelete extends StartSessionSelect {
|
|
|
20
20
|
handleDel = () => {
|
|
21
21
|
const { store } = window
|
|
22
22
|
const {
|
|
23
|
-
checkedKeys
|
|
24
|
-
bookmarks,
|
|
25
|
-
bookmarkGroups
|
|
23
|
+
checkedKeys
|
|
26
24
|
} = this.props
|
|
27
|
-
store.setBookmarks(
|
|
28
|
-
bookmarks.filter(f => {
|
|
29
|
-
return !checkedKeys.includes(f.id)
|
|
30
|
-
})
|
|
31
|
-
)
|
|
32
|
-
store.setBookmarkGroups(
|
|
33
|
-
bookmarkGroups.filter(f => {
|
|
34
|
-
return f.id === defaultBookmarkGroupId || !checkedKeys.includes(f.id)
|
|
35
|
-
})
|
|
36
|
-
)
|
|
37
25
|
const arr = checkedKeys.filter(d => d !== defaultBookmarkGroupId)
|
|
38
26
|
store.delItems(arr, settingMap.bookmarks)
|
|
39
27
|
store.delItems(arr, settingMap.bookmarkGroups)
|
|
@@ -3,17 +3,16 @@
|
|
|
3
3
|
*/
|
|
4
4
|
|
|
5
5
|
import React from 'react'
|
|
6
|
-
import uid from '../../common/uid'
|
|
7
6
|
import './animate-text.styl'
|
|
8
7
|
|
|
9
8
|
export default class AnimateText extends React.PureComponent {
|
|
10
9
|
constructor (props) {
|
|
11
10
|
super(props)
|
|
12
|
-
this.
|
|
11
|
+
this.textRef = React.createRef()
|
|
13
12
|
}
|
|
14
13
|
|
|
15
14
|
componentDidUpdate () {
|
|
16
|
-
const dom =
|
|
15
|
+
const dom = this.textRef.current
|
|
17
16
|
dom.className = (this.props.className || 'animate-text-wrap') + ' animated bounceIn'
|
|
18
17
|
this.timer = setTimeout(() => {
|
|
19
18
|
if (dom) {
|
|
@@ -29,7 +28,7 @@ export default class AnimateText extends React.PureComponent {
|
|
|
29
28
|
render () {
|
|
30
29
|
const { children, className } = this.props
|
|
31
30
|
return (
|
|
32
|
-
<div className={className}
|
|
31
|
+
<div className={className} ref={this.textRef}>
|
|
33
32
|
{children}
|
|
34
33
|
</div>
|
|
35
34
|
)
|