diff --git a/README.md b/README.md index 688dda462..86dbefd0f 100644 --- a/README.md +++ b/README.md @@ -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": "响应成功" } ``` --- diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 65910cfc0..d3ce1e97a 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -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 diff --git a/app/controllers/issue_tags_controller.rb b/app/controllers/issue_tags_controller.rb index 345627f8d..fa7412df3 100644 --- a/app/controllers/issue_tags_controller.rb +++ b/app/controllers/issue_tags_controller.rb @@ -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) diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb index a11662af4..b7068dc0c 100644 --- a/app/controllers/issues_controller.rb +++ b/app/controllers/issues_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/journals_controller.rb b/app/controllers/journals_controller.rb new file mode 100644 index 000000000..02096be17 --- /dev/null +++ b/app/controllers/journals_controller.rb @@ -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 \ No newline at end of file diff --git a/app/controllers/praise_tread_controller.rb b/app/controllers/praise_tread_controller.rb index 459eb4bad..fa6931c0e 100644 --- a/app/controllers/praise_tread_controller.rb +++ b/app/controllers/praise_tread_controller.rb @@ -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 diff --git a/app/controllers/project_categories_controller.rb b/app/controllers/project_categories_controller.rb index 273f73c95..a515e45b6 100644 --- a/app/controllers/project_categories_controller.rb +++ b/app/controllers/project_categories_controller.rb @@ -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 diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a3bcf65cb..cbefd8d1f 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -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] diff --git a/app/forms/projects/migrate_form.rb b/app/forms/projects/migrate_form.rb index f3804beaa..1c0b25493 100644 --- a/app/forms/projects/migrate_form.rb +++ b/app/forms/projects/migrate_form.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index cabf8d244..9f8d52d61 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -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 diff --git a/app/helpers/issues_helper.rb b/app/helpers/issues_helper.rb index f742d5af8..3c3bfd08f 100644 --- a/app/helpers/issues_helper.rb +++ b/app/helpers/issues_helper.rb @@ -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 \ No newline at end of file diff --git a/app/helpers/projects_helper.rb b/app/helpers/projects_helper.rb index db5c5ce1a..8a860eca8 100644 --- a/app/helpers/projects_helper.rb +++ b/app/helpers/projects_helper.rb @@ -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 diff --git a/app/models/concerns/matchable.rb b/app/models/concerns/matchable.rb new file mode 100644 index 000000000..cd7b7e256 --- /dev/null +++ b/app/models/concerns/matchable.rb @@ -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 diff --git a/app/models/concerns/publicable.rb b/app/models/concerns/publicable.rb index a9c8cb41f..6a06d27db 100644 --- a/app/models/concerns/publicable.rb +++ b/app/models/concerns/publicable.rb @@ -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 diff --git a/app/models/issue.rb b/app/models/issue.rb index 8f8ccceea..431334be9 100644 --- a/app/models/issue.rb +++ b/app/models/issue.rb @@ -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 diff --git a/app/models/issue_tag.rb b/app/models/issue_tag.rb index 4f1ac9757..e39e72df4 100644 --- a/app/models/issue_tag.rb +++ b/app/models/issue_tag.rb @@ -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 diff --git a/app/models/issue_tags_relate.rb b/app/models/issue_tags_relate.rb new file mode 100644 index 000000000..33c181d1c --- /dev/null +++ b/app/models/issue_tags_relate.rb @@ -0,0 +1,4 @@ +class IssueTagsRelate < ApplicationRecord + belongs_to :issue + belongs_to :issue_tag +end diff --git a/app/models/journal.rb b/app/models/journal.rb index dd42bc743..2bf12d9be 100644 --- a/app/models/journal.rb +++ b/app/models/journal.rb @@ -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 \ No newline at end of file diff --git a/app/models/praise_tread.rb b/app/models/praise_tread.rb index 58ec965b4..8420a29cd 100644 --- a/app/models/praise_tread.rb +++ b/app/models/praise_tread.rb @@ -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) diff --git a/app/models/project.rb b/app/models/project.rb index 9aecb1feb..0b02cd4e2 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -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 diff --git a/app/models/repository.rb b/app/models/repository.rb index fdfbad582..d21761af2 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -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 diff --git a/app/queries/projects/list_query.rb b/app/queries/projects/list_query.rb new file mode 100644 index 000000000..88a8f42ed --- /dev/null +++ b/app/queries/projects/list_query.rb @@ -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 diff --git a/app/services/projects/migrate_service.rb b/app/services/projects/migrate_service.rb index a3c6b131e..c29d58a8e 100644 --- a/app/services/projects/migrate_service.rb +++ b/app/services/projects/migrate_service.rb @@ -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 diff --git a/app/services/repositories/create_service.rb b/app/services/repositories/create_service.rb index 70dc84799..6fe5a4a6a 100644 --- a/app/services/repositories/create_service.rb +++ b/app/services/repositories/create_service.rb @@ -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 diff --git a/app/views/issue_tags/edit.json.jbuilder b/app/views/issue_tags/edit.json.jbuilder index 7aa831920..7e54d8526 100644 --- a/app/views/issue_tags/edit.json.jbuilder +++ b/app/views/issue_tags/edit.json.jbuilder @@ -1,2 +1,2 @@ json.partial! "commons/success" -json.extract! @issue_tag, :id, :title, :description, :color,:project_id \ No newline at end of file +json.extract! @issue_tag, :id, :name, :description, :color,:project_id \ No newline at end of file diff --git a/app/views/issue_tags/index.json.jbuilder b/app/views/issue_tags/index.json.jbuilder index e71945841..7b2ddee3a 100644 --- a/app/views/issue_tags/index.json.jbuilder +++ b/app/views/issue_tags/index.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/issues/_journal_item.json.jbuilder b/app/views/issues/_journal_item.json.jbuilder deleted file mode 100644 index 24c3d3356..000000000 --- a/app/views/issues/_journal_item.json.jbuilder +++ /dev/null @@ -1,3 +0,0 @@ -json.issue_id journal.journalized_id -json.notes journal.try(:notes) -json.created_at time_from_now(journal.created_on) \ No newline at end of file diff --git a/app/views/issues/commit_issues.json.jbuilder b/app/views/issues/commit_issues.json.jbuilder new file mode 100644 index 000000000..e57ce29ac --- /dev/null +++ b/app/views/issues/commit_issues.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/issues/copy.json.jbuilder b/app/views/issues/copy.json.jbuilder new file mode 100644 index 000000000..13db86a1a --- /dev/null +++ b/app/views/issues/copy.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/issues/edit.json.jbuilder b/app/views/issues/edit.json.jbuilder index 8de9d1576..fe60f436e 100644 --- a/app/views/issues/edit.json.jbuilder +++ b/app/views/issues/edit.json.jbuilder @@ -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 diff --git a/app/views/issues/index.json.jbuilder b/app/views/issues/index.json.jbuilder new file mode 100644 index 000000000..cee72b8b6 --- /dev/null +++ b/app/views/issues/index.json.jbuilder @@ -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 diff --git a/app/views/issues/index.xlsx.axlsx b/app/views/issues/index.xlsx.axlsx new file mode 100644 index 000000000..fd8f7b120 --- /dev/null +++ b/app/views/issues/index.xlsx.axlsx @@ -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 \ No newline at end of file diff --git a/app/views/issues/index_chosen.json.jbuilder b/app/views/issues/index_chosen.json.jbuilder new file mode 100644 index 000000000..1f442f713 --- /dev/null +++ b/app/views/issues/index_chosen.json.jbuilder @@ -0,0 +1,2 @@ +json.partial! "commons/success" +json.issue_chosen @issue_chosen \ No newline at end of file diff --git a/app/views/issues/show.json.jbuilder b/app/views/issues/show.json.jbuilder index cd1442a5f..a1b928bcd 100644 --- a/app/views/issues/show.json.jbuilder +++ b/app/views/issues/show.json.jbuilder @@ -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 + diff --git a/app/views/journals/_journal_item.json.jbuilder b/app/views/journals/_journal_item.json.jbuilder new file mode 100644 index 000000000..03fd35c7b --- /dev/null +++ b/app/views/journals/_journal_item.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/journals/index.json.jbuilder b/app/views/journals/index.json.jbuilder new file mode 100644 index 000000000..2485e72bd --- /dev/null +++ b/app/views/journals/index.json.jbuilder @@ -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 \ No newline at end of file diff --git a/app/views/project_categories/group_list.json.jbuilder b/app/views/project_categories/group_list.json.jbuilder new file mode 100644 index 000000000..58e6a6c40 --- /dev/null +++ b/app/views/project_categories/group_list.json.jbuilder @@ -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 diff --git a/app/views/projects/_project.json.jbuilder b/app/views/projects/_project.json.jbuilder new file mode 100644 index 000000000..b3f6c752a --- /dev/null +++ b/app/views/projects/_project.json.jbuilder @@ -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) diff --git a/app/views/projects/group_type_list.json.jbuilder b/app/views/projects/group_type_list.json.jbuilder new file mode 100644 index 000000000..218db18a1 --- /dev/null +++ b/app/views/projects/group_type_list.json.jbuilder @@ -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 diff --git a/app/views/projects/index.json.jbuilder b/app/views/projects/index.json.jbuilder index f4f2b0b91..07170e1e0 100644 --- a/app/views/projects/index.json.jbuilder +++ b/app/views/projects/index.json.jbuilder @@ -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 diff --git a/config/locales/zh-CN.yml b/config/locales/zh-CN.yml index f11271ff5..b72db9435 100644 --- a/config/locales/zh-CN.yml +++ b/config/locales/zh-CN.yml @@ -13,4 +13,25 @@ zh-CN: 'pending': '待审批' 'processed': '已审批' 'refused': '已拒绝' - 'agreed': '已同意' \ No newline at end of file + '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: 悬赏金额 diff --git a/config/routes.rb b/config/routes.rb index 65c2476ff..6be06bbfc 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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' diff --git a/db/migrate/20191225125634_add_praises_count_to_projects.rb b/db/migrate/20191225125634_add_praises_count_to_projects.rb new file mode 100644 index 000000000..95d5e510d --- /dev/null +++ b/db/migrate/20191225125634_add_praises_count_to_projects.rb @@ -0,0 +1,5 @@ +class AddPraisesCountToProjects < ActiveRecord::Migration[5.2] + def change + add_column :projects, :praises_count, :integer, :default => 0 + end +end diff --git a/db/migrate/20191227013202_change_forked_count_default_from_projects.rb b/db/migrate/20191227013202_change_forked_count_default_from_projects.rb new file mode 100644 index 000000000..99a102878 --- /dev/null +++ b/db/migrate/20191227013202_change_forked_count_default_from_projects.rb @@ -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 diff --git a/db/migrate/20191227084951_add_issues_type_and_token.rb b/db/migrate/20191227084951_add_issues_type_and_token.rb new file mode 100644 index 000000000..4d547f596 --- /dev/null +++ b/db/migrate/20191227084951_add_issues_type_and_token.rb @@ -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 diff --git a/db/migrate/20191227090611_add_issue_priority_to_model.rb b/db/migrate/20191227090611_add_issue_priority_to_model.rb new file mode 100644 index 000000000..f6a4e9ba6 --- /dev/null +++ b/db/migrate/20191227090611_add_issue_priority_to_model.rb @@ -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 diff --git a/db/migrate/20191227105755_rename_issue_tag_title.rb b/db/migrate/20191227105755_rename_issue_tag_title.rb new file mode 100644 index 000000000..70d530584 --- /dev/null +++ b/db/migrate/20191227105755_rename_issue_tag_title.rb @@ -0,0 +1,5 @@ +class RenameIssueTagTitle < ActiveRecord::Migration[5.2] + def change + rename_column :issue_tags, :title, :name + end +end diff --git a/db/migrate/20191227140150_create_issue_tags_relates.rb b/db/migrate/20191227140150_create_issue_tags_relates.rb new file mode 100644 index 000000000..857f1706e --- /dev/null +++ b/db/migrate/20191227140150_create_issue_tags_relates.rb @@ -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 diff --git a/db/migrate/20191227162744_rename_issues_issue_tag_ids.rb b/db/migrate/20191227162744_rename_issues_issue_tag_ids.rb new file mode 100644 index 000000000..a910b1379 --- /dev/null +++ b/db/migrate/20191227162744_rename_issues_issue_tag_ids.rb @@ -0,0 +1,5 @@ +class RenameIssuesIssueTagIds < ActiveRecord::Migration[5.2] + def change + rename_column :issues, :issue_tag_ids, :issue_tags_value + end +end diff --git a/spec/models/issue_tags_relate_spec.rb b/spec/models/issue_tags_relate_spec.rb new file mode 100644 index 000000000..2ff3a27f3 --- /dev/null +++ b/spec/models/issue_tags_relate_spec.rb @@ -0,0 +1,5 @@ +require 'rails_helper' + +RSpec.describe IssueTagsRelate, type: :model do + pending "add some examples to (or delete) #{__FILE__}" +end