mirror of https://github.com/openspug/spug
# 发布详情窗口增加直接开web终端功能
parent
4b2df549ab
commit
a7b17f09f3
|
@ -6,7 +6,7 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { observer, useLocalStore } from 'mobx-react';
|
import { observer, useLocalStore } from 'mobx-react';
|
||||||
import { Card, Progress, Modal, Collapse, Steps, Skeleton } from 'antd';
|
import { Card, Progress, Modal, Collapse, Steps, Skeleton } from 'antd';
|
||||||
import { ShrinkOutlined, CaretRightOutlined, LoadingOutlined, CloseOutlined } from '@ant-design/icons';
|
import { ShrinkOutlined, CaretRightOutlined, LoadingOutlined, CloseOutlined, CodeOutlined } from '@ant-design/icons';
|
||||||
import OutView from './OutView';
|
import OutView from './OutView';
|
||||||
import { http, X_TOKEN } from 'libs';
|
import { http, X_TOKEN } from 'libs';
|
||||||
import styles from './index.module.less';
|
import styles from './index.module.less';
|
||||||
|
@ -98,6 +98,11 @@ function Ext1Console(props) {
|
||||||
terms[key] = term
|
terms[key] = term
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTerminal(e, item) {
|
||||||
|
e.stopPropagation()
|
||||||
|
window.open(`/ssh?id=${item.id}`)
|
||||||
|
}
|
||||||
|
|
||||||
let {local, ...hosts} = outputs;
|
let {local, ...hosts} = outputs;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -173,6 +178,7 @@ function Ext1Console(props) {
|
||||||
<StepItem title="执行发布" item={item} step={3}/>
|
<StepItem title="执行发布" item={item} step={3}/>
|
||||||
<StepItem title="发布后任务" item={item} step={4}/>
|
<StepItem title="发布后任务" item={item} step={4}/>
|
||||||
</Steps>
|
</Steps>
|
||||||
|
<CodeOutlined className={styles.codeIcon} onClick={e => openTerminal(e, item)}/>
|
||||||
</div>}>
|
</div>}>
|
||||||
<OutView setTerm={term => handleSetTerm(term, key)}/>
|
<OutView setTerm={term => handleSetTerm(term, key)}/>
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
import React, { useEffect, useState } from 'react';
|
import React, { useEffect, useState } from 'react';
|
||||||
import { observer, useLocalStore } from 'mobx-react';
|
import { observer, useLocalStore } from 'mobx-react';
|
||||||
import { Card, Progress, Modal, Collapse, Steps, Skeleton } from 'antd';
|
import { Card, Progress, Modal, Collapse, Steps, Skeleton } from 'antd';
|
||||||
import { ShrinkOutlined, CaretRightOutlined, LoadingOutlined, CloseOutlined } from '@ant-design/icons';
|
import { ShrinkOutlined, CaretRightOutlined, LoadingOutlined, CloseOutlined, CodeOutlined } from '@ant-design/icons';
|
||||||
import OutView from './OutView';
|
import OutView from './OutView';
|
||||||
import { http, X_TOKEN } from 'libs';
|
import { http, X_TOKEN } from 'libs';
|
||||||
import styles from './index.module.less';
|
import styles from './index.module.less';
|
||||||
|
@ -106,6 +106,11 @@ function Ext2Console(props) {
|
||||||
terms[key] = term
|
terms[key] = term
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function openTerminal(e, item) {
|
||||||
|
e.stopPropagation()
|
||||||
|
window.open(`/ssh?id=${item.id}`)
|
||||||
|
}
|
||||||
|
|
||||||
const hostOutputs = Object.values(outputs).filter(x => x.id !== 'local');
|
const hostOutputs = Object.values(outputs).filter(x => x.id !== 'local');
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
|
@ -180,6 +185,7 @@ function Ext2Console(props) {
|
||||||
<StepItem key={index} title={action.title} item={item} step={index + 1}/>
|
<StepItem key={index} title={action.title} item={item} step={index + 1}/>
|
||||||
))}
|
))}
|
||||||
</Steps>
|
</Steps>
|
||||||
|
<CodeOutlined className={styles.codeIcon} onClick={e => openTerminal(e, item)}/>
|
||||||
</div>}>
|
</div>}>
|
||||||
<OutView setTerm={term => handleSetTerm(term, item.id)}/>
|
<OutView setTerm={term => handleSetTerm(term, item.id)}/>
|
||||||
</Collapse.Panel>
|
</Collapse.Panel>
|
||||||
|
|
|
@ -86,6 +86,11 @@
|
||||||
margin-right: 16px;
|
margin-right: 16px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.codeIcon {
|
||||||
|
font-size: 22px;
|
||||||
|
color: #1890ff;
|
||||||
|
}
|
||||||
|
|
||||||
.icon {
|
.icon {
|
||||||
font-size: 22px;
|
font-size: 22px;
|
||||||
font-weight: 300;
|
font-weight: 300;
|
||||||
|
|
|
@ -20,6 +20,7 @@ function WebSSH(props) {
|
||||||
const [visible, setVisible] = useState(false);
|
const [visible, setVisible] = useState(false);
|
||||||
const [fetching, setFetching] = useState(true);
|
const [fetching, setFetching] = useState(true);
|
||||||
const [rawTreeData, setRawTreeData] = useState([]);
|
const [rawTreeData, setRawTreeData] = useState([]);
|
||||||
|
const [rawHostList, setRawHostList] = useState([]);
|
||||||
const [treeData, setTreeData] = useState([]);
|
const [treeData, setTreeData] = useState([]);
|
||||||
const [searchValue, setSearchValue] = useState();
|
const [searchValue, setSearchValue] = useState();
|
||||||
const [hosts, setHosts] = useState([]);
|
const [hosts, setHosts] = useState([]);
|
||||||
|
@ -30,40 +31,57 @@ function WebSSH(props) {
|
||||||
window.document.title = 'Spug web terminal'
|
window.document.title = 'Spug web terminal'
|
||||||
window.addEventListener('beforeunload', leaveTips)
|
window.addEventListener('beforeunload', leaveTips)
|
||||||
http.get('/api/host/group/?with_hosts=1')
|
http.get('/api/host/group/?with_hosts=1')
|
||||||
.then(res => setRawTreeData(res.treeData))
|
.then(res => {
|
||||||
.finally(() => setFetching(false))
|
const tmp = {}
|
||||||
return () => window.removeEventListener('beforeunload', leaveTips)
|
setRawTreeData(res.treeData)
|
||||||
}, [])
|
setTreeData(res.treeData)
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (searchValue) {
|
|
||||||
const newTreeData = []
|
|
||||||
const loop = (data) => {
|
const loop = (data) => {
|
||||||
for (let item of data) {
|
for (let item of data) {
|
||||||
if (item.children) {
|
if (item.children) {
|
||||||
loop(item.children)
|
loop(item.children)
|
||||||
} else if (item.isLeaf && includes(item.title, searchValue)) {
|
} else if (item.isLeaf) {
|
||||||
newTreeData.push(item)
|
tmp[item.id] = item
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
loop(rawTreeData)
|
loop(res.treeData)
|
||||||
|
setRawHostList(Object.values(tmp))
|
||||||
|
const query = new URLSearchParams(props.location.search);
|
||||||
|
const id = query.get('id');
|
||||||
|
if (id) {
|
||||||
|
const node = lds.find(Object.values(tmp), {id: Number(id)})
|
||||||
|
if (node) _openNode(node)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.finally(() => setFetching(false))
|
||||||
|
return () => window.removeEventListener('beforeunload', leaveTips)
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (searchValue) {
|
||||||
|
const newTreeData = rawHostList.filter(x => includes(x.title, searchValue))
|
||||||
setTreeData(newTreeData)
|
setTreeData(newTreeData)
|
||||||
} else {
|
} else {
|
||||||
setTreeData(rawTreeData)
|
setTreeData(rawTreeData)
|
||||||
}
|
}
|
||||||
}, [rawTreeData, searchValue])
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [searchValue])
|
||||||
|
|
||||||
function leaveTips(e) {
|
function leaveTips(e) {
|
||||||
e.returnValue = '确定要离开页面?'
|
e.returnValue = '确定要离开页面?'
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _openNode(node) {
|
||||||
|
node.vId = String(new Date().getTime())
|
||||||
|
hosts.push(node);
|
||||||
|
setHosts(lds.cloneDeep(hosts))
|
||||||
|
setActiveId(node.vId)
|
||||||
|
}
|
||||||
|
|
||||||
function handleSelect(e) {
|
function handleSelect(e) {
|
||||||
if (e.nativeEvent.detail > 1 && e.node.isLeaf) {
|
if (e.nativeEvent.detail > 1 && e.node.isLeaf) {
|
||||||
e.node.vId = String(new Date().getTime())
|
_openNode(e.node)
|
||||||
hosts.push(e.node);
|
|
||||||
setHosts(lds.cloneDeep(hosts))
|
|
||||||
setActiveId(e.node.vId)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue