Merge remote-tracking branch 'origin/dev_jupyter' into dev_jupyter

chromesetting
杨树明 5 years ago
commit 09ada81439

@ -327,7 +327,7 @@ module.exports = {
}, },
compress: { compress: {
drop_debugger: true, drop_debugger: true,
drop_console: false drop_console: true
} }
} }
}), }),

@ -617,7 +617,11 @@ class App extends Component {
{/* jupyter */} {/* jupyter */}
<Route path="/tasks/:identifier/jupyter/" <Route path="/tasks/:identifier/jupyter/"
component={JupyterTPI} render={
(props) => {
return (<JupyterTPI {...this.props} {...props} {...this.state}/>)
}
}
/> />
<Route path="/tasks/:stageId" component={IndexWrapperComponent}/> <Route path="/tasks/:stageId" component={IndexWrapperComponent}/>

@ -4,12 +4,12 @@
* @Github: * @Github:
* @Date: 2019-12-10 09:03:48 * @Date: 2019-12-10 09:03:48
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-12-10 09:05:41 * @LastEditTime: 2019-12-12 10:53:47
*/ */
import { Icon } from 'antd'; import { Icon } from 'antd';
const MyIcon = Icon.createFromIconfontCN({ const MyIcon = Icon.createFromIconfontCN({
scriptUrl: '//at.alicdn.com/t/font_1535266_ss6796i6f6j.js' scriptUrl: '//at.alicdn.com/t/font_1535266_i4ilpm93kp.js'
}); });
export default MyIcon; export default MyIcon;

@ -314,12 +314,14 @@ class TPMDataset extends Component {
} }
deleteRemovedata(){ deleteRemovedata(){
if(this.state.selectedRowKeysdata===undefined || this.state.selectedRowKeysdata===null ||this.state.selectedRowKeysdata.length===0){ if(this.state.selectedRowKeysdata===undefined || this.state.selectedRowKeysdata===null ||this.state.selectedRowKeysdata.length===0){
this.props.showNotification(`请选择要删除的文件`); this.props.showNotification(`请选择要删除的文件`);
return return
} }
confirm({ confirm({
title: '确定要删除文件吗?', title: '确定要删除文件吗?',
okText: '确定', okText: '确定',

@ -4,46 +4,164 @@
* @Github: * @Github:
* @Date: 2019-12-11 08:35:23 * @Date: 2019-12-11 08:35:23
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-12-12 09:26:17 * @LastEditTime: 2019-12-12 18:00:03
*/ */
import './index.scss'; import './index.scss';
import React, { useEffect } from 'react'; import React, { useEffect, useState } from 'react';
import SplitPane from 'react-split-pane'; import SplitPane from 'react-split-pane';
import { Button } from 'antd'; import { Button, Modal } from 'antd';
import { import {
connect connect
} from 'react-redux'; } from 'react-redux';
import UserInfo from '../../developer/components/userInfo'; import UserInfo from '../../developer/components/userInfo';
import actions from '../../../redux/actions'; import actions from '../../../redux/actions';
import LeftPane from './leftPane';
import RightPane from './rightPane';
function JupyterTPI (props) { function JupyterTPI (props) {
// 获取 identifier 值
const {
match: {
params = {}
},
url,
loading, // 保存按钮状态
jupyter_info,
getJupyterInfo,
syncJupyterCode,
jupyter_tpi_url_state,
// getJupyterTpiDataSet,
getJupyterTpiUrl,
saveJupyterTpi,
changeLoadingState,
changeGetJupyterUrlState
} = props;
const {identifier} = params;
const [userInfo, setUserInfo] = useState({});
const [jupyterInfo, setJupyterInfo] = useState({});
const [updateTip, setUpdateTip] = useState(true);
const [myIdentifier, setMyIdentifier] = useState('');
useEffect(() => { 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);
Modal.confirm({
title: '更新通知',
content: (<div className="update_notice">
<p className="update_txt">关卡任务的代码文件有更新啦</p>
<p className="update_txt">更新操作将保留已完成的评测记录和成绩</p>
<p className="update_txt">还未完成评测的任务代码请自行保存</p>
</div>),
okText: '确定',
cancelText: '取消',
onOk () {
syncJupyterCode(myshixun_identifier, '同步成功');
}
})
}
}, [props]);
// 重置实训
const handleClickResetTpi = () => {
Modal.confirm({
title: '重置实训',
content: (
<p style={{ lineHeight: '24px' }}>
你在本文件中修改的内容将丢失,<br />
是否确定重新加载初始代码
</p>
),
okText: '确定',
cancelText: '取消',
onOk () {
console.log('调用重置代码....', myIdentifier);
if (myIdentifier) {
syncJupyterCode(myIdentifier, '重置成功');
}
}
})
}
// 退出实训
const handleClickQuitTpi = () => {
// console.log(jupyterInfo);
const { identifier } = jupyterInfo;
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();
}
// 获取jupyter地址
}, []);
return ( return (
<div className="jupyter_area"> <div className="jupyter_area">
<div className="jupyter_header"> <div className="jupyter_header">
<UserInfo userInfo={{}} /> <UserInfo userInfo={userInfo} />
<p className="jupyter_title"> <p className="jupyter_title">
<span className="title_desc">MySQL数据库编程开发实训(基础篇)</span> <span className="title_desc" style={{ marginTop: '20px' }}>{jupyterInfo.name}</span>
<span className="title_time">时间</span> <span className="title_time"></span>
</p> </p>
<p className="jupyter_btn"> <p className="jupyter_btn">
{/* sync | poweroff */} {/* sync | poweroff */}
<Button className="btn_common" type="link" icon="sync">重置实训</Button> <Button
<Button className="btn_common" type="link" icon="poweroff">退出实训</Button> className="btn_common"
type="link"
icon="sync"
onClick={handleClickResetTpi}
>重置实训</Button>
<Button
className="btn_common"
type="link"
icon="poweroff"
onClick={handleClickQuitTpi}
>退出实训</Button>
</p> </p>
</div> </div>
<div className="jupyter_ctx"> <div className="jupyter_ctx">
<SplitPane split="vertical" minSize={350} maxSize={-350} defaultSize="30%"> <SplitPane split="vertical" minSize={350} maxSize={-350} defaultSize="30%">
<div className={'split-pane-left'}> <div className={'split-pane-left'}>
左侧内容 <LeftPane dataSets={[]} />
</div> </div>
<SplitPane split="vertical" defaultSize="100%" allowResize={false}> <SplitPane split="vertical" defaultSize="100%" allowResize={false}>
<div>右侧内容</div> <RightPane
identifier={myIdentifier}
status={jupyter_tpi_url_state}
url={url}
loading={loading}
onReloadUrl={handleOnReloadUrl}
onSave={handleOnSave}
/>
<div /> <div />
</SplitPane> </SplitPane>
</SplitPane> </SplitPane>
@ -53,17 +171,31 @@ function JupyterTPI (props) {
} }
const mapStateToProps = (state) => { const mapStateToProps = (state) => {
const {jupyter_tpi_url, jupyter_data_set, jupyter_identifier} = state.jupyterReducer; const {
jupyter_info,
jupyter_tpi_url,
jupyter_data_set,
jupyter_tpi_url_state
} = state.jupyterReducer;
const { loading } = state.commonReducer;
return { return {
loading,
jupyter_info,
url: jupyter_tpi_url, url: jupyter_tpi_url,
dataSets: jupyter_data_set, dataSets: jupyter_data_set,
identifier: jupyter_identifier jupyter_tpi_url_state
}; };
} }
const mapDispatchToProps = (dispatch) => ({ const mapDispatchToProps = (dispatch) => ({
getJupyterTpiDataSet: (identifier) => dispatch(actions.getJupyterTpiDataSet(identifier)), changeGetJupyterUrlState: (status) => dispatch(actions.changeGetJupyterUrlState(status)),
getJupyterTpiUrl: (identifier) => dispatch(actions.getJupyterTpiUrl(identifier)) getJupyterInfo: (identifier) => dispatch(actions.getJupyterInfo(identifier)),
// 重置代码
syncJupyterCode: (identifier, msg) => dispatch(actions.syncJupyterCode(identifier, msg)),
// getJupyterTpiDataSet: (identifier) => dispatch(actions.getJupyterTpiDataSet(identifier)),
getJupyterTpiUrl: (identifier) => dispatch(actions.getJupyterTpiUrl(identifier)),
saveJupyterTpi: () => dispatch(actions.saveJupyterTpi()),
changeLoadingState: (flag) => dispatch(actions.changeLoadingState(flag))
}); });
export default connect( export default connect(

@ -55,7 +55,7 @@
height: 60px; height: 60px;
line-height: 60px; line-height: 60px;
background-color: #070F1A; background-color: #070F1A;
padding-left: 30px;
.jupyter_title{ .jupyter_title{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
@ -90,4 +90,12 @@
position: relative; position: relative;
height: calc(100vh - 60px); height: calc(100vh - 60px);
} }
.update_notice{
text-align: center;
.update_txt{
line-height: 18px;
font-size: 14px;
}
}
} }

@ -0,0 +1,55 @@
/*
* @Description:
* @Author: tangjiang
* @Github:
* @Date: 2019-12-12 10:34:03
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-12 11:22:11
*/
import './index.scss';
import React from 'react';
import {Icon, Empty} from 'antd';
import MyIcon from '../../../../common/components/MyIcon';
function LeftPane (props) {
// 获取数据集
const { dataSets = [] } = props;
// 渲染数据集
const renderList = () => {
// 空数据
if (dataSets.length === 0) {
return <div className="jupyter_empty">
<Empty />
</div>
} else {
// 渲染列表
const oList = dataSets.map((item, i) => {
return (
<li className="jupyter_item" key={`key_${i}`}>
<Icon type="file-text" className="jupyter_icon"/>
<span className="jupyter_name">{item.title}</span>
</li>
);
});
return (
<ul className="jupyter_data_list">
{ oList }
</ul>
);
}
}
return (
<div className="jupyter_data_sets_area">
<h2 className="jupyter_h2_title">
<MyIcon type="iconwenti" className="jupyter_data_icon"/> 数据集
</h2>
{renderList()}
</div>
)
}
export default LeftPane;

@ -0,0 +1,50 @@
.jupyter_data_sets_area{
height: 100%;
.jupyter_h2_title{
height: 50px;
line-height: 50px;
background-color: #EEEEEE;
padding: 0 30px;
.jupyter_data_icon{
color: #7286ff;
font-size: 24px;
position: relative;
top: 2px;
transform: scale(1.5);
}
}
.jupyter_data_list,
.jupyter_empty{
height: calc(100vh - 110px);
}
.jupyter_data_list{
.jupyter_item{
line-height:45px;
border-bottom: 1px solid rgba(238,238,238, 1);
padding: 0 30px 0 60px;
overflow: hidden;
text-overflow:ellipsis;
white-space: nowrap;
cursor: pointer;
.jupyter_icon{
color: rgb(74, 188, 125);
font-size: 16px;
transform: scale(1.2);
margin-right: 5px;
}
.jupyter_name{
color: #000;
font-size: 16px;
}
}
}
.jupyter_empty{
display: flex;
align-items: center;
justify-content: center;
width: 100%;
}
}

@ -0,0 +1,90 @@
/*
* @Description:
* @Author: tangjiang
* @Github:
* @Date: 2019-12-12 15:04:20
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-12 17:41:41
*/
import './index.scss';
import React, { useEffect, useState } from 'react';
import { Spin, Button } from 'antd';
function RightPane (props) {
const {
status,
url,
onReloadUrl,
onSave,
loading
} = props;
const [renderCtx, setRenderCtx] = useState(() => loadInit);
// 重新获取 url
const handleClickReload = () => {
onReloadUrl && onReloadUrl();
}
const loadInit = (
<div className="jupyter_loading_init">
<Spin tip="加载中..."></Spin>
</div>
);
const loadError = (
<div className="jupyter_load_url_error">
<p className="jupyter_error_txt">
加载实训出错是否
<span
className="jupyter_reload"
onClick={handleClickReload}
>重新加载</span>
</p>
</div>
);
// 保存
const handleClickSubmit = () => {
console.log('调用了保存接口....');
onSave && onSave();
}
useEffect(() => {
if (status === -1) {
setRenderCtx(() => loadInit);
} else if (status === 0 && url) {
setRenderCtx(() => (
<div className="jupyter_result">
<div className="jupyter_iframe">
<iframe
title=" "
width="100%"
height="100%"
src={url}
className='jupyter_iframe_style'
></iframe>
</div>
<div className="jupyter_submit">
<Button
loading={loading}
type="primary"
onClick={handleClickSubmit}
>保存</Button>
</div>
</div>
));
} else {
setRenderCtx(() => loadError);
}
}, [status, url, loading]);
return (
<div className="jupyter_right_pane_area">
{ renderCtx }
</div>
)
}
export default RightPane;

@ -0,0 +1,62 @@
.jupyter_right_pane_area{
position: relative;
height: calc(100vh - 60px);
// background: pink;
.jupyter_load_url_error,
.jupyter_loading_init{
display: flex;
position: relative;
align-items: center;
justify-content: center;
height: 100%;
&::before{
position: absolute;
left: 0;
right: 0;
top: 0;
bottom: 0;
content: '';
}
}
.jupyter_loading_init{
&::before{
background-color: rgba(0,0,0,.2);
}
}
.jupyter_load_url_error{
// &::before{
// background-color: rgba(0,0,0,.2);
// }
.jupyter_error_txt{
position: relative;
z-index: 1;
.jupyter_reload{
cursor: pointer;
color: #1890ff;
}
}
}
.jupyter_result{
height: 100%;
.jupyter_iframe{
height: calc(100% - 56px);
// background: pink;
.jupyter_iframe_style{
border: none;
outline: none;
}
}
.jupyter_submit{
display: flex;
align-items: center;
height: 56px;
justify-content: flex-end;
padding-right: 30px;
}
}
}

@ -34,6 +34,8 @@ class Challengesjupyter extends Component {
jupyter_port:0, jupyter_port:0,
jupyter_url:null, jupyter_url:null,
username:"", username:"",
booljupyterurls:false,
loading:false,
} }
} }
@ -54,41 +56,35 @@ class Challengesjupyter extends Component {
} }
} }
}).catch((error) => { }).catch((error) => {
console.log(error) //console.log(error)
}); });
} }
componentDidMount() { componentDidMount() {
setTimeout(this.ChallengesList(), 1000); setTimeout(this.ChallengesList(), 1000);
let id = this.props.match.params.shixunId; let id = this.props.match.params.shixunId;
let ChallengesURL = `/jupyters/get_info_with_tpm.json`; let ChallengesURL = `/jupyters/get_info_with_tpm.json`;
let datas={ let datas={
identifier:id, identifier:id,
} }
axios.get(ChallengesURL, {params: datas}).then((response) => { axios.get(ChallengesURL, {params: datas}).then((response) => {
debugger
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) { if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else{ }else{
// console.log("componentDidMountChallengesjupyter");
// console.log(response.data);
if(response.data.status===0){ if(response.data.status===0){
this.setState({ this.setState({
jupyter_url:response.data.url, jupyter_url:response.data.url,
jupyter_port:response.data.port, jupyter_port:response.data.port,
}) })
}else{ }else{
} }
} }
this.setState({
booljupyterurls:true,
})
}).catch((error) => { }).catch((error) => {
console.log(error) this.setState({
booljupyterurls:true,
})
}); });
@ -96,7 +92,36 @@ class Challengesjupyter extends Component {
} }
updatamakedown = (id) => { updatamakedowns = () => {
this.setState({
loading:true,
})
let id = this.props.match.params.shixunId;
let ChallengesURL = `/jupyters/get_info_with_tpm.json`;
let datas={
identifier:id,
}
axios.get(ChallengesURL, {params: datas}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else{
if(response.data.status===0){
this.setState({
jupyter_url:response.data.url,
jupyter_port:response.data.port,
})
}else{
}
}
this.setState({
booljupyterurls:true,
loading:false,
})
}).catch((error) => {
this.setState({
booljupyterurls:true,
loading:false,
})
});
} }
@ -148,8 +173,8 @@ class Challengesjupyter extends Component {
}; };
modifyjupyter=()=>{ modifyjupyter=()=>{
// console.log("propsysl"); // //console.log("propsysl");
// console.log(propsysl); // //console.log(propsysl);
let id=this.props.match.params.shixunId; let id=this.props.match.params.shixunId;
var jupyter_port=""; var jupyter_port="";
try{ try{
@ -173,16 +198,16 @@ class Challengesjupyter extends Component {
} }
sendToken=()=>{ sendToken=()=>{
// console.log("sendToken"); // //console.log("sendToken");
// const iframe = document.getElementById('iframe'); // const iframe = document.getElementById('iframe');
// console.log("modifyjupyter"); // //console.log("modifyjupyter");
// const frameWindow = iframe.contentWindow; // const frameWindow = iframe.contentWindow;
// console.log("frameWindow"); // //console.log("frameWindow");
// console.log(frameWindow); // //console.log(frameWindow);
} }
render() { render() {
let{ChallengesDataList}=this.state; let{ChallengesDataList,booljupyterurls}=this.state;
let id = this.props.match.params.shixunId; let id = this.props.match.params.shixunId;
// var deptObjs=document.getElementById("IFRAMEID").contentWindow.document.getElementById("TAGID"); // var deptObjs=document.getElementById("IFRAMEID").contentWindow.document.getElementById("TAGID");
// //判断此元素是否存在 // //判断此元素是否存在
@ -201,7 +226,7 @@ class Challengesjupyter extends Component {
// window.onload=()=>{ // window.onload=()=>{
// debugger // debugger
// var _iframe = document.getElementById('header'); // var _iframe = document.getElementById('header');
// console.log(_iframe); // //console.log(_iframe);
// // .contentWindow.document.getElementById('shutdown_widget') //get iframe下的id // // .contentWindow.document.getElementById('shutdown_widget') //get iframe下的id
// // _iframe.style.display= "none"; //修改样式 // // _iframe.style.display= "none"; //修改样式
// } // }
@ -213,6 +238,7 @@ class Challengesjupyter extends Component {
return ( return (
<React.Fragment> <React.Fragment>
<div className="mt30 pl20 pr20" > <div className="mt30 pl20 pr20" >
<Spin spinning={this.state.loading}>
<p className="clearfix mb20"> <p className="clearfix mb20">
<span className="font-16 fl">简介</span> <span className="font-16 fl">简介</span>
<Tooltip placement="bottom" title={"编辑"}> <Tooltip placement="bottom" title={"编辑"}>
@ -231,6 +257,23 @@ class Challengesjupyter extends Component {
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(ChallengesDataList.description).replace(/▁/g,"▁▁▁")}}></div> <div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(ChallengesDataList.description).replace(/▁/g,"▁▁▁")}}></div>
} }
</p> </p>
{
booljupyterurls===true?
(
this.state.jupyter_url === null?
<div className="mt50">
<p className="intermediatecenter sortinxdirection"><p className="colorbluetest">加载实训出错是否</p><p className="colorbluetwo" onClick={()=>this.updatamakedowns()}></p></p>
</div>
:""
)
:""
}
<style> <style>
{ {
` `
@ -299,8 +342,6 @@ class Challengesjupyter extends Component {
{ {
is_teacher===true? is_teacher===true?
<div className="mt35"> <div className="mt35">
{/*https://48888.jupyter.educoder.net/tree?*/}
<div className="pb47"> <div className="pb47">
{ {
this.state.jupyter_url===null || this.state.jupyter_url===undefined? this.state.jupyter_url===null || this.state.jupyter_url===undefined?
@ -316,6 +357,7 @@ class Challengesjupyter extends Component {
:"" :""
} }
</div> </div>
</Spin>
</div> </div>
</React.Fragment> </React.Fragment>

@ -64,3 +64,13 @@
.pb47{ .pb47{
padding-bottom: 47px; padding-bottom: 47px;
} }
.colorbluetwo{
color: #1E8FFD;
font-size: 12px;
cursor:pointer;
}
.colorbluetest{
color: #06101A;
font-size: 12px;
cursor:default
}

@ -54,6 +54,9 @@ const types = {
GET_JUPYTER_DATA_SETS: 'GET_JUPYTER_DATA_SETS', // jupyter 数据集 GET_JUPYTER_DATA_SETS: 'GET_JUPYTER_DATA_SETS', // jupyter 数据集
GET_JUPYTER_TPI_URL: 'GET_JUPYTER_TPI_URL', // 获取 jupyter url GET_JUPYTER_TPI_URL: 'GET_JUPYTER_TPI_URL', // 获取 jupyter url
SAVE_JUPYTER_IDENTIFIER: 'SAVE_JUPYTER_IDENTIFIER', // 保存jupyter identifier SAVE_JUPYTER_IDENTIFIER: 'SAVE_JUPYTER_IDENTIFIER', // 保存jupyter identifier
SAVE_JUPYTER_INFO: 'SAVE_JUPYTER_INFO', // 保存 jupyter 信息
CHANGE_JUPYTER_URL_STATE: 'CHANGE_JUPYTER_URL_STATE', // 获取url返回的状态值
SAVE_JUPYTER_TPI: 'SAVE_JUPYTER_TPI', // 保存 jupyter tpi
} }
export default types; export default types;

@ -64,7 +64,11 @@ import {
import { import {
getJupyterTpiDataSet, getJupyterTpiDataSet,
getJupyterTpiUrl getJupyterTpiUrl,
getJupyterInfo,
syncJupyterCode,
changeGetJupyterUrlState,
saveJupyterTpi
} from './jupyter'; } from './jupyter';
export default { export default {
@ -111,6 +115,10 @@ export default {
saveEditorCodeForDetail, saveEditorCodeForDetail,
// jupyter // jupyter
getJupyterTpiDataSet, getJupyterTpiDataSet,
getJupyterTpiUrl getJupyterTpiUrl,
getJupyterInfo,
syncJupyterCode,
changeGetJupyterUrlState,
saveJupyterTpi
// isUpdateCodeCtx // isUpdateCodeCtx
} }

@ -4,31 +4,81 @@
* @Github: * @Github:
* @Date: 2019-12-12 09:01:30 * @Date: 2019-12-12 09:01:30
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-12-12 09:30:53 * @LastEditTime: 2019-12-12 17:58:38
*/ */
import types from "./actionTypes"; import types from "./actionTypes";
import { fetchJupyterTpiDataSet, fetchJupyterTpiUrl } from "../../services/jupyterServer"; import { message } from 'antd';
import {
fetchJupyterTpiDataSet,
fetchJupyterTpiUrl,
fetchJupyterInfo,
fetchSyncJupyterCode,
fetchSaveJupyterTpi
} from "../../services/jupyterServer";
// 获取 jupyter 相关信息
export const getJupyterInfo = (id) => {
return (dispatch) => {
fetchJupyterInfo(id).then(res => {
if (res.data.status === 401) return;
if (res.status === 200) {
const { data } = res;
console.log(data);
if (data.status === 0) {
dispatch({
type: types.SAVE_JUPYTER_INFO,
payload: data
});
const { identifier, myshixun_identifier } = data;
// 调用获取数据集接口
dispatch(getJupyterTpiDataSet(identifier));
// 调用获取url接口
dispatch(getJupyterTpiUrl({identifier: myshixun_identifier}));
}
}
})
}
}
// 获取 jupyter tpi 数据集 // 获取 jupyter tpi 数据集
export const getJupyterTpiDataSet = (identifier) => { export const getJupyterTpiDataSet = (identifier) => {
return (dispatch) => { return (dispatch) => {
fetchJupyterTpiDataSet(identifier).then(res => { fetchJupyterTpiDataSet(identifier).then(res => {
if (res.data.status === 401) return; // 用户未登录 if (res.data.status === 401) return; // 用户未登录
console.log('数据集:', res); console.log('数据集:', res);
if (res.status === 200) {
const {data_sets} = res.data;
dispatch({
type: types.GET_JUPYTER_DATA_SETS,
payload: data_sets
});
}
}); });
} }
} }
// 获取 jupyter tpi 地址 // 获取 jupyter tpi 地址
export const getJupyterTpiUrl = (identifier) => { export const getJupyterTpiUrl = (obj) => {
return (dispatch) => { return (dispatch, getState) => {
fetchJupyterTpiUrl(identifier).then(res => { const {jupyter_info} = getState().jupyterReducer;
console.log(obj.identifier, jupyter_info.myshixun_identifier);
if (!obj.identifier && !jupyter_info.myshixun_identifier) return;
const id = obj.identifier || jupyter_info.myshixun_identifier;
fetchJupyterTpiUrl({identifier: id}).then(res => {
if (res.data.status === 401) return; // 用户未登录 if (res.data.status === 401) return; // 用户未登录
console.log('获取url', res); console.log('获取url', res);
if (res.status === 200) {
const { status, url = '', port } = res.data;
dispatch({
type: types.GET_JUPYTER_TPI_URL,
payload: {
status,
url,
port
}
})
}
}) })
} }
} }
// 保存 jupyter identifer // 保存 jupyter identifer
export const saveJupyterIdentifier = (identifier) => { export const saveJupyterIdentifier = (identifier) => {
return { return {
@ -36,3 +86,54 @@ export const saveJupyterIdentifier = (identifier) => {
payload: identifier payload: identifier
} }
} }
// 重置代码
export const syncJupyterCode = (identifier, msg) => {
return (dispatch) => {
fetchSyncJupyterCode(identifier).then(res => {
// console.log('同步代码成功: ', res);
if (res.data.status === 401) return;
if (res.status === 200) {
const {status} = res.data
if (status === 0) message.success(msg);
}
})
}
}
// 改变状态值
export const changeGetJupyterUrlState = (status) => {
return {
type: types.CHANGE_JUPYTER_URL_STATE,
payload: status
}
}
// 保存 jupyter tpi
export const saveJupyterTpi = () => {
return (dispatch, getState) => {
const { jupyter_tpi_code, jupyter_info }= getState().jupyterReducer;
// console.log(jupyter_info.myshixun_identifier, jupyter_tpi_code);
if (!jupyter_info.myshixun_identifier) return;
const params = {
identifier: jupyter_info.myshixun_identifier,
jupyter_port: jupyter_tpi_code
};
console.log(params);
fetchSaveJupyterTpi(params).then(res => {
dispatch({
type: types.LOADING_STATUS,
payload: false
});
if (res.status === 200) {
const { data } = res;
if (data.status === 0) {
message.success('保存成功!')
}
}
}).catch(() => {
dispatch({
type: types.LOADING_STATUS,
payload: false
});
});
}
}

@ -4,7 +4,7 @@
* @Github: * @Github:
* @Date: 2019-11-27 16:27:09 * @Date: 2019-11-27 16:27:09
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-12-03 11:00:19 * @LastEditTime: 2019-12-12 17:36:51
*/ */
import types from "../actions/actionTypes"; import types from "../actions/actionTypes";

@ -4,14 +4,17 @@
* @Github: * @Github:
* @Date: 2019-12-12 09:01:39 * @Date: 2019-12-12 09:01:39
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-12-12 09:29:49 * @LastEditTime: 2019-12-12 17:23:54
*/ */
import types from "../actions/actionTypes"; import types from "../actions/actionTypes";
const initState = { const initState = {
jupyter_tpi_url: '', jupyter_tpi_url: '',
jupyter_info: {}, // 保存用户信息及实训相关的内容
jupyter_data_set: [], jupyter_data_set: [],
jupyter_identifier: '' jupyter_identifier: '',
jupyter_tpi_url_state: -1, // 获取 url 状态值: 0 成功, 其它 失败
jupyter_tpi_code: '' // 端口号
}; };
const JupyterReducer = (state = initState, action) => { const JupyterReducer = (state = initState, action) => {
@ -22,15 +25,28 @@ const JupyterReducer = (state = initState, action) => {
jupyter_data_set: action.payload jupyter_data_set: action.payload
} }
case types.GET_JUPYTER_TPI_URL: case types.GET_JUPYTER_TPI_URL:
const {url, status, port} = action.payload;
return { return {
...state, ...state,
jupyter_tpi_url: action.payload jupyter_tpi_url: url,
jupyter_tpi_url_state: status,
jupyter_tpi_code: port
} }
case types.SAVE_JUPYTER_IDENTIFIER: case types.SAVE_JUPYTER_IDENTIFIER:
return { return {
...state, ...state,
jupyter_identifier: action.payload jupyter_identifier: action.payload
} }
case types.SAVE_JUPYTER_INFO:
return {
...state,
jupyter_info: action.payload
}
case types.CHANGE_JUPYTER_URL_STATE:
return {
...state,
jupyter_tpi_url_state: action.payload
}
default: default:
return { return {
...state ...state

@ -4,10 +4,15 @@
* @Github: * @Github:
* @Date: 2019-12-12 09:07:07 * @Date: 2019-12-12 09:07:07
* @LastEditors: tangjiang * @LastEditors: tangjiang
* @LastEditTime: 2019-12-12 09:10:58 * @LastEditTime: 2019-12-12 17:46:17
*/ */
import axios from 'axios'; import axios from 'axios';
// 获取 jupyter实训相关的内容
export async function fetchJupyterInfo (identifier) {
const url = `/tasks/${identifier}/jupyter.json`;
return axios.get(url);
}
// 获取数据集 // 获取数据集
export async function fetchJupyterTpiDataSet (identifier) { export async function fetchJupyterTpiDataSet (identifier) {
const url = `/shixuns/${identifier}/jupyter_data_sets.json`; const url = `/shixuns/${identifier}/jupyter_data_sets.json`;
@ -18,3 +23,13 @@ export async function fetchJupyterTpiUrl (params) {
const url = `/jupyters/get_info_with_tpi.json`; const url = `/jupyters/get_info_with_tpi.json`;
return axios.get(url, { params }); return axios.get(url, { params });
} }
// 同步代码功能
export async function fetchSyncJupyterCode (identifier) {
const url = `/myshixuns/${identifier}/sync_code.json`;
return axios.post(url);
}
// jupyter 保存
export async function fetchSaveJupyterTpi (params) {
const url = `/jupyters/save_with_tpi.json`;
return axios.get(url, { params });
}
Loading…
Cancel
Save