diff --git a/src/common/DateUtil.js b/src/common/DateUtil.js index 630b2d7d6..8846d274c 100644 --- a/src/common/DateUtil.js +++ b/src/common/DateUtil.js @@ -107,7 +107,7 @@ export function timeAgo(backDate) { try { moment(backDate); } catch (e) { - return; + return '刚刚'; } if(typeof backDate ==='number'){ backDate=backDate*1000 @@ -134,4 +134,5 @@ export function timeAgo(backDate) { if (seconds) { return seconds + "秒前"; } + return "刚刚"; } \ No newline at end of file diff --git a/src/forge/Component/AddGroup.jsx b/src/forge/Component/AddGroup.jsx index 656175d5f..feff6f372 100644 --- a/src/forge/Component/AddGroup.jsx +++ b/src/forge/Component/AddGroup.jsx @@ -55,6 +55,7 @@ function AddGroup({organizeId,getGroupID}){ function addCollaborator(){ getGroupID && getGroupID(id); + setID(undefined); } return( diff --git a/src/forge/Component/CopyTool.jsx b/src/forge/Component/CopyTool.jsx new file mode 100644 index 000000000..e659c077e --- /dev/null +++ b/src/forge/Component/CopyTool.jsx @@ -0,0 +1,44 @@ +import React, { useState, useCallback, memo } from 'react'; +import { Tooltip } from 'antd'; + +CopyTool.defaultProps = { + beforeText: '复制', //浮动过去显示的文字 + afterText: '复制成功', //点击后显示的文字 + className: '', //传给svg的class + inputId: 'copyText', //要复制的文本的ID +}; + + +function CopyTool({ beforeText, afterText, className,inputId }) { + const [title, setTitle] = useState(() => { + return beforeText; + }); + + // 复制链接 + const copyUrl = useCallback(() => { + let inputDom = document.getElementById(inputId); + if (!inputDom) { + console.error("您的CopyTool未设置正确的inputId"); + return; + } + inputDom.select(); + if (document.execCommand('copy')) { + document.execCommand('copy'); + } + setTitle(afterText); + inputDom.blur(); + }, []); + + return ( + { setTitle(beforeText) }} + > + + + ); +} + + +export default memo(CopyTool); \ No newline at end of file diff --git a/src/forge/Divert/DivertModal.jsx b/src/forge/Divert/DivertModal.jsx index a6ecdc05f..40dd68296 100644 --- a/src/forge/Divert/DivertModal.jsx +++ b/src/forge/Divert/DivertModal.jsx @@ -104,7 +104,7 @@ function DivertModal({form , visible , onSuccess , onCancel,owner,repo}){ : diff --git a/src/forge/Main/CoderDepot.jsx b/src/forge/Main/CoderDepot.jsx index cfe3c6a8d..227aac79f 100644 --- a/src/forge/Main/CoderDepot.jsx +++ b/src/forge/Main/CoderDepot.jsx @@ -147,6 +147,7 @@ function CoderDepot(props){ setReadme(result.data.readme); setEditReadme(false); setHide(true); + console.log("dddd:",result.data.entries); } setTimeout(function(){setIsSpin(false);},500); }).catch(error=>{setIsSpin(false);}) @@ -383,7 +384,7 @@ function CoderDepot(props){ { - dirInfo || fileInfo ? + (dirInfo && dirInfo.length>0) || fileInfo ?
{ lastCommit && @@ -441,7 +442,7 @@ function CoderDepot(props){ : "" } { - (dirInfo && dirInfo.length === 0) && (fileInfo && fileInfo.length === 0) ? :"" + (dirInfo && dirInfo.length === 0) && !fileInfo ? :"" } {/* readme文件显示(显示文件详情时不显示readme文件) */} { dirInfo && (readme && readme.content) ? :"" } @@ -511,11 +512,11 @@ function CoderDepot(props){ } {/* 贡献者 */} { - projectDetail && projectDetail.contributors && + projectDetail && projectDetail.contributors && projectDetail.contributors.length >0 && } {/* 语言 */} - { projectDetail && projectDetail.languages && + { projectDetail && projectDetail.languages && projectDetail.languages.length >0 && diff --git a/src/forge/Main/Detail.js b/src/forge/Main/Detail.js index 4f930ce42..46d5a72d6 100644 --- a/src/forge/Main/Detail.js +++ b/src/forge/Main/Detail.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; -import { Spin, Tooltip , Button } from 'antd'; +import { Spin, Tooltip, Button } from 'antd'; import { Link, Route, Switch } from 'react-router-dom'; -import { Content , AlignTop } from '../Component/layout'; +import { Content, AlignTop } from '../Component/layout'; import DetailBanner from './sub/DetailBanner'; import '../css/index.scss' import './list.css'; @@ -103,12 +103,12 @@ const Contribute = Loadable({ }) const CoderRootCommit = Loadable({ - loader: () => import('./CoderRootCommit'), - loading: Loading, + loader: () => import('./CoderRootCommit'), + loading: Loading, }) const CoderDepot = Loadable({ - loader: () => import('./CoderDepot'), - loading: Loading, + loader: () => import('./CoderDepot'), + loading: Loading, }) const TrendsIndex = Loadable({ @@ -139,28 +139,28 @@ const WikiEdit = Loadable({ /** * permission:Manager:管理员,Reporter:报告人员(只有读取权限),Developer:开发人员(除不能设置仓库信息外) */ -function checkPathname(projectsId,owner,pathname){ +function checkPathname(projectsId, owner, pathname) { let name = ""; - if(pathname && pathname !== `/projects/${owner}/${projectsId}`){ + if (pathname && pathname !== `/projects/${owner}/${projectsId}`) { let url = pathname.split(`/projects/${owner}/${projectsId}`)[1]; - if(url.indexOf("/about")>-1){ - name="about" - }else if(url.indexOf("/issues")>-1 ||url.indexOf("Milepost") > 0){ + if (url.indexOf("/about") > -1) { + name = "about" + } else if (url.indexOf("/issues") > -1 || url.indexOf("Milepost") > 0) { name = "issues"; - }else if(url.indexOf("/pulls")>-1){ - name="pulls" - }else if(url.indexOf("/milestones")>-1){ - name="milestones" - }else if(url.indexOf("/activity")>-1){ - name="activity" - }else if(url.indexOf("/setting")>-1){ - name="setting" - }else if(url.indexOf(`/devops`)>-1){ - name="devops" - }else if(url.indexOf(`/source`)>-1){ - name="source" - }else if(url.indexOf(`/wiki`)>-1){ - name="wiki" + } else if (url.indexOf("/pulls") > -1) { + name = "pulls" + } else if (url.indexOf("/milestones") > -1) { + name = "milestones" + } else if (url.indexOf("/activity") > -1) { + name = "activity" + } else if (url.indexOf("/setting") > -1) { + name = "setting" + } else if (url.indexOf(`/devops`) > -1) { + name = "devops" + } else if (url.indexOf(`/source`) > -1) { + name = "source" + } else if (url.indexOf(`/wiki`) > -1) { + name = "wiki" } } return name; @@ -183,15 +183,15 @@ class Detail extends Component { branchs: undefined, branchList: undefined, project: null, - firstSync:false, - secondSync:false, - open_devops:false, - forkSpin:false, + firstSync: false, + secondSync: false, + open_devops: false, + forkSpin: false, // 默认分支 - defaultBranch:undefined, + defaultBranch: undefined, // 非本平台项目 - platform:false + platform: false } } @@ -208,36 +208,38 @@ class Detail extends Component { } getProject = (num) => { - const { projectsId , owner } = this.props.match.params; + const { projectsId, owner } = this.props.match.params; const url = `/${owner}/${projectsId}/simple.json`; axios.get(url).then((result) => { if (result && result.data) { this.setState({ project: result.data, - open_devops:result.data.open_devops, - platform:result.data.platform && result.data.platform !== 'educoder' + open_devops: result.data.open_devops, + platform: result.data.platform && result.data.platform !== 'educoder' }) if (result.data.type !== 0 && result.data.mirror_status === 1) { console.log("--------start channel --------"); // 是镜像项目,且未完成迁移 this.canvasChannel(); - if(num){ + if (num) { this.setState({ - secondSync:true, - firstSync:false + secondSync: true, + firstSync: false }) - }else{ + } else { this.setState({ - firstSync:true, - secondSync:false + firstSync: true, + secondSync: false }) } - }else{ + } else if (result.data.mirror_status === 2) { + this.deleteProjectBack(); + } else { this.getDetail(); this.setState({ - firstSync:false, - secondSync:false + firstSync: false, + secondSync: false }) } } @@ -245,9 +247,9 @@ class Detail extends Component { } // 工作流激活后修改状态 - changeOpenDevops=(flag)=>{ + changeOpenDevops = (flag) => { this.setState({ - open_devops:flag + open_devops: flag }) } canvasChannel = () => { @@ -265,11 +267,15 @@ class Detail extends Component { disconnected: () => { }, received: data => { console.log(`###### ---received data--- ######`); + console.log(data); if (data) { + if ( data.project && data.project.mirror_status === 2) { + this.deleteProjectBack(); + } this.getDetail(); this.setState({ - firstSync:false, - secondSync:false + firstSync: false, + secondSync: false }); cable.subscriptions.consumer.disconnect(); } @@ -277,8 +283,25 @@ class Detail extends Component { }) } + deleteProjectBack = () => { + const { history } = this.props; + const { projectsId, owner } = this.props.match.params; + axios.delete(`/${owner}/${projectsId}.json`).then(res => { + let hash = '/projects/mirror/new'; + if (res && res.data) { + history.push({ + pathname: hash, + mirror_status: 2 + }); + } + else { + window.location.hash = hash; + } + }); + } + getDetail = () => { - const { projectsId , owner } = this.props.match.params; + const { projectsId, owner } = this.props.match.params; this.getBanner(); const url = `/${owner}/${projectsId}/detail.json`; axios.get(url).then((result) => { @@ -295,29 +318,29 @@ class Detail extends Component { watchers_count: result.data.watchers_count, praises_count: result.data.praises_count, forked_count: result.data.forked_count, - defaultBranch:result.data.default_branch + defaultBranch: result.data.default_branch }) } }).catch((error) => { }) } // 获取动态导航栏菜单 - getBanner(){ - const { projectsId , owner } = this.props.match.params; + getBanner() { + const { projectsId, owner } = this.props.match.params; const url = `/${owner}/${projectsId}/menu_list.json`; - axios.get(url).then(result=>{ - if(result){ + axios.get(url).then(result => { + if (result) { this.setState({ - bannerList:result.data + bannerList: result.data }) } - }).catch(error=>{}) + }).catch(error => { }) } // 关注和取消关注 focusFunc = (flag) => { const { platform } = this.state; - if(!platform)return; + if (!platform) return; const { project_id } = this.state; axios({ @@ -332,15 +355,15 @@ class Detail extends Component { this.setWatchersCount(result.data.watchers_count, result.data.watched); } }) - .catch(error => { - console.log(error); - }); + .catch(error => { + console.log(error); + }); } // 点赞和取消点赞 pariseFunc = (flag) => { const { platform } = this.state; - if(!platform)return; + if (!platform) return; const { project_id } = this.state; axios({ method: flag ? 'delete' : 'post', @@ -350,9 +373,9 @@ class Detail extends Component { this.setPraisesCount(result.data.praises_count, result.data.praised) } }) - .catch(error => { - console.log(error); - }); + .catch(error => { + console.log(error); + }); } setWatchersCount = (count, is_watched) => { @@ -372,12 +395,12 @@ class Detail extends Component { // fork项目 forkFunc = () => { const { platform } = this.state; - if(!platform)return; + if (!platform) return; this.setState({ - forkSpin:true + forkSpin: true }) const { current_user } = this.props - const { projectsId , owner } = this.props.match.params; + const { projectsId, owner } = this.props.match.params; const url = `/${owner}/${projectsId}/forks.json`; axios.post(url).then(result => { if (result && result.data.status === 0) { @@ -385,11 +408,11 @@ class Detail extends Component { this.props.showNotification(result.data.message); } this.setState({ - forkSpin:false + forkSpin: false }) }).catch(error => { this.setState({ - forkSpin:false + forkSpin: false }) }) } @@ -397,8 +420,8 @@ class Detail extends Component { // 同步镜像 synchronismMirror = () => { const { platform } = this.state; - if(!platform)return; - const { projectsId , owner } = this.props.match.params; + if (!platform) return; + const { projectsId, owner } = this.props.match.params; const url = `/${owner}/${projectsId}/sync_mirror.json`; axios.post(url).then(result => { if (result && result.data && result.data.status === 0) { @@ -412,42 +435,43 @@ class Detail extends Component { }) } - textFunc = (forked_from_project_id,fork_info)=>{ + textFunc = (forked_from_project_id, fork_info) => { + let type = fork_info && fork_info.fork_project_user_type; return forked_from_project_id && fork_info ?
复刻自 {fork_info.fork_project_user_name} / - {fork_info.fork_form_name} + {fork_info.fork_form_name}
: "" } - + render() { - const { projectDetail, watchers_count, praises_count, - forked_count, firstSync , secondSync , - isManager, watched, praised, - project , open_devops , platform , defaultBranch , bannerList , forkSpin } = this.state; + const { projectDetail, watchers_count, praises_count, + forked_count, firstSync, secondSync, + isManager, watched, praised, + project, open_devops, platform, defaultBranch, bannerList, forkSpin } = this.state; const url = this.props.history.location.pathname; const urlArr = url.split("/"); const urlFlag = (urlArr.length === 3); - const { projectsId , owner } = this.props.match.params; + const { projectsId, owner } = this.props.match.params; const { current_user } = this.props; - let pathname = checkPathname(projectsId,owner,url); + let pathname = checkPathname(projectsId, owner, url); const { state } = this.props.history.location; - + const common = { getDetail: this.getDetail, - changeOpenDevops:this.changeOpenDevops, + changeOpenDevops: this.changeOpenDevops, defaultBranch } return (
- +
@@ -457,298 +481,298 @@ class Detail extends Component { / {projectDetail && projectDetail.name}
- { projectDetail && projectDetail.private && 私有} + {projectDetail && projectDetail.private && 私有}
{ projectDetail && projectDetail.forked_from_project_id && projectDetail.fork_info ? - this.textFunc(projectDetail.forked_from_project_id,projectDetail.fork_info) - :"" + this.textFunc(projectDetail.forked_from_project_id, projectDetail.fork_info) + : "" } { - projectDetail && projectDetail.type && projectDetail.type !== 0 ? - 镜像自 {projectDetail.mirror_url} - :"" + projectDetail && projectDetail.type && projectDetail.type !== 0 ? + 镜像自 {projectDetail.mirror_url} + : "" }
{ - firstSync ? "": - - { - ((current_user && current_user.admin) || isManager) && (projectDetail && projectDetail.type && projectDetail.type === 2) ? - 同步镜像 : "" - } - - - - + { + watchers_count > 0 ? + platform ? + + {watchers_count} + + : + {watchers_count} + : "" + } + + + + }
{ firstSync ? "" : - + }
{ firstSync ? - - - - : - - - {/* 资源 */} - () - } - > - {/* 主页 */} - () - } - > - {/* wiki新增文件 */} - () - } - > - {/* wiki编辑文件 */} - () - } - > - {/* wiki */} - () - } - > - {/* 工作流 */} - () - } - > - {/* 标签列表 */} - () - } - > - {/* 仓库设置 */} - () - } - > - {/* 任务详情 */} - () - } - > - {/*修改里程碑*/} - () - } - > - {/* 新建里程碑 */} - () - } - > - {/*里程碑详情*/} - () - } - > - {/* 里程碑 */} - () - } - > - {/* 里程碑页面新建任务 */} - () - } - > - {/* 新建任务 */} - () - } - > - {/* 修改详情 */} - () - } - > - {/* 复制详情 */} - () - } - > - {/* 动态 */} - () - } - > - {/* 代码Index */} - () - } - > - {/* 新建合并请求 */} - () - } - > - () - } - > - () - } - > - () - } - > - () - } - > + + + + : + + + {/* 资源 */} + () + } + > + {/* 主页 */} + () + } + > + {/* wiki新增文件 */} + () + } + > + {/* wiki编辑文件 */} + () + } + > + {/* wiki */} + () + } + > + {/* 工作流 */} + () + } + > + {/* 标签列表 */} + () + } + > + {/* 仓库设置 */} + () + } + > + {/* 任务详情 */} + () + } + > + {/*修改里程碑*/} + () + } + > + {/* 新建里程碑 */} + () + } + > + {/*里程碑详情*/} + () + } + > + {/* 里程碑 */} + () + } + > + {/* 里程碑页面新建任务 */} + () + } + > + {/* 新建任务 */} + () + } + > + {/* 修改详情 */} + () + } + > + {/* 复制详情 */} + () + } + > + {/* 动态 */} + () + } + > + {/* 代码Index */} + () + } + > + {/* 新建合并请求 */} + () + } + > + () + } + > + () + } + > + () + } + > + () + } + > - () - } - > - () - } - > - () - } - > - () - } - > - {/* 贡献者列表 */} - () - } - > + () + } + > + () + } + > + () + } + > + () + } + > + {/* 贡献者列表 */} + () + } + > - {/* 代码库----详情页面 */} - () - } - > - () - } - > - () - } - > - () - } - > - - + {/* 代码库----详情页面 */} + () + } + > + () + } + > + () + } + > + () + } + > + + }
) diff --git a/src/forge/Main/sub/DetailBanner.jsx b/src/forge/Main/sub/DetailBanner.jsx index e0ca4db10..3c37a730d 100644 --- a/src/forge/Main/sub/DetailBanner.jsx +++ b/src/forge/Main/sub/DetailBanner.jsx @@ -85,14 +85,14 @@ function DetailBanner({ history,list , owner , projectsId , isManager , url , pa :"" } { - item.menu_name === "resources" && -
  • - - - 资源库 - {projectDetail && projectDetail.source_count ? {projectDetail.source_count} :""} - -
  • + // item.menu_name === "resources" && + //
  • + // + // + // 资源库 + // {projectDetail && projectDetail.source_count ? {projectDetail.source_count} :""} + // + //
  • } { item.menu_name === "versions" && diff --git a/src/forge/Merge/MergeItem.js b/src/forge/Merge/MergeItem.js index bfb8eace7..3bc6ed8a2 100644 --- a/src/forge/Merge/MergeItem.js +++ b/src/forge/Merge/MergeItem.js @@ -49,7 +49,7 @@ class MergeItem extends Component { }; render() { - const { issues, project_name, project_author_name , user_admin_or_member} = this.props; + const { issues, project_name, project_author_name , user_admin_or_developer} = this.props; const { projectsId , owner } = this.props.match.params; const { current_user } = this.props; const renderList = () => { @@ -183,7 +183,7 @@ class MergeItem extends Component { ) : ( "" )} - {user_admin_or_member && item.pull_request_status === 0 ? ( + {user_admin_or_developer && item.pull_request_status === 0 ? (
    { - data && data.user_admin_or_member && + data && data.user_admin_or_developer && this.checkOperation()}> + 新建合并请求 @@ -387,7 +387,7 @@ class merge extends Component { {data && data.search_count && data.search_count > 0 ? (
    - + user_admin_or_developer={data && data.user_admin_or_developer} + >
    ):""} {search_count > select_params.limit ? ( diff --git a/src/forge/New/Index.js b/src/forge/New/Index.js index b0f073261..18f2aa9a3 100644 --- a/src/forge/New/Index.js +++ b/src/forge/New/Index.js @@ -1,6 +1,6 @@ import React, { Component } from 'react'; import { Link } from 'react-router-dom'; -import { Input , Form , Select , Checkbox , Button , Spin , AutoComplete } from 'antd'; +import { Input , Form , Select , Checkbox , Button , Spin , AutoComplete, Modal } from 'antd'; import { Base64 } from 'js-base64'; import '../css/index.scss'; @@ -58,6 +58,8 @@ class Index extends Component { this.getGitignore(); // 获取开源许可证 this.getLicenses(); + //判断是否为删除新建项目失败后返回,并执行对应逻辑 + this.isDeleteProjectBack(); } componentDidUpdate=(prevPros)=>{ if(prevPros && this.props && !this.props.checkIfLogin()){ @@ -69,6 +71,7 @@ class Index extends Component { getOwner=()=>{ const { OIdentifier } = this.props.match.params; const { user_id } = this.props && this.props.current_user; + const url = `/owners.json`; axios.get(url).then(result=>{ if(result && result.data){ @@ -77,16 +80,13 @@ class Index extends Component { OwnerList: owner, }) if(OIdentifier){ - owner = owner.filter(item=>item.name === OIdentifier); - this.props.form.setFieldsValue({ - user_id:OIdentifier - }) + owner = owner.filter(item=>item.login === OIdentifier); }else if(user_id){ owner = owner.filter(item=>item.id === user_id); - this.props.form.setFieldsValue({ - user_id:owner && owner[0].name - }) } + this.props.form.setFieldsValue({ + user_id:owner && owner[0].name + }) owner && this.setState({ owners_id:owner[0].id, owners_name:owner[0].name @@ -144,6 +144,31 @@ class Index extends Component { }).catch((error) => { }) } + isDeleteProjectBack = () => { + let mirror_status = this.props.history.location.mirror_status; + if (mirror_status === 2 && sessionStorage.newProjectValue) { + Modal.warning({ + title: '警告', + content: '镜像项目创建失败!请按操作规范重新创建项目!', + }); + let newProjectValue = JSON.parse(sessionStorage.newProjectValue); + if (newProjectValue) { + this.setState({ + project_language_id: newProjectValue.project_language_id, + project_category_id: newProjectValue.project_category_id, + license_id: newProjectValue.license_id, + ignore_id: newProjectValue.ignore_id + }); + delete newProjectValue.project_language_id; + delete newProjectValue.project_category_id; + delete newProjectValue.license_id; + delete newProjectValue.ignore_id; + this.props.form.setFieldsValue(newProjectValue); + } + + } + } + // 设置option setOptionsList = (data, _head, name) => { if (data && data.length > 0) { @@ -172,6 +197,8 @@ class Index extends Component { const { project_language_id, project_category_id, license_id, ignore_id , owners_id , owners_name } = this.state; const decoderPass = Base64.encode(values.password); const url = (projectsType && projectsType === "mirror") ? "/projects/migrate.json" : "/projects.json"; + // 新建项目的时候,暂存数据,如果失败,返回的时候可以重新赋值 + sessionStorage.newProjectValue=JSON.stringify({...values,project_language_id,project_category_id,license_id,ignore_id}); axios.post(url, { ...values, auth_password:decoderPass, @@ -185,7 +212,7 @@ class Index extends Component { this.setState({ isSpin: false }) - this.props.showNotification(`${projectsType && projectsType === "mirror" ? "镜像" : "托管"}项目创建成功!`); + projectsType && projectsType !== "mirror" && this.props.showNotification(`托管项目创建成功!`); this.props.history.push(`/projects/${result.data.login}/${result.data.identifier}`); } }).catch((error) => { @@ -337,7 +364,9 @@ class Index extends Component { { projectsType && projectsType === "mirror" && -

    需要授权验证

    +

    + 需要授权验证 + 如果源项目为公有仓库,禁止填写用户名密码。如果源项目为私有仓库,则必须填写正确的用户名和密码!

    { mirrorCheck &&
    diff --git a/src/forge/Notice/Index.jsx b/src/forge/Notice/Index.jsx index 9c52fca16..3f61688fb 100644 --- a/src/forge/Notice/Index.jsx +++ b/src/forge/Notice/Index.jsx @@ -70,9 +70,9 @@ function Index(props){ function deleteEvent(type,count) { let c = count; if(type==="apply"){ - setTransferCount(transferCount-count); - }else if(type==="undo"){ setApplyCount(applyCount-count); + }else if(type==="undo"){ + setTransferCount(transferCount-count); }else{ setMessagesCount(0); c = messagesCount; diff --git a/src/forge/Notice/UndoEvent.jsx b/src/forge/Notice/UndoEvent.jsx index bf700be28..f2b71c3c1 100644 --- a/src/forge/Notice/UndoEvent.jsx +++ b/src/forge/Notice/UndoEvent.jsx @@ -53,7 +53,7 @@ function UndoEvent(props){ Axios.post(url).then(result=>{ if(result && result.data){ getList(); - props && props.deleteEvent("apply",1); + props && props.deleteEvent("undo",1); } }).catch(error=>{}) } diff --git a/src/forge/Settings/Collaborator.js b/src/forge/Settings/Collaborator.js index 0b94eee5b..0a50cae10 100644 --- a/src/forge/Settings/Collaborator.js +++ b/src/forge/Settings/Collaborator.js @@ -1,4 +1,4 @@ -import React, { useState } from "react"; +import React, { useState , useRef } from "react"; import {WhiteBack} from '../Component/layout'; import AddMember from '../Component/AddMember'; import AddGroup from '../Component/AddGroup'; @@ -8,9 +8,11 @@ import Group from './CollaboratorGroup'; function Collaborator(props){ const [ nav , setNav] = useState("1"); const [ newId , setNewId] = useState(undefined); + const [ addOperation , setAddOperation] = useState(true); const [ newGroupId , setNewGroupId] = useState(undefined); const {projectsId ,owner} = props.match.params; + const author = props && props.projectDetail && props.projectDetail.author; function getID(id){ @@ -19,6 +21,7 @@ function Collaborator(props){ function getGroupID(id){ setNewGroupId(id); } + return ( @@ -27,15 +30,17 @@ function Collaborator(props){ author && author.type === "Organization" ? {setNav("1");setNewId(undefined)}}>协作者管理 - {setNav("2");setNewId(undefined)}}>团队管理 + {setNav("2");setNewId(undefined);setNewGroupId(undefined)}}>团队管理 : 协作者管理 } { - nav === "1" ? + nav === "1" && - : + } + { + (nav !== "1" && addOperation) && }
    @@ -44,7 +49,7 @@ function Collaborator(props){ nav === "1" ? : - + }
    diff --git a/src/forge/Settings/CollaboratorGroup.jsx b/src/forge/Settings/CollaboratorGroup.jsx index 3afd9e03e..4002d4cde 100644 --- a/src/forge/Settings/CollaboratorGroup.jsx +++ b/src/forge/Settings/CollaboratorGroup.jsx @@ -10,7 +10,7 @@ const roles = { read: "报告者", }; const limit = 15; -function CollaboratorGroup({ newGroupId, owner, projectsId }) { +function CollaboratorGroup({ newGroupId, owner, projectsId , setAddOperation }) { const [list, setList] = useState(undefined); const [isSpin, setIsSpin] = useState(true); const [page, setPage] = useState(1); @@ -34,6 +34,7 @@ function CollaboratorGroup({ newGroupId, owner, projectsId }) { setList(result.data.teams); setTotal(result.data.total_count); setIsSpin(false); + setAddOperation(result.data.can_add); } }) .catch((error) => {}); @@ -47,16 +48,15 @@ function CollaboratorGroup({ newGroupId, owner, projectsId }) { // 添加团队 function addGroup(id) { const url = `/${owner}/${projectsId}/teams.json`; - axios - .post(url, { - team_id: id, - }) - .then((result) => { - if (result && result.data) { - getData(); - } - }) - .catch((error) => {}); + axios.post(url, { + team_id: id, + }) + .then((result) => { + if (result && result.data) { + getData(); + } + }) + .catch((error) => {}); } // 删除团队 @@ -77,7 +77,11 @@ function CollaboratorGroup({ newGroupId, owner, projectsId }) { title: "团队名", dataIndex: "name", render: (value, item) => { - return {value}; + if(item.is_admin || item.is_member){ + return {value}; + }else{ + return {value}; + } }, }, { diff --git a/src/forge/Settings/Setting.js b/src/forge/Settings/Setting.js index 02295ce0d..a9e5cc44d 100644 --- a/src/forge/Settings/Setting.js +++ b/src/forge/Settings/Setting.js @@ -16,7 +16,7 @@ const menu = [ {name:"合并请求",index:"pulls"}, {name:"Wiki",index:"wiki"}, {name:"工作流(beta版)",index:"devops"}, - {name:"资源库",index:"resources"}, + // {name:"资源库",index:"resources"}, {name:"里程碑",index:"versions"}, {name:"动态",index:"activity"}, ] diff --git a/src/forge/Team/Group/GroupForm.jsx b/src/forge/Team/Group/GroupForm.jsx index 108ef2400..29fe28582 100644 --- a/src/forge/Team/Group/GroupForm.jsx +++ b/src/forge/Team/Group/GroupForm.jsx @@ -24,21 +24,32 @@ export default Form.create()( const [check_box, setCheckBox] = useState(false); const [switch_box, setSwtichBox] = useState([]); const [onwers, setOnwers] = useState(false); + const [auth, setAuth] = useState(""); const [ descNum , setDescNum ] = useState(0); const [switch_box_code, setSwtichBoxCode] = useState(false); const [switch_box_pull, setSwtichBoxPull] = useState(false); const [switch_box_issue, setSwtichBoxIssue] = useState(false); const [switch_box_release, setSwtichBoxRelease] = useState(false); + const [switch_box_wiki, setSwtichBoxWiki] = useState(false); const { getFieldDecorator, validateFields, setFieldsValue } = form; const { OIdentifier, groupId } = match.params; + useEffect(()=>{ + setFieldsValue({ + authorize:"read", + includes_all_project:0 + }) + },[]) + useEffect(() => { if (GroupDetail) { setOnwers(GroupDetail.authorize === "owner"); + setAuth(GroupDetail.authorize); setCheckBox(GroupDetail.can_create_org_project) setSwtichBox(GroupDetail.units) setFieldsValue({ - ...GroupDetail + ...GroupDetail, + includes_all_project:GroupDetail.includes_all_project ? 1 :0 }) setDescNum(GroupDetail.description ? GroupDetail.description.length : 0); } @@ -50,6 +61,7 @@ export default Form.create()( setSwtichBoxPull(switch_checked("pulls")) setSwtichBoxIssue(switch_checked("issues")) setSwtichBoxRelease(switch_checked("releases")) + setSwtichBoxWiki(switch_checked("wiki")) } }, [switch_box]) @@ -68,11 +80,13 @@ export default Form.create()( setIsSpin(true) validateFields((error, values) => { if (!error) { - values.unit_types = switch_box + // values.unit_types = switch_box + values.unit_types = ['code','pulls','issues','releases','wiki']; if (groupId) { // 表示编辑,否则为新建 const url = `/organizations/${OIdentifier}/teams/${groupId}.json`; axios.put(url, { - ...values + ...values, + includes_all_project:values.includes_all_project === 1?true:false }).then(result => { if (result && result.data) { showNotification("基本设置更新成功!"); @@ -82,7 +96,8 @@ export default Form.create()( } else { const url = `/organizations/${OIdentifier}/teams.json`; axios.post(url, { - ...values + ...values, + includes_all_project:values.includes_all_project === 1?true:false }).then(result => { if (result && result.data) { showNotification("团队创建成功!"); @@ -132,6 +147,11 @@ export default Form.create()( setSwtichBoxRelease(checked) } + function switch_wiki_types(checked, event) { + switch_unit_types(checked, "wiki"); + setSwtichBoxWiki(checked); + } + function cancelEdit(){ if(groupId){ history.push(`/${OIdentifier}/group/${groupId}`); @@ -140,6 +160,9 @@ export default Form.create()( } } + function changeAuth(params) { + setAuth(params.target.value) + } function checkname(rule, value, callback){ if(!value){ @@ -192,8 +215,8 @@ export default Form.create()( "includes_all_project", [], - 指定项目(团队成员将只能访问添加到团队的项目。 选择此项 将不会 自动删除已经添加的项目) - 所有项目(团队可以访问所有项目。选择此选项将 添加所有现有的 项目到指定团队) + 指定项目(团队成员将只能访问添加到团队的项目。 选择此项 将不会 自动删除已经添加的项目) + 所有项目(团队可以访问所有项目。选择此选项将 添加所有现有的 项目到指定团队) , false, 0,onwers ? "hide":"" )} {helper( @@ -202,37 +225,42 @@ export default Form.create()( [], 新建项目(成员可以在组织中新建项目。创建者将自动获得新建的项目的管理员权限), false, 20,onwers ? "hide":"" )} - {/* {helper( + {helper( '版本库权限:', "authorize", [], - + 读取权限(成员可以查看和克隆团队项目) 写入权限(成员可以查看和推送提交到团队项目) 管理员权限(成员可以拉取和推送到团队项目同时可以添加协作者) , false, 20,onwers ? "hide":"" - )} */} + )} - {/*

    允许访问项目单元:

    - - - 代码库(查看源码、文件、提交和分支) - - - - 任务(组织 bug 报告、任务和里程碑) - - - - 合并请求(启用合并请求和代码评审) - - - - 版本发布(跟踪项目版本和下载) - - */} + {/*
    +

    允许访问项目单元:

    + + + 代码库(查看源码、文件、提交和分支) + + + + 任务(组织 bug 报告、任务和里程碑) + + + + 合并请求(启用合并请求和代码评审) + + + + 版本发布(跟踪项目版本和下载) + + + + wiki(编辑此仓库的相关文档说明) + +
    */} - cancelEdit()}>取消 + cancelEdit()}>取消 diff --git a/src/forge/Team/Index.scss b/src/forge/Team/Index.scss index a046f99d8..112379734 100644 --- a/src/forge/Team/Index.scss +++ b/src/forge/Team/Index.scss @@ -368,5 +368,5 @@ } } .hide{ - display: hidden; + display: none; } \ No newline at end of file diff --git a/src/forge/Team/List.jsx b/src/forge/Team/List.jsx index b43fb75d1..8cf96587a 100644 --- a/src/forge/Team/List.jsx +++ b/src/forge/Team/List.jsx @@ -75,7 +75,7 @@ function List(props){

    - { organizeDetail && organizeDetail.is_admin ? + { organizeDetail && organizeDetail.can_create_project ? + 新建项目 diff --git a/src/forge/Team/RightBox.jsx b/src/forge/Team/RightBox.jsx index c4e70fd02..57239d38f 100644 --- a/src/forge/Team/RightBox.jsx +++ b/src/forge/Team/RightBox.jsx @@ -97,7 +97,12 @@ function RightBox({ OIdentifier , history , admin }) { return(

    - {item.name} + { + (item.is_admin || item.is_member) ? + {item.name} + : + {item.name} + } {item.num_users}名成员 {item.num_projects}个仓库 diff --git a/src/forge/Team/Setting/TeamSettingCommon.jsx b/src/forge/Team/Setting/TeamSettingCommon.jsx index a9eca4004..5bab8f53f 100644 --- a/src/forge/Team/Setting/TeamSettingCommon.jsx +++ b/src/forge/Team/Setting/TeamSettingCommon.jsx @@ -168,7 +168,7 @@ export default Form.create()( '权限:', "repo_admin_change_team_access", [], - 仓库管理员可以添加或移除团队的访问权限,false,true + 项目管理员可以添加或移除团队的访问权限,false,true )} {helper( diff --git a/src/forge/Team/TeamGroupItems.jsx b/src/forge/Team/TeamGroupItems.jsx index f7f12b2d2..78085b773 100644 --- a/src/forge/Team/TeamGroupItems.jsx +++ b/src/forge/Team/TeamGroupItems.jsx @@ -75,7 +75,12 @@ function TeamGroupItems({organizeDetail,limit, count , history}){ return(

    - {item.nickname} + { + (item.is_admin || item.is_member) ? + {item.nickname} + : + {item.nickname} + } { item.is_admin && item.authorize!=="owner" && disMissGroup(item.id)}>解散团队} { item.is_member && } diff --git a/src/forge/Wiki/Index.jsx b/src/forge/Wiki/Index.jsx index 6eb76ee59..417f79671 100644 --- a/src/forge/Wiki/Index.jsx +++ b/src/forge/Wiki/Index.jsx @@ -2,7 +2,7 @@ import React, { useEffect, useCallback, useState } from 'react'; import { Button, Dropdown, Icon, Input, Menu, Tooltip, Select, Upload, message, Spin } from 'antd'; import { getImageUrl, timeAgo } from 'educoder'; import cookie from 'react-cookies'; -// import Loading from "../../Loading"; +import CopyTool from '../Component/CopyTool'; import DelModal from './components/ModalFun'; import Welcome from './Welcome'; import { wikiPages, getWiki, deleteWiki } from './api'; @@ -14,15 +14,12 @@ const InputGroup = Input.Group; const { Option } = Select; export default (props) => { - const { match, current_user, history, showNotification, project, projectDetail } = props; - // const permission = projectDetail && projectDetail.permission !== "Reporter"; + const { match, history, showNotification, project, projectDetail } = props; const permission = projectDetail && projectDetail.permission && projectDetail.permission !== "Reporter"; let projectsId = match.params.projectsId; let owner = match.params.owner; - console.log(project); - const [fileArrInit, setFileArrInit] = useState(null); const [checkItem, setCheckItem] = useState({}); const [itemDetail, setItemDetail] = useState({}); @@ -85,7 +82,7 @@ export default (props) => { DelModal({ title: '删除页面', contentTitle: `您确定要删除“${item.name}”此页面吗?`, - content: '此操作将删除该页面,请进行确认以防文件的丢失。', + content: '此操作将删除该页面,请进行确认以防文件的丢失', onOk: () => { deleteWiki({ owner: owner, @@ -109,17 +106,6 @@ export default (props) => { window.location.href = `/${login}`; } - // 复制链接 - const copyUrl = useCallback(() => { - let wikiUrl = document.getElementById("wikiUrl"); - wikiUrl.select(); - if (document.execCommand('copy')) { - document.execCommand('copy'); - } - message.success('复制成功'); - wikiUrl.blur(); - }, []) - function addFile() { history.push(`/projects/${owner}/${projectsId}/wiki/add`); } @@ -231,6 +217,7 @@ export default (props) => { +

    @@ -246,8 +233,8 @@ export default (props) => { { fileArr.map(item => { - return
    -
    { setCheckItem(item) }}> + return
    +
    { setCheckItem(item) }}>
    {item.name} @@ -266,9 +253,7 @@ export default (props) => { - - - + }
    @@ -277,11 +262,11 @@ export default (props) => {

    {checkItem.name}

    - { goUser(current_user.login) }}> + { checkItem.commit && goUser(checkItem.commit.author.name) }}> {itemDetail.image_url && 头像} - {checkItem.commit ? checkItem.commit.author.name : ''} + {itemDetail.userName} - 上次修改于{checkItem.commit && timeAgo(checkItem.commit.author.when)} + 上次修改于{checkItem.commit ? timeAgo(checkItem.commit.author.when):'刚刚'}
    {permission && }
    diff --git a/src/forge/Wiki/Index.scss b/src/forge/Wiki/Index.scss index c571da25f..e40de299f 100644 --- a/src/forge/Wiki/Index.scss +++ b/src/forge/Wiki/Index.scss @@ -199,7 +199,7 @@ body { word-break: break-all; } - .copy-svg { + .copy-wiki { display: inline-flex; align-items: center; justify-content: center; diff --git a/src/forge/Wiki/Preview.jsx b/src/forge/Wiki/Preview.jsx index 20645246a..e7c6a6236 100644 --- a/src/forge/Wiki/Preview.jsx +++ b/src/forge/Wiki/Preview.jsx @@ -1,5 +1,6 @@ import React, { useEffect, useCallback, useState } from 'react'; -import { Input, Button, Tooltip, Select, Dropdown, Icon, Menu, message } from 'antd'; +import { Input, Button, Select, Dropdown, Icon, Menu, message } from 'antd'; +import CopyTool from '../Component/CopyTool'; import { wikiPages, getWiki, } from './api'; import { httpUrl } from './fetch'; import './Index.scss'; @@ -59,16 +60,6 @@ export default (props) => { }); }, [project, checkItem]); - const copyUrl = useCallback(() => { - let wikiUrl = document.getElementById("wikiUrl"); - wikiUrl.select(); - if (document.execCommand('copy')) { - document.execCommand('copy'); - } - message.success('复制成功'); - wikiUrl.blur(); - }, []); - function goEdit() { history.push(`/projects/${owner}/${projectsId}/wiki/edit/${checkItem.name}`); } @@ -113,9 +104,7 @@ export default (props) => { - - - + } diff --git a/src/forge/Wiki/components/Login/index.jsx b/src/forge/Wiki/components/Login/index.jsx index 9574a9a51..abfa52957 100644 --- a/src/forge/Wiki/components/Login/index.jsx +++ b/src/forge/Wiki/components/Login/index.jsx @@ -1,10 +1,9 @@ import React, { useState } from 'react'; import * as ReactDOM from 'react-dom'; import LoginDialog from '../../../../modules/login/LoginDialog'; -import './index.scss'; -// 使用函数调用删除组件 -export default function DelModal(props) { +// 使用函数调用登录组件 +export default function Login(props) { const div = document.createElement('div'); document.body.appendChild(div); @@ -16,9 +15,6 @@ export default function DelModal(props) { } function render() { - /** - * Sync render blocks React event. Let's make this async. - */ setTimeout(() => { ReactDOM.render( diff --git a/src/forge/Wiki/components/Login/index.scss b/src/forge/Wiki/components/Login/index.scss deleted file mode 100644 index 13d160665..000000000 --- a/src/forge/Wiki/components/Login/index.scss +++ /dev/null @@ -1,56 +0,0 @@ -.delete-modal { - .ant-modal-header { - padding: 9px 24px; - background: #f8f8f8; - border-bottom: 1px solid #eee; - } - .ant-modal-title { - text-align: left; - } - .ant-modal-close { - top: 0px !important; - } - .ant-modal-close-x { - font-size: 24px; - } - .ant-modal-body { - text-align: center; - } - .delete-title { - display: flex; - justify-content: center; - align-items: center; - margin: 2rem 0 1rem !important; - font-size: 16px; - color: #333; - letter-spacing: 0; - line-height: 29px; - font-weight: 400; - } - .red-circle { - align-self: flex-start; - color: #ca0002; - font-size: 1.5rem !important; - } - .delete-descibe { - font-size: 14px; - color: #666; - line-height: 33px; - font-weight: 400; - } - .ant-modal-footer { - padding: 2rem 0; - text-align: center; - border: 0; - .ant-btn { - width: 6rem; - } - } - .foot-submit { - margin-left: 3rem; - color: #df0002; - &:hover { - border-color: #df0002; - } - } -} \ No newline at end of file diff --git a/src/forge/Wiki/components/ModalFun/index.jsx b/src/forge/Wiki/components/ModalFun/index.jsx index 661eca31b..d9a62e8fd 100644 --- a/src/forge/Wiki/components/ModalFun/index.jsx +++ b/src/forge/Wiki/components/ModalFun/index.jsx @@ -1,23 +1,33 @@ +/* eslint-disable react/jsx-no-duplicate-props */ import React, { useState } from 'react'; import * as ReactDOM from 'react-dom'; import { Modal, Button } from 'antd'; import './index.scss'; +InitModal.defaultProps = { + okText: '确认', //确定按钮的文字 + cancelText: '取消', //取消按钮的文字 + className: '', // + inputId: 'copyText', //要复制的文本的ID +}; + // 使用函数调用删除组件 export default function DelModal(props) { renderModal({ ...props, type: 'delete' }) } -export function confirmModal(props) { +// 使用函数调用选择模态框组件 +export function Confirm(props) { renderModal({ ...props, type: 'confirm' }) } function renderModal(props) { - const type = props.type; + const { type, afterClose } = props; const div = document.createElement('div'); document.body.appendChild(div); function destroy() { + afterClose && afterClose(); const unmountResult = ReactDOM.unmountComponentAtNode(div); if (unmountResult && div.parentNode) { div.parentNode.removeChild(div); @@ -26,18 +36,26 @@ function renderModal(props) { function modalType(type) { if (type === 'delete') { - return + return + + {props.contentTitle} + } + /> } else if (type === 'confirm') { - return + return } else { - return + return } } function render() { - /** - * Sync render blocks React event. Let's make this async. - */ setTimeout(() => { ReactDOM.render( modalType(type), @@ -48,16 +66,17 @@ function renderModal(props) { render(); } -// 真正的删除组件 -function DeleteModal({ +// 选择模态框组件 +function InitModal({ onCancel, onOk, title, contentTitle, content, - afterClose, okText, cancelText, + afterClose, + className, }) { const [visible, setVisible] = useState(true); @@ -78,71 +97,20 @@ function DeleteModal({ onCancel={onCancelModal} afterClose={afterClose} title={title} - className="myself-modal" + className={`myself-modal ${className}`} centered footer={[ - , , ]} >
    -

    - - {contentTitle}

    -

    {content}

    -
    - - ) -} - -// 选择组件 -function ConfirmModal({ - onCancel, - onOk, - title, - contentTitle, - content, - okText, - cancelText, - afterClose, -}) { - - const [visible, setVisible] = useState(true); - - function onCancelModal() { - setVisible(false); - onCancel && onCancel() - } - - function onSuccess() { - setVisible(false); - onOk && onOk(); - } - - return ( - - {cancelText||'取消'} - , - , - ]} - > -
    - {contentTitle &&

    {contentTitle}

    } -

    {content}

    + {contentTitle &&

    {contentTitle}

    } +

    {content}

    ) diff --git a/src/forge/Wiki/components/ModalFun/index.scss b/src/forge/Wiki/components/ModalFun/index.scss index a598d2bf0..24f7b0219 100644 --- a/src/forge/Wiki/components/ModalFun/index.scss +++ b/src/forge/Wiki/components/ModalFun/index.scss @@ -16,7 +16,7 @@ .ant-modal-body { text-align: center; } - .delete-title { + .content-title { display: flex; justify-content: center; align-items: center; @@ -32,7 +32,7 @@ color: #ca0002; font-size: 1.5rem !important; } - .delete-descibe { + .content-descibe { font-size: 14px; color: #666; line-height: 33px; @@ -53,4 +53,11 @@ border-color: #df0002; } } + .ant-btn-default:hover, + .ant-btn-default:active, + .ant-btn-default:focus { + background: #f3f4f6; + color: #333; + border-color: #d0d0d0; + } } \ No newline at end of file diff --git a/src/forge/users/Team.jsx b/src/forge/users/Team.jsx index 9378106e3..bf401d2cd 100644 --- a/src/forge/users/Team.jsx +++ b/src/forge/users/Team.jsx @@ -5,6 +5,7 @@ import Search from '../Component/Search'; import Item from './Team-item'; import Nodata from '../Nodata'; import axios from 'axios'; +import { Link } from 'react-router-dom'; const limit = 15; function Team(props){ @@ -14,7 +15,7 @@ function Team(props){ const [ sort_direction , setSort_direction ] = useState("asc"); const [ sort_by ,setSort_by ] = useState("created_at"); const [ search ,setSearch ] = useState(undefined); - + const { checkIfLogin , showLoginDialog } = props; const { username } = props.match.params; useEffect(()=>{ if(username){ @@ -47,14 +48,6 @@ function Team(props){ ) - function newFunc() { - const { checkIfLogin , showLoginDialog } = props; - if(checkIfLogin()){ - props.history.push(`/organize/new`); - }else{ - showLoginDialog && showLoginDialog(); - } - } return(
    @@ -62,7 +55,10 @@ function Team(props){ setSearch(e.target.value)} placeholder="请输入组织名称关键字进行搜索" onSearch={onSearch}/>

    - 新建组织 + { + checkIfLogin() && + 新建组织 + } 排序