fix issue

pull/410/head
vapao 2021-09-05 00:37:08 +08:00
parent 4e900006be
commit 80c6e3d498
10 changed files with 221 additions and 218 deletions

View File

@ -47,7 +47,7 @@ class DeployRequest(models.Model, ModelMixin):
@property @property
def is_quick_deploy(self): def is_quick_deploy(self):
if self.deploy.extend == '1' and self.extra: if self.type == '1' and self.deploy.extend == '1' and self.extra:
extra = json.loads(self.extra) extra = json.loads(self.extra)
return extra[0] in ('branch', 'tag') return extra[0] in ('branch', 'tag')
return False return False

View File

@ -7,6 +7,7 @@ from .views import *
urlpatterns = [ urlpatterns = [
path('request/', RequestView.as_view()), path('request/', RequestView.as_view()),
path('request/info/', get_request_info),
path('request/ext1/', post_request_ext1), path('request/ext1/', post_request_ext1),
path('request/ext1/rollback/', post_request_ext1_rollback), path('request/ext1/rollback/', post_request_ext1_rollback),
path('request/ext2/', post_request_ext2), path('request/ext2/', post_request_ext2),

View File

@ -173,25 +173,28 @@ def _deploy_ext1_host(req, helper, h_id, env):
f'mkdir -p {extend.dst_repo} && [ -e {extend.dst_dir} ] && [ ! -L {extend.dst_dir} ]') f'mkdir -p {extend.dst_repo} && [ -e {extend.dst_dir} ] && [ ! -L {extend.dst_dir} ]')
if code == 0: if code == 0:
helper.send_error(host.id, f'检测到该主机的发布目录 {extend.dst_dir!r} 已存在为了数据安全请自行备份后删除该目录Spug 将会创建并接管该目录。') helper.send_error(host.id, f'检测到该主机的发布目录 {extend.dst_dir!r} 已存在为了数据安全请自行备份后删除该目录Spug 将会创建并接管该目录。')
# clean if req.type == '1':
clean_command = f'ls -d {extend.deploy_id}_* 2> /dev/null | sort -t _ -rnk2 | tail -n +{extend.versions + 1} | xargs rm -rf' # clean
helper.remote_raw(host.id, ssh, f'cd {extend.dst_repo} && {clean_command}') clean_command = f'ls -d {extend.deploy_id}_* 2> /dev/null | sort -t _ -rnk2 | tail -n +{extend.versions + 1} | xargs rm -rf'
# transfer files helper.remote_raw(host.id, ssh, f'cd {extend.dst_repo} && {clean_command}')
tar_gz_file = f'{req.spug_version}.tar.gz' # transfer files
try: tar_gz_file = f'{req.spug_version}.tar.gz'
ssh.put_file(os.path.join(REPOS_DIR, 'build', tar_gz_file), os.path.join(extend.dst_repo, tar_gz_file)) try:
except Exception as e: ssh.put_file(os.path.join(REPOS_DIR, 'build', tar_gz_file), os.path.join(extend.dst_repo, tar_gz_file))
helper.send_error(host.id, f'Exception: {e}') except Exception as e:
helper.send_error(host.id, f'Exception: {e}')
command = f'cd {extend.dst_repo} && rm -rf {req.spug_version} && tar xf {tar_gz_file} && rm -f {req.deploy_id}_*.tar.gz' command = f'cd {extend.dst_repo} && rm -rf {req.spug_version} && tar xf {tar_gz_file} && rm -f {req.deploy_id}_*.tar.gz'
helper.remote_raw(host.id, ssh, command) helper.remote_raw(host.id, ssh, command)
helper.send_step(h_id, 1, '\033[32m完成√\033[0m\r\n') helper.send_step(h_id, 1, '\033[32m完成√\033[0m\r\n')
else:
helper.send_step(h_id, 1, '\033[33m跳过√\033[0m\r\n')
# pre host # pre host
repo_dir = os.path.join(extend.dst_repo, req.spug_version) repo_dir = os.path.join(extend.dst_repo, req.spug_version)
if extend.hook_pre_host: if extend.hook_pre_host:
helper.send_step(h_id, 2, f'{human_time()} 发布前任务... \r\n') helper.send_step(h_id, 2, f'{human_time()} 发布前任务... \r\n')
command = f'cd {repo_dir} ; {extend.hook_pre_host}' command = f'cd {repo_dir} && {extend.hook_pre_host}'
helper.remote(host.id, ssh, command) helper.remote(host.id, ssh, command)
# do deploy # do deploy
@ -202,7 +205,7 @@ def _deploy_ext1_host(req, helper, h_id, env):
# post host # post host
if extend.hook_post_host: if extend.hook_post_host:
helper.send_step(h_id, 4, f'{human_time()} 发布后任务... \r\n') helper.send_step(h_id, 4, f'{human_time()} 发布后任务... \r\n')
command = f'cd {extend.dst_dir} ; {extend.hook_post_host}' command = f'cd {extend.dst_dir} && {extend.hook_post_host}'
helper.remote(host.id, ssh, command) helper.remote(host.id, ssh, command)
helper.send_step(h_id, 100, f'\r\n{human_time()} ** \033[32m发布成功\033[0m **') helper.send_step(h_id, 100, f'\r\n{human_time()} ** \033[32m发布成功\033[0m **')
@ -237,7 +240,7 @@ def _deploy_ext2_host(helper, h_id, actions, env, spug_version):
command += f'&& rm -rf {action["dst"]} && mv /tmp/{spug_version}/{sd_dst} {action["dst"]} ' command += f'&& rm -rf {action["dst"]} && mv /tmp/{spug_version}/{sd_dst} {action["dst"]} '
command += f'&& rm -rf /tmp/{spug_version}* && echo "transfer completed"' command += f'&& rm -rf /tmp/{spug_version}* && echo "transfer completed"'
else: else:
command = f'cd /tmp ; {action["data"]}' command = f'cd /tmp && {action["data"]}'
helper.remote(host.id, ssh, command) helper.remote(host.id, ssh, command)
helper.send_step(h_id, 100, f'\r\n{human_time()} ** \033[32m发布成功\033[0m **') helper.send_step(h_id, 100, f'\r\n{human_time()} ** \033[32m发布成功\033[0m **')

View File

@ -334,6 +334,18 @@ def post_request_ext2(request):
return json_response(error=error) return json_response(error=error)
def get_request_info(request):
form, error = JsonParser(
Argument('id', type=int, help='参数错误')
).parse(request.GET)
if error is None:
req = DeployRequest.objects.get(pk=form.id)
response = req.to_dict(selects=('status', 'reason'))
response['status_alias'] = req.get_status_display()
return json_response(response)
return json_response(error=error)
def do_upload(request): def do_upload(request):
repos_dir = settings.REPOS_DIR repos_dir = settings.REPOS_DIR
file = request.FILES['file'] file = request.FILES['file']

View File

@ -15,6 +15,8 @@ import store from './store';
function Ext1Console(props) { function Ext1Console(props) {
const outputs = useLocalStore(() => ({})); const outputs = useLocalStore(() => ({}));
const terms = useLocalStore(() => ({})); const terms = useLocalStore(() => ({}));
const [mini, setMini] = useState(false);
const [visible, setVisible] = useState(true);
const [fetching, setFetching] = useState(true); const [fetching, setFetching] = useState(true);
useEffect(props.request.mode === 'read' ? readDeploy : doDeploy, []) useEffect(props.request.mode === 'read' ? readDeploy : doDeploy, [])
@ -39,7 +41,7 @@ function Ext1Console(props) {
Object.assign(outputs, res.outputs) Object.assign(outputs, res.outputs)
setTimeout(() => setFetching(false), 100) setTimeout(() => setFetching(false), 100)
socket = _makeSocket() socket = _makeSocket()
store.fetchRecords() store.fetchInfo(props.request.id)
}) })
return () => socket && socket.close() return () => socket && socket.close()
} }
@ -85,8 +87,8 @@ function Ext1Console(props) {
} }
function switchMiniMode() { function switchMiniMode() {
const value = store.tabModes[props.request.id]; setMini(true)
store.tabModes[props.request.id] = !value setVisible(false)
} }
function handleSetTerm(term, key) { function handleSetTerm(term, key) {
@ -97,86 +99,90 @@ function Ext1Console(props) {
} }
let {local, ...hosts} = outputs; let {local, ...hosts} = outputs;
return store.tabModes[props.request.id] ? ( return (
<Card <div>
className={styles.item} {mini && (
bodyStyle={{padding: '8px 12px'}} <Card
onClick={switchMiniMode}> className={styles.item}
<div className={styles.header}> bodyStyle={{padding: '8px 12px'}}
<div className={styles.title}>{props.request.name}</div> onClick={() => setVisible(true)}>
<CloseOutlined onClick={() => store.showConsole(props.request, true)}/> <div className={styles.header}>
</div> <div className={styles.title}>{props.request.name}</div>
{local && ( <CloseOutlined onClick={() => store.showConsole(props.request, true)}/>
<Progress </div>
percent={(local.step + 1) * 18} {local && (
status={local.step === 100 ? 'success' : outputs.local.status === 'error' ? 'exception' : 'active'}/> <Progress
)} percent={(local.step + 1) * 18}
{Object.values(hosts).map(item => ( status={local.step === 100 ? 'success' : outputs.local.status === 'error' ? 'exception' : 'active'}/>
<Progress )}
key={item.id} {Object.values(hosts).map(item => (
percent={(item.step + 1) * 18} <Progress
status={item.step === 100 ? 'success' : item.status === 'error' ? 'exception' : 'active'}/> key={item.id}
))} percent={(item.step + 1) * 18}
</Card> status={item.step === 100 ? 'success' : item.status === 'error' ? 'exception' : 'active'}/>
) : (
<Modal
visible
width={1000}
footer={null}
maskClosable={false}
className={styles.console}
onCancel={() => store.showConsole(props.request, true)}
title={[
<span key="1">{props.request.name}</span>,
<div key="2" className={styles.miniIcon} onClick={switchMiniMode}>
<ShrinkOutlined/>
</div>
]}>
<Skeleton loading={fetching} active>
{local && (
<Collapse defaultActiveKey={['0']} className={styles.collapse} style={{marginBottom: 24}}>
<Collapse.Panel header={(
<div className={styles.header}>
<b className={styles.title}/>
<Steps size="small" className={styles.step} current={local.step} status={local.status}>
<StepItem title="构建准备" item={local} step={0}/>
<StepItem title="检出前任务" item={local} step={1}/>
<StepItem title="执行检出" item={local} step={2}/>
<StepItem title="检出后任务" item={local} step={3}/>
<StepItem title="执行打包" item={local} step={4}/>
</Steps>
</div>
)}>
<OutView setTerm={term => handleSetTerm(term, 'local')}/>
</Collapse.Panel>
</Collapse>
)}
<Collapse
defaultActiveKey="0"
className={styles.collapse}
expandIcon={({isActive}) => <CaretRightOutlined style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{Object.entries(hosts).map(([key, item], index) => (
<Collapse.Panel
key={index}
header={
<div className={styles.header}>
<b className={styles.title}>{item.title}</b>
<Steps size="small" className={styles.step} current={item.step} status={item.status}>
<StepItem title="等待调度" item={item} step={0}/>
<StepItem title="数据准备" item={item} step={1}/>
<StepItem title="发布前任务" item={item} step={2}/>
<StepItem title="执行发布" item={item} step={3}/>
<StepItem title="发布后任务" item={item} step={4}/>
</Steps>
</div>}>
<OutView setTerm={term => handleSetTerm(term, key)}/>
</Collapse.Panel>
))} ))}
</Collapse> </Card>
</Skeleton> )}
</Modal> <Modal
visible={visible}
width={1000}
footer={null}
maskClosable={false}
className={styles.console}
onCancel={() => store.showConsole(props.request, true)}
title={[
<span key="1">{props.request.name}</span>,
<div key="2" className={styles.miniIcon} onClick={switchMiniMode}>
<ShrinkOutlined/>
</div>
]}>
<Skeleton loading={fetching} active>
{local && (
<Collapse defaultActiveKey={['0']} className={styles.collapse} style={{marginBottom: 24}}>
<Collapse.Panel header={(
<div className={styles.header}>
<b className={styles.title}/>
<Steps size="small" className={styles.step} current={local.step} status={local.status}>
<StepItem title="构建准备" item={local} step={0}/>
<StepItem title="检出前任务" item={local} step={1}/>
<StepItem title="执行检出" item={local} step={2}/>
<StepItem title="检出后任务" item={local} step={3}/>
<StepItem title="执行打包" item={local} step={4}/>
</Steps>
</div>
)}>
<OutView setTerm={term => handleSetTerm(term, 'local')}/>
</Collapse.Panel>
</Collapse>
)}
<Collapse
defaultActiveKey="0"
className={styles.collapse}
expandIcon={({isActive}) => <CaretRightOutlined style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{Object.entries(hosts).map(([key, item], index) => (
<Collapse.Panel
key={index}
header={
<div className={styles.header}>
<b className={styles.title}>{item.title}</b>
<Steps size="small" className={styles.step} current={item.step} status={item.status}>
<StepItem title="等待调度" item={item} step={0}/>
<StepItem title="数据准备" item={item} step={1}/>
<StepItem title="发布前任务" item={item} step={2}/>
<StepItem title="执行发布" item={item} step={3}/>
<StepItem title="发布后任务" item={item} step={4}/>
</Steps>
</div>}>
<OutView setTerm={term => handleSetTerm(term, key)}/>
</Collapse.Panel>
))}
</Collapse>
</Skeleton>
</Modal>
</div>
) )
} }
export default observer(Ext1Console) export default observer(Ext1Console)

View File

@ -17,6 +17,8 @@ function Ext2Console(props) {
const outputs = useLocalStore(() => ({local: {id: 'local'}})); const outputs = useLocalStore(() => ({local: {id: 'local'}}));
const [sActions, setSActions] = useState([]); const [sActions, setSActions] = useState([]);
const [hActions, setHActions] = useState([]); const [hActions, setHActions] = useState([]);
const [mini, setMini] = useState(false);
const [visible, setVisible] = useState(true);
const [fetching, setFetching] = useState(true); const [fetching, setFetching] = useState(true);
useEffect(props.request.mode === 'read' ? readDeploy : doDeploy, []) useEffect(props.request.mode === 'read' ? readDeploy : doDeploy, [])
@ -45,6 +47,7 @@ function Ext2Console(props) {
Object.assign(outputs, res.outputs) Object.assign(outputs, res.outputs)
setTimeout(() => setFetching(false), 100) setTimeout(() => setFetching(false), 100)
socket = _makeSocket() socket = _makeSocket()
store.fetchInfo(props.request.id)
}) })
return () => socket && socket.close() return () => socket && socket.close()
} }
@ -92,8 +95,8 @@ function Ext2Console(props) {
} }
function switchMiniMode() { function switchMiniMode() {
const value = store.tabModes[props.request.id]; setMini(true)
store.tabModes[props.request.id] = !value setVisible(false)
} }
function handleSetTerm(term, key) { function handleSetTerm(term, key) {
@ -104,81 +107,84 @@ function Ext2Console(props) {
} }
const hostOutputs = Object.values(outputs).filter(x => x.id !== 'local'); const hostOutputs = Object.values(outputs).filter(x => x.id !== 'local');
return store.tabModes[props.request.id] ? ( return (
<Card <div>
className={styles.item} {mini && (
bodyStyle={{padding: '8px 12px'}} <Card
onClick={switchMiniMode}> className={styles.item}
<div className={styles.header}> bodyStyle={{padding: '8px 12px'}}
<div className={styles.title}>{props.request.name}</div> onClick={() => setVisible(true)}>
<CloseOutlined onClick={() => store.showConsole(props.request, true)}/> <div className={styles.header}>
</div> <div className={styles.title}>{props.request.name}</div>
<Progress percent={(outputs.local.step + 1) * (90 / (1 + sActions.length)).toFixed(0)} <CloseOutlined onClick={() => store.showConsole(props.request, true)}/>
status={outputs.local.step === 100 ? 'success' : outputs.local.status === 'error' ? 'exception' : 'active'}/> </div>
{Object.values(outputs).filter(x => x.id !== 'local').map(item => ( <Progress percent={(outputs.local.step + 1) * (90 / (1 + sActions.length)).toFixed(0)}
<Progress status={outputs.local.step === 100 ? 'success' : outputs.local.status === 'error' ? 'exception' : 'active'}/>
key={item.id} {Object.values(outputs).filter(x => x.id !== 'local').map(item => (
percent={item.step * (90 / (hActions.length).toFixed(0))} <Progress
status={item.step === 100 ? 'success' : item.status === 'error' ? 'exception' : 'active'}/> key={item.id}
))} percent={item.step * (90 / (hActions.length).toFixed(0))}
</Card> status={item.step === 100 ? 'success' : item.status === 'error' ? 'exception' : 'active'}/>
) : ( ))}
<Modal </Card>
visible )}
width={1000} <Modal
footer={null} visible={visible}
maskClosable={false} width={1000}
className={styles.console} footer={null}
onCancel={() => store.showConsole(props.request, true)} maskClosable={false}
title={[ className={styles.console}
<span key="1">{props.request.name}</span>, onCancel={() => store.showConsole(props.request, true)}
<div key="2" className={styles.miniIcon} onClick={switchMiniMode}> title={[
<ShrinkOutlined/> <span key="1">{props.request.name}</span>,
</div> <div key="2" className={styles.miniIcon} onClick={switchMiniMode}>
]}> <ShrinkOutlined/>
<Skeleton loading={fetching} active> </div>
<Collapse defaultActiveKey={['0']} className={styles.collapse}> ]}>
<Collapse.Panel header={( <Skeleton loading={fetching} active>
<div className={styles.header}> <Collapse defaultActiveKey={['0']} className={styles.collapse}>
<b className={styles.title}/> <Collapse.Panel header={(
<Steps size="small" className={styles.step} current={outputs.local.step} status={outputs.local.status}> <div className={styles.header}>
<StepItem title="建立连接" item={outputs.local} step={0}/> <b className={styles.title}/>
{sActions.map((item, index) => ( <Steps size="small" className={styles.step} current={outputs.local.step} status={outputs.local.status}>
<StepItem key={index} title={item.title} item={outputs.local} step={index + 1}/> <StepItem title="建立连接" item={outputs.local} step={0}/>
))} {sActions.map((item, index) => (
</Steps> <StepItem key={index} title={item.title} item={outputs.local} step={index + 1}/>
</div> ))}
)}> </Steps>
<OutView setTerm={term => handleSetTerm(term, 'local')}/> </div>
</Collapse.Panel> )}>
</Collapse> <OutView setTerm={term => handleSetTerm(term, 'local')}/>
{hostOutputs.length > 0 && ( </Collapse.Panel>
<Collapse
accordion
defaultActiveKey="0"
className={styles.collapse}
style={{marginTop: 24}}
expandIcon={({isActive}) => <CaretRightOutlined style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{hostOutputs.map((item, index) => (
<Collapse.Panel
key={index}
header={
<div className={styles.header}>
<b className={styles.title}>{item.title}</b>
<Steps size="small" className={styles.step} current={item.step} status={item.status}>
<StepItem title="等待调度" item={item} step={0}/>
{hActions.map((action, index) => (
<StepItem key={index} title={action.title} item={item} step={index + 1}/>
))}
</Steps>
</div>}>
<OutView setTerm={term => handleSetTerm(term, item.id)}/>
</Collapse.Panel>
))}
</Collapse> </Collapse>
)} {hostOutputs.length > 0 && (
</Skeleton> <Collapse
</Modal> accordion
defaultActiveKey="0"
className={styles.collapse}
style={{marginTop: 24}}
expandIcon={({isActive}) => <CaretRightOutlined style={{fontSize: 16}} rotate={isActive ? 90 : 0}/>}>
{hostOutputs.map((item, index) => (
<Collapse.Panel
key={index}
header={
<div className={styles.header}>
<b className={styles.title}>{item.title}</b>
<Steps size="small" className={styles.step} current={item.step} status={item.status}>
<StepItem title="等待调度" item={item} step={0}/>
{hActions.map((action, index) => (
<StepItem key={index} title={action.title} item={item} step={index + 1}/>
))}
</Steps>
</div>}>
<OutView setTerm={term => handleSetTerm(term, item.id)}/>
</Collapse.Panel>
))}
</Collapse>
)}
</Skeleton>
</Modal>
</div>
) )
} }

View File

@ -9,7 +9,6 @@ import { BranchesOutlined, BuildOutlined, TagOutlined, PlusOutlined, TagsOutline
import { Radio, Modal, Popover, Tag, Popconfirm, Tooltip, message } from 'antd'; import { Radio, Modal, Popover, Tag, Popconfirm, Tooltip, message } from 'antd';
import { http, hasPermission } from 'libs'; import { http, hasPermission } from 'libs';
import { Action, AuthButton, TableCard } from 'components'; import { Action, AuthButton, TableCard } from 'components';
import styles from './index.module.less';
import store from './store'; import store from './store';
function ComTable() { function ComTable() {
@ -146,18 +145,7 @@ function ComTable() {
} }
function handleDeploy(e, info) { function handleDeploy(e, info) {
const right = document.body.clientWidth - 25 - e.target.getBoundingClientRect().x; store.showConsole(info);
const bottom = document.body.clientHeight - 40 - e.target.getBoundingClientRect().y;
store.box.setAttribute('style', `display: block; bottom: ${bottom}px; right: ${right}px;`);
setTimeout(() => {
store.box.setAttribute('class', `${styles.floatBox} ${styles.floatBoxAnimate}`)
}, 10);
setTimeout(() => {
store.showConsole(info);
store.box.setAttribute('style', 'display: none');
store.box.setAttribute('class', styles.floatBox)
}, 300)
} }
return ( return (

View File

@ -90,16 +90,14 @@ function Index() {
{store.rollbackVisible && <Rollback/>} {store.rollbackVisible && <Rollback/>}
{store.tabs.length > 0 && ( {store.tabs.length > 0 && (
<Space className={styles.miniConsole}> <Space className={styles.miniConsole}>
{store.tabs.map(item => ( {store.tabs.map(item => item.id ?
item.app_extend === '1' ? ( item.app_extend === '1' ? (
<Ext1Console key={item.id} request={item}/> <Ext1Console key={item.id} request={item}/>
) : ( ) : (
<Ext2Console key={item.id} request={item}/> <Ext2Console key={item.id} request={item}/>
) ) : null)}
))}
</Space> </Space>
)} )}
<div ref={el => store.box = el} id='floatBox' className={styles.floatBox}/>
</AuthDiv> </AuthDiv>
) )
} }

View File

@ -101,20 +101,3 @@
.upload :global(.ant-upload-list-item) { .upload :global(.ant-upload-list-item) {
margin: 0; margin: 0;
} }
.floatBox {
display: none;
position: fixed;
width: 20px;
height: 10px;
transition: right 0.3s, width 0.3s, height0 .3s, bottom 0.3s ease-in-out;
background: rgba(0, 0, 0, 0.1);
border-radius: 5px;
}
.floatBoxAnimate {
width: 180px;
height: 64px;
bottom: 12px !important;
right: 24px !important;
}

View File

@ -12,9 +12,7 @@ class Store {
@observable records = []; @observable records = [];
@observable record = {}; @observable record = {};
@observable counter = {}; @observable counter = {};
@observable box = null;
@observable tabs = []; @observable tabs = [];
@observable tabModes = {};
@observable isFetching = false; @observable isFetching = false;
@observable addVisible = false; @observable addVisible = false;
@observable ext1Visible = false; @observable ext1Visible = false;
@ -55,6 +53,19 @@ class Store {
.finally(() => this.isFetching = false) .finally(() => this.isFetching = false)
}; };
fetchInfo = (id) => {
http.get('/api/deploy/request/info/', {params: {id}})
.then(res => {
for (let item of this.records) {
if (item.id === id) {
Object.assign(item, res)
break
}
}
})
.then(this._updateCounter)
}
_updateCounter = () => { _updateCounter = () => {
const counter = {'all': 0, '-3': 0, '0': 0, '1': 0, '3': 0, '99': 0}; const counter = {'all': 0, '-3': 0, '0': 0, '1': 0, '3': 0, '99': 0};
for (let item of this.records) { for (let item of this.records) {
@ -122,18 +133,15 @@ class Store {
const index = lds.findIndex(this.tabs, x => x.id === info.id); const index = lds.findIndex(this.tabs, x => x.id === info.id);
if (isClose) { if (isClose) {
if (index !== -1) { if (index !== -1) {
this.tabs.splice(index, 1) this.tabs[index] = {}
delete this.tabModes[info.id]
} }
this.fetchRecords() this.fetchInfo(info.id)
} else if (index === -1) { } else if (index === -1) {
this.tabModes[info.id] = true
this.tabs.push(info) this.tabs.push(info)
} }
}; };
readConsole = (info) => { readConsole = (info) => {
this.tabModes[info.id] = false
const index = lds.findIndex(this.tabs, x => x.id === info.id); const index = lds.findIndex(this.tabs, x => x.id === info.id);
if (index === -1) { if (index === -1) {
info = Object.assign({}, info, {mode: 'read'}) info = Object.assign({}, info, {mode: 'read'})
@ -142,9 +150,7 @@ class Store {
}; };
leaveConsole = () => { leaveConsole = () => {
for (let item of this.tabs) { this.tabs = []
item.mode = 'read'
}
} }
} }