dev_forge
sylor_huang@126.com 5 years ago
commit e523011736

@ -470,10 +470,10 @@ http://localhost:3000/api/projects/3263 | jq
|参数名|必选|类型|说明|
-|-|-|-
|id |是|int |项目id |
|name ||string |项目名称 |
|description ||string |项目描述 |
|project_category_id||int |项目类别id |
|project_language_id||int |项目语言id |
|name ||string |项目名称 |
|description ||string |项目描述 |
|project_category_id||int |项目类别id |
|project_language_id||int |项目语言id |
|private |否|boolean|项目是否私有, true为私有false: 公开,默认为公开 |
@ -1274,11 +1274,15 @@ http://localhost:3000/api/18816895620/mirror_demo | jq
|参数名|类型|说明|
-|-|-
|identifier |string|仓库标识|
|project_id |int|项目id|
|project_identifier|string|项目标识|
|praises_count |int|点赞数量|
|forked_count |int|fork数量|
|watchers_count |int|关注数量|
|branches_count |int|分支数量|
|commits_count |int|总提交记录数量|
|praised |boolean|当前登录用户是否已点赞true:已点赞fasle:未点赞, 用户未登录状态为null|
|watched |boolean|当前登录用户是否已关注true:已关注fasle:未关注, 用户未登录状态为null|
|permission |string|当前登录用户对该仓库的操作权限, Manager:管理员,可以在线编辑文件、在线新建文件、可以设置仓库的基本信息; Developer:开发人员,可在线编辑文件、在线新建文件、不能设置仓库信息; Reporter: 报告人员只能查看信息不能设置仓库信息、不能在线编辑文件、不能在线新建文件用户未登录时也会返回Reporter, 说明也只有读取文件的权限 |
|mirror_url |string|镜像地址, 只有通过镜像过来的项目才会有这个地址|
|author |object|提交用户|
@ -1289,6 +1293,8 @@ http://localhost:3000/api/18816895620/mirror_demo | jq
返回值
```
{
"project_id": 3263,
"project_identifier": "mirror_demo",
"identifier": "mirror_demo",
"praises_count": 1,
"forked_count": 0,
@ -1296,6 +1302,8 @@ http://localhost:3000/api/18816895620/mirror_demo | jq
"branches_count": 6,
"commits_count": 105,
"permission": "Manager",
"watched": true,
"praised": true,
"mirror_url": "https://gitea.com/CasperVector/slew.git",
"author": {
"name": "18816895620",
@ -1488,7 +1496,7 @@ http://localhost:3000/api/projects/3263/praise_tread | jq
|参数名|类型|说明|
-|-|-
|total_count |int|总条数|
|praises |array|关注数据|
|praises |array|点赞数据|
|-- name |string|用户名称|
|-- login |string|用户标识/登录名(login)|
|-- image_url |string|用户头像|

@ -328,7 +328,8 @@ class ApplicationController < ActionController::Base
def current_user
# User.current
User.find_by_id 50207
User.find_by_id 36401
# nil
end
## 默认输出json
@ -355,21 +356,21 @@ class ApplicationController < ActionController::Base
# 通关后,把最后一次成功的代码存到数据库
# type 0 创始内容, 1 最新内容
def game_passed_code(path, myshixun, game_id)
# 如果代码窗口是隐藏的,则不用保存代码
return if myshixun.shixun.hide_code || myshixun.shixun.vnc
file_content = git_fle_content myshixun.repo_path, path
#unless file_content.present?
# raise("获取文件代码异常")
#end
logger.info("#######game_id:#{game_id}, file_content:#{file_content}")
game_code = GameCode.where(:game_id => game_id, :path => path).first
if game_code.nil?
GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path)
else
game_code.update_attributes!(:new_code => file_content)
end
end
# def game_passed_code(path, myshixun, game_id)
# # 如果代码窗口是隐藏的,则不用保存代码
# return if myshixun.shixun.hide_code || myshixun.shixun.vnc
# file_content = git_fle_content myshixun.repo_path, path
# #unless file_content.present?
# # raise("获取文件代码异常")
# #end
# logger.info("#######game_id:#{game_id}, file_content:#{file_content}")
# game_code = GameCode.where(:game_id => game_id, :path => path).first
# if game_code.nil?
# GameCode.create!(:game_id => game_id, :new_code => file_content, :path => path)
# else
# game_code.update_attributes!(:new_code => file_content)
# end
# end
# Post请求
def uri_post(uri, params)
@ -647,19 +648,20 @@ class ApplicationController < ActionController::Base
render_not_found("未找到’#{params[:id]}’相关的项目") unless @project
end
def find_project_with_identifier
@project = Project.find_by_identifier! params[:id]
render_not_found("未找到’#{params[:id]}’相关的项目") unless @project
end
def find_project_with_id
@project = Project.find params[:project_id]
@project = Project.find(params[:project_id] || params[:id])
rescue Exception => e
logger_error(e.message)
tip_exception(e.message)
end
def render_response(interactor)
if interactor.success?
render_ok
else
render_error(interactor.error)
end
interactor.success? ? render_ok : render_error(interactor.error)
end
private

@ -3,6 +3,7 @@ class RepositoriesController < ApplicationController
before_action :find_user, :find_repository, :authorizate!
def show
@project = @repo.project
@branches_count = Gitea::Repository::BranchesService.new(@user, @repo.identifier).call.size
@commits_count = Gitea::Repository::Commits::ListService.new(@user, @repo.identifier).call[:total_count]
end

@ -8,11 +8,11 @@ module ProjectsHelper
end
def render_zip_url(project, archive_name)
[gitea_domain, project.owner.login, project.identifier, "#{archive_name}.zip"].join('/')
[gitea_domain, project.owner.login, project.identifier, "archive", "#{archive_name}.zip"].join('/')
end
def render_tar_url(project, archive_name)
[gitea_domain, project.owner.login, project.identifier, "#{archive_name}.tar.gz"].join('/')
[gitea_domain, project.owner.login, project.identifier, "archive", "#{archive_name}.tar.gz"].join('/')
end
def render_http_url(project)

@ -1,9 +1,13 @@
json.identifier @repo.identifier
json.project_id @project.id
json.project_identifier @project.identifier
json.praises_count @repo.project.praises_count
json.forked_count @repo.project.forked_count
json.watchers_count @repo.project.watchers_count
json.branches_count @branches_count
json.commits_count @commits_count
json.permission render_edit_project_permission(current_user, @repo.project)
json.permission render_edit_project_permission(current_user, @project)
json.mirror_url @repo.mirror_url
json.watched current_user&.watched?(@project)
json.praised current_user&.liked?(@project)
json.partial! 'author', locals: { user: @repo.user }

@ -12,6 +12,10 @@ const FileNew = Loadable({
loader: () => import('../Newfile/Index'),
loading: Loading,
})
const OrderNew = Loadable({
loader: () => import('../Order/New'),
loading: Loading,
})
const OrderIndex = Loadable({
loader: () => import('../Order/order'),
loading: Loading,
@ -30,7 +34,10 @@ class Detail extends Component{
projectDetail:undefined,
isManager:false,
isReporter:false,
isDeveloper:false
isDeveloper:false,
watchers_count:undefined ,
praises_count:undefined ,
forked_count:undefined
}
}
@ -48,16 +55,60 @@ class Detail extends Component{
projectDetail:result.data,
isManager:result.data.permission && result.data.permission === "Manager",
isReporter:result.data.permission && result.data.permission === "Reporter",
isDeveloper:result.data.permission && result.data.permission === "Developer"
isDeveloper:result.data.permission && result.data.permission === "Developer",
watchers_count:result.data.watchers_count,
praises_count:result.data.praises_count,
forked_count:result.data.forked_count,
})
}
}).catch((error)=>{})
}
// 关注和取消关注
focusFunc =(flag)=>{
const { projectsId } = this.props.match.params;
if(flag){
const url = `/projects/${projectsId}/watchers/follow.json`;
axios.post(url).then(result=>{
if(result){
this.props.showNotification('关注成功');
}
})
}else{
const url = `/projects/${projectsId}/watchers/unfollow.json`;
axios.delete(url).then(result=>{
if(result){
this.props.showNotification('取消关注成功');
}
})
}
}
// 点赞和取消点赞
pariseFunc=(flag)=>{
const { projectsId } = this.props.match.params;
if(flag){
const url = `/projects/${projectsId}/praise_tread/like.json`;
axios.post(url).then(result=>{
if(result){
this.props.showNotification('点赞成功');
}
})
}else{
const url = `/projects/${projectsId}/praise_tread/unlike.json`;
axios.delete(url).then(result=>{
if(result){
this.props.showNotification('取消点赞成功');
}
})
}
}
render(){
const { projectsId } = this.props.match.params;
const { projectDetail } = this.state;
const { projectDetail , watchers_count , praises_count , forked_count } = this.state;
const url = this.props.history.location.pathname;
return(
<div>
@ -65,10 +116,19 @@ class Detail extends Component{
<div className="normal f-wrap-between mb20">
<p className="font-18 color-blue df flex-1" style={{alignItems:"center"}}>{projectDetail && projectDetail.author && projectDetail.author.name} / <span className="hide-1 flex-1">{ projectDetail && projectDetail.identifier }</span></p>
<span className="p-r-tags large">
<span><label>关注</label><span>{projectDetail && projectDetail.watchers_count}</span></span>
<span><label>点赞</label><span>{projectDetail && projectDetail.praises_count}</span></span>
<span><label>Fork</label><span>{projectDetail && projectDetail.forked_count}</span></span>
<span className="p-r-btn large">
<span>
<a onClick={()=>this.focusFunc(true)}><i className="iconfont icon-xianshi font-18 mr5 color-grey-6"></i></a>
<span>{watchers_count}</span>
</span>
<span>
<a onClick={()=>this.pariseFunc(true)}><i className="iconfont icon-dianzan-xian font-18 mr5 color-grey-6"></i></a>
<span>{praises_count}</span>
</span>
<span>
<a><i className="iconfont icon-fork font-18 mr5 color-grey-6"></i>Fork</a>
<span>{forked_count}</span>
</span>
</span>
</div>
<div className="normal f-wrap-between">
@ -83,6 +143,7 @@ class Detail extends Component{
</div>
<Switch {...this.props}>
{/* 新建文件 */}
<Route path="/projects/:projectsId/coder/:branch/newfile/:path"
render={
(props) => (<FileNew {...this.props} {...props} {...this.state}/>)
@ -93,6 +154,16 @@ class Detail extends Component{
(props) => (<FileNew {...this.props} {...props} {...this.state}/>)
}
></Route>
{/* 新建工单 */}
<Route path="/projects/:projectsId/orders/new"
render={
(props) => (<OrderNew {...this.props} {...props} {...this.state}/>)
}
></Route>
{/* 代码Index */}
<Route path="/projects/:projectsId/orders"
render={
(props) => (<OrderIndex {...this.props} {...props} {...this.state}/>)

@ -111,6 +111,32 @@ body,#root{
flex: 1;
width: 0;
}
.p-r-btn{
display: flex;
align-items: center;
}
.p-r-btn > span{
height: 35px;
line-height: 35px;
border:1px solid #f4f4f4;
border-radius: 5px;
display: block;
margin-left: 20px;
background-color: #fff;
display: flex;
}
.p-r-btn > span > a{
display: flex;
align-items: center;
padding:0px 12px;
background:#ececec;
}
.p-r-btn > span > a:active{
background: #f4f4f4;
}
.p-r-btn > span > span{
padding:0px 8px;
}
.p-r-tags{
display: flex;
opacity: 1;

@ -1,5 +1,5 @@
import React , { Component } from 'react';
import { Link } from 'react-router-dom';
import { Input , Form , Select , Checkbox , Button , Divider } from 'antd';
import '../css/index.css';
@ -285,7 +285,7 @@ class Index extends Component{
<p className="formTip">只有企业所有人或拥有权限的企业成员才能看到</p>
<Form.Item className="formTip">
<Button type="primary" onClick={this.subMitFrom} className="mr20">创建项目</Button>
<a className="btn_32" onClick={() => this.props.onCancel()}>取消</ a>
<Link to={'/projects'} className="btn_32">取消</Link>
</Form.Item>
</div>

@ -0,0 +1,14 @@
import React , { Component } from "react";
import { Link } from 'react-router-dom';
import './order.css'
class Nav extends Component{
render(){
return(
<p className="topWrapper_nav">
<Link to={``} >标签</Link>
<Link to={``}>里程</Link>
</p>
)
}
}
export default Nav;

@ -0,0 +1,16 @@
import React , { Component } from "react";
import Nav from './Nav';
class New extends Component{
render(){
return(
<div className="main">
<div className="topWrapper">
<Nav />
</div>
</div>
)
}
}
export default New;

@ -28,7 +28,7 @@
}
.topWrapper_btn {
background: #21ba45;
color: #FFFFFF;
color: #FFFFFF!important;
padding:0px 12px;
text-align: center;
height: 32px;

@ -3,15 +3,12 @@ import {Link} from 'react-router-dom';
import { Input ,Dropdown , Menu , Icon } from 'antd';
import './order.css';
import Nav from './Nav';
import axios from 'axios';
const Search = Input.Search;
const tagList= ['release','test'];
const typeList= ['普通','悬赏'];
const categoryList=['缺陷','支持','任务','功能','周报'];
const levelList=['低','正常','高','紧急','立刻'];
const percentList=['0%','10%','20%','30%','40%','50%','60%','70%','80%','90%','100%'];
class order extends Component{
constructor(props){
super(props);
@ -79,10 +76,7 @@ class order extends Component{
return(
<div className="main">
<div className="topWrapper">
<p className="topWrapper_nav">
<Link to={``} >标签</Link>
<Link to={``}>里程</Link>
</p>
<Nav />
<Link to={``} className="topWrapper_btn">创建工单</Link>
</div>
<div className="topWrapper" style={{borderBottom:"none"}}>

Loading…
Cancel
Save