forgeplus-react/src/forge/Main/CoderRootDirectory.js

385 lines
12 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import React , { Component } from 'react';
import {Menu, Spin} from 'antd';
import { getImageUrl , markdownToHTML } from 'educoder';
import { Router , Route , Link } from 'react-router-dom';
import Top from './DetailTop';
import './list.css';
import readme_img from '../Images/book.svg';
import SelectBranch from '../Branch/SelectBranch';
import CloneAddress from '../Branch/CloneAddress';
import RootTable from './RootTable';
import CoderRootFileDetail from './CoderRootFileDetail';
import NullData from './NullData';
import { truncateCommitId } from '../common/util';
import axios from 'axios';
import img_fork from "../Images/fork.png";
/**
* address:http和SSHhttp_url(对应git地址)
* branch:当前分支
* filePath:点击目录时当前目录的路径
* subfileType:保存当前点击目录的文件类型(显示目录列表时才显示新建文件,如果点击的是文件就不显示新建文件按钮)
* readMeContent:根目录下面的readme文件内容
*/
class CoderRootDirectory extends Component{
constructor(props){
super(props);
this.state={
address:"http",
branch:"master",
filePath:undefined,
http_url:undefined,
subFileType:"",
readMeContent:undefined,
readMeFile: undefined,
isSpin:true,
branchList:undefined,
fileDetail:undefined,
branchLastCommit:undefined,
rootList:undefined,
readOnly: true
}
}
changeAddress=(address)=>{
this.setState({
address
})
}
componentDidMount=()=>{
this.Init();
}
componentDidUpdate=(prevState)=>{
const {location} = this.props;
const prevlocation = prevState && prevState.location;
if(location !== prevlocation){
this.setState({
isSpin:true
})
this.Init();
}
}
Init=()=>{
let { search } = this.props.history.location;
let branchName = undefined;
if(search && search.indexOf("branch")>-1){
branchName = search.split("branch=")[1];
this.setState({
branch:branchName
})
}
const { pathname } = this.props.location;
if(pathname && pathname.indexOf("/filesurl/")>-1){
let url =pathname.split("filesurl/")[1];
this.setState({
filePath:url
})
this.getFileDetail(url);
}else{
const { branch } = this.state;
this.getProjectRoot( branchName || branch);
}
}
// 页面地址返回到主目录
returnMain=(branch)=>{
const { projectsId } = this.props.match.params;
this.props.history.push(`/projects/${projectsId}/coders`);
this.getProjectRoot(branch);
}
// 获取根目录
getProjectRoot=(branch)=>{
const { projectsId } = this.props.match.params;
const url = `/repositories/${projectsId}/entries.json`;
axios.get((url),{
params:{
branch
}
}).then((result)=>{
if(result){
if(result && result.data && result.data.length > 0){
this.setState({
filePath:undefined,
fileDetail:undefined,
isSpin: false
})
this.renderData(result.data);
}
this.setState({
rootList:result.data,
subFileType: "dir"
})
}
}).catch((error)=>{})
}
ChangeFile=(arr,readOnly)=>{
const { projectsId } = this.props.match.params;
//点击直接跳转页面 加载一次路由
this.props.history.push(`/projects/${projectsId}/coders/filesurl/${arr.path}`);
this.setState({
subFileType:arr.type,
readOnly: readOnly
})
}
renderUrl=(name,path,type)=>{
let list =[];
const { filePath } = this.state;
if(path.indexOf("/")){
const array = path.split("/");
let str = "";
array.map((i,k)=>{
str += '/'+i;
return list.push({
index:k,
name:i,
path:str.substr(1),
type:(filePath && filePath.length>0) ? (filePath[k] ? filePath[k].type : type) : type
})
})
const { projectsId } = this.props.match.params;
//点击直接跳转页面 加载一次路由
this.props.history.push(`/projects/${projectsId}/coders/filesurl/${str.substr(1)}`);
}else{
list.push({
index:0,
name,path,type
})
}
this.setState({
filePath:list
})
}
// 获取子目录
getFileDetail=(path)=>{
const { projectsId } = this.props.match.params;
const { branch } = this.state;
const url =`/repositories/${projectsId}/sub_entries.json`;
axios.get(url,{
params:{
filepath:path,
ref:branch
}
}).then((result)=>{
if(result && result.data && result.data.length > 0){
// 当前返回的子目录只有一条数据,且这条数据返回的是文件类型
if(result.data.length === 1 && result.data[0].type === "file"){
this.setState({
fileDetail:result.data,
rootList:undefined,
isSpin:false
})
}else{
this.setState({
fileDetail:undefined,
rootList:result.data,
isSpin:false
})
this.renderData(result.data)
}
}
}).catch((error)=>{
console.log(error);
})
}
renderData=(data)=>{
const rootList = [];
const readMeContent = [];
const readMeFile = [];
data && data.map((item,key)=>{
rootList.push({
key,
...item
})
if(item.name === 'README.md'){
readMeContent.push({...item})
readMeFile.push({...item})
}
})
this.setState({
rootList:rootList,
readMeContent,
readMeFile
})
}
// 点击跳转到子目录
goToSubRoot=(path)=>{
const { projectsId } = this.props.match.params;
this.props.history.push(`/projects/${projectsId}/coders/filesurl/${path}`);
}
// readme文件内容
renderReadMeContent=(readMeContent, permission)=>{
const { fileDetail,readMeFile } = this.state;
if(fileDetail){return;}
if(readMeContent && readMeContent.length > 0){
return(
<div className="commonBox">
<div className="commonBox-title">
<span className="mr5"><img src={readme_img} alt="" width="16px"/></span>
<span className="commonBox-title-read">{readMeContent[0].name}</span>
{
permission ?
<a onClick={()=>this.ChangeFile(readMeFile[0],false)} className="ml20 pull-right"><i className="iconfont icon-bianji font-15 color-grey-6"></i></a>
: ""
}
</div>
<div className="commonBox-info">
{
readMeContent[0].content ?
<div className={"markdown-body"} dangerouslySetInnerHTML={{__html: markdownToHTML(readMeContent[0].content).replace(/▁/g, "▁▁▁")}}></div>
:
<span>暂无~</span>
}
</div>
</div>
)
}
}
// 选择分支
changeBranch=(value)=>{
const { branchList } = this.props;
let branchLastCommit = branchList && branchList.length >0 && branchList.filter(item=>item.name === value)[0];
this.setState({
branch:branchLastCommit && branchLastCommit.name,
branchLastCommit,
http_url:branchLastCommit && branchLastCommit.http_url,
isSpin: true
})
this.Init();
}
render(){
const { rootList , branch ,filePath , fileDetail , subFileType , readMeContent, isSpin } = this.state;
const { branchLastCommit , http_url , isManager , isDeveloper } = this.props;
const { projectsId } = this.props.match.params;
const columns = [
{
dataIndex: 'name',
width:"100%",
render: (text,item) => (
<a onClick={()=>this.goToSubRoot(item.path)}>
<i className={ item.type === "file" ? "iconfont icon-zuoye font-15 color-blue mr5":"iconfont icon-wenjian font-15 color-blue mr5"}></i>{text}
</a>
),
}
];
const title = () =>{
if(branchLastCommit && branchLastCommit.last_commit){
return(
<div className="f-wrap-alignCenter">
{
branchLastCommit.author ?
<React.Fragment>
<img src={getImageUrl(`images/${branchLastCommit.author.image_url}`)} className="radius mr10" width="32" height="32" alt=""/>
<span className="mr15">{branchLastCommit.author.login}</span>
</React.Fragment>
:""
}
<span className="color-blue flex-1 hide-1">{branchLastCommit.last_commit.message}</span>
<span className="commitKey">{truncateCommitId(branchLastCommit.last_commit.id)}</span>
<span>{branchLastCommit.last_commit.time_from_now}</span>
</div>
)
}else{
return undefined;
}
}
const downloadUrl = ()=>{
if(branchLastCommit && branchLastCommit.zip_url){
return(
<Menu>
<Menu.Item><a href={branchLastCommit.zip_url}>ZIP</a></Menu.Item>
<Menu.Item><a href={branchLastCommit.tar_url}>TAR.GZ</a></Menu.Item>
</Menu>
)
}
}
const urlRoot = `/${filePath}`;
const { projectDetail } = this.props;
let array = filePath && filePath.split("/");
return(
<Spin spinning={isSpin}>
<div>
<Top { ...this.props } {...this.state} />
<div className="f-wrap-between mt20">
<div className="f-wrap-alignCenter">
<SelectBranch branch={branch} changeBranch={this.changeBranch} {...this.props} {...this.state}></SelectBranch>
{
filePath &&
<span className="ml20 font-16">
<a onClick={()=>this.returnMain(branch)} className="color-blue">{ projectDetail && projectDetail.identifier }</a>
{
array && array.map((item,key)=>{
return(
<React.Fragment>
{
key === array.length-1 ?
<span className="color-grey-6 subFileName" key={key}>{item}</span>
:
key === 0?
<Link to={`/projects/${projectsId}/coders/filesurl/${item}`} className="color-blue subFileName" key={key}>{item}</Link>
:
<Link to={`/projects/${projectsId}/coders/filesurl/${array[key-1]}/${item}`} className="color-blue subFileName" key={key}>{item}</Link>
}
</React.Fragment>
)
})
}
</span>
}
</div>
<div className="f-wrap-alignCenter">
{
subFileType !== "file" && (isManager || isDeveloper) &&
<p className="addFile mr30">
<Link to={`/projects/${projectsId}/coders/${branch}/newfile${urlRoot}`} >新建文件</Link>
</p>
}
{
http_url && <CloneAddress http_url={http_url} downloadUrl={downloadUrl} showNotification={this.props.showNotification}></CloneAddress>
}
</div>
</div>
{/* 主目录列表 */}
{
rootList &&
<RootTable columns = {columns} data={rootList} title={() => title()}></RootTable>
}
{/* 子目录列表、文件 */}
{
fileDetail && fileDetail.length>0 &&
<CoderRootFileDetail detail = {fileDetail[0]} {...this.props} {...this.state} readOnly={this.state.readOnly}></CoderRootFileDetail>
}
{/* readme.txt (isManager || isDeveloper)*/}
{ this.renderReadMeContent(readMeContent,(isManager || isDeveloper)) }
</div>
</Spin>
)
}
}
export default CoderRootDirectory;