私密版本库

dev_cs
hjm 5 years ago
parent fd502d2142
commit a83dfb9f9e

@ -190,6 +190,8 @@ class TPMIndex extends Component {
identity: response.data.identity,
propaedeutics:response.data.propaedeutics,
status: response.data.shixun_status,
secret_repository: response.data.secret_repository,
});
}
}).catch((error) => {
@ -300,6 +302,11 @@ class TPMIndex extends Component {
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props}
/>)
}></Route>
<Route path="/shixuns/:shixunId/secret_repository" render={
(props) => (<TPMRepositoryComponent {...this.props} {...this.state} {...props} secret_repository={true}
/>)
}></Route>
{/* <Route exact path="/shixuns/:shixunId/propaedeutics" component={TPMPropaedeuticsComponent}></Route> */}
<Route exact path="/shixuns/:shixunId/propaedeutics" render={

@ -11,6 +11,8 @@ import Repository from './shixunchild/Repository/Repository'
import TPMRightSection from './component/TPMRightSection'
import TPMNav from './component/TPMNav'
import RepositoryChooseModal from './component/modal/RepositoryChooseModal'
class TPMRepository extends Component {
constructor(props) {
super(props)
@ -34,6 +36,7 @@ class TPMRepository extends Component {
shixun={shixun}
{...this.props}
></TPMNav>
{/* <RepositoryChooseModal {...this.props}></RepositoryChooseModal> */}
{ loadingContent ?
<CircularProgress size={40} thickness={3} style={{ marginLeft: 'auto', marginRight: 'auto', marginTop: '200px', display: 'block' }}/> :
<Repository

@ -30,6 +30,12 @@ class TPMRepositoryComponent extends Component {
isContentWidth100: this._isFileInPathArray(pathArray)
}
}
componentDidUpdate(prevProps, prevState) {
if (this.props.secret_repository != prevProps.secret_repository) {
this.fetchRepo()
}
}
componentDidMount = () => {
this.fetchRepo()
@ -72,7 +78,8 @@ class TPMRepositoryComponent extends Component {
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/file_content.json`;
axios.post(url, {
path: path
path: path,
secret_repository: this.props.secret_repository
}).then((response) => {
trace_collapse('repository res: ', response)
@ -138,7 +145,7 @@ class TPMRepositoryComponent extends Component {
const path = urlNewPathArray.join('/')
let id = this.props.match.params.shixunId;
let url = `/shixuns/${id}/repository.json`;
let url = `/shixuns/${id}/${this.props.secret_repository ? 'secret_repository' : 'repository'}.json`;
// this.props.setLoadingContent(true)
axios.post(url, {
path: path ? path : ''

@ -353,6 +353,8 @@ export default class TPMsettings extends Component {
test_set_permission: response.data.shixun.test_set_permission,
hide_code: response.data.shixun.hide_code,
code_hidden: response.data.shixun.code_hidden,
is_secret_repository: response.data.shixun.is_secret_repository,
init_is_secret_repository: response.data.shixun.is_secret_repository,
forbid_copy: response.data.shixun.forbid_copy,
vnc: response.data.shixun.vnc,
vnc_evaluate: response.data.shixun.vnc_evaluate,
@ -439,20 +441,52 @@ export default class TPMsettings extends Component {
SelectshixunCommand=(e)=>{
// console.log( e.target.value)
this.setState({
webssh: e.target.value,
});
if(e.target.value===2){
this.setState({
SelectTheCommandtype: true,
multi_webssh:false
});
}else{
this.setState({
SelectTheCommandtype: false,
multi_webssh:false
});
}
const webssh = e.target.value
if (webssh == 2) {
this.setState({
webssh: webssh,
SelectTheCommandtype: true,
multi_webssh:false
});
} else {
if (this.state.init_is_secret_repository && !this.state.vnc) {
this.confirmDeleteSecretRepo({
onOk: () => {
this.setState({
webssh: webssh,
SelectTheCommandtype: false,
multi_webssh:false
});
}
})
} else {
if (!this.state.vnc) {
this.setState({
is_secret_repository: false,
})
}
this.setState({
webssh: webssh,
SelectTheCommandtype: false,
multi_webssh:false
});
}
}
// this.setState({
// webssh: webssh,
// });
// if(webssh===2){
// this.setState({
// SelectTheCommandtype: true,
// multi_webssh:false
// });
// }else{
// this.setState({
// SelectTheCommandtype: false,
// multi_webssh:false
// });
// }
}
SelectOpenpublic=(e)=>{
@ -525,6 +559,35 @@ export default class TPMsettings extends Component {
});
}
confirmDeleteSecretRepo = ({title, onOk}) => {
confirm({
title: title || <div>
<div>已创建的私密版本库及其内容将在保存时被删除</div>
<div>是否确认取消勾选</div>
</div>,
okText: '确定',
cancelText: '取消',
onOk: () => {
this.setState({ is_secret_repository: false })
onOk && onOk()
},
onCancel() {
},
});
}
is_secret_repository = (e) => {
const checked = e.target.checked
if (!checked) {
if (this.state.init_is_secret_repository) {
this.confirmDeleteSecretRepo({
})
} else {
this.setState({ is_secret_repository: false })
}
} else {
this.setState({ is_secret_repository: true })
}
}
forbid_copy = (e) => {
let sum = ""
if (e.target.checked === false) {
@ -550,11 +613,34 @@ export default class TPMsettings extends Component {
// } else if (e.target.checked === true) {
// sum = 1
// }
this.setState({
vnc: e.target.checked,
vnc_evaluate: false,
});
const vnc = e.target.checked;
if (!vnc) {
if (this.state.init_is_secret_repository && this.state.webssh != 2) {
this.confirmDeleteSecretRepo({
onOk: () => {
this.setState({
vnc: e.target.checked,
vnc_evaluate: false,
});
}
})
} else {
if (this.state.webssh != 2) {
this.setState({
is_secret_repository: false
})
}
this.setState({
vnc: e.target.checked,
vnc_evaluate: false,
});
}
} else {
this.setState({
vnc: e.target.checked,
vnc_evaluate: false,
});
}
}
shixunsname = (e) => {
// let {shixunsstatus}=this.state;
@ -782,7 +868,7 @@ export default class TPMsettings extends Component {
let {
name, choice_main_type, choice_small_type, choice_standard_scripts, scope_partment, choice_standard_scriptssum, vnc_evaluate,
evaluate_script, webssh, use_scope, trainee, can_copy, task_pass, test_set_permission, hide_code, code_hidden, forbid_copy, vnc,multi_webssh,
opening_time,shixunmemoMDvalue,shixun_service_configlist
opening_time,shixunmemoMDvalue,shixun_service_configlist, is_secret_repository
} = this.state;
let newshixun_service_configlist = shixun_service_configlist.map(v => {
@ -886,6 +972,7 @@ export default class TPMsettings extends Component {
let Url = `/shixuns/` + id + `.json`;
let data = {
shixun:{
name: name,
webssh: webssh,
use_scope: use_scope,
@ -906,6 +993,7 @@ export default class TPMsettings extends Component {
description: description_editormd,
evaluate_script: evaluate_script_editormd,
},
is_secret_repository: is_secret_repository,
main_type: choice_main_type,
small_type: choice_small_type,
scope_partment: scope_partment,
@ -1460,6 +1548,7 @@ export default class TPMsettings extends Component {
name,
settingsData,
webssh,
is_secret_repository,
use_scope,
shixunsID,
can_copy,
@ -2199,6 +2288,15 @@ export default class TPMsettings extends Component {
</span>
</div>
{ (vnc || webssh == 2) && <div className="clearfix mt20 ml30">
<span className="color-grey-6 mt5 fl" style={{minWidth: '95px'}}>私密版本库:</span>
<span className="fl mt5">
<Checkbox checked={is_secret_repository === undefined ? false : is_secret_repository}
onChange={this.is_secret_repository}></Checkbox>
<label style={{top:'6px'}} className="color-grey-9 ml10" >勾选则启用私密版本库学员页面不能查看该版本库目录</label>
</span>
</div>}
<div className="clearfix mt20 ml30">
<span className="color-grey-6 mt5 fl" style={{minWidth: '95px'}}>禁用复制粘贴:</span>
<span className="fl mt5">
@ -2239,7 +2337,7 @@ export default class TPMsettings extends Component {
<span className="color-grey-6 mt5 fl" style={{minWidth: '95px'}}>VNC图形化评测:</span>
<span className="fl mt5 ml5">
<Checkbox checked={vnc_evaluate === undefined ? false : vnc_evaluate} onChange={this.shixun_vnc_evaluate}></Checkbox>
<label style={{top:'6px'}} className="color-grey-9 ml10" >勾选则在VNC图形化实训中给学员开启评测</label>
<label style={{top:'6px'}} className="color-grey-9 ml10" >勾选则在学员的VNC图形化页面中开启评测功能</label>
</span>
</div>:""}

@ -5,7 +5,7 @@ import { BrowserRouter as Router, Route, Link } from "react-router-dom";
class TPMNav extends Component {
render() {
const { user, match, shixun } = this.props;
const { user, match, shixun, secret_repository } = this.props;
let isAdminOrCreator = false;
if (user) {
isAdminOrCreator = user.admin || user.manager
@ -30,7 +30,10 @@ class TPMNav extends Component {
<Link to={`/shixuns/${shixunId}/repository`}
style={{display: this.props.identity >4||this.props.identity===undefined ? "none" : 'block'}}
className={`${match.url.indexOf('repository') != -1 ? 'active' : ''} fl mr40`}>版本库</Link>
className={`${match.url.indexOf('/repository') != -1 ? 'active' : ''} fl mr40`}>版本库</Link>
{secret_repository && <Link to={`/shixuns/${shixunId}/secret_repository`}
style={{display: this.props.identity >4||this.props.identity===undefined ? "none" : 'block'}}
className={`${match.url.indexOf('secret_repository') != -1 ? 'active' : ''} fl mr40`}>私密版本库</Link>}
<Link to={`/shixuns/${shixunId}/collaborators`}
className={`${match.url.indexOf('collaborators') != -1 ? 'active' : ''} fl mr40`}>合作者</Link>

@ -0,0 +1,148 @@
import React, { useState, useEffect, memo } from 'react';
import axios from 'axios'
import { Modal, Input } from 'antd';
function RepositoryChooseModal(props) {
const [trees, setTrees] = useState([])
const [path, setPath] = useState('')
const [pathArray, setPathArray] = useState([{val: "根目录/", path: ""}])
const [modalVisible, setModalVisible] = useState(true)
useEffect(() => {
repository('')
}, [])
function onOk() {
}
function onCancel() {
}
/**
点nav 会传入key
点item 会传入 newPath
item => name, type type tree/leaf
*/
const repository=(item, key, newPath)=>{
let newPathArray = [] //
//
if (key) {
for(var i=0; i<=key; i++){
newPathArray.push(pathArray[i])
}
} else if (item) {
newPathArray = pathArray.slice(0)
newPathArray.push({val: item.name, path: pathArray[pathArray.length - 1] + "/" + item.name})
}
const path = item || key ? newPathArray[newPathArray.length - 1] : ''
let id = this.props.match.params.shixunId;
let url ="/shixuns/"+id+"/repository.json";
axios.post(url,{
path: path
}).then((response) => {
if (response.data.status === 403||response.data.status === 401||response.data.status === 500) {
}else{
setTrees(response.data.trees)
setPath(path)
pathArray(newPathArray)
}
}).catch((error) => {
console.log(error)
});
}
const savegetfilepath=(value)=>{
let {selectpath,saveshixunfilepath,pathtype} = this.state
if(pathtype===1){
let newselectpath;
if(saveshixunfilepath==="shixunfilepathplay"){
newselectpath=value
}else{
const type = selectpath.split('');
let types=false;
for(var i=0; i<type.length; i++){
if(type[i]===value){
types=true
return
}
}
if(types===false){
newselectpath=selectpath+value+ ""
}else{
newselectpath=selectpath
}
}
this.setState({
// selectpatharr:newarr,
selectpath: newselectpath,
})
}
const goblakepath=(path,key)=>{
}
}
return (
<Modal
keyboard={false}
title="文件路径"
visible={modalVisible}
closable={false}
footer={false}
>
<div className="task_popup_con">
<div className="newupload_conbox clearfix">
<ul id="directory_file">
{/*文件导航*/}
{
pathArray.length===0?"":pathArray.map((item,key)=>{
return(
<a className="f14 fb" onClick={()=>goblakepath(item.path,key,item)}>{item.val}</a>
)
})
}
{/*文件*/}
{trees === undefined || trees === null ? "" : trees.map((item, key) => {
return(
<li className="entry" key={key}>
<div className="filename_no_report hidden">{
item.type==="tree"?<a onClick={()=>sendgetfilepath(item.name,item.type,path+item.name)} data-remote="true">
<i className="iconfont icon-wenjianjia color-blue mr2"></i>
{path+item.name}</a>:<a data-remote="true">
<i className="iconfont icon-zuoye color-blue mr2"></i>
<span onClick={()=>savegetfilepath(path+item.name,item.type)}>{path+item.name}</span>
</a>
}
</div>
</li>
)
})}
</ul>
<div className="clearfix mt20">
<label className="fl mt5 directory_filepath">选中的文件路径</label>
<Input id="points_tusi" placeholder="选中的文件路径" className="fl input-60-40"
style={{width:"400px"}}
onInput={(e)=>this.saveselectpath(e)}
value={path}/>
</div>
<a className="task-btn task-btn-orange fr"
style={{marginTop: '20px',marginLeft:'20px'}} id="add_path" onClick={()=>onOk()}>确定</a>
<a className="pop_close task-btn mb10 fr"
style={{marginTop: '20px'}} id="back_page" onClick={()=>onCancel()}>取消</a>
</div>
</div>
</Modal>
)
}
export default RepositoryChooseModal

@ -15,7 +15,7 @@ import { trace, trace_collapse ,getImageUrl, toPath} from "educoder";
import RepositoryDirectories from './RepositoryDirectories'
import { ActionBtn , NoneData } from 'educoder'
import RepositoryCombinePath from './RepositoryCombinePath'
const $ = window.$;
// 点击按钮复制功能
@ -85,10 +85,13 @@ class Repository extends Component {
className=" guideBtn" >Git使用指南</a>
{
this.props.current_user && (this.props.current_user.admin ==true || (TPMRightSectionData && TPMRightSectionData.creator && TPMRightSectionData.creator.login == this.props.current_user.login)) ?
<ActionBtn style="orangeLine" className="ml20" to={`/shixuns/${match.params.shixunId}/repository/add_file`}>+添加文件</ActionBtn>:""
!this.props.secret_repository &&
<ActionBtn style="orangeLine" className="ml20" to={`/shixuns/${match.params.shixunId}/repository/add_file`}>+添加文件</ActionBtn>
:""
}
<div className="fr font-12 color-grey-9 pr">
<label className="fl mt2">网址克隆</label>
<input type="text" id="copy_rep_content" className="fl url-input mt2"
@ -155,6 +158,10 @@ class Repository extends Component {
</div>
</div>
{this.props.secret_repository && <RepositoryCombinePath {...this.props}>
</RepositoryCombinePath>}
</div>
</div>

@ -121,6 +121,7 @@ class RepositoryCodeEditor extends Component {
const path = pathArray.join('/')
this.setState({ codeSaving: true })
axios.post(url, {
secret_repository: this.props.secret_repository,
content: this.extend_editor.getValue(),
// type: forTest === true ? 1 : 0,
path: path

@ -0,0 +1,82 @@
import React, { Component } from 'react';
import { Redirect } from 'react-router';
import { BrowserRouter as Router, Route, Link, Switch } from "react-router-dom";
import PropTypes from 'prop-types';
import classNames from 'classnames';
import axios from 'axios';
import { trace_collapse, WordsBtn } from 'educoder'
import { message, Input } from 'antd';
const $ = window.$;
class RepositoryCombinePath extends Component {
constructor(props) {
super(props)
this.state = {
value: this.props.secret_dir_path || '',
isEdit: false,
}
}
onSave = () => {
const { shixunId, pathArray } = this.props;
const url = `/shixuns/${shixunId}/set_secret_dir.json`
this.setState({ codeSaving: true })
axios.post(url, {
secret_dir_path: this.state.value
}
).then((response) => {
if (response.data) {
message.success('保存成功');
this.setState({isEdit: false})
}
})
}
onChange = (e) => {
const { value } = e.target;
this.setState({ value })
}
onEdit = () => {
this.setState({isEdit: true}, () => {
window.$('.combinePathEditRow input')[0].focus()
});
}
render() {
const { fileContent, match, saveCode } = this.props;
const { isEdit, value } = this.state;
return (
<div className="df combinePathEditRow">
<style>{`
.combinePathEditRow {
margin: 4px 0;
}
.combinePathEditRow input {
flex: 0 0 300px;
border: none;
}
.combinePathEditRow .wordsBtn {
margin-left: 24px;
}
`}</style>
<span>第一版本库合并路径</span>
<Input disabled={!isEdit} value={value} onChange={this.onChange}></Input>
{!isEdit && <WordsBtn className="wordsBtn" onClick={this.onEdit} style="blue">修改</WordsBtn>}
{isEdit && <WordsBtn className="wordsBtn" onClick={this.onSave} style="blue">保存</WordsBtn>}
</div>
);
}
}
export default RepositoryCombinePath;
Loading…
Cancel
Save