forked from Gitlink/forgeplus-react
753 lines
32 KiB
JavaScript
753 lines
32 KiB
JavaScript
import React , { useEffect , useState } from 'react';
|
||
import { Dropdown , Menu , Divider , Spin, Button, Tooltip } from 'antd';
|
||
import { getImageUrl , turnbar , returnbar } from "educoder";
|
||
import { Link } from 'react-router-dom';
|
||
import { connect } from 'react-redux';
|
||
import { truncateCommitId } from "../common/util";
|
||
import CloneAddress from '../Branch/CloneAddress';
|
||
import CheckProfile from '../Component/ProfileModal/Profile';
|
||
import SelectBranch from '../Branch/Select';
|
||
import User from '../Component/User';
|
||
import axios from 'axios';
|
||
import Path from './CoderDepotPath';
|
||
import Catalogue from './CoderDepotCatalogue';
|
||
import ReadMe from './CoderDepotReadme';
|
||
// import CoderRootFileDetail from './CoderRootFileDetail';
|
||
import './Index.scss';
|
||
import Releases from '../Component/Releases';
|
||
import Contributors from '../Component/Contributors';
|
||
import LanguagePower from '../Component/LanguagePower';
|
||
import DrawerPanel from '../Component/DrawerPanel';
|
||
import UpdateDescModal from './sub/UpdateDescModal';
|
||
import Nodata from '../Nodata';
|
||
import Invite from './sub/Invite';
|
||
import RenderHtml from '../../components/render-html';
|
||
import Loadable from 'react-loadable';
|
||
import Loading from '../../Loading';
|
||
import ProjectPortrait from '../Component/projectPortrait';
|
||
import imNoneImg from './img/importNone.png';
|
||
import LicenseModal from '../Component/licenseModal/index';
|
||
import moment from 'moment';
|
||
|
||
const ProjectCompass = Loadable({
|
||
loader: () => import('../Component/projectCompass'),
|
||
loading: Loading,
|
||
})
|
||
|
||
const format = "YYYY-MM-DD HH:mm"
|
||
const CoderRootFileDetail = Loadable({
|
||
loader: () => import("./CoderRootFileDetail"),
|
||
loading: Loading,
|
||
});
|
||
const mangementOperate =["Manager","Admin","Owner"]
|
||
/**
|
||
* projectDetail.type:0是托管项目,1是镜像项目,2是同步镜像项目(为2时不支持在线创建、在线上传、在线修改、在线删除、创建合并请求等功能)
|
||
* project.open_portrait: 是否开启项目画像展示
|
||
*/
|
||
function CoderDepot(props){
|
||
// const [ projectDetail , setProjectDetail ]= useState(undefined);
|
||
let { platform , mirror_status , bannerList , projectDetail, projectEntries, projectReadMe, project } = props ;
|
||
projectDetail = props.defaultDetail || projectDetail || {}
|
||
|
||
const [ inviteCode , setInviteCode ] = useState(projectDetail.invite_code || undefined);
|
||
const [ treeValue , setTreeValue ] = useState(undefined);
|
||
const [ treeValuePath , setTreeValuePath ] = useState(undefined);
|
||
const [ lastCommit,setLastCommit ] = useState((projectEntries.last_commit && projectEntries.last_commit.commit) || undefined);
|
||
const [ lastCommitAuthor,setLastCommitAuthor ] = useState((projectEntries.last_commit && projectEntries.last_commit.author) || undefined);
|
||
const [ type ,setType ] = useState('dir');
|
||
const [ hide , setHide ] = useState(true);
|
||
const [ hideBtn , setHideBtn ] = useState(true);
|
||
const [ commitCount ,setCommitCount ] = useState(projectEntries.commits_count || 0);
|
||
const [ dirInfo ,setDirInfo ] = useState(projectEntries.entries || undefined);//文件夹目录列表
|
||
const [ fileInfo ,setFileInfo ] = useState(undefined);//文件内容信息
|
||
const [ zip_url , setZip_url ] = useState(projectEntries.zip_url || undefined);
|
||
const [ tar_url , setTar_url ] = useState(projectEntries.tar_url || undefined);
|
||
const [ readOnly , setReadOnly] = useState(undefined);
|
||
const [ isSpin , setIsSpin] = useState(false);
|
||
const [ visible ,setVisible ] = useState(false);
|
||
const [ mainFlag ,setMainFlag ] = useState(false);
|
||
const [ openModal , setOpenModal ] = useState(false);
|
||
const [ desc , setDesc ] = useState(projectDetail.description || undefined);
|
||
const [ website , setWebsite ] = useState(projectDetail.website ||undefined);
|
||
const [ lesson_url , setLessonUrl ] = useState(projectDetail.lesson_url || undefined);
|
||
const [ topics, setTopics] = useState(projectDetail.topics || undefined);
|
||
const [ readme , setReadme ] = useState((projectReadMe && JSON.parse(decodeURIComponent(projectReadMe))) || undefined);
|
||
const [ defaultBranch , setDefaultBranch ] = useState(projectDetail.default_branch || undefined);
|
||
const [ editReadme , setEditReadme ] = useState(false);
|
||
const [ pullsFlag , setPullsFlag ] = useState(true);
|
||
const [ issuesFlag , setIssuesFlag ] = useState(true);
|
||
const [ releaseVersions , setReleaseVersions] = useState(undefined);
|
||
const [ licenseVisible ,setLicenseVisible] = useState(false);
|
||
|
||
const owner = props.match.params.owner;
|
||
const projectsId = props.match.params.projectsId;
|
||
let branchName = props.match.params.branchName;
|
||
branchName = returnbar(branchName);
|
||
let pathname = props.history.location.pathname;
|
||
let search = props.history.location.search
|
||
//distribution:判断此用户是否可以创建发行版
|
||
const distribution = projectDetail && ( projectDetail.permission && projectDetail.permission !== "Reporter");
|
||
|
||
useEffect(()=>{
|
||
if(bannerList && bannerList.length>0){
|
||
let a = bannerList.filter(i=>i.menu_name === "pulls");
|
||
let i = bannerList.filter(i=>i.menu_name === "issues");
|
||
if(a && a.length === 0){
|
||
setPullsFlag(false);
|
||
}
|
||
if(i && i.length === 0){
|
||
setIssuesFlag(false);
|
||
}
|
||
}
|
||
},[bannerList])
|
||
|
||
// 埋点
|
||
function eventTrack(path){
|
||
const url = `/users/action.json`;
|
||
|
||
axios.post(url,{
|
||
action_type:"webide",
|
||
action_id:projectDetail && projectDetail.repo_id
|
||
}).then(result=>{});
|
||
window.open(path,"_blank");
|
||
}
|
||
|
||
useEffect(()=>{
|
||
if(projectDetail){
|
||
// setProjectDetail(projectDetail);
|
||
setTopics(projectDetail.topics);
|
||
setDesc(projectDetail.description);
|
||
setWebsite(projectDetail.website);
|
||
setLessonUrl(projectDetail.lesson_url);
|
||
setDefaultBranch(projectDetail.default_branch);
|
||
setInviteCode(projectDetail.invite_code);
|
||
}
|
||
},[projectDetail,mirror_status])
|
||
|
||
useEffect(()=>{
|
||
// 设置网页标题
|
||
if(projectDetail && projectDetail.project_identifier){
|
||
const { author, name, description, default_branch} = projectDetail;
|
||
if(branchName && branchName !== default_branch){
|
||
// 处于某分支/标签
|
||
document.title = `${author.name}/${name}-${branchName} | GitLink`;
|
||
}else{
|
||
document.title = `${author.name}/${name}${description?': '+description:''} | GitLink` ;
|
||
}
|
||
}
|
||
}, [treeValuePath, projectDetail, branchName])
|
||
|
||
useEffect(()=>{
|
||
if(treeValue){
|
||
setTreeValuePath(decodeURIComponent(treeValue).split('/'));
|
||
}else{
|
||
setTreeValuePath(undefined);
|
||
}
|
||
},[treeValue])
|
||
|
||
useEffect(()=>{
|
||
if (projectsId && owner && defaultBranch && mirror_status===0){
|
||
let b = turnbar(branchName) ;
|
||
if(pathname.indexOf(`/${owner}/${projectsId}`) > -1 && pathname.indexOf(`/tree/${b}/`) > -1) {
|
||
let url = pathname.split(`/tree/${b}/`)[1];
|
||
setTreeValue(url);
|
||
getFileInfo(url,branchName);
|
||
setType("file");
|
||
}else{
|
||
setTreeValue(undefined);
|
||
if (!projectEntries) {
|
||
getDirInfo(branchName || defaultBranch);
|
||
}
|
||
setType("dir");
|
||
}
|
||
}
|
||
},[projectsId,owner,pathname,defaultBranch,mirror_status])
|
||
|
||
// 编辑完回来重新获取
|
||
useEffect(()=>{
|
||
let b = turnbar(branchName) ;
|
||
if (projectsId && owner && defaultBranch && mirror_status===0 && !search && pathname.indexOf(`/tree/${b}/`) > -1){
|
||
let url = pathname.split(`/tree/${b}/`)[1];
|
||
getFileInfo(url,branchName);
|
||
}
|
||
},[search])
|
||
|
||
useEffect(()=>{
|
||
if(platform && mirror_status===0){
|
||
setReadOnly(props.history.location.search.indexOf('edit') !== -1);
|
||
axios.get(`/${owner}/${projectsId}/releases.json`).then((result)=>{
|
||
if(result && result.data){
|
||
const release = {
|
||
"list":result.data.releases,
|
||
"total_count":result.data.releases && result.data.releases.length
|
||
}
|
||
setReleaseVersions(release);
|
||
}
|
||
})
|
||
}
|
||
},[platform,mirror_status])
|
||
|
||
// 获取readme信息
|
||
function getReadmeInfo(path, ref) {
|
||
axios.get(`/${owner}/${projectsId}/readme.json`, {
|
||
params:{
|
||
owner: owner,
|
||
repo: projectsId,
|
||
filepath:path,
|
||
ref:ref || branchName
|
||
}
|
||
}).then((result) => {
|
||
if (result) {
|
||
setReadme(result.data);
|
||
} else {
|
||
setReadme(undefined);
|
||
}
|
||
})
|
||
}
|
||
|
||
// 获取主目录列表
|
||
function getDirInfo(branch){
|
||
setIsSpin(true);
|
||
const url = `/${owner}/${projectsId}/entries.json`;
|
||
|
||
axios.get(url, {
|
||
params: { ref:branch}
|
||
}).then((result) => {
|
||
if (result && result.data.status !== 404) {
|
||
setCommitCount(result.data.commits_count);
|
||
setDirInfo(result.data.entries);
|
||
setFileInfo(undefined);
|
||
setTar_url(result.data.tar_url);
|
||
setZip_url(result.data.zip_url);
|
||
let c = result.data.last_commit
|
||
setLastCommit(c && c.commit);
|
||
setLastCommitAuthor(c && c.author);
|
||
setMainFlag(true);
|
||
setReadOnly(true);
|
||
// setReadme(result.data.readme);
|
||
setEditReadme(false);
|
||
setHide(true);
|
||
getReadmeInfo('', branchName || defaultBranch);
|
||
}else{
|
||
// entries接口返回404:分支不存在或被删除
|
||
props.history.push(`/${owner}/${projectsId}`)
|
||
}
|
||
setTimeout(function(){setIsSpin(false);},500);
|
||
}).catch(error=>{setIsSpin(false);})
|
||
}
|
||
|
||
useEffect(()=>{
|
||
if(projectDetail && lastCommit)
|
||
{
|
||
let ele = document.getElementById("ptxt");
|
||
if(ele){
|
||
let h = ele.offsetHeight;
|
||
if( h <= 36 ) setHideBtn(false);
|
||
}
|
||
}
|
||
},[projectDetail,lastCommit])
|
||
// 获取子目录列表
|
||
function getFileInfo(path, ref){
|
||
setIsSpin(true);
|
||
const url = `/${owner}/${projectsId}/sub_entries.json`;
|
||
axios.get(url, {
|
||
params:{
|
||
filepath:returnbar(path),
|
||
ref:ref || branchName,
|
||
type
|
||
}
|
||
}).then((result) => {
|
||
if(result.data.status === -2){
|
||
props.showNotification(result.data.message);
|
||
props.history.push(`/${owner}/${projectsId}/tree/${turnbar(ref || branchName)}`)
|
||
}
|
||
if (result) {
|
||
let en = result.data.entries;
|
||
if(en.type){
|
||
setDirInfo(undefined);
|
||
setFileInfo(en);
|
||
setType(en.type);
|
||
setReadme(undefined);
|
||
}else{
|
||
setFileInfo(undefined);
|
||
setDirInfo(en);
|
||
setType("dir");
|
||
getReadmeInfo(path, branchName || defaultBranch);
|
||
}
|
||
let c = result.data.last_commit
|
||
setLastCommit(c && c.commit);
|
||
setLastCommitAuthor(c && c.author);
|
||
setMainFlag(false);
|
||
setReadOnly(true);
|
||
setReadOnly(!editReadme);
|
||
setHide(true);
|
||
}
|
||
setTimeout(function(){setIsSpin(false);},500)
|
||
}).catch(error=>{setIsSpin(false);})
|
||
}
|
||
|
||
// 切换分支或者标签
|
||
function changeBranch(value){
|
||
let checkvalue = value;
|
||
let u = `/${owner}/${projectsId}${checkvalue && `/tree/${checkvalue}`}${treeValue ? `/${treeValue}`:""}`;
|
||
props.history.push(u);
|
||
}
|
||
|
||
// 文件相关的下拉项
|
||
function fileMenu(){
|
||
let b = branchName || defaultBranch;
|
||
let checkvalue = turnbar(b);
|
||
return (
|
||
<Menu className="fileMenu">
|
||
<Menu.Item>
|
||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/uploadfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>上传文件</CheckProfile>
|
||
</Menu.Item>
|
||
<Menu.Item>
|
||
<CheckProfile {...props} sureFunc={()=>urlLink(`/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`)}>新建文件</CheckProfile>
|
||
</Menu.Item>
|
||
</Menu>
|
||
)
|
||
}
|
||
|
||
|
||
function getPathUrl(array,index){
|
||
if(array && array.length>0 && index){
|
||
let str = "";
|
||
for(let i=0;i<index;i++){
|
||
str += `/${array[i]}`;
|
||
}
|
||
return str.substr(1);
|
||
}
|
||
}
|
||
// 页面地址返回到主目录
|
||
function returnMain(){
|
||
setTreeValue(undefined);
|
||
let branch = branchName || defaultBranch;
|
||
let checkvalue = turnbar(branch);
|
||
props.history.push(`/${owner}/${projectsId}/tree/${checkvalue}`);
|
||
};
|
||
// 子目录路径返回链接
|
||
function returnUlr(url){
|
||
let enBranch = turnbar(branchName);
|
||
setType('dir');
|
||
props.history.push(`/${owner}/${projectsId}/tree${enBranch?`/${enBranch}`:""}/${url}`);
|
||
}
|
||
// 点击跳转到子目录
|
||
function goToSubRoot(path,type,filename){
|
||
if(type!=="submodule"){
|
||
let enBranch = branchName || defaultBranch;
|
||
let checkvalue = turnbar(enBranch);
|
||
let enPath = turnbar(path);
|
||
setType(type);
|
||
window.scrollTo(0,0)
|
||
props.history.push(`/${owner}/${projectsId}${`/tree/${checkvalue}`}${enPath?`/${enPath}`:""}`);
|
||
}
|
||
}
|
||
|
||
function onEdit(readOnly){
|
||
setReadOnly(readOnly);
|
||
setEditReadme(false);
|
||
const {history} = props;
|
||
if(readOnly){
|
||
history.push(history.location.pathname);
|
||
}else{
|
||
history.push(`${history.location.pathname}?edit`);
|
||
}
|
||
}
|
||
function ChangeFile(path, readOnly){
|
||
//点击直接跳转页面 加载一次路由
|
||
let enBranch = branchName || defaultBranch;
|
||
let checkvalue = turnbar(enBranch);
|
||
props.history.push(`/${owner}/${projectsId}/tree/${checkvalue}/${path}?edit`);
|
||
setType("file");
|
||
setEditReadme(true);
|
||
};
|
||
|
||
function changeHide(hide){
|
||
setHide(!hide);
|
||
}
|
||
|
||
function urlLink(link){
|
||
if(props.checkIfLogin()===false){
|
||
props.showLoginDialog()
|
||
return false;
|
||
}
|
||
props.history.push(link);
|
||
}
|
||
|
||
const downloadMenu = (
|
||
<CloneAddress
|
||
http_url={projectDetail && projectDetail.clone_url}
|
||
ssh_url = {(projectDetail && props && props.platform) && projectDetail.ssh_url}
|
||
zip_url={(props && props.platform) && zip_url}
|
||
tar_url={(props && props.platform) && tar_url}
|
||
showNotification={props.showNotification}/>
|
||
)
|
||
// 确认修改简介、website、实践课程链接
|
||
function okUpdate(d,w,l, projectTopicNames){
|
||
const url = `/${owner}/${projectsId}.json`;
|
||
axios.put(url,{
|
||
description:d,website:w || "",lesson_url:l||"",
|
||
project_topic_names: projectTopicNames
|
||
}).then(result=>{
|
||
if(result && result.data && result.data.id){
|
||
setDesc(result.data.description);
|
||
setWebsite(result.data.website);
|
||
setLessonUrl(result.data.lesson_url);
|
||
setTopics(result.data.topics);
|
||
}
|
||
})
|
||
}
|
||
|
||
function createIssue(){
|
||
if(baseOper){
|
||
props.history.push(`/${owner}/${projectsId}/issues/new`);
|
||
}else{
|
||
props.showLoginDialog(`/${owner}/${projectsId}/issues/new`);
|
||
}
|
||
}
|
||
// 创建自定义许可证
|
||
function createDefaultLicense(id){
|
||
if(props.checkIfLogin()===false){
|
||
props.showLoginDialog()
|
||
return false;
|
||
}
|
||
let b = branchName || defaultBranch;
|
||
let checkvalue = turnbar(b);
|
||
props.history.push({pathname:`/${owner}/${projectsId}/${checkvalue}/newfile${treeValue === undefined ? "" : `/${treeValue}`}`,state:`${id}`})
|
||
}
|
||
|
||
// 如果项目是fork的项目,pr自动指向源仓库,否则指向本仓库默认分支
|
||
function compare() {
|
||
if (projectDetail && projectDetail.fork_info) {
|
||
urlLink(`/${projectDetail.fork_info.fork_project_user_login}/${projectDetail.fork_info.fork_project_identifier}/compare/${turnbar(branchName || defaultBranch)}...${owner +'/' + projectsId + ':' + turnbar(branchName || defaultBranch)}`)
|
||
} else {
|
||
urlLink(`/${owner}/${projectsId}/compare/${turnbar(defaultBranch)}...${turnbar(branchName || defaultBranch)}`);
|
||
}
|
||
}
|
||
|
||
let n = fileInfo && fileInfo.name;
|
||
const mdFlag = n && n.substring(n.length-3,n.length) === ".md";
|
||
const { current_user , checkIfLogin , showLoginDialog } = props;
|
||
const baseOper = current_user && current_user.login && issuesFlag;
|
||
const baseOperate = projectDetail && projectDetail.permission && projectDetail.permission !=="Reporter" && projectDetail.type !==2 && pullsFlag && props.platform;
|
||
const fileOperate = type === "dir" && projectDetail && projectDetail.type !==2 && ((projectDetail.permission && projectDetail.permission !=="Reporter") || (current_user && current_user.admin));
|
||
return(
|
||
<div className='WhiteBack'>
|
||
{mirror_status ===0 && <UpdateDescModal desc={desc} website={website} lesson_url={lesson_url} topicsInfo={topics} visible={openModal} onCancel={()=>setOpenModal(false)} onOk={okUpdate}/> }
|
||
<LicenseModal visible={licenseVisible} onCancel={()=>{setLicenseVisible(false)}} createDefaultLicense={createDefaultLicense}/>
|
||
<Spin spinning={isSpin}>
|
||
{
|
||
((dirInfo || fileInfo) && mirror_status===0 ) &&
|
||
<React.Fragment>
|
||
<DrawerPanel
|
||
history={props.history}
|
||
owner={owner}
|
||
projectsId={projectsId}
|
||
name={projectDetail && projectDetail.name}
|
||
branch={branchName || defaultBranch}
|
||
visible={visible}
|
||
onClose={()=>setVisible(false)}
|
||
list = {mainFlag ? dirInfo : undefined}
|
||
/>
|
||
<div className="drawerBtn" onClick={()=>setVisible(true)}>
|
||
<i className="iconfont icon-zuohuaicon font-14"></i>
|
||
<span>目录</span>
|
||
</div>
|
||
</React.Fragment>
|
||
}
|
||
<div style={{minHeight:"500px"}}>
|
||
{
|
||
mirror_status === 2 &&
|
||
<div className='importFailTip'>
|
||
<img src={imNoneImg} alt="" width={290}/>
|
||
{
|
||
projectDetail.permission && mangementOperate.includes(projectDetail.permission) ?
|
||
<div className='failInfo'>
|
||
<p className='font-18 weight500 color-grey-3'>导入项目失败,可能存在以下原因:</p>
|
||
<li>1、导入的仓库 URL 错误。</li>
|
||
<li>2、您需要导入的可能是一个您无权访问的私有仓库,需要输入授权验证仓库的帐号、密码(或者个人令牌),此信息仅用于本次代码同步,不做任何记录。</li>
|
||
<p className='font-18 weight500 color-grey-3'>请前往 <Link className='color-blue' to={`/${owner}/${projectsId}/settings`}>仓库设置</Link> 删除本项目后重新导入!</p>
|
||
</div>
|
||
:
|
||
<p className='font-17 weight500'>导入项目失败,请联系管理员重新导入!</p>
|
||
}
|
||
</div>
|
||
}
|
||
{
|
||
projectDetail && mirror_status === 0 &&
|
||
<div className="Panels Box">
|
||
<div className="LongWidth">
|
||
<div className="panelmenu">
|
||
<div className="FlexAJ">
|
||
<div className="AlignCenter">
|
||
<div className="mr30">
|
||
{
|
||
props && (props.platform && mirror_status ===0) ?
|
||
<SelectBranch
|
||
repo_id={projectDetail && projectDetail.repo_id}
|
||
projectsId={projectsId}
|
||
branch={branchName || defaultBranch}
|
||
changeBranch={changeBranch}
|
||
owner={owner}
|
||
history={props.history}
|
||
branchList={projectDetail && projectDetail.branches && projectDetail.branches.list}
|
||
></SelectBranch>
|
||
:
|
||
<span>分支:<span className="color-grey-6">{branchName || defaultBranch}</span></span>
|
||
}
|
||
</div>
|
||
{
|
||
treeValuePath && treeValuePath.length > 0 ?
|
||
<Path
|
||
identifier={projectDetail && projectDetail.identifier}
|
||
treeValuePath={treeValuePath}
|
||
returnUlr={returnUlr}
|
||
returnMain={returnMain}
|
||
getPathUrl={getPathUrl}
|
||
/>
|
||
:
|
||
<React.Fragment>
|
||
<div className="mr20 AlignCenter">
|
||
{
|
||
props.platform ?
|
||
<Link to={`/${owner}/${projectsId}/branches`} className="iconBtn">
|
||
<i className="iconfont icon-master_icon font-16"></i>
|
||
<span>分支</span>
|
||
<span>{projectDetail && projectDetail.branches_count}</span>
|
||
</Link>
|
||
:
|
||
<span>
|
||
<i className="iconfont icon-master_icon font-16 color-grey-6"></i>
|
||
<span className="ml3 color-grey-6">分支</span>
|
||
<span className="ml3">{projectDetail && projectDetail.branches_count}</span>
|
||
</span>
|
||
}
|
||
</div>
|
||
<div className="mr20 AlignCenter">
|
||
{
|
||
props.platform ?
|
||
<Link to={`/${owner}/${projectsId}/tags`} className="iconBtn">
|
||
<i className="iconfont icon-biaoqianicon font-16"></i>
|
||
<span>标签</span>
|
||
<span>{projectDetail && projectDetail.tags_count}</span>
|
||
</Link>:
|
||
<span>
|
||
<i className="iconfont icon-biaoqianicon font-16 color-grey-6"></i>
|
||
<span className="ml3 color-grey-6">标签</span>
|
||
<span className="ml3">{projectDetail && projectDetail.tags_count}</span>
|
||
</span>
|
||
}
|
||
</div>
|
||
</React.Fragment>
|
||
}
|
||
</div>
|
||
<div className="depotBtn AlignCenter">
|
||
<div className="addOptionBtn">
|
||
{
|
||
baseOperate &&
|
||
<CheckProfile {...props} sureFunc={compare}>+ 合并请求</CheckProfile>
|
||
}
|
||
{
|
||
issuesFlag &&
|
||
<CheckProfile {...props} sureFunc={createIssue} checklogin>+ 疑修</CheckProfile>
|
||
}
|
||
|
||
</div>
|
||
{ fileOperate &&
|
||
<Dropdown
|
||
overlay={fileMenu()}
|
||
className="mr10"
|
||
trigger={['click']}
|
||
getPopupContainer={document.parentNode}
|
||
>
|
||
<a>文件 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-grey-6 mr-5"></i></a>
|
||
</Dropdown>
|
||
}
|
||
{
|
||
checkIfLogin && checkIfLogin()?
|
||
<a className='newBtn' onClick={()=>eventTrack(`/${owner}/${projectsId}/webIDE/tree/${branchName||defaultBranch}`)}>Web IDE</a>
|
||
:
|
||
<a className='newBtn' onClick={()=>{showLoginDialog(`/${owner}/${projectsId}`)}}>Web IDE</a>
|
||
}
|
||
|
||
<Dropdown overlay={downloadMenu} placement="bottomRight" trigger={['click']}>
|
||
<Button type={'primary'}>下载 <i className="iconfont icon-sanjiaoxing-down ml3 font-14 color-white mr-3"></i></Button>
|
||
</Dropdown>
|
||
</div>
|
||
</div>
|
||
{
|
||
(dirInfo && dirInfo.length>0) || fileInfo ?
|
||
<div className="listtable">
|
||
{
|
||
((lastCommit && lastCommit.message) || lastCommitAuthor) &&
|
||
<div className="listtablehead">
|
||
{
|
||
lastCommitAuthor &&
|
||
<User url={getImageUrl(`/${lastCommitAuthor.image_url}`)} name={lastCommitAuthor.name} id={lastCommitAuthor.id} login={lastCommitAuthor.login}/>
|
||
}
|
||
{
|
||
lastCommit.message &&
|
||
<div className={hideBtn && hide ? "ellipsistxt hidetxt" :"ellipsistxt"}>
|
||
<pre id="ptxt"><Link to={`/${owner}/${projectsId}/commits/${truncateCommitId(lastCommit.sha)}`}><RenderHtml value={lastCommit.message}/></Link></pre>
|
||
</div>
|
||
}
|
||
{ hideBtn && __CLIENT__ && <div className="ellipsis" onClick={()=>changeHide(hide)}><i className="iconfont icon-shenglvehao"></i></div> }
|
||
|
||
<Tooltip title={lastCommit.committer && moment(lastCommit.committer.date).format(format)}><span className="ml20 color-grey-6 font-12 mt3">{lastCommit.time_from_now}</span></Tooltip>
|
||
{
|
||
commitCount ?
|
||
<Link to={`/${owner}/${projectsId}/commits/branch/${turnbar(branchName || defaultBranch)}`} className="ml20 color-grey-3"style={{height:"28px",lineHeight:"28px"}}>
|
||
<i className="iconfont icon-tijiaoicon mr3 font-16"></i><span style={{fontWeight:"500"}}>{commitCount}次提交</span>
|
||
</Link>:""
|
||
}
|
||
</div>
|
||
}
|
||
<ul className="listtablebody">
|
||
{
|
||
dirInfo && dirInfo.length > 0 &&
|
||
dirInfo.map((item,key)=>{
|
||
return(
|
||
<Catalogue
|
||
key={item.id||key}
|
||
owner={owner}
|
||
item={item}
|
||
projectsId={projectsId}
|
||
goToSubRoot={goToSubRoot}
|
||
platform={props.platform}
|
||
/>
|
||
)
|
||
})
|
||
}
|
||
{
|
||
fileInfo && __CLIENT__ &&
|
||
<CoderRootFileDetail
|
||
{...props}
|
||
detail={fileInfo}
|
||
readOnly={readOnly}
|
||
md={mdFlag}
|
||
onEdit={onEdit}
|
||
currentBranch={branchName || defaultBranch}
|
||
branch={branchName || defaultBranch}
|
||
type={projectDetail.type}
|
||
treeValuePath={treeValuePath}
|
||
></CoderRootFileDetail>
|
||
}
|
||
</ul>
|
||
</div>
|
||
: ""
|
||
}
|
||
{
|
||
(dirInfo && dirInfo.length === 0) && !fileInfo ? <Nodata _html="暂未发现文件"/> :""
|
||
}
|
||
{/* readme文件显示(显示文件详情时不显示readme文件) */}
|
||
{ (readme && readme.replace_content) ? <ReadMe ChangeFile={ChangeFile} readme={readme} operate={props && (props.isManager || props.isDeveloper) && projectDetail.type !==2 } history={props.history} /> :"" }
|
||
</div>
|
||
</div>
|
||
{
|
||
(!(treeValuePath && treeValuePath.length > 0) && !fileInfo ) &&
|
||
<div className="ShortWidth">
|
||
<div className="Gap" style={{paddingLeft:"30px"}}>
|
||
<div className="panelmenu">
|
||
<div className="font-18 color-ooo mb20 FlexAJ" style={{lineHeight:"28px"}}>关于
|
||
{
|
||
projectDetail.permission && (projectDetail.permission==="Admin" || projectDetail.permission==="Owner" || projectDetail.permission==="Manager") &&
|
||
<i onClick={()=>setOpenModal(true)} className="iconfont icon-a-shezhi color-grey-9 font-15 pointer"></i>
|
||
}
|
||
</div>
|
||
{desc && <p className="font-14 color-grey-3 mb15 task-hide-2" style={{lineHeight:"24px",WebkitLineClamp:"4",textAlign:"justify",wordBreak:"break-all"}} title={desc}>{desc}</p>}
|
||
{/* 项目标签 */}
|
||
{topics && <div className='projectHomeTopics'>
|
||
{topics.map(item=><Link to={`/explore/topic/${item.id}/${encodeURIComponent(item.name)}`} className='proHomeTopic mr15 mb10 font-13 task-hide'>{item.name}</Link>)}
|
||
</div>}
|
||
{
|
||
website &&
|
||
<div className="color-grey-6 df pinfos mb5">
|
||
<i className="iconfont icon-lianjie2 font-15 mr10"></i>
|
||
<a href={website} target="_blank" style={{wordBreak:"break-all",lineHeight:"20px",marginTop:"5px",textDecoration:"underline"}}>{website}</a>
|
||
</div>
|
||
}
|
||
<div className="pinfos mb5">
|
||
<i className="iconfont icon-zishuwenjian_icon font-15 mr10"></i>
|
||
<a href="#readme">README.md</a>
|
||
</div>
|
||
<div className="color-grey-6 mb5">
|
||
<i className="iconfont icon-neicunicon font-15 mr10"></i>
|
||
<span>{projectDetail && projectDetail.size}</span>
|
||
</div>
|
||
{
|
||
projectDetail && projectDetail.license_id !== 0 &&
|
||
<div className={projectDetail.license_name ? "pinfos" :"color-grey-6"}>
|
||
<i className="iconfont icon-xieyiicon font-16 mr10"></i>
|
||
{
|
||
projectDetail.license_name ?
|
||
<Link to={`/${owner}/${projectsId}/tree/${turnbar(branchName || defaultBranch)}/LICENSE`} className="color-grey-6">{projectDetail.license_name}</Link>
|
||
:
|
||
<a className='color-blue' onClick={()=>{setLicenseVisible(true)}}>点击选择许可证(LICENSE)</a>
|
||
}
|
||
</div>
|
||
}
|
||
</div>
|
||
{
|
||
inviteCode &&
|
||
<div>
|
||
<Divider />
|
||
<Invite code={inviteCode}/>
|
||
</div>
|
||
}
|
||
{
|
||
lesson_url &&
|
||
<div>
|
||
<Divider />
|
||
<p className="font-16 color-ooo">实践课程</p>
|
||
<a href={lesson_url} target="_blank" className="color-grey-6" style={{textDecoration:"underline",wordBreak:"break-all"}}>{lesson_url}</a>
|
||
</div>
|
||
}
|
||
{/* 发布 */}
|
||
{
|
||
releaseVersions &&
|
||
<React.Fragment>
|
||
<Divider />
|
||
<Releases
|
||
owner={owner}
|
||
projectsId={projectsId}
|
||
releaseVersions={releaseVersions}
|
||
history={props.history}
|
||
distribution={distribution}
|
||
/>
|
||
</React.Fragment>
|
||
}
|
||
{__CLIENT__ && projectDetail && projectDetail.project_id && !projectDetail.private && <ProjectCompass owner={owner} projectsId={projectsId} />}
|
||
{/* 贡献者 */}
|
||
{mirror_status ===0 && <Contributors owner={owner} projectsId={projectsId} /> }
|
||
{/* 项目画像: 导入/fork项目不展示, open_portrait后台配置是否开启仓库 */}
|
||
{__CLIENT__ && projectDetail && !projectDetail.type && !projectDetail.forked_from_project_id && project && project.open_portrait && <ProjectPortrait owner={owner} projectsId={projectsId}/>}
|
||
{/* 语言 */}
|
||
{ mirror_status ===0 && <LanguagePower owner={owner} projectsId={projectsId}/> }
|
||
</div>
|
||
</div>
|
||
}
|
||
</div>
|
||
}
|
||
</div>
|
||
</Spin>
|
||
</div>
|
||
)
|
||
}
|
||
|
||
const mapStateToProps = (state) => {
|
||
const {
|
||
defaultDetail,
|
||
projectEntries,
|
||
projectReadMe
|
||
} = state.projectReducer;
|
||
return {
|
||
defaultDetail,
|
||
projectEntries,
|
||
projectReadMe
|
||
};
|
||
}
|
||
|
||
export default connect(
|
||
mapStateToProps
|
||
)(CoderDepot); |