/* * @Description: jupyter tpi * @Author: tangjiang * @Github: * @Date: 2019-12-11 08:35:23 * @LastEditors: tangjiang * @LastEditTime: 2019-12-13 15:25:50 */ import './index.scss'; import React, { useEffect, useState } from 'react'; import SplitPane from 'react-split-pane'; import { Button, Modal,Drawer ,Pagination,Empty,Tooltip,Icon,message,Statistic,Spin} from 'antd'; import { connect } from 'react-redux'; import FloatButton from '../../page/component/FloatButton'; import UserInfo from '../../developer/components/userInfo'; import actions from '../../../redux/actions'; import RightPane from './rightPane'; import MyIcon from "../../../common/components/MyIcon"; function clearSlct() { if("getSelection" in window){ window.getSelection().removeAllRanges(); }else{ document.selection.empty(); }; } function jsCopy(s) { clearSlct(); const copyEle = document.getElementById(s); copyEle.select(); const copyStatus=document.execCommand("Copy"); // 对成功与否定进行提示 copyStatuss(copyStatus) } function copyStatuss(copyStatus){ if (copyStatus) { message.success('复制成功'); } else { message.error('复制失败'); } } function JupyterTPI (props) { // 获取 identifier 值 const { match: { params = {} }, url, loading, // 保存按钮状态 total, pagination, dataSets, // 数据集 jupyter_info, getJupyterInfo, syncJupyterCode, jupyter_tpi_url_state, getJupyterTpiDataSet, getJupyterTpiUrl, saveJupyterTpi, changeLoadingState, changeGetJupyterUrlState, jupyter_identifier, changeCurrentPage, changeshowDrawer, drawervisible, reset_with_tpi, jupytertime, active_with_tpi, spinning, updataspinning, jupyter_folder_name } = props; const emptyCtx = ( <div className="jupyter_empty"> <style> { ` .ant-empty{ margin-top:80px; color:#fff; } ` } </style> <Empty /> </div> ); const { Countdown } = Statistic; const {identifier} = params; const [userInfo, setUserInfo] = useState({}); const [jupyterInfo, setJupyterInfo] = useState({}); const [updateTip, setUpdateTip] = useState(true); const [myIdentifier, setMyIdentifier] = useState(''); const [renderCtx, setRenderCtx] = useState(() => (emptyCtx)); let newHandletype=false const newHandle = function (event) { if(newHandletype===false){ newHandletype=true saveJupyterTpi(event); setTimeout(()=>{newHandletype=false},500) } } // 保存代码 const addEventListeners = () => { window.addEventListener('message', (e) => { // console.log("触发了jupytermessage"); if(e){ if(e.data){ if(e.data==="jupytermessage"){ newHandle() } } } }) } const stopposttpip=(sum)=>{ var _iframe = document.getElementById("rightPaneframe"); if(_iframe == null || _iframe == undefined || _iframe == ""){ return; } if(sum===1){ _iframe.contentWindow.postMessage("stopParent", "*"); }else{ _iframe.contentWindow.postMessage("clonsParent", "*"); } } useEffect(() => { addEventListeners() }, []); useEffect(() => { /* 先调用 jupyter的 TPI 接口, * 获取 用户信息, * 实训的 identifier, 状态, 名称, 是否被修改等信息 */ getJupyterInfo(identifier); }, [identifier]); useEffect(() => { // 设置jupyter信息 setJupyterInfo(jupyter_info || {}); const {user, tpm_modified, myshixun_identifier} = jupyter_info; if (user) { setUserInfo(user); } if (myshixun_identifier) { setMyIdentifier(myshixun_identifier); } // 同步代码 if (tpm_modified && updateTip && myshixun_identifier) { setUpdateTip(false); updataspinning(true) Modal.confirm({ title: '更新通知', content: (<div className="update_notice"> {stopposttpip(1)} <p className="update_txt">该实训已更新,您选择更新后之前编写的实训代码将会丢失</p> <p className="update_txt">如有需要请先使用【jupyter中-文件-下载】保存代码,再进行更新</p> {/*<p className="update_txt">还未完成评测的任务代码,请自行保存</p>*/} </div>), okText: '立即更新', cancelText: '稍后再说', onOk () { syncJupyterCode(myshixun_identifier, '同步成功'); },onCancel() { updataspinning(false) stopposttpip(2) }, }) } }, [props]); // 重置实训 const handleClickResetTpi = () => { stopposttpip(1) Modal.confirm({ title: '重置实训', content: ( <p style={{ lineHeight: '24px' }}> 你在本文件中修改的内容将丢失,<br /> 是否确定重新加载初始代码? </p> ), okText: '确定', cancelText: '取消', onOk () { console.log('调用重置代码....', myIdentifier); if (myIdentifier) { syncJupyterCode(myIdentifier, '重置成功'); } }, onCancel() { stopposttpip(2) }, }) } // 重置环境 const handleEnvironmentTpi = () => { stopposttpip(1) updataspinning(true) Modal.confirm({ title: '重置环境', content: ( <p style={{ lineHeight: '24px' }}> 你在本文件中修改的内容将丢失,<br /> 是否确定重置环境? </p> ), okText: '确定', cancelText: '取消', onOk () { console.log('调用重置代码....', myIdentifier); // if (myIdentifier) { // // } reset_with_tpi(myIdentifier, '重置成功'); }, onCancel() { updataspinning(false) stopposttpip(2) }, }) } // 退出实训 const handleClickQuitTpi = () => { // console.log(jupyterInfo); const { identifier } = jupyterInfo; if (!identifier) return; props.history.push(`/shixuns/${identifier}/challenges`); } // 重新获取 jupyter url const handleOnReloadUrl = (id) => { // console.log('jupyter 信息: ', jupyterInfo); // 改变加载状态值 changeGetJupyterUrlState(-1); getJupyterTpiUrl({identifier: myIdentifier}); } // 保存代码 const handleOnSave = () => { // 改变按钮状态 changeLoadingState(true); saveJupyterTpi(); } // 分页信息改变时 const handlePageChange = (current) => { // 改变当前页 changeCurrentPage(current); // 分页查找数据 getJupyterTpiDataSet(jupyter_identifier); } const swtichFirstDrawer = () => { changeshowDrawer(!drawervisible) } const firstDrawerWidth = ()=>{ return 260 }; // 分页处理 const handleChangePage = (page) => { handlePageChange(page); } // const listCtx = ; useEffect(() => { if (dataSets.length > 0) { console.log('数据集的个数: ', dataSets.length); const oList = dataSets.map((item, i) => { return ( <li className="jupyter_item" key={`key_${i}`}> <Tooltip placement="right" // title={item.file_path} mouseLeaveDelay={0.3} > <div className="sortinxdirection"> <Icon type="file-text" className="jupyter_icon fl lineheighttaj filestyles" /> <a className="jupyter_name ml10 maxnamewidth181 lineheighttaj colorlineheighttaj" title={item.title}>{item.title}</a> <a className={"fr color-blue lineheighttaj"} onClick={() => { jsCopy("file_path"+i) }}>复制地址</a> </div> <input id={"file_path"+i} className={"file_path_input"} value={item.file_path}/> </Tooltip> </li> ); }); const oUl = ( <ul className="jupyter_data_list" > { oList } </ul> ); setRenderCtx(oUl); } }, [props]); const onFinish= () =>{ Modal.confirm({ title: '倒计时截止', content: ( <p style={{ lineHeight: '24px' }}> Jupyter将中断服务,是否需要延长使用时间? </p> ), okText: '确定', cancelText: '取消', onOk () { active_with_tpi(myIdentifier, '重置成功'); } }) } return ( <Spin tip="加载中..." spinning={spinning}> <div className="jupyter_area"> <div className="jupyter_header"> <UserInfo userInfo={userInfo} /> <p className="jupyter_title"> <span className="title_desc" style={{ marginTop: '10px' }}>{jupyterInfo.name}</span> <span className="title_time jupytertitle_time"> <Countdown value={jupytertime} format="HH:mm:ss" onFinish={onFinish}/> </span> </p> <p className="jupyter_btn"> {/*sync | poweroff */} <Button className="btn_common" type="link" icon="history" onClick={handleClickResetTpi} >重置实训</Button> <Button className="btn_common" type="link" icon="sync" onClick={handleEnvironmentTpi} >重置环境</Button> <Button className="btn_common" type="link" icon="poweroff" onClick={handleClickQuitTpi} >退出实训</Button> </p> </div> <div className="jupyter_ctx"> <SplitPane split="vertical" minSize={350} maxSize={-350} defaultSize="100%"> {/*<div className={'split-pane-left'}>*/} {/* <LeftPane*/} {/* dataSets={dataSets}*/} {/* total={total}*/} {/* pagination={pagination}*/} {/* onPageChange={handlePageChange}*/} {/* />*/} {/*</div>*/} <SplitPane split="vertical" defaultSize="100%" allowResize={false}> <RightPane identifier={myIdentifier} status={jupyter_tpi_url_state} url={url} loading={loading} onReloadUrl={handleOnReloadUrl} onSave={handleOnSave} /> <FloatButton onClick={swtichFirstDrawer} className={drawervisible===false?"jupyter_float_button":"jupyter_float_button newjupyter_float_button"}>{"数据集"}</FloatButton> </SplitPane> </SplitPane> <Drawer placement={"right"} closable={false} mask={false} // onClose={this.onClose} visible={drawervisible} className={"RightPaneDrawer"} > {/*<p className={"RightPaneDrawertop"}></p>*/} <div className="jupyter_data_sets_area newjupyter_data_sets_area"> <h2 className="jupyter_h2_title bortop17212F"> {/*<MyIcon type="iconwenti" className="jupyter_data_icon"/>*/} <i className={"iconfont icon-base"}></i>数据集 {/* <span className="iconfont icon-java jupyter_data_icon"></span>数据集 */} </h2> <h2 className="borbottom17212F jupyterfilepaths"> <span className={"ml50"}>文件路径</span> <div className="sortinxdirection"> <a className="jupyter_name ml50 maxnamewidth186JUPYTER lineheighttaj colorlineheighttaj">{jupyter_folder_name}</a> <a className={"fr color-blue lineheighttaj font-14"} onClick={() => { jsCopy("jupyter_folder_name") }}>复制地址</a> </div> <input id="jupyter_folder_name" className={"file_path_input"} value={jupyter_folder_name}/> </h2> { renderCtx } <div className='jupyter_pagination'> {total<20?"":<Pagination simple current={pagination.page} pageSize={pagination.limit} total={total} onChange={handleChangePage} />} </div> </div> </Drawer> </div> </div> </Spin> ); } const mapStateToProps = (state) => { const { jupyter_info, jupyter_tpi_url, jupyter_data_set, jupyter_tpi_url_state, jupyter_data_set_count, jupyter_folder_name, jupyter_pagination, jupyter_identifier } = state.jupyterReducer; const { loading ,drawervisible,jupytertime,spinning} = state.commonReducer; return { loading, jupyter_info, url: jupyter_tpi_url, dataSets: jupyter_data_set, jupyter_tpi_url_state, total: jupyter_data_set_count, pagination: jupyter_pagination, jupyter_folder_name:jupyter_folder_name, jupyter_identifier, drawervisible, jupytertime, spinning }; } const mapDispatchToProps = (dispatch) => ({ changeGetJupyterUrlState: (status) => dispatch(actions.changeGetJupyterUrlState(status)), getJupyterInfo: (identifier) => dispatch(actions.getJupyterInfo(identifier)), // 重置代码 syncJupyterCode: (identifier, msg) => dispatch(actions.syncJupyterCode(identifier, msg)), // 重置代码 reset_with_tpi: (identifier, msg) => dispatch(actions.reset_with_tpi(identifier, msg)), getJupyterTpiDataSet: (identifier, current) => dispatch(actions.getJupyterTpiDataSet(identifier, current)), getJupyterTpiUrl: (identifier) => dispatch(actions.getJupyterTpiUrl(identifier)), saveJupyterTpi: () => dispatch(actions.saveJupyterTpi()), changeLoadingState: (flag) => dispatch(actions.changeLoadingState(flag)), changeCurrentPage: (current) => dispatch(actions.changeCurrentPage(current)), //展开Drawer changeshowDrawer: (type) => dispatch(actions.changeshowDrawer(type)), //倒计时增加 addjypertime: (type) => dispatch(actions.addjypertime(type)), //延时 active_with_tpi:(identifier, msg) => dispatch(actions.active_with_tpi(identifier, msg)), updataspinning:(identifier, msg) => dispatch(actions.updataspinning(identifier, msg)), }); export default connect( mapStateToProps, mapDispatchToProps )(JupyterTPI);