Merge branch 'dev_aliyun' of https://bdgit.educoder.net/Hjqreturn/educoder into dev_aliyun

dev_hss
杨树林 6 years ago
commit 1ec2feaf32

@ -1,5 +1,6 @@
function createMDEditor(element, opts){ function createMDEditor(element, opts){
var defaults = { var defaults = {
height: 600,
path: '/editormd/lib/', path: '/editormd/lib/',
syncScrolling: "single", syncScrolling: "single",
tex: true, tex: true,

@ -67,13 +67,19 @@ class GamesController < ApplicationController
uri = "#{shixun_tomcat}/bridge/vnc/getvnc" uri = "#{shixun_tomcat}/bridge/vnc/getvnc"
params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}"} params = {tpiID: @myshixun.id, :containers => "#{Base64.urlsafe_encode64(shixun_container_limit(@shixun))}"}
res = uri_post uri, params res = uri_post uri, params
logger.info("###############---- ")
if res && res['code'].to_i != 0 if res && res['code'].to_i != 0
raise("实训云平台繁忙繁忙等级99") raise("实训云平台繁忙繁忙等级99")
end end
# 无域名版本
#@vnc_url = "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless" if request.subdomain == "pre-newweb"
# 有域名版本 # 无域名版本
@vnc_url = "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless" @vnc_url = "http://#{service_host}:#{res['port']}/vnc_lite.html?password=headless"
else
# 有域名版本
@vnc_url = "https://#{res['port']}.#{service_host}/vnc_lite.html?password=headless"
end
@vnc_evaluate = @shixun.vnc_evaluate @vnc_evaluate = @shixun.vnc_evaluate
rescue Exception => e rescue Exception => e
Rails.logger.error(e.message) Rails.logger.error(e.message)

@ -265,6 +265,7 @@ class QuestionBanksController < ApplicationController
# exercise.update_column(:quotes, exercise.quotes+1) # exercise.update_column(:quotes, exercise.quotes+1)
# end # end
new_exercise if new_exercise.save! new_exercise if new_exercise.save!
exercise.update_column(:quotes, exercise.quotes+1)
end end
end end
@ -292,6 +293,7 @@ class QuestionBanksController < ApplicationController
# poll.update_column(:quotes, poll.quotes+1) # poll.update_column(:quotes, poll.quotes+1)
# end # end
new_poll if new_poll.save! new_poll if new_poll.save!
poll.update_column(:quotes, poll.quotes+1)
end end
end end

@ -448,6 +448,7 @@ class ShixunsController < ApplicationController
ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror) ShixunMirrorRepository.create(:shixun_id => @shixun.id, :mirror_repository_id => mirror)
end end
end end
logger.info("#########shixun_params#{shixun_params}")
@shixun.update_attributes(shixun_params) @shixun.update_attributes(shixun_params)
logger.info("##########shixun_info_params: #{shixun_info_params}") logger.info("##########shixun_info_params: #{shixun_info_params}")
logger.info("##########params[:shixun_info][:evaluate_script]: #{params[:shixun_info][:evaluate_script]}") logger.info("##########params[:shixun_info][:evaluate_script]: #{params[:shixun_info][:evaluate_script]}")

@ -1,7 +1,7 @@
class GtopicBank < ApplicationRecord class GtopicBank < ApplicationRecord
belongs_to :user belongs_to :user
belongs_to :graduation_topic belongs_to :graduation_topic, optional: true
belongs_to :course_list belongs_to :course_list, optional: true
has_many :attachments, as: :container, dependent: :destroy has_many :attachments, as: :container, dependent: :destroy
has_many :graduation_topics, dependent: :nullify has_many :graduation_topics, dependent: :nullify

@ -24,7 +24,7 @@ module Searchable::Course
author_name: teacher&.real_name, author_name: teacher&.real_name,
author_school_name: teacher&.school_name, author_school_name: teacher&.school_name,
visits_count: visits, visits_count: visits,
members_count: members_count, members_count: course_members_count,
is_public: is_public == 1, is_public: is_public == 1,
first_category_url: ApplicationController.helpers.module_url(none_hidden_course_modules.first, self) first_category_url: ApplicationController.helpers.module_url(none_hidden_course_modules.first, self)
} }

@ -0,0 +1,31 @@
class MigrateBankReferenceId < ActiveRecord::Migration[5.2]
def change
HomeworkBank.all.each do |bank|
if bank.homework_common
bank.homework_common.update_column("homework_bank_id", bank.id) if bank.homework_common.homework_bank_id.nil?
end
end
GtopicBank.all.each do |bank|
if bank.graduation_topic
bank.graduation_topic.update_column("gtopic_bank_id", bank.id) if bank.graduation_topic.gtopic_bank_id.nil?
end
end
GtaskBank.all.each do |bank|
if bank.graduation_task
bank.graduation_task.update_column("gtask_bank_id", bank.id) if bank.graduation_task.gtask_bank_id.nil?
end
end
ExerciseBank.all.each do |bank|
if bank.container_type == 'Exercise'
exercise = Exercise.find_by(id: bank.container_id)
exercise.update_column("exercise_bank_id", bank.id) if exercise && exercise.exercise_bank_id.nil?
elsif bank.container_type == 'Poll'
poll = Poll.find_by(id: bank.container_id)
poll.update_column("exercise_bank_id", bank.id) if poll && poll.exercise_bank_id.nil?
end
end
end
end

@ -41,7 +41,7 @@ function CourseGroupChooser({ course_groups, isAdminOrCreator = true, item, inde
console.log('arg_course_groups', arg_course_groups) console.log('arg_course_groups', arg_course_groups)
const urlStyle = {"lef":"tunset", minWidth: '262px'}; const urlStyle = {"left":"unset", minWidth: '262px'};
if (alwaysShow == true) { if (alwaysShow == true) {
urlStyle.display = 'block' urlStyle.display = 'block'
} }

@ -70,17 +70,22 @@ function CourseGroupChooserModal({ course_groups = [], isAdminOrCreator, item, i
text-align: center; text-align: center;
margin-bottom: 20px; margin-bottom: 20px;
} }
.courseGroupChooserModal .drop_down_menu { .courseGroupChooserModal .drop_down_menu {
position: relative; position: relative;
top: auto; top: auto;
box-shadow: none; box-shadow: none;
padding-top: 12px;
}
.courseGroupChooserModal .drop_down_menu .mainGroup{
background: #f2f9ff;
padding: 0 20px; padding: 0 20px;
}
.courseGroupChooserModal .drop_down_menu li:hover,.courseGroupChooserModal .drop_down_normal li:hover{
background: #f2f9ff; background: #f2f9ff;
padding-top: 12px;
} }
.courseGroupChooserModal .drop_down_menu .mainGroup.ant-checkbox-group { .courseGroupChooserModal .drop_down_menu .mainGroup.ant-checkbox-group {
width: 100%; width: 100%;
max-height: 300px height: 300px;
} }
.courseGroupChooserModal .drop_down_search { .courseGroupChooserModal .drop_down_search {
margin: 0; margin: 0;

@ -1,204 +1,206 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import { Link } from 'react-router-dom' import { Link } from 'react-router-dom'
import { withStyles } from 'material-ui/styles'; import { withStyles } from 'material-ui/styles';
import Button from 'material-ui/Button'; import Button from 'material-ui/Button';
import Tooltip from 'material-ui/Tooltip'; import Tooltip from 'material-ui/Tooltip';
import './ActionView.css' import './ActionView.css'
/* /*
color: #1B4061 !important; color: #1B4061 !important;
background-color: transparent; background-color: transparent;
border: 1px solid #1B4061 !important; border: 1px solid #1B4061 !important;
*/ */
const styles = theme => ({ const styles = theme => ({
button: { button: {
margin: theme.spacing.unit, margin: theme.spacing.unit,
border: '1px solid #1B4061', border: '1px solid #1B4061',
color: '#1B4061', color: '#1B4061',
height: '30px', height: '30px',
padding: '0 16px', padding: '0 16px',
'&:hover': { '&:hover': {
color: '#4CACFF', color: '#4CACFF',
border: '1px solid #4CACFF' border: '1px solid #4CACFF'
} }
}, },
hoverButton: { hoverButton: {
margin: theme.spacing.unit, margin: theme.spacing.unit,
height: '30px', height: '30px',
padding: '0 16px', padding: '0 16px',
color: '#4CACFF', color: '#4CACFF',
border: '1px solid #4CACFF' border: '1px solid #4CACFF'
}, },
buttonText: { buttonText: {
color: '#1B4061 !important', color: '#1B4061 !important',
'&:hover': { '&:hover': {
color: '#1B4061', color: '#1B4061',
} }
} }
}); });
class ActionView extends Component { class ActionView extends Component {
constructor(props) { constructor(props) {
super(props) super(props)
} }
componentDidMount() { componentDidMount() {
// request // request
window._tpiWidthResize = () => { window._tpiWidthResize = () => {
const _w = window.$('#actionView').width(); const _w = window.$('#actionView').width();
// if (_w < 446) { // if (_w < 446) {
// window.$('#time-consuming').hide() // window.$('#time-consuming').hide()
// // window.$('#time-consuming').hide() // // window.$('#time-consuming').hide()
// } else if (_w < 746) { // } else if (_w < 746) {
// // 文字放出来之前是 580 // // 文字放出来之前是 580
// window.$('#time-consuming').show() // window.$('#time-consuming').show()
// window.$('.time_limit').hide() // window.$('.time_limit').hide()
// } else { // } else {
// window.$('#time-consuming').show() // window.$('#time-consuming').show()
// window.$('.time_limit').show() // window.$('.time_limit').show()
// } // }
} }
} }
showWebDisplay(challenge) { showWebDisplay(challenge) {
window.open(challenge.webDisplayUrl, '_blank'); window.open(challenge.webDisplayUrl, '_blank');
} }
/*<span className="mt10 -flex c_grey ml15" id="time-consuming">耗时0 天 3 小时 11 分钟 57 秒 </span>*/ /*<span className="mt10 -flex c_grey ml15" id="time-consuming">耗时0 天 3 小时 11 分钟 57 秒 </span>*/
render() { render() {
const { onRunCodeTest, onShowPrevStage, onShowNextStage, gameBuilding const { onRunCodeTest, onShowPrevStage, onShowNextStage, gameBuilding
, game, classes, st, shixun, record, challenge, time_limit, real_time_limit } = this.props; , game, classes, st, shixun, record, challenge, time_limit, real_time_limit } = this.props;
return (
<div className="-flex -layout-h" id="game_operate_action"> console.log(shixun)
<style>{` return (
#game_operate_action { <div className="-flex -layout-h" id="game_operate_action">
width: 100%; <style>{`
} #game_operate_action {
.time_limit { width: 100%;
margin-right: 0px; }
} .time_limit {
.spliter { margin-right: 0px;
border-right: 1px solid; }
padding-right: 8px; .spliter {
margin-right: 8px; border-right: 1px solid;
height: 14px; padding-right: 8px;
display: inline-block; margin-right: 8px;
position: relative; height: 14px;
top: 3px; display: inline-block;
} position: relative;
#time-consuming { top: 3px;
flex: auto; }
overflow: hidden; #time-consuming {
white-space: nowrap; flex: auto;
} overflow: hidden;
#game_operate_action .act_btn { white-space: nowrap;
flex: 0 0 90px; }
} #game_operate_action .act_btn {
`}</style> flex: 0 0 90px;
<span className="mt10 -flex c_grey ml15" id="time-consuming"> }
{!!time_limit && `}</style>
<span className="time_limit">{`本关最大执行时间:${real_time_limit}`} <span className="mt10 -flex c_grey ml15" id="time-consuming">
{!gameBuilding && record && <span className="spliter"></span>} {!!time_limit &&
</span>} <span className="time_limit">{`本关最大执行时间:${real_time_limit}`}
{!gameBuilding && record ? {!gameBuilding && record && <span className="spliter"></span>}
// <Tooltip title={ "本次评测耗时(编译、运行总时间)" }></Tooltip> </span>}
<span>本次评测耗时(编译运行总时间){ record } </span> {!gameBuilding && record ?
// <Tooltip title={ "本次评测耗时(编译、运行总时间)" }></Tooltip>
: ""} <span>本次评测耗时(编译运行总时间){ record } </span>
</span>
: ""}
{/*将第一个按钮改为visibility方式隐藏不然加载时测评按钮会出现没有垂直居中的情况*/} </span>
<Tooltip title={ "倒计时为0时服务将被关闭" }>
<Button size="small" className={classes.button + ' actionViewfirstButton'} onClick={()=>this.showWebDisplay(challenge)} {/*将第一个按钮改为visibility方式隐藏不然加载时测评按钮会出现没有垂直居中的情况*/}
style={{ visibility: challenge.showWebDisplayButton ? '': 'hidden', <Tooltip title={ "倒计时为0时服务将被关闭" }>
minWidth: challenge.showWebDisplayButton ? '': '1px', <Button size="small" className={classes.button + ' actionViewfirstButton'} onClick={()=>this.showWebDisplay(challenge)}
width: challenge.showWebDisplayButton ? '': '1px', style={{ visibility: challenge.showWebDisplayButton ? '': 'hidden',
flex: `0 0 ${challenge.showWebDisplayButton ? '110px': '1px'}` minWidth: challenge.showWebDisplayButton ? '': '1px',
}} width: challenge.showWebDisplayButton ? '': '1px',
id="showWebDisplayButton" flex: `0 0 ${challenge.showWebDisplayButton ? '110px': '1px'}`
// style={{ display: challenge.showWebDisplayButton ? 'flex': 'none'}} }}
> id="showWebDisplayButton"
查看效果 // style={{ display: challenge.showWebDisplayButton ? 'flex': 'none'}}
</Button> >
</Tooltip> 查看效果
</Button>
{ </Tooltip>
!gameBuilding &&
(game && !!game.prev_game) ? {
<Link to={`/tasks/${game.prev_game}`} className={classes.buttonText + ' act_btn'}> !gameBuilding &&
<Button size="small" className={classes.button}> (game && !!game.prev_game) ?
上一关 <Link to={`/tasks/${game.prev_game}`} className={classes.buttonText + ' act_btn'}>
</Button> <Button size="small" className={classes.button}>
</Link> 上一关
: ''} </Button>
</Link>
{/*未发布的都能跳转*/} : ''}
{ !gameBuilding &&
((game && (game.status === 2 || shixun.status < 2) || shixun && shixun.task_pass ) && !!game.next_game) ? {/*未发布的都能跳转*/}
<Link to={`/tasks/${game.next_game}`} className={classes.buttonText + ' act_btn'}> { !gameBuilding &&
<Button size="small" className={classes.button}> ((game && (game.status === 2 || shixun.status < 2) || shixun && shixun.task_pass ) && !!game.next_game) ?
下一关 <Link to={`/tasks/${game.next_game}`} className={classes.buttonText + ' act_btn'}>
</Button> <Button size="small" className={classes.button}>
</Link> 下一关
: ''} </Button>
</Link>
: ''}
<div id="code_test" className="act_btn">
{
st === 1 && game.status === 2 ? {(shixun&&shixun.vnc || shixun&&shixun.vnc_evaluate) && <div id="code_test" className="act_btn">
<Tooltip title={ "已通关的选择题任务无法再次测评" }> {
<a href="javascript:void(0)" className="shixun-task-btn mr15 gray " st === 1 && game.status === 2 ?
> <Tooltip title={ "已通关的选择题任务无法再次测评" }>
<i className="fa fa-play-circle font-16"></i> <a href="javascript:void(0)" className="shixun-task-btn mr15 gray "
测评 >
</a> <i className="fa fa-play-circle font-16"></i>
</Tooltip> 测评
: </a>
gameBuilding ? </Tooltip>
:
<a href="javascript:void(0)" className="shixun-task-btn mr15 gray " gameBuilding ?
>
<i className="fa fa-play-circle font-16"></i> <a href="javascript:void(0)" className="shixun-task-btn mr15 gray "
测评 >
</a> <i className="fa fa-play-circle font-16"></i>
: 测评
<a href="javascript:void(0)" className="shixun-task-btn mr15 " </a>
onClick={onRunCodeTest}> :
<i className="fa fa-play-circle font-16"></i> <a href="javascript:void(0)" className="shixun-task-btn mr15 "
测评 onClick={onRunCodeTest}>
</a>} <i className="fa fa-play-circle font-16"></i>
</div> 测评
</div> </a>}
); </div>}
/* </div>
<a href="/shixuns/8arufxzl" id="exit_shixun" className="shixun-task-btn task-newbtn-grey mt8 mr15">离开</a> );
/*
<a href="javascript:void(0)" className="shixun-task-btn task-btn-blue mr15 mt8" id="prev_step" <a href="/shixuns/8arufxzl" id="exit_shixun" className="shixun-task-btn task-newbtn-grey mt8 mr15">离开</a>
onClick={onShowNextStage}>下一关 </a>
<a href="javascript:void(0)" className="shixun-task-btn task-btn-blue mr15 mt8" id="prev_step"
onclick="training_task_submmit();" onClick={onShowNextStage}>下一关 </a>
onclick="training_task_submmit();"
{game && !!game.prev_game ?
<div id="prev_step_area">
<Link to={`/tasks/${game.prev_game}`} className="shixun-task-btn task-btn-blue mr15 mt8">上一关</Link> {game && !!game.prev_game ?
</div> <div id="prev_step_area">
: ''} <Link to={`/tasks/${game.prev_game}`} className="shixun-task-btn task-btn-blue mr15 mt8">上一关</Link>
</div>
{game && !!game.next_game ? : ''}
<div id="next_step_area">
<Link to={`/tasks/${game.next_game}`} className="shixun-task-btn task-btn-blue mr15 mt8">下一关</Link> {game && !!game.next_game ?
</div> <div id="next_step_area">
: ''} <Link to={`/tasks/${game.next_game}`} className="shixun-task-btn task-btn-blue mr15 mt8">下一关</Link>
*/ </div>
} : ''}
} */
}
export default withStyles(styles)( ActionView ); }
export default withStyles(styles)( ActionView );

@ -1,309 +1,312 @@
import React, { Component } from 'react'; import React, { Component } from 'react';
import CodeRepositoryView from './CodeRepositoryView' import CodeRepositoryView from './CodeRepositoryView'
import axios from 'axios' import axios from 'axios'
import './CodeRepositoryView.css' import './CodeRepositoryView.css'
// 自己处理path加上父节点的path, 这里是处理树节点了所以是set key // 自己处理path加上父节点的path, 这里是处理树节点了所以是set key
function addPrePath(treeData, parentNodePath) { function addPrePath(treeData, parentNodePath) {
return treeData.map(item => { return treeData.map(item => {
return { return {
...item, ...item,
key: `${parentNodePath}/${item.name}` key: `${parentNodePath}/${item.name}`
} }
}) })
} }
function getNewTreeData(treeData, curKey, child, level) { function getNewTreeData(treeData, curKey, child, level) {
const loop = (data) => { const loop = (data) => {
data.forEach((item) => { data.forEach((item) => {
// 这里不能用indexOf 同一级可能出现test目录和test.py文件 // 这里不能用indexOf 同一级可能出现test目录和test.py文件
if (item.key == curKey) { if (item.key == curKey) {
child = addPrePath(child, curKey); child = addPrePath(child, curKey);
item.children = child; item.children = child;
} else { } else {
if (item.children) { if (item.children) {
loop(item.children); loop(item.children);
} }
} }
}); });
}; };
loop(treeData); loop(treeData);
} }
function fileData2TreeData(repoFilesData) { function fileData2TreeData(repoFilesData) {
const fileTreeData = []; if(repoFilesData!=null){
repoFilesData.forEach((item) => { const fileTreeData = [];
if (item.kind === 'file') { repoFilesData.forEach((item) => {
fileTreeData.push({ if (item.kind === 'file') {
key: item.path, fileTreeData.push({
name: item.name, key: item.path,
isLeaf: true name: item.name,
}) isLeaf: true
} else { })
fileTreeData.push({ } else {
key: item.path, fileTreeData.push({
name: item.name, key: item.path,
// isLeaf: false name: item.name,
}) // isLeaf: false
} })
}) }
return fileTreeData; })
} return fileTreeData;
}
class CodeRepositoryViewContainer extends Component {
}
constructor(props) {
super(props) class CodeRepositoryViewContainer extends Component {
this.showFilesDrawer = this.showFilesDrawer.bind(this) constructor(props) {
this.onRepositoryViewExpand = this.onRepositoryViewExpand.bind(this) super(props)
this.state = { this.showFilesDrawer = this.showFilesDrawer.bind(this)
drawerOpen: false, this.onRepositoryViewExpand = this.onRepositoryViewExpand.bind(this)
loadingFirstRepoFiles: false,
fileTreeData: "", this.state = {
fileTreeSelectedKeys: [], drawerOpen: false,
codeRepositoryViewExpanded: false, loadingFirstRepoFiles: false,
tabIndex: 0, fileTreeData: "",
fileTreeSelectedKeys: [],
settingDrawerOpen: false codeRepositoryViewExpanded: false,
} tabIndex: 0,
}
showSettingDrawer = (open) => { settingDrawerOpen: false
this.setState({settingDrawerOpen: open}) }
} }
tabIndexChange = (index) => { showSettingDrawer = (open) => {
this.setState({tabIndex: index}); this.setState({settingDrawerOpen: open})
} }
onRepositoryViewExpand() { tabIndexChange = (index) => {
window.repository_extend_and_zoom(); this.setState({tabIndex: index});
this.setState({ }
evaluateViewExpanded: !this.state.evaluateViewExpanded onRepositoryViewExpand() {
}, () => { window.repository_extend_and_zoom();
setTimeout(()=>{ this.setState({
window.__tpiOnResize() evaluateViewExpanded: !this.state.evaluateViewExpanded
}, 300) }, () => {
}) setTimeout(()=>{
} window.__tpiOnResize()
}, 300)
showFilesDrawer(open) { })
if (this.props.loading === true) { }
return;
} showFilesDrawer(open) {
if (!this.state.fileTreeData) { if (this.props.loading === true) {
this.fetchRepoFiles(); return;
} }
if (!this.state.fileTreeData) {
this.setState({ this.fetchRepoFiles();
drawerOpen: open, }
})
} this.setState({
loadRepoFiles = () => { drawerOpen: open,
if (!this.state.fileTreeData) { })
this.fetchRepoFiles(); }
} loadRepoFiles = () => {
} if (!this.state.fileTreeData) {
this.fetchRepoFiles();
componentWillReceiveProps(newProps, oldProps) { }
}
}
componentDidMount() { componentWillReceiveProps(newProps, oldProps) {
} }
componentDidMount() {
componentDidUpdate(prevProps, prevState, snapshot) {
const { game, challenge } = this.props }
if (this.props.game && (!prevProps.game || prevProps.game.identifier !== this.props.game.identifier) ) {
this.setState({ componentDidUpdate(prevProps, prevState, snapshot) {
fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ] const { game, challenge } = this.props
}) if (this.props.game && (!prevProps.game || prevProps.game.identifier !== this.props.game.identifier) ) {
// 初始化 this.setState({
} else if (this.state.fileTreeSelectedKeys.length === 0 && challenge && challenge.path) { fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ]
this.setState({ })
fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ] // 初始化
}) } else if (this.state.fileTreeSelectedKeys.length === 0 && challenge && challenge.path) {
} else if (challenge && prevProps && prevProps.challenge this.setState({
&& challenge.pathIndex != prevProps.challenge.pathIndex fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[0] : challenge.path ]
&& challenge.pathIndex !== -1) { })
this.setState({ } else if (challenge && prevProps && prevProps.challenge
fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[challenge.pathIndex] : challenge.path ] && challenge.pathIndex != prevProps.challenge.pathIndex
}) && challenge.pathIndex !== -1) {
} this.setState({
} fileTreeSelectedKeys: [ challenge.multiPath ? challenge.path[challenge.pathIndex] : challenge.path ]
})
handleDialogClose() { }
this.setState({ }
dialogOpen: false
}) handleDialogClose() {
} this.setState({
onLoadData = (treeNode) => { dialogOpen: false
if (treeNode.props.children && treeNode.props.children.length) { })
return new Promise((resolve) => { }
resolve(); onLoadData = (treeNode) => {
}); if (treeNode.props.children && treeNode.props.children.length) {
} return new Promise((resolve) => {
return new Promise((resolve, reject) => { resolve();
this.fetchRepoFiles(treeNode, resolve, reject) });
}); }
} return new Promise((resolve, reject) => {
map2OldData = (treeData) => { this.fetchRepoFiles(treeNode, resolve, reject)
if (!treeData || treeData.length === 0) return treeData; });
treeData = treeData.map(item => { }
return { map2OldData = (treeData) => {
kind: item.type == "blob" ? "file" : "dir", // blob->file tree->dir if (!treeData || treeData.length === 0) return treeData;
path: item.name, treeData = treeData.map(item => {
name: item.name return {
} kind: item.type == "blob" ? "file" : "dir", // blob->file tree->dir
}) path: item.name,
return treeData; name: item.name
} }
})
fetchRepoFiles(treeNode, resolve, reject) { return treeData;
// http://localhost:3000/api/v1/games/829al3mst4fy/entries?path=src/step1&rev=master }
if (!this.props.challenge || !this.props.game) {
return; fetchRepoFiles(treeNode, resolve, reject) {
} // http://localhost:3000/api/v1/games/829al3mst4fy/entries?path=src/step1&rev=master
// var ar = this.props.challenge.path.split('/'); if (!this.props.challenge || !this.props.game) {
// ar.length = ar.length - 2; return;
// var _path = ar.join('/'); }
var _path = treeNode ? treeNode.props.eventKey : '' ; // var ar = this.props.challenge.path.split('/');
if (_path.charAt(0) === '/') { // ar.length = ar.length - 2;
_path = _path.substring(1) // var _path = ar.join('/');
} var _path = treeNode ? treeNode.props.eventKey : '' ;
// var url = `/api/v1/games/${this.props.game.identifier}/entries?path=${_path}&rev=master&gpid=${this.props.myshixun.gpid}` if (_path.charAt(0) === '/') {
let url = `/myshixuns/${this.props.myshixun.identifier}/repository.json` _path = _path.substring(1)
}
// var url = `/api/v1/games/${this.props.game.identifier}/entries?path=${_path}&rev=master&gpid=${this.props.myshixun.gpid}`
if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) { let url = `/myshixuns/${this.props.myshixun.identifier}/repository.json`
this.setState({
loadingFirstRepoFiles: true,
}) if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) {
} this.setState({
var that = this; loadingFirstRepoFiles: true,
axios.post(url, { })
path: _path }
// withCredentials: true, var that = this;
}) axios.post(url, {
.then((response) => { path: _path
const repoFilesData = this.map2OldData(response.data.trees) // withCredentials: true,
if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) { // 还没树节点,没加载过 })
.then((response) => {
const fileTreeData = fileData2TreeData(repoFilesData) const repoFilesData = this.map2OldData(response.data.trees)
this.setState({ if (!this.state.fileTreeData || this.state.fileTreeData.length === 0) { // 还没树节点,没加载过
fileTreeData,
loadingFirstRepoFiles: false, const fileTreeData = fileData2TreeData(repoFilesData)
}); this.setState({
} else { fileTreeData,
var _treeNode = treeNode; loadingFirstRepoFiles: false,
var _eventKey = _treeNode.props.eventKey; });
} else {
const fileTreeData = that.state.fileTreeData; var _treeNode = treeNode;
// 新的数组放置到treenode下 var _eventKey = _treeNode.props.eventKey;
const tempFileTreeData = fileData2TreeData(repoFilesData) const fileTreeData = that.state.fileTreeData;
// 新的数组放置到treenode下
getNewTreeData(fileTreeData, _eventKey, tempFileTreeData, 2);
this.setState({ const tempFileTreeData = fileData2TreeData(repoFilesData)
fileTreeData,
}) getNewTreeData(fileTreeData, _eventKey, tempFileTreeData, 2);
} this.setState({
fileTreeData,
resolve && resolve(); })
}
})
.catch(function (error) { resolve && resolve();
console.log(error);
reject && reject(); })
}); .catch(function (error) {
} console.log(error);
onTreeSelect = (selectedKeys, info) => { reject && reject();
const isLeaf = info.node.props.isLeaf; });
if (isLeaf) { // 叶子节点 }
selectedKeys.length && this.setState({ onTreeSelect = (selectedKeys, info) => {
fileTreeSelectedKeys: selectedKeys const isLeaf = info.node.props.isLeaf;
}) if (isLeaf) { // 叶子节点
const { fetchRepositoryCode, onPathChange, showSnackbar, challenge } = this.props; selectedKeys.length && this.setState({
fileTreeSelectedKeys: selectedKeys
const nodePath = info.node.props.eventKey; })
// 设置pathIndex为-1那么代码文件下拉可以切回可编辑的文件 const { fetchRepositoryCode, onPathChange, showSnackbar, challenge } = this.props;
if (!challenge.multiPath) { // 单path任务 多path任务 path是数组
if (challenge.path.trim() == nodePath.trim()) { const nodePath = info.node.props.eventKey;
if (challenge.pathIndex === 0) { // 设置pathIndex为-1那么代码文件下拉可以切回可编辑的文件
showSnackbar(`当前编辑文件已经是${nodePath}`) if (!challenge.multiPath) { // 单path任务 多path任务 path是数组
} else { if (challenge.path.trim() == nodePath.trim()) {
onPathChange(0) if (challenge.pathIndex === 0) {
} showSnackbar(`当前编辑文件已经是${nodePath}`)
return; } else {
} else { onPathChange(0)
onPathChange(-1) }
} return;
} else { } else {
let isCurrentFile = false; onPathChange(-1)
let cur_index = -1; }
if (challenge.path && challenge.path.forEach) { } else {
challenge.path.forEach((item, index) => { let isCurrentFile = false;
if (nodePath == item) { let cur_index = -1;
isCurrentFile = true; if (challenge.path && challenge.path.forEach) {
cur_index = index; challenge.path.forEach((item, index) => {
} if (nodePath == item) {
}) isCurrentFile = true;
} cur_index = index;
if (isCurrentFile) { }
onPathChange(cur_index) })
showSnackbar(`当前编辑文件已经是${nodePath}`) }
} else { if (isCurrentFile) {
onPathChange(-1) onPathChange(cur_index)
} showSnackbar(`当前编辑文件已经是${nodePath}`)
} } else {
if (nodePath) { onPathChange(-1)
const filetype = nodePath.split('.').pop().toLowerCase(); }
if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg' }
|| filetype == 'jar' if (nodePath) {
|| filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') { const filetype = nodePath.split('.').pop().toLowerCase();
showSnackbar(`不支持加载${filetype}类型的文件。`) if (filetype == 'jpg' || filetype == 'png' || filetype == 'gif' || filetype == 'jpeg'
return; || filetype == 'jar'
} || filetype == 'doc' || filetype == 'pdf' || filetype == 'xsl' || filetype == 'ppt') {
fetchRepositoryCode(null, nodePath, 1); showSnackbar(`不支持加载${filetype}类型的文件。`)
} else { return;
console.error('no eventKey:', info.node) }
} fetchRepositoryCode(null, nodePath, 1);
} } else {
} console.error('no eventKey:', info.node)
// /shixuns/mnf6b7z3/shixun_discuss?challenge_id=88 }
render() { }
}
return ( // /shixuns/mnf6b7z3/shixun_discuss?challenge_id=88
<React.Fragment> render() {
{this.props.isOnlyContainer == true ?
React.Children.map(this.props.children, child => { return (
if(!child) { <React.Fragment>
return '' {this.props.isOnlyContainer == true ?
} React.Children.map(this.props.children, child => {
return React.cloneElement(child, Object.assign({...this.state}, { if(!child) {
loadRepoFiles: this.loadRepoFiles, return ''
onTreeSelect: this.onTreeSelect, }
onLoadData: this.onLoadData, return React.cloneElement(child, Object.assign({...this.state}, {
})) loadRepoFiles: this.loadRepoFiles,
}) onTreeSelect: this.onTreeSelect,
onLoadData: this.onLoadData,
: }))
})
<CodeRepositoryView {...this.props}
{...this.state} :
showFilesDrawer={this.showFilesDrawer}
loadRepoFiles={this.loadRepoFiles} <CodeRepositoryView {...this.props}
onLoadData={this.onLoadData} {...this.state}
onTreeSelect={ this.onTreeSelect } showFilesDrawer={this.showFilesDrawer}
onRepositoryViewExpand={this.onRepositoryViewExpand} loadRepoFiles={this.loadRepoFiles}
tabIndexChange={this.tabIndexChange} onLoadData={this.onLoadData}
showSettingDrawer={this.showSettingDrawer} onTreeSelect={ this.onTreeSelect }
></CodeRepositoryView> } onRepositoryViewExpand={this.onRepositoryViewExpand}
</React.Fragment> tabIndexChange={this.tabIndexChange}
); showSettingDrawer={this.showSettingDrawer}
} ></CodeRepositoryView> }
} </React.Fragment>
);
export default CodeRepositoryViewContainer; }
}
export default CodeRepositoryViewContainer;

@ -1653,8 +1653,6 @@ export default class TPMsettings extends Component {
// onMouseEnter={operateauthority?this.bigopen:""} // onMouseEnter={operateauthority?this.bigopen:""}
onSelect={operateauthority?this.bigopens:""} onSelect={operateauthority?this.bigopens:""}
// open={opers} // open={opers}
showSearch
optionFilterProp="children" optionFilterProp="children"
filterOption={(input, option) => filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0 option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0

@ -84,36 +84,33 @@ class InfosTopics extends Component{
if(user_id===undefined){ if(user_id===undefined){
user_id=this.props.match.params&&this.props.match.params.username; user_id=1
} }
if(user_id!=undefined){
let {per_page}=this.state;
let url=`/users/${user_id}/question_banks.json`;
axios.get(encodeURI(url),{params:{
type,
object_type:category,
course_list_id,
sort_by,
sort_direction,
page,
per_page
}
}).then((response) => {
this.setState({
data:response.data,
checkBoxValues:[],
isSpin:false
})
}).catch((error) => {
this.setState({
isSpin:false
})
});
}
let {per_page}=this.state;
let url=`/users/${user_id}/question_banks.json`;
axios.get(encodeURI(url),{params:{
type,
object_type:category,
course_list_id,
sort_by,
sort_direction,
page,
per_page
}
}).then((response) => {
this.setState({
data:response.data,
checkBoxValues:[],
isSpin:false
})
}).catch((error) => {
this.setState({
isSpin:false
})
});
} }

Loading…
Cancel
Save