dev_forge
caicai8 5 years ago
commit ef13ccedb9

@ -379,49 +379,342 @@ http://localhost:3000/api/projects/migrate | jq
```
---
#### 项目类别列表(用于项目列表左侧导航中的项目类别列表)
```
GET api/project_categories/group_list
```
*示例*
```
curl -X GET http://localhost:3000/api/project_categories/group_list | jq
```
*返回参数说明:*
|参数名|类型|说明|
-|-|-
|id |int |项目分类id |
|name |string|项目分类名称|
|projects_count |int |项目数量|
返回值
```
[
{
"id": 1,
"name": "大数据",
"projects_count": 30
},
{
"id": 2,
"name": "机器学习",
"projects_count": 1
},
{
"id": 3,
"name": "深度学习",
"projects_count": 1
}
]
```
---
#### 项目类型列表(用于项目列表左侧导航上方中的项目类型列表)
```
GET api/projects/group_type_list
```
*示例*
```
curl -X GET http://localhost:3000/api/projects/group_type_list | jq
```
*返回参数说明:*
|参数名|类型|说明|
-|-|-
|project_type |string|项目类型 |
|name |string|项目类型名称|
|projects_count |int |项目数量|
返回值
```
[
{
"project_type": "common",
"name": "开源托管项目",
"projects_count": 2106
},
{
"project_type": "mirror",
"name": "开源镜像项目",
"projects_count": 1
}
]
```
---
#### 项目列表
```
GET api/projects
```
*示例*
```
curl -X POST \
-d "user_id=36401" \
-d "clone_addr=https://gitea.com/CasperVector/slew.git" \
-d "name=ni项目" \
-d "description=my first project" \
-d "repository_name=mirror_demo" \
-d "project_category_id=1" \
-d "project_language_id=2" \
http://localhost:3000/api/projects/migrate | jq
curl -X GET \
-d "page=1" \
-d "limit=5" \
http://localhost:3000/api/projects | jq
```
*请求参数说明:*
|参数名|必选|类型|说明|
-|-|-|-
|user_id |是|int |用户id或者组织id |
|name |是|string |项目名称 |
|clone_addr |是|string |镜像项目clone地址 |
|description |否|string |项目描述 |
|repository_name |是|string |仓库名称, 只含有数字、字母、下划线不能以下划线开头和结尾,且唯一 |
|project_category_id|是|int |项目类别id |
|project_language_id|是|int |项目语言id |
|private |否|boolean|项目是否私有, true为私有false: 非私有,默认为公开 |
|page |否|string |页数,第几页 |
|limit |否|string |每页多少条数据默认15条 |
|sort_by |否|string |排序类型, 取值updated_on \| created_on \| forked_count \| praises_count, updated_on: 更新时间排序created_on: 创建时间排序forked_count: fork数据排序praises_count: 点赞数量排序默认为updated_on更新时间排序 |
|sort_direction|否|string |排序方式,取值为: desc \| asc; desc: 降序排序, asc: 升序排序, 默认为desc |
|name |否|string |项目名称, 按照项目名称搜索 |
|category_id |否|int |项目类别id |
|language_id |否|int |项目语言id |
|project_type |否|string |项目类型, 取值为common \| mirror; common:开源托管项目, mirror:开源镜像项目 |
*返回参数说明:*
|参数名|类型|说明|
-|-|-
|id |int |id |
|id |string |项目标识 |
|name |string|项目名称|
|description |string|项目简介|
|visits |int|流量数|
|forked_count |int|被fork的数量|
|is_public |boolean|是否公开, true:公开false:未公开|
|mirror_url |string|镜像url|
|last_update_time |int|最后更新时间为UNIX格式的时间戳|
|author |object|项目创建者|
|-- name |string|用户名,也是用户标识|
|category |object|项目类别|
|-- id |int|项目类型id|
|-- name |string|项目类型名称|
|language |object|项目语言|
|-- id |int|项目语言id|
|-- name |string|项目语言名称|
返回值
```
[
{
"id": "tongjj",
"name": "统计局",
"description": "my first project",
"visits": 0,
"forked_count": 0,
"is_public": true,
"mirror_url": null,
"last_update_time": 1577415173,
"author": {
"name": "18816895620"
},
"category": {
"id": 1,
"name": "大数据"
},
"language": {
"id": 2,
"name": "C"
}
},
{
"id": null,
"name": "开源同名",
"description": "my first project",
"visits": 0,
"forked_count": 0,
"is_public": false,
"mirror_url": "https://gitea.com/CasperVector/slew.git",
"last_update_time": 1577346228,
"author": {
"name": "18816895620"
},
"category": {
"id": 1,
"name": "大数据"
},
"language": {
"id": 2,
"name": "C"
}
},
{
"id": "mvp_demo",
"name": "开源支持",
"description": "my first project",
"visits": 0,
"forked_count": 0,
"is_public": true,
"mirror_url": null,
"last_update_time": 1577341572,
"author": {
"name": "18816895620"
},
"category": {
"id": 1,
"name": "大数据"
},
"language": {
"id": 2,
"name": "C"
}
},
{
"id": null,
"name": "ni项目1",
"description": "my first project",
"visits": 0,
"forked_count": 0,
"is_public": true,
"mirror_url": "https://gitea.com/CasperVector/slew.git",
"last_update_time": 1577092908,
"author": {
"name": "18816895620"
},
"category": {
"id": 1,
"name": "大数据"
},
"language": {
"id": 2,
"name": "C"
}
},
{
"id": "mirror_demo",
"name": "ni项目",
"description": "my first project",
"visits": 0,
"forked_count": 0,
"is_public": false,
"mirror_url": "https://gitea.com/CasperVector/slew.git",
"last_update_time": 1577085412,
"author": {
"name": "18816895620"
},
"category": {
"id": 1,
"name": "大数据"
},
"language": {
"id": 2,
"name": "C"
}
}
]
```
---
### 获取分支列表
```
GET /api/projects/:identifier/branches
```
*示例*
```
curl -X GET http://localhost:3000/api/projects/mirror_demo/branches | jq
```
*请求参数说明:*
|参数名|必选|类型|说明|
-|-|-|-
|identifier |是|string |项目标识 |
*返回参数说明:*
|参数名|类型|说明|
-|-|-
|name |string|分支名称|
返回值
```
[
{
"name": "develop"
},
{
"name": "master"
}
]
```
---
### 点赞
```
POST /api/praise_tread/like
```
*示例*
```
curl -X POST \
-d 'object_id=1' \
-d 'object_type=project' \
http://localhost:3000/api/praise_tread/like | jq
```
*请求参数说明:*
|参数名|必选|类型|说明|
-|-|-|-
|object_id |是 |int |项目id |
|object_type |否 |string | 点赞类型默认为project|
*返回参数说明:*
|参数名|类型|说明|
-|-|-
|status |int|0:点赞成功,-1:操作失败2:表示已经点过赞了|
返回值
```
{
"id": 3263,
"name": "ni项目"
"status": 0,
"message": "响应成功"
}
```
---
### 取消点赞
```
DELETE /api/praise_tread/unlike
```
*示例*
```
curl -X DELETE \
-d 'object_id=1' \
-d 'object_type=project' \
http://localhost:3000/api/praise_tread/unlike | jq
```
*请求参数说明:*
|参数名|必选|类型|说明|
-|-|-|-
|object_id |是 |string |点赞对象的唯一标识如项目的identifier字段 |
|object_type |是 |string | 点赞类型默认为project|
*返回参数说明:*
|参数名|类型|说明|
-|-|-
|status |int|0:点赞成功,-1:操作失败2:表示还未点赞|
返回值
```
{
"status": 0,
"message": "响应成功"
}
```
---

@ -328,7 +328,7 @@ class ApplicationController < ActionController::Base
def current_user
# User.current
User.find_by_id 50207
User.find_by_id 1
end
## 默认输出json

@ -19,18 +19,18 @@ class IssueTagsController < ApplicationController
def create
title = params[:title].to_s.strip
title = params[:name].to_s.strip
desc = params[:description]
color = params[:color] || "#ccc"
tag_params = {
title: title,
name: title,
description: desc,
color: color
}
if title.present?
if IssueTag.exists?(title: title, project_id: @project.id)
if IssueTag.exists?(name: title, project_id: @project.id)
normal_status(-1, "标签已存在")
else
issue_tag = IssueTag.new(tag_params.merge(project_id: @project.id, user_id: current_user.id))
@ -52,17 +52,17 @@ class IssueTagsController < ApplicationController
end
def update
title = params[:title]
title = params[:name]
desc = params[:description]
color = params[:color] || "#ccc"
tag_params = {
title: title,
name: title,
description: desc,
color: color
}
if title.present?
if IssueTag.exists?(title: title, project_id: @project.id) && (@issue_tag.title != title)
if IssueTag.exists?(name: title, project_id: @project.id) && (@issue_tag.name != title)
normal_status(-1, "标签已存在")
else
if @issue_tag.update_attributes(tag_params)

@ -1,12 +1,124 @@
class IssuesController < ApplicationController
before_action :require_login
before_action :set_project
before_action :check_project_public, only: [:index ,:show]
before_action :check_issue_permission, except: [:index, :show]
before_action :set_issue, only: [:edit, :update, :destroy, :show]
before_action :check_project_public, only: [:index ,:show, :copy, :index_chosen]
before_action :check_issue_permission, except: [:index, :show, :copy, :index_chosen]
before_action :set_issue, only: [:edit, :update, :destroy, :show, :copy, :index_chosen]
def index
issues = @project.issues.includes(:user,:tracker, :priority, :version, :issue_status, :journals)
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@all_issues_size = issues.size
@open_issues_size = issues.where.not(status_id: 5).size
@close_issues_size = issues.where(status_id: 5).size
@assign_to_me_size = issues.where(assigned_to_id: current_user&.id).size
@my_published_size = issues.where(author_id: current_user&.id).size
status_type = params[:status_type].to_s #issue状态的选择
search_name = params[:search].to_s
start_time = params[:start_date]
end_time = params[:due_date]
if status_type.to_s == "1" #表示开启中的
issues = issues.where.not(status_id: 5)
elsif status_type.to_s == "2" #表示关闭中的
issues = issues.where(status_id: 5)
end
if search_name.present?
issues = issues.where("subject like ?", "%#{search_name}%")
end
if start_time&.present? || end_time&.present?
issues = issues.where("start_date between ? and ?",start_time&.present? ? start_time.to_date : Time.now.to_date, end_time&.present? ? end_time.to_date : Time.now.to_date)
end
issues = issues.where(author_id: params[:author_id]) if params[:author_id].present?
issues = issues.where(assigned_to_id: params[:assigned_to_id]) if params[:assigned_to_id].present?
issues = issues.where(tracker_id: params[:tracker_id]) if params[:tracker_id].present?
issues = issues.where(status_id: params[:status_id]) if params[:status_id].present?
issues = issues.where(priority_id: params[:priority_id]) if params[:priority_id].present?
issues = issues.where(fixed_version_id: params[:fixed_version_id]) if params[:fixed_version_id].present?
issues = issues.where(done_ratio: params[:done_ratio].to_i) if params[:done_ratio].present?
issues = issues.where(issue_type: params[:issue_type]) if params[:issue_type].present?
issues = issues.joins(:issue_tags).where(issue_tags: {id: params[:issue_tag_id].to_i}) if params[:issue_tag_id].present?
order_type = params[:order_type] || "desc" #或者"asc"
order_name = params[:order_name] || "created_on" #或者"updated_on"
@page = params[:page]
@limit = params[:limit] || "15"
@issues = issues.order("#{order_name} #{order_type}")
@issues_size = issues.size
@issues = issues.order("#{order_name} #{order_type}").page(@page).per(@limit)
respond_to do |format|
format.json
format.xlsx{
set_export_cookies
export_issues(@issues)
export_name = "#{@project.name}_issues列表_#{Time.now.strftime('%Y%m%d_%H%M%S')}"
render xlsx: "#{export_name.strip}",template: "issues/index.xlsx.axlsx",locals: {table_columns:@table_columns,issues:@export_issues}
}
end
end
def index_chosen
@issue_chosen = issue_left_chosen(@project, nil)
end
def commit_issues
issues = @project.issues.includes(:user,:tracker)
issues = issues.where(is_private: false) unless current_user.present? && (current_user.admin? || @project.member?(current_user))
@all_issues_size = issues.size
@open_issues_size = issues.where.not(status_id: 5).size
@close_issues_size = issues.where(status_id: 5).size
@normal_issues_size = issues.where(issue_type: "1").size
@pay_issues_size = issues.where(issue_type: "2").size
status_type = params[:status_type].to_s
if status_type.to_s == "1" #表示开启中的
issues = issues.where.not(status_id: 5)
elsif status_type.to_s == "2" #表示关闭中的
issues = issues.where(status_id: 5)
elsif status_type.to_s == "3" #普通
issues = issues.where(issue_type: "1")
elsif status_type.to_s == "4" #悬赏
issues = issues.where(issue_type: "2")
end
@commit_issues = []
total_commit_issues = {
name: "合计",
user_login: nil,
all_count: issues.size,
trackers: trackers_size(issues)
}
@commit_issues.push(total_commit_issues)
members = issues.pluck(:assigned_to_id).uniq
members.each do |m|
user = User.select(:id, :login, :firstname, :lastname).find(m)
user_issues = issues.where(assigned_to_id: m) #指派给
member_params = {
name: user.try(:show_real_name),
user_login: user.try(:login),
all_count: issues.size,
trackers: trackers_size(user_issues)
}
@commit_issues.push(member_params)
end
un_assign = issues.where(assigned_to_id: nil)
total_commit_issues = {
name: "未指派",
user_login: nil,
all_count: un_assign.size,
trackers: trackers_size(un_assign)
}
@commit_issues.push(total_commit_issues)
end
@ -17,6 +129,10 @@ class IssuesController < ApplicationController
def create
if params[:subject].blank?
normal_status(-1, "标题不能为空")
elsif params[:subject].to_s.size > 255
normal_status(-1, "标题不能超过255个字符")
elsif (params[:issue_type].to_s == "2") && params[:token].to_i == 0
normal_status(-1, "悬赏的奖金必须大于0")
else
issue_params = {
subject: params[:subject],
@ -30,7 +146,11 @@ class IssuesController < ApplicationController
start_date: params[:start_date].to_s.to_date,
due_date: params[:due_date].to_s.to_date,
estimated_hours: params[:estimated_hours],
done_ratio: params[:done_ratio]
done_ratio: params[:done_ratio],
issue_type: params[:issue_type],
token: params[:token],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",") : "",
closed_on: (params[:status_id].to_i == 5) ? Time.now : nil,
}
@issue = Issue.new(issue_params.merge(author_id: current_user.id, project_id: @project.id))
if @issue.save!
@ -43,6 +163,11 @@ class IssuesController < ApplicationController
end
end
end
if params[:issue_tag_ids].present?
params[:issue_tag_ids].each do |tag|
IssueTagsRelate.create!(issue_id: @issue.id, issue_tag_id: tag)
end
end
if params[:assigned_to_id].present?
Tiding.create!(user_id: params[:assigned_to_id], trigger_user_id: current_user.id,
container_id: @issue.id, container_type: 'Issue',
@ -75,7 +200,11 @@ class IssuesController < ApplicationController
start_date: params[:start_date].to_s.to_date,
due_date: params[:due_date].to_s.to_date,
estimated_hours: params[:estimated_hours],
done_ratio: params[:done_ratio]
done_ratio: params[:done_ratio],
closed_on: (params[:status_id].to_i == 5) ? Time.now : nil,
issue_type: params[:issue_type],
issue_tags_value: params[:issue_tag_ids].present? ? params[:issue_tag_ids].join(",").to_s : "",
token: params[:token]
}
if @issue.update_attributes(issue_params)
@ -102,6 +231,19 @@ class IssuesController < ApplicationController
end
end
end
if params[:issue_tag_ids].present?
issue_current_tags = @issue&.issue_tags&.select(:id)&.pluck(:id)
new_tag_ids = params[:issue_tag_ids] - issue_current_tags
old_tag_ids = issue_current_tags - params[:issue_tag_ids]
if old_tag_ids.size > 0
@issue.issue_tags_relates.where(issue_tag_id: old_tag_ids).delete_all
end
if new_tag_ids.size > 0
new_tag_ids.each do |tag|
IssueTagsRelate.create(issue_id: @issue.id, issue_tag_id: tag)
end
end
end
@issue.create_journal_detail(change_files, issue_files, issue_file_ids)
normal_status(0, "更新成功")
@ -115,7 +257,6 @@ class IssuesController < ApplicationController
@issue_attachments = @issue.attachments
@issue_user = @issue.user
@issue_assign_to = @issue.get_assign_user
@journals = @issue.journals.journal_includes.order("created_on desc")
end
def destroy
@ -124,9 +265,16 @@ class IssuesController < ApplicationController
else
normal_status(-1, "删除失败")
end
end
def copy
@new_issue = @issue.dup
if @new_issue.save
@status = 1
else
@status = -1
end
end
private
def set_project
@ -156,9 +304,11 @@ class IssuesController < ApplicationController
end
def issue_left_chosen(project,issue_id)
issue_info = Array.new(9)
issue_info = Array.new(11)
use_tags = []
if issue_id.present?
select_arrays = [:assigned_to_id, :tracker_id, :status_id, :priority_id, :fixed_version_id, :start_date, :due_date, :estimated_hours, :done_ratio]
use_tags = Issue.find(issue_id).issue_tags.select(:id).pluck(:id)
select_arrays = [:assigned_to_id, :tracker_id, :status_id, :priority_id, :fixed_version_id, :start_date, :due_date, :estimated_hours, :done_ratio, :issue_type, :token]
issue_info = Issue.select(select_arrays).where(id: issue_id).pluck(select_arrays)
issue_info = issue_info[0]
end
@ -196,13 +346,12 @@ class IssuesController < ApplicationController
end
end
issue_priority = project.issue_tags&.pluck(:id,:title, :color)
new_priority_info = [] #issue标签优先程度
issue_priority = IssuePriority&.pluck(:id,:name, :position)
new_priority_info = [] #优先度
if issue_priority.size > 0
issue_priority.each do |t|
is_chosen = (t[0] == issue_info[3]) ? "1" : "0"
new_issue = {id: t[0], name: t[1], color: t[2], is_chosen: is_chosen}
new_issue = {id: t[0], name: t[1], position: t[2], is_chosen: is_chosen}
new_priority_info.push(new_issue)
end
end
@ -223,23 +372,70 @@ class IssuesController < ApplicationController
if issue_done_ratio.size > 0
issue_done_ratio.each do |t|
is_chosen = (t == issue_info[8].to_s) ? "1" : "0"
new_issue = {ratio: (t.to_s + "%"), is_chosen: is_chosen}
new_issue = {id:t.to_i, ratio: (t.to_s + "%"), is_chosen: is_chosen}
new_done_info.push(new_issue)
end
end
issue_tags = project.issue_tags&.pluck(:id,:name, :color)
new_tags_info = [] #issue标签
if issue_tags.size > 0
issue_tags.each do |t|
is_chosen = (use_tags.size > 0 && use_tags.include?(t[0])) ? "1" : "0"
new_issue = {id: t[0], name: t[1], color: t[2], is_chosen: is_chosen}
new_tags_info.push(new_issue)
end
end
issue_types = %w(普通 悬赏)
new_types_info = [] #issue标签
issue_types.each_with_index do |i, index|
is_chosen = (issue_info[9] == "#{index+1}") ? "1" : "0"
is_token = (index.to_s == "1") ? issue_info[10] : nil
new_type_info = {id: index+1, name: i, token: is_token, is_chosen: is_chosen}
new_types_info.push(new_type_info)
end
{
"assign_user": project_members_info,
"tracker": new_tracker_info,
"issue_status": new_status_info,
"issue_tag": new_priority_info,
"priority": new_priority_info,
"issue_version": new_version_info,
"start_date": issue_info[5],
"due_date": issue_info[6],
"estimated_hours": issue_info[7],
"done_ratio": new_done_info
"done_ratio": new_done_info,
"issue_tag": new_tags_info,
"issue_type": new_types_info
}
end
def export_issues(issues)
@table_columns = %w(ID 类型 标题 描述 状态 指派给 优先级 标签 发布人 创建时间 里程碑 开始时间 截止时间 完成度 分类 金额)
@export_issues = []
issues.each do |i|
issue_array = [i.id, i.tracker.try(:name), i.subject, i.description, i.issue_status.try(:name),i.get_assign_user.try(:show_real_name),
i.priority.try(:name), i.get_issue_tags_name, i.user.try(:show_real_name), format_time(i.created_on), i.version.try(:title),
i.start_date.to_s, i.due_date.to_s, i.done_ratio.to_s + "%", i.issue_type == "2" ? "悬赏" : "普通", i.token.to_s ]
@export_issues.push(issue_array)
end
end
def trackers_size(issues)
trackers_id = Tracker.pluck(:id,:name)
tracker_array = []
trackers_id.each do |t|
tracker_info = {
id: t[0],
name: t[1],
issues_count: issues.issues_count(t[0])
}
tracker_array.push(tracker_info)
end
tracker_array
end
end

@ -0,0 +1,73 @@
class JournalsController < ApplicationController
before_action :require_login
before_action :set_issue
before_action :check_issue_permission
def index
@page = params[:page] || 1
@limit = params[:limit] || 10
journals = @issue.journals.journal_includes.order("created_on desc")
@journals_size = journals.size
@journals = journals.parent_journals.page(@page).per(@limit)
end
def create
notes = params[:content]
if notes.blank?
normal_status(-1, "评论内容不能为空")
else
journal_params = {
journalized_id: @issue.id ,
journalized_type: "Issue",
user_id: current_user.id ,
notes: notes.to_s.strip,
parent_id: params[:parent_id]
}
journal = Journal.new journal_params
if journal.save
if params[:attachment_ids].present?
params[:attachment_ids].each do |id|
attachment = Attachment.select(:id, :container_id, :container_type)&.find_by_id(id)
unless attachment.blank?
attachment.container = journal
attachment.save
end
end
end
normal_status(0, "评论成功")
else
normal_status(-1, "评论失败")
end
end
end
def destroy
journal = Journal.find(params[:id])
if journal.present?
if journal.destroy #如果有子评论,子评论删除吗?
normal_status(0, "评论删除成功")
else
normal_status(-1, "评论删除失败")
end
else
normal_status(-1, "评论不存在")
end
end
private
def set_issue
@issue = Issue.find_by_id(params[:issue_id])
unless @issue.present?
normal_status(-1, "标签不存在")
end
end
def check_issue_permission
@project = @issue.project
unless @project.member?(current_user) || current_user.admin?
normal_status(-1, "您没有权限")
end
end
end

@ -31,7 +31,8 @@ class PraiseTreadController < ApplicationController
private
def find_object
begin
@obj = params[:object_type].strip.classify.constantize.find params[:object_id]
object_type = params[:object_type] || 'project'
@obj = object_type.strip.classify.constantize.find_by_identifier params[:id]
rescue Exception => e
uid_logger_error(e.message)
tip_exception(e.message)
@ -41,6 +42,5 @@ class PraiseTreadController < ApplicationController
def validate_params
return normal_status(2, "缺少参数object_id") if params[:object_id].blank?
return normal_status(2, "缺少参数object_type") if params[:object_type].blank?
end
end

@ -2,4 +2,10 @@ class ProjectCategoriesController < ApplicationController
def index
@project_categories = ProjectCategory.search(params[:name]).without_content
end
def group_list
@category_group_list =
Project.visible.joins(:project_category).group(:project_category_id)
.select("project_category_id, count(*) AS projects_count, project_categories.name")
end
end

@ -1,9 +1,10 @@
class ProjectsController < ApplicationController
before_action :require_login
before_action :require_login, except: %i[index branches group_type_list]
before_action :find_project, only: %i[branches]
def index
scope = Projects::ListQuery.call(params)
@projects = paginate(scope)
end
def create
@ -30,6 +31,10 @@ class ProjectsController < ApplicationController
@branches = Gitea::Repository::BranchesService.new(current_user, @project.identifier).call
end
def group_type_list
@project_group_list = Project.visible.group(:project_type).select('project_type, count(*) AS projects_count')
end
private
def find_project
@project = Project.find_by_identifier! params[:id]

@ -8,8 +8,8 @@ class Projects::MigrateForm < BaseForm
validates :repository_name, format: { with: REPOSITORY_NAME_REGEX, multiline: true, message: "只能含有数字、字母、下划线且不能以下划线开头和结尾" }
validates :clone_addr, format: { with: URL_REGEX, multiline: true, message: "地址格式不正确" }
validate do
check_project_name(user_id, name)
check_repository_name(user_id, repository_name)
check_project_name(user_id, name) unless name.blank?
check_repository_name(user_id, repository_name) unless repository_name.blank?
check_project_category(project_category_id)
check_project_language(project_language_id)
end

@ -422,6 +422,8 @@ module ApplicationHelper
when 3 then 'text-secondary'
end
end
end
def render_unix_time(date)
date.to_time.to_i
end
end

@ -20,4 +20,28 @@ module IssuesHelper
end
def children_content(journal_id)
children_journals = Journal.children_journals(journal_id).journal_includes
children_journal_content = []
if children_journals.present?
children_journals.each do |j|
journal_info = {
id: j.id,
content: j.try(:notes),
format_time: time_from_now(j.created_on),
created_at: format_time(j.created_on),
user_name: j.user.try(:show_real_name),
user_login: j.user.try(:login),
user_pictrue: url_to_avatar(j.user)
}
children_journal_content.push(journal_info)
end
end
children_journal_content
end
# def get_issue_tags(issue_tag_ids)
# IssueTag.where(id: issue_tag_ids).select(:id,:name,:color).as_json
# end
end

@ -1,2 +1,9 @@
module ProjectsHelper
def render_zh_project_type(project_type)
case project_type
when 'common' then "开源托管项目"
when 'mirror' then "开源镜像项目"
end
end
end

@ -0,0 +1,13 @@
module Matchable
extend ActiveSupport::Concern
included do
scope :like, lambda { |keywords|
where("name LIKE ?", "%#{keywords.split(" ").join('|')}%") unless keywords.blank?
}
scope :with_project_category, ->(category_id) { where(project_category_id: category_id) unless category_id.blank? }
scope :with_project_language, ->(language_id) { where(project_language_id: language_id) unless language_id.blank? }
scope :with_project_type, ->(project_type) { where(project_type: project_type) if Project.project_types.include?(project_type) }
end
end

@ -2,8 +2,6 @@ module Publicable
extend ActiveSupport::Concern
included do
alias_attribute :public, :is_public
enum public: { publiced: 1, hidden: 0 }
scope :visible, -> { where(is_public: true) }
end
end

@ -1,15 +1,19 @@
class Issue < ApplicationRecord
#issue_type 1为普通2为悬赏
belongs_to :project
belongs_to :tracker
belongs_to :issue_tag, foreign_key: :priority_id
# belongs_to :issue_tag,optional: true
belongs_to :priority, :class_name => 'IssuePriority', foreign_key: :priority_id,optional: true #
belongs_to :version, foreign_key: :fixed_version_id,optional: true
belongs_to :user,optional: true, foreign_key: :author_id
belongs_to :issue_status, foreign_key: :status_id,optional: true
has_many :commit_issues
has_many :attachments, as: :container, dependent: :destroy
has_many :memos
has_many :journals
has_many :journals, :as => :journalized, :dependent => :destroy
has_many :journal_details, through: :journals
has_many :issue_tags_relates, dependent: :destroy
has_many :issue_tags, through: :issue_tags_relates
scope :issue_includes, ->{includes(:user)}
@ -19,26 +23,47 @@ class Issue < ApplicationRecord
end
def create_journal_detail(change_files, issue_files, issue_file_ids)
journal = Journal.where(journalized_id: self.id, journalized_type: "Issue", user_id: self.author_id, notes: [nil,""])
if journal.present?
journal.update_all(created_on: Time.now)
journal = journal.last
else
journal_params = {
journalized_id: self.id, journalized_type: "Issue", user_id: self.author_id
}
journal = Journal.new journal_params
journal.save
journal_params = {
journalized_id: self.id, journalized_type: "Issue", user_id: self.author_id
}
journal = Journal.new journal_params
if journal.save
if change_files
old_attachment_names = self.attachments.select(:filename,:id).where(id: issue_file_ids).pluck(:filename).join(",")
new_attachment_name = self.attachments.select(:filename,:id).where(id: issue_files).pluck(:filename).join(",")
journal.journal_details.create(property: "attachment", prop_key: "#{issue_files.size}", old_value: old_attachment_names, value: new_attachment_name)
end
change_values = %w(subject description is_private assigned_to_id tracker_id status_id priority_id fixed_version_id start_date due_date estimated_hours done_ratio issue_tags_value issue_type token)
change_values.each do |at|
if self.send("saved_change_to_#{at}?")
journal.journal_details.create(property: "attr", prop_key: "#{at}", old_value: self.send("#{at}_before_last_save"), value: self.send(at))
end
end
end
if change_files
journal.journal_details.create(property: "attachment", prop_key: "#{issue_files.size}", old_value: issue_file_ids, value: issue_files)
end
def get_journals_size
journals.size
end
def self.issues_count(tracker_id)
includes(:trakcer).where(tracker_id: tracker_id).size
end
def get_issue_tags
if issue_tags.present?
issue_tags.select(:id,:name,:color).uniq.as_json
else
nil
end
end
change_values = %w(subject description is_private assigned_to_id tracker_id status_id priority_id fixed_version_id start_date due_date estimated_hours done_ratio)
change_values.each do |at|
if self.send("saved_change_to_#{at}?")
journal.journal_details.create(property: "attr", prop_key: "#{at}", old_value: self.send("#{at}_before_last_save"), value: self.send(at))
end
def get_issue_tags_name
if issue_tags.present?
issue_tags.select(:name).uniq.pluck(:name).join(",")
else
nil
end
end

@ -1,4 +1,7 @@
class IssueTag < ApplicationRecord
has_many :issues
has_many :issue_tags_relates, dependent: :destroy
has_many :issues, through: :issue_tags_relates
belongs_to :project, optional: true
end

@ -0,0 +1,4 @@
class IssueTagsRelate < ApplicationRecord
belongs_to :issue
belongs_to :issue_tag
end

@ -1,7 +1,79 @@
class Journal < ApplicationRecord
belongs_to :user
belongs_to :issue, foreign_key: :journalized_id
belongs_to :issue, foreign_key: :journalized_id, :touch => true
has_many :journal_details, :dependent => :delete_all
has_many :attachments, as: :container, dependent: :destroy
scope :journal_includes, ->{includes(:user, :journal_details, :attachments)}
scope :parent_journals, ->{where(parent_id: nil)}
scope :children_journals, lambda{|journal_id| where(parent_id: journal_id)}
def is_journal_detail?
self.notes.blank? && self.journal_details.present?
end
def journal_content
send_details = []
if self.is_journal_detail?
details = self.journal_details.select(:property, :prop_key, :old_value, :value).pluck(:property, :prop_key, :old_value, :value)
if details.size > 0
details.each do |de|
if de[0] == "attr"
content = ""
else
content = "附件"
end
old_value = de[2]
value = de[3]
if de[1].to_i > 0
prop_name = ""
else
prop_name = I18n.t("journal_detail.#{de[1]}")
case de[1]
when "is_private"
old_value = I18n.t("journal_detail.#{de[2]}")
value = I18n.t("journal_detail.#{de[3]}")
when "assigned_to_id"
u = User.select(:id, :login, :lastname, :firstname)
old_value = u.find(de[2]).try(:show_real_name)
value = u.find(de[3]).try(:show_real_name)
when "tracker_id"
t = Tracker.select(:id, :name)
old_value = t.find(de[2]).try(:name)
value = t.find(de[3]).try(:name)
when "status_id"
t = IssueStatus.select(:id, :name)
old_value = t.find(de[2]).try(:name)
value = t.find(de[3]).try(:name)
when "priority_id"
t = IssuePriority.select(:id, :name)
old_value = t.find(de[2]).try(:name)
value = t.find(de[3]).try(:name)
when "issue_tags_value"
t = IssueTag.select(:id, :name)
old_value = t.where(id: de[2].split(",")).select(:id,:name,:color).as_json
value = t.where(id: de[3].split(",")).select(:id,:name,:color).as_json
when "fixed_version_id"
t = Version.select(:id, :title)
old_value = t.find(de[2]).try(:title)
value = t.find(de[3]).try(:title)
else
old_value = de[2]
value = de[3]
end
end
prop_hash = {
detail: (content + prop_name),
old_value: old_value,
value: value
}
send_details.push(prop_hash)
end
end
end
send_details
end
scope :journal_includes, ->{includes(:user, :journal_details)}
end

@ -9,12 +9,12 @@ class PraiseTread < ApplicationRecord
after_create :send_tiding
def send_tiding
case self.praise_tread_object_type
when "Memo","Message","Issue"
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.author_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
when "Discuss","Challenge","HomeworkCommon","JournalsForMessage","Journal","GraduationTopic","GraduationTask"
self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.user_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
end
# case self.praise_tread_object_type
# when "Memo","Message","Issue"
# self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.author_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
# when "Discuss","Challenge","HomeworkCommon","JournalsForMessage","Journal","GraduationTopic","GraduationTask"
# self.tidings << Tiding.new(:trigger_user_id => self.user_id, :user_id => self.praise_tread_object.user_id, :parent_container_id => self.praise_tread_object_id, :parent_container_type => self.praise_tread_object_type, :viewed => 0, :tiding_type => "Praise")
# end
end
def self.find_object_by_type_and_id(id, type)

@ -1,4 +1,9 @@
class Project < ApplicationRecord
include Matchable
include Publicable
enum project_type: { mirror: 1, common: 0 } # common:开源托管项目, mirror:开源镜像项目
belongs_to :ignore, optional: true
belongs_to :license, optional: true
belongs_to :owner, class_name: 'User', foreign_key: :user_id

@ -1,6 +1,6 @@
class Repository < ApplicationRecord
self.inheritance_column = nil # FIX The single-table inheritance mechanism failed
belongs_to :project
belongs_to :project, :touch => true
belongs_to :user
validates :identifier, presence: true, uniqueness: true

@ -0,0 +1,21 @@
class Projects::ListQuery < ApplicationQuery
include CustomSortable
attr_reader :params
sort_columns :updated_on, :created_on, :forked_count, :praises_count, default_by: :updated_on, default_direction: :desc
def initialize(params)
@params = params
end
def call
scope = Project.like(params[:search])
.with_project_type(params[:project_type])
.with_project_category(params[:category_id])
.with_project_language(params[:language_id])
.includes(:project_category, :project_language, :repository, :owner)
custom_sort(scope, params[:sort_by], params[:sort_direction])
end
end

@ -30,7 +30,8 @@ class Projects::MigrateService < ApplicationService
description: params[:description],
project_category_id: params[:project_category_id],
project_language_id: params[:project_language_id],
is_public: get_is_public
is_public: get_is_public,
project_type: Project.project_types[:mirror]
}
end

@ -25,12 +25,16 @@ class Repositories::CreateService < ApplicationService
private
def sync_project(repository, gitea_repository)
project.update_column('identifier', repository.identifier)
project.update_columns(gpid: gitea_repository["id"]) if gitea_repository
if gitea_repository
project.update_columns(
gpid: gitea_repository["id"],
identifier: repository.identifier,
forked_count: gitea_repository["forks_count"])
end
end
def sync_repository(repository, gitea_repository)
repository.update_columns(url: remote_repository_url) if gitea_repository
repository.update_columns(url: remote_repository_url,) if gitea_repository
end
def remote_repository_url

@ -1,2 +1,2 @@
json.partial! "commons/success"
json.extract! @issue_tag, :id, :title, :description, :color,:project_id
json.extract! @issue_tag, :id, :name, :description, :color,:project_id

@ -3,6 +3,6 @@ json.issue_tags_count @issue_tags_size
json.issue_tags do
json.array! @issue_tags.each.to_a do |tag|
json.extract! tag, :id, :title, :description, :color, :issues_count, :project_id
json.extract! tag, :id, :name, :description, :color, :issues_count, :project_id
end
end

@ -1,3 +0,0 @@
json.issue_id journal.journalized_id
json.notes journal.try(:notes)
json.created_at time_from_now(journal.created_on)

@ -0,0 +1,6 @@
json.all_count @all_issues_size
json.open_count @open_issues_size
json.close_count @close_issues_size
json.normal_count @normal_issues_size
json.pay_count @pay_issues_size
json.commit_issues @commit_issues

@ -0,0 +1,8 @@
if @status > 0
json.status 0
json.message "复制成功"
json.issue_id @new_issue.id
else
json.status -1
json.message "复制失败"
end

@ -1,10 +1,12 @@
json.partial! "commons/success"
json.extract! @issue, :id,:subject,:description,:is_private,:assigned_to_id,:tracker_id,:status_id,:priority_id,:fixed_version_id,
:start_date,:due_date,:estimated_hours,:done_ratio
:start_date,:due_date,:estimated_hours, :issue_type, :token
json.done_ratio @issue.done_ratio.to_s + "%"
json.issue_tags @issue.get_issue_tags
json.issue_chosen @issue_chosen
json.attachments do
json.array! @issue_attachments do |attachment|
json.partial! "attachments/attachment", attachment: attachment
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
end
end

@ -0,0 +1,32 @@
json.partial! "commons/success"
json.all_count @all_issues_size
json.open_count @open_issues_size
json.close_count @close_issues_size
json.assign_me_count @assign_to_me_size
json.my_published_count @my_published_size
json.search_count @issues_size
json.limit @limit
json.issues do
json.array! @issues.to_a do |issue|
json.id issue.id
json.name issue.subject
json.format_time format_time(issue.created_on)
json.created_at time_from_now(issue.created_on)
json.updated_at format_time(issue.updated_on)
json.assign_user_name issue.get_assign_user.try(:show_real_name)
json.assign_user_login issue.get_assign_user.try(:login)
json.author_name issue.user.try(:show_real_name)
json.author_login issue.user.try(:login)
json.tracker issue.tracker.try(:name)
json.issue_status issue.issue_status.try(:name)
json.priority issue.priority.try(:title)
json.version issue.version.try(:title)
json.done_ratio issue.done_ratio.to_s + "%"
json.journals_count issue.get_journals_size
json.issue_tags issue.get_issue_tags
json.issue_type issue.issue_type == "1" ? "普通" : "悬赏"
json.token issue.issue_type == "2" ? issue.token : ""
end
end

@ -0,0 +1,13 @@
wb = xlsx_package.workbook
wb.styles do |s|
sz_all = s.add_style :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center, :vertical => :center}
blue_cell = s.add_style :bg_color => "FAEBDC", :sz => 10,:height => 20,:b => true, :border => { :style => :thin, :color =>"000000" },:alignment => {wrap_text: true,:horizontal => :center,:vertical => :center}
wb.add_worksheet(:name => "issues列表") do |sheet|
sheet.add_row table_columns, :style => blue_cell, height: 30
sheet.column_info.first.width = 12
issues.each do |user|
sheet.add_row user, :style => sz_all #用户id
end #each_widh_index
end #add_worksheet
end

@ -0,0 +1,2 @@
json.partial! "commons/success"
json.issue_chosen @issue_chosen

@ -1,25 +1,26 @@
json.partial! "commons/success"
json.extract! @issue, :id,:subject,:description,:is_private, :start_date,:due_date,:estimated_hours
json.closed_on @issue.closed_on.present? ? format_time(@issue.closed_on) : ""
json.created_at format_time(@issue.created_on)
json.assign_user_name @issue_assign_to.try(:show_real_name)
json.assign_user_login @issue_assign_to.try(:login)
json.author_name @issue_user.try(:show_real_name)
json.author_login @issue_user.try(:login)
json.author_picture url_to_avatar(@issue_user)
json.tracker @issue.tracker.try(:name)
json.issue_status @issue.issue_status.try(:name)
json.priority @issue.issue_tag.try(:title)
json.priority @issue.priority.try(:name)
json.version @issue.version.try(:title)
json.issue_tags @issue.get_issue_tags
json.done_ratio @issue.done_ratio.to_s + "%"
json.issue_type @issue.issue_type == "1" ? "普通" : "悬赏"
json.token @issue.issue_type == "2" ? @issue.token : ""
json.attachments do
json.array! @issue_attachments do |attachment|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
end
end
json.issue_comments do
json.array! @journals do |journal|
json.partial! "issues/journal_item", journal: journal
end
end

@ -0,0 +1,16 @@
json.id journal.id
json.user_name journal.user.try(:show_real_name)
json.user_login journal.user.try(:login)
json.user_picture url_to_avatar(journal.user)
json.is_journal_detail journal.is_journal_detail? #判断是否修改了参数而添加的回复内容
json.content journal.try(:notes)
json.children_journals children_content(journal.id)
json.journal_details journal.journal_content
json.format_time format_time(journal.created_on)
json.created_at time_from_now(journal.created_on)
json.attachments do
json.array! journal.attachments do |attachment|
json.partial! "attachments/attachment_simple", locals: {attachment: attachment}
end
end

@ -0,0 +1,8 @@
json.partial! "commons/success"
json.limit @limit
json.journals_count @journals_size
json.issue_journals do
json.array! @journals do |journal|
json.partial! "journals/journal_item", journal: journal
end
end

@ -0,0 +1,5 @@
json.array! @category_group_list do |category|
json.id category.project_category_id
json.name category.name
json.projects_count category.projects_count
end

@ -0,0 +1,8 @@
json.id project.identifier
json.name project.name
json.description project.description
json.visits project.visits
json.forked_count project.forked_count
json.is_public project.is_public
json.mirror_url project.repository&.mirror_url
json.last_update_time render_unix_time(project.updated_on)

@ -0,0 +1,5 @@
json.array! @project_group_list do |group|
json.project_type group.project_type
json.name render_zh_project_type(group.project_type)
json.projects_count group.projects_count
end

@ -1 +1,22 @@
json.projects []
json.array! @projects do |project|
json.partial! 'project', project: project
json.author do
json.name project.owner.login
end
json.category do
if project.project_category.blank?
json.nil!
else
json.id project.project_category.id
json.name project.project_category.name
end
end
json.language do
if project.project_language.blank?
json.nil!
else
json.id project.project_language.id
json.name project.project_language.name
end
end
end

@ -13,4 +13,25 @@ zh-CN:
'pending': '待审批'
'processed': '已审批'
'refused': '已拒绝'
'agreed': '已同意'
'agreed': '已同意'
journal_detail:
subject: 主题
description: 描述
is_private: 私有
assigned_to_id: 指派给
tracker_id: 类型
status_id: 状态
priority_id: 优先级
fixed_version_id: 里程碑
start_date: 开始日期
due_date: 结束日期
estimated_hours: 工时
done_ratio: 完成度
t:
f:
true:
false:
issue_tag_ids: 标签
issue_type: 分类
token: 悬赏金额

@ -27,13 +27,23 @@ Rails.application.routes.draw do
put 'commons/unhidden', to: 'commons#unhidden'
delete 'commons/delete', to: 'commons#delete'
resources :project_categories, only: [:index, :show]
resources :project_categories, only: [:index, :show] do
get :group_list, on: :collection
end
resources :project_languages, only: [:index, :show]
resources :ignores, only: [:index, :show]
resources :licenses, only: [:index, :show]
resources :projects, only: [:index, :create, :show] do
resources :issues
resources :issues do
collection do
get :commit_issues
end
member do
post :copy
get :index_chosen
end
end
resources :issue_tags, only: [:create, :edit, :update, :destroy, :index]
resources :versions do
member do
@ -42,6 +52,7 @@ Rails.application.routes.draw do
end
collection do
post :migrate
get :group_type_list
end
member do
get :branches
@ -118,6 +129,7 @@ Rails.application.routes.draw do
member do
get :homepage_info
end
get 'me', on: :collection
get :question_banks, on: :collection, to: 'users/question_banks#index'

@ -0,0 +1,5 @@
class AddPraisesCountToProjects < ActiveRecord::Migration[5.2]
def change
add_column :projects, :praises_count, :integer, :default => 0
end
end

@ -0,0 +1,11 @@
class ChangeForkedCountDefaultFromProjects < ActiveRecord::Migration[5.2]
def change
change_column_default :projects, :forked_count, { from: nil, to: 0 }
change_column_default :projects, :project_type, { from: nil, to: 0 }
Project.find_each do |project|
project.update_column('forked_count', 0) if project.forked_count.nil?
project.update_column('project_type', 0) if project.project_type.nil?
end
end
end

@ -0,0 +1,8 @@
class AddIssuesTypeAndToken < ActiveRecord::Migration[5.2]
def change
add_column :issues, :issue_type, :string
add_column :issues, :token, :string
add_column :issues, :issue_tag_ids, :string
end
end

@ -0,0 +1,18 @@
class AddIssuePriorityToModel < ActiveRecord::Migration[5.2]
def change
unless ActiveRecord::Base.connection.table_exists? 'IssuePriority'
create_table :issue_priorities do |t|
t.string :name
t.integer :position
t.timestamps
end
add_index :issue_priorities, [:name]
pr_values = %w(低 正常 高 紧急 立刻)
pr_values.each_with_index do |v, index|
IssuePriority.create!(name: v, position: index+1)
end
end
end
end

@ -0,0 +1,5 @@
class RenameIssueTagTitle < ActiveRecord::Migration[5.2]
def change
rename_column :issue_tags, :title, :name
end
end

@ -0,0 +1,10 @@
class CreateIssueTagsRelates < ActiveRecord::Migration[5.2]
def change
create_table :issue_tags_relates do |t|
t.integer :issue_id
t.integer :issue_tag_id
t.timestamps
end
add_index :issue_tags_relates, [:issue_id, :issue_tag_id]
end
end

@ -0,0 +1,5 @@
class RenameIssuesIssueTagIds < ActiveRecord::Migration[5.2]
def change
rename_column :issues, :issue_tag_ids, :issue_tags_value
end
end

@ -0,0 +1,5 @@
require 'rails_helper'
RSpec.describe IssueTagsRelate, type: :model do
pending "add some examples to (or delete) #{__FILE__}"
end
Loading…
Cancel
Save