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

# Conflicts:
#	public/react/src/modules/tpm/shixunchild/Challenges/Challengesjupyter.js
chromesetting
杨树明 5 years ago
commit f095a6c162

@ -3,12 +3,14 @@
$(function(){
console.log("educoder jupyter js init");
console.log("开始发送消息了");
runEvery10Sec();
})
$(function(){
console.log("开始发送消息了");
function runEvery10Sec() {
// 1000 * 10 = 10 秒钟
console.log("每隔10秒中一次runEvery10Sec");
window.parent.postMessage('jupytermessage','*');
})
setTimeout( runEvery10Sec, 1000 * 10 );
}

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 16:02:36
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-19 19:47:32
* @LastEditTime: 2019-12-20 14:37:39
*/
import './index.scss';
import React, { useState, useRef, useEffect } from 'react';
@ -24,7 +24,7 @@ const ControlSetting = (props) => {
identifier,
excuteState,
showOrHideControl,
commitRecordDetail,
commitTestRecordDetail,
changeLoadingState,
changeSubmitLoadingStatus,
changeShowOrHideControl,
@ -102,7 +102,7 @@ const ControlSetting = (props) => {
<TabPane tab={'代码执行结果'} key={'2'} style={{ height: '280px', overflowY: 'auto' }}>
<ExecResult
excuteState={excuteState}
excuteDetail={commitRecordDetail}
excuteDetail={commitTestRecordDetail}
/>
</TabPane>
</Tabs>
@ -137,14 +137,14 @@ const ControlSetting = (props) => {
const mapStateToProps = (state) => {
const {commonReducer, ojForUserReducer} = state;
const {loading, excuteState, submitLoading, showOrHideControl } = commonReducer;
const { commitRecordDetail } = ojForUserReducer;
const { commitTestRecordDetail } = ojForUserReducer;
return {
loading,
submitLoading,
excuteState,
showOrHideControl,
// identifier: user_program_identifier,
commitRecordDetail // 提交详情
commitTestRecordDetail // 提交详情
};
};
// changeSubmitLoadingStatus

@ -51,7 +51,7 @@
align-items: center;
z-index: 20;
height: 56px;
padding-right: 30px;
padding-right: 20px;
padding-left: 10px;
background: rgba(18,28,36,1);
// background:rgba(48,48,48,1);

@ -3,6 +3,7 @@
position: absolute;
color: #fff;
line-height: 65px;
left: 20px;
// height: 65px;
.student_img,
.student_nicker{

@ -70,13 +70,13 @@ const NewOrEditTask = (props) => {
// 模拟挑战
const imitationChallenge = () => {
// 调用 start 接口, 成功后跳转到模拟页面
startProgramQuestion(identifier, props);
identifier && startProgramQuestion(identifier, props);
}
// 开始挑战
const startChallenge = () => {
// 调用 start 接口, 成功后跳转到开启实战
// TODO
startProgramQuestion(identifier, props);
identifier && startProgramQuestion(identifier, props);
}
// 取消

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-12-04 08:36:21
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 10:38:00
* @LastEditTime: 2019-12-20 10:52:36
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@ -87,9 +87,11 @@ function RecordDetail (props) {
</span>
</span>
<span className="status_label">
语言: <span className="status_label_sub">C</span>
语言: <span className="status_label_sub">{detail.language}</span>
</span>
<span className="status_label" style={{ visibility: detail.status === 0 ? 'visible' : 'hidden'}}>
执行用时: <span className="status_label_sub">{`${detail.execute_time && (+detail.execute_time * 1000)}ms`}</span>
</span>
{/* <span className> */}
</div>
<div className="result_error_area">
<ErrorResult detail={detail}/>

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-23 10:53:19
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-19 19:48:20
* @LastEditTime: 2019-12-20 14:54:39
*/
import './index.scss';
import React, { useEffect, useState } from 'react';
@ -92,9 +92,12 @@ function StudentStudy (props) {
changeShowOrHideControl(false);
props.saveEditorCodeForDetail();
props.history.push(`/problems/${_hack_id}/edit`);
props.clearOjForUserReducer();
}
// 处理退出
const handleClickQuit = () => {
// 退出时,清空内容
props.clearOjForUserReducer();
// 将控制台关闭
changeShowOrHideControl(false);
props.saveEditorCodeForDetail();
@ -116,7 +119,11 @@ function StudentStudy (props) {
</div>
<div className={'study_quit'}>
{/* to={`/problems/${_hack_id}/edit`} */}
<span onClick={handleClickEditor} className={`quit-btn`}>
<span
style={{ display: userInfo.hack_manager ? 'inline-block' : 'none' }}
onClick={handleClickEditor}
className={`quit-btn`}
>
<Icon type="form" className="quit-icon"/> 编辑
</span>
{/* to="/problems" */}
@ -168,7 +175,8 @@ const mapDispatchToProps = (dispatch) => ({
saveEditorCodeForDetail: (code) => dispatch(actions.saveEditorCodeForDetail(code)),
// 恢复初始代码
restoreInitialCode: (identifier, msg) => dispatch(actions.restoreInitialCode(identifier, msg)),
changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag))
changeShowOrHideControl: (flag) => dispatch(actions.changeShowOrHideControl(flag)),
clearOjForUserReducer: () => dispatch(actions.clearOjForUserReducer())
});
export default withRouter(connect(

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 09:49:33
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 09:35:00
* @LastEditTime: 2019-12-20 13:55:07
*/
import './index.scss';
import React, { useState, useEffect } from 'react';
@ -73,6 +73,7 @@ const CommitRecord = (props) => {
commitRecord,
// excuteState,
language,
operateType,
commitRecordDetail,
getUserCommitRecord
} = props;
@ -146,22 +147,32 @@ const CommitRecord = (props) => {
// 提交详情变化时,显示当前提交信息
useEffect(() => {
// setRecordDetail(commitRecordDetail);
setRenderCtx(() => (renderRecordDetail))
}, [commitRecordDetail]);
if (operateType === 'submit') {
setRenderCtx(() => (renderRecordDetail))
}
}, [commitRecordDetail, operateType]);
// 复制功能
let count = 0;
useEffect(() => {
if (!clipboard) {
clipboard = new ClipboardJS('.copy_error');
}
if (commitRecordDetail.status !== 0) {
clipboard.on('success', (e) => {
message.success('复制成功');
e.clearSelection();
});
}
}, [commitRecordDetail.status]);
clipboard = new ClipboardJS('.copy_error');
clipboard.on('success', (e) => {
e.clearSelection();
if (count > 0) return;
count++;
message.success('复制成功');
setTimeout(() => {
message.destroy();
}, 300);
});
}, []);
// if (commitRecordDetail.status !== 0) {
// clipboard.on('success', (e) => {
// console.log('成功=====》》》》》');
// message.success('复制成功');
// e.clearSelection();
// });
// }
//
const handleTableChange = (pagination) => {
setPagination(Object.assign({}, pagination));
@ -190,7 +201,8 @@ const mapStateToProps = (state) => {
user_program_identifier,
commitRecordDetail,
commitRecord,
hack
hack,
operateType
} = ojForUserReducer;
const { excuteState } = commonReducer;
return {
@ -198,7 +210,8 @@ const mapStateToProps = (state) => {
commitRecordDetail,
commitRecord, // 提交记录
excuteState, // 代码执行状态
language: hack.language
language: hack.language,
operateType
}
}
const mapDispatchToProps = (dispatch) => ({

@ -1,6 +1,8 @@
.commit_record_area{
// padding: 20px 30px;
padding: 0 20px;
overflow-y: auto;
height: calc(100vh - 177px);
.record_header{
display: flex;
// justify-content: space-between;

@ -65,7 +65,7 @@
.student_study_header{
.study_quit{
position: absolute;
right: 30px;
right: 20px;
}
.quit-btn{
cursor: pointer;

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 14:59:51
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-19 19:13:05
* @LastEditTime: 2019-12-20 14:01:57
*/
import React, { useState, useEffect } from 'react';
import {connect} from 'react-redux';
@ -27,6 +27,7 @@ const RightPane = (props) => {
updateNotice,
saveUserInputCode,
restoreInitialCode,
saveOpacityType,
saveUserCodeForInterval
} = props;
@ -43,6 +44,7 @@ const RightPane = (props) => {
const handleSubmitForm = () => {
// 提交时, 先调用提交接口,提交成功后,循环调用测评接口
// saveOpacityType('submit');
submitUserCode(identifier, submitInput, 'submit');
// // 提交时,先调用评测接口, 评测通过后才调用保存接口
// updateCode(identifier, submitInput, 'submit');
@ -71,6 +73,7 @@ const RightPane = (props) => {
// 代码调试
const handleDebuggerCode = (value) => {
// 调用保存代码块接口,成功后,调用调试接口
// saveOpacityType('debug');
updateCode(identifier, value, 'debug');
}
// 恢复初始代码
@ -137,6 +140,7 @@ const mapDispatchToProps = (dispatch) => ({
saveUserCodeForInterval: (identifier, code) => dispatch(actions.saveUserCodeForInterval(identifier, code)),
// 恢复初始代码
restoreInitialCode: (identifier, msg) => dispatch(actions.restoreInitialCode(identifier, msg)),
// saveOpacityType: (type) => dispatch(actions.saveOpacityType(type))
});
export default connect(

@ -868,8 +868,8 @@ class TPMBanner extends Component {
</li>
</ul>
{
this.props.is_jupyter===true?"":
{/*{*/}
{/* this.props.is_jupyter===true?"":*/}
<Popover placement="right" content={
<div style={{"width": "530px"}} >
@ -934,7 +934,7 @@ class TPMBanner extends Component {
</div>
</Popover>
}
{/*// }*/}
{

@ -68,7 +68,7 @@
align-items: center;
height: 56px;
justify-content: flex-end;
padding-right: 30px;
padding-right: 20px;
}
}
}

@ -105,9 +105,9 @@ class Challengesjupyter extends Component {
setTimeout(this.ChallengesList(), 1000);
let id = this.props.match.params.shixunId;
let ChallengesURL = `/jupyters/get_info_with_tpm.json`;
let datas={
identifier:id,
}
let datas={
identifier:id,
}
axios.get(ChallengesURL, {params: datas}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
setTimeout(() => {
@ -115,26 +115,29 @@ class Challengesjupyter extends Component {
booljupyterurls:true,
})
}, 600)
}else{
if(response.data.status===0){
}else{
if(response.data.status===0){
setTimeout(() => {
this.setState({
jupyter_url:response.data.url,
jupyter_port:response.data.port,
booljupyterurls:true,
})
}, 800)
setTimeout(() => {
}else{
setTimeout(() => {
this.setState({
booljupyterurls:true,
})
}, 600)
var url=response.data.url;
var url2=url.replace("http://","https://");
this.setState({
jupyter_url:url2,
jupyter_port:response.data.port,
booljupyterurls:true,
})
}, 800)
}else{
setTimeout(() => {
this.setState({
booljupyterurls:true,
})
}, 600)
}
}
}
}).catch((error) => {
@ -148,15 +151,19 @@ class Challengesjupyter extends Component {
setTimeout(this.getjianjiesize(), 1000);
window.addEventListener('message', (e) => {
console.log("触发了jupytermessage");
console.log(e);
if(e){
if(e.data){
if(e.data==="jupytermessage"){
that.modifyjupyter();
}
}
}
window.addEventListener('jupytermessage', (e) => {
console.log("触发了jupytermessage");
console.log("触发了jupytermessage");
that.modifyjupyter();
});
setTimeout(this.getjianjiesize(), 1000);
}
updatamakedowns = () => {
@ -210,13 +217,13 @@ class Challengesjupyter extends Component {
modifyjupyter=()=>{
let id=this.props.match.params.shixunId;
var jupyter_port="";
try{
jupyter_port= parseInt(this.state.jupyter_port);
}catch (e) {
jupyter_port=this.state.jupyter_port;
var jupyter_port="";
try{
jupyter_port= parseInt(this.state.jupyter_port);
}catch (e) {
jupyter_port=this.state.jupyter_port;
}
}
const url=`/jupyters/save_with_tpm.json`;
const data={
identifier:id,
@ -225,8 +232,8 @@ class Challengesjupyter extends Component {
axios.get(url, {params: data})
.then((result) => {
if (result.data.status === 0) {
this.props.showNotification(`应用成功`);
console.log("触发了jupytermessage调用了应用成功");
// this.props.showNotification(`应用成功`);
console.log("应用成功");
}
}).catch((error) => {
})
@ -237,15 +244,12 @@ class Challengesjupyter extends Component {
opentitletype:!this.state.opentitletype
})
}
onclki=(bool)=>{
this.setState({
enlarge:bool
})
}
render() {
let{ChallengesDataList,booljupyterurls,enlarge}=this.state;
let id = this.props.match.params.shixunId;
@ -255,8 +259,6 @@ class Challengesjupyter extends Component {
const business = this.props&&this.props.current_user&&this.props.current_user.business?this.props.current_user.business:false;
//管理员
const admin = this.props&&this.props.current_user&&this.props.current_user.admin?this.props.current_user.admin:false;
//用户
const login = this.props&&this.props.current_user&&this.props.current_user.login?this.props.current_user.login:"";
let mysidentity =false;
try {
@ -377,9 +379,8 @@ class Challengesjupyter extends Component {
display: flex;
flex-direction:row-reverse;
}
;
}
}
`
}
</style>
@ -388,29 +389,35 @@ class Challengesjupyter extends Component {
""
:
(
admin===true||business===true||mysidentity===true?
<div className={"shixunjianjiecballenges edu-back-white sortinxdirection mt20"}>
<div className="renwuxiangssi sortinxdirection">
<div><p className="renwuxiangqdiv">任务详情</p></div>
<div><p className="renwuxiangqdivtest ml1 shixunbingbaocun">请将实训题目写在下方并保存</p></div>
</div>
<div className="renwuxiangssit xaxisreverseorder">
{
enlarge===true?
<i className="iconfont icon-suoxiao2 font-20 ml2 ysliconfont" style={{
marginLeft: '30px',
}} onClick={()=>this.onclki(false)}></i>
:
<i className="iconfont icon-fangda font-20 ml2 ysliconfont" style={{
marginLeft: '30px',
}} onClick={()=>this.onclki(true)}></i>
}
<div className="challenbaocun" ><p
className="challenbaocuntest">导入</p>
admin===true||business===true||mysidentity===true?
<div style={{
height: '63px',
}} className={enlarge?"shixunjianjiecballenges edu-back-white intermediatecenter fangdaone":"shixunjianjiecballenges edu-back-white mt20"}>
<div className={enlarge?"sortinxdirection jupyterswidth":"sortinxdirection"} >
<div className="renwuxiangssi sortinxdirection">
<div><p className="renwuxiangqdiv">任务详情</p></div>
<div><p className="renwuxiangqdivtest ml1 shixunbingbaocun">请将实训题目写在下方并保存</p></div>
</div>
<div className="renwuxiangssit xaxisreverseorder">
{
enlarge===true?
<i className="iconfont icon-suoxiao2 font-18 ml2 ysliconfont" style={{
marginLeft: '30px',
}} onClick={()=>this.onclki(false)}></i>
:
<i className="iconfont icon-fangda font-18 ml2 ysliconfont" style={{
marginLeft: '30px',
}} onClick={()=>this.onclki(true)}></i>
}
{/*<div className="challenbaocun" ><p*/}
{/* className="challenbaocuntest">导入</p>*/}
{/*</div>*/}
</div>
</div>
</div>
:
:
""
)
@ -442,34 +449,25 @@ class Challengesjupyter extends Component {
}
</style>
{
admin===true||business===true||mysidentity===true?
<div>
<div className="pb47">
{
this.state.jupyter_url===null || this.state.jupyter_url===undefined?
(
booljupyterurls===false?
<LoadingSpin></LoadingSpin>
:""
)
:
(
login==="innov"?
<iframe src={"http://121.41.4.83:46666/notebooks/root/work/01.ipynb"} className={enlarge?"fangdatwo":""}
sandbox="allow-same-origin allow-scripts allow-top-navigation " scrolling="no" id="frame"
name="framename" width="100%" height="700" frameBorder="0"
></iframe>
:
admin===true||business===true||mysidentity===true?
<div>
<div className="pb47">
{
this.state.jupyter_url===null || this.state.jupyter_url===undefined?
(
booljupyterurls===false?
<LoadingSpin></LoadingSpin>
:""
)
:
<iframe src={this.state.jupyter_url} className={enlarge?"fangdatwo":""}
sandbox="allow-same-origin allow-scripts allow-top-navigation " scrolling="no" id="frame"
name="framename" width="100%" height="700" frameBorder="0"
sandbox="allow-same-origin allow-scripts allow-top-navigation " scrolling="no" id="frame"
name="framename" width="100%" height="700" frameBorder="0"
></iframe>
)
}
</div>
}
</div>
:""
</div>
:""
}
</div>
</div>

@ -187,7 +187,7 @@
}
.ysliconfont{
text-align: center;
line-height: 30px;
line-height: 29px;
}
.fangdaone{

@ -51,6 +51,8 @@ const types = {
SAVE_USER_INFO: 'SAVE_USER_INFO', // 只在用户信息
SAVE_HACK_IDENTIFIER: 'SAVE_HACK_IDENTIFIER', // 用户界面跑到编辑界面需要用的id值
SAVE_EDITOR_CODE: 'SAVE_EDITOR_CODE', // 保存详情页面中编辑时的代码
CLICK_OPERATE_TYPE: 'CLICK_OPERATE_TYPE', // 点击类型
CLEAR_OJ_FOR_USER_REDUCER: 'CLEAR_OJ_FOR_USER_REDUCER', // 退出时清空 ojForUserReducer保存内容
/*** jupyter */
GET_JUPYTER_DATA_SETS: 'GET_JUPYTER_DATA_SETS', // jupyter 数据集
GET_JUPYTER_TPI_URL: 'GET_JUPYTER_TPI_URL', // 获取 jupyter url

@ -48,6 +48,8 @@ import {
restoreInitialCode,
saveUserCodeForInterval,
saveEditorCodeForDetail,
saveOpacityType,
clearOjForUserReducer
// isUpdateCodeCtx
} from './ojForUser';
@ -117,6 +119,8 @@ export default {
getUserInfoForNew,
saveUserCodeForInterval,
saveEditorCodeForDetail,
saveOpacityType,
clearOjForUserReducer,
// jupyter
getJupyterTpiDataSet,
getJupyterTpiUrl,

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 13:42:11
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-20 10:25:42
* @LastEditTime: 2019-12-20 14:47:26
*/
import types from "./actionTypes";
import { Base64 } from 'js-base64';
@ -208,7 +208,10 @@ export const codeEvaluate = (dispatch, identifier, type, time_limit) => {
// 返回评测结果
dispatch({
type: types.COMMIT_RECORD_DETAIL,
payload: returnData
payload: {
type,
data: returnData
}
});
if (!type || type === 'debug') {
dispatch({ // 改变 loading 值
@ -233,6 +236,7 @@ export const codeEvaluate = (dispatch, identifier, type, time_limit) => {
});
// 重新调用一下提交记录接口
dispatch(getUserCommitRecord(identifier));
dispatch(saveOpacityType(type));
}
}
}).catch(err => { // 评测异常时
@ -454,5 +458,20 @@ export const saveEditorCodeForDetail = (code) => {
}
}
// 保存操作类型: 提交或调试
export const saveOpacityType = (type) => {
return {
type: types.CLICK_OPERATE_TYPE,
payload: type
}
}
export const clearOjForUserReducer = () => {
return {
type: types.CLEAR_OJ_FOR_USER_REDUCER
};
}
// 更新通知状态

@ -4,7 +4,7 @@
* @Github:
* @Date: 2019-11-27 13:41:48
* @LastEditors: tangjiang
* @LastEditTime: 2019-12-19 20:10:39
* @LastEditTime: 2019-12-20 14:46:07
*/
import types from "../actions/actionTypes";
import { Base64 } from 'js-base64';
@ -13,6 +13,7 @@ const initialState = {
user_program_identifier: '', // 开启OJ题的唯一标题
hack: {}, // 编程题主要内容
test_case: {}, // 测试用例
commitTestRecordDetail: {}, // 调试代码执行结果
commitRecordDetail: {}, // 提交成功后记录提交的详情
commitRecord: [], // 提交记录
userCode: '', // 保存当前用户输入的代码
@ -24,6 +25,7 @@ const initialState = {
editor_code: '', // 保存编辑代码
notice: false, // 通知
hadCodeUpdate: false, // 更新代码
operateType: '', // 点击类型: 调度或提交
};
const ojForUserReducer = (state = initialState, action) => {
@ -51,7 +53,7 @@ const ojForUserReducer = (state = initialState, action) => {
test_case: Object.assign({}, test_case)
}
case types.COMMIT_RECORD_DETAIL:
let result = action.payload;
let result = action.payload.data;
if (result['expected_output']) {
result['expected_output'] = Base64.decode(result['expected_output'])
}
@ -63,10 +65,18 @@ const ojForUserReducer = (state = initialState, action) => {
} catch (e) {
console.log('错误信息:', e);
}
return {
...state,
commitRecordDetail: Object.assign({}, result)
if (action.payload.type === 'submit') {
return {
...state,
commitRecordDetail: Object.assign({}, result)
}
} else {
return {
...state,
commitTestRecordDetail: Object.assign({}, result)
}
}
case types.COMMIT_RECORD:
return {
...state,
@ -144,6 +154,31 @@ const ojForUserReducer = (state = initialState, action) => {
...state,
hadCodeUpdate: action.payload
};
case types.CLICK_OPERATE_TYPE:
return {
...state,
operateType: action.payload
}
case types.CLEAR_OJ_FOR_USER_REDUCER:
return {
...state,
user_program_identifier: '', // 开启OJ题的唯一标题
hack: {}, // 编程题主要内容
test_case: {}, // 测试用例
commitTestRecordDetail: {}, // 调试代码执行结果
commitRecordDetail: {}, // 提交成功后记录提交的详情
commitRecord: [], // 提交记录
userCode: '', // 保存当前用户输入的代码
isUpdateCode: false, // 是否更新了代码内容
userCodeTab: 'task', // 学员测评tab位置: task | record | comment
userTestInput: '', // 用户自定义输入值
recordDetail: {}, // 根据id号获取的记录详情
hack_identifier: '', // 用户界面编辑时
editor_code: '', // 保存编辑代码
notice: false, // 通知
hadCodeUpdate: false, // 更新代码
operateType: '', // 点击类型: 调度或提交
};
default:
return state;
}

Loading…
Cancel
Save