issue links
This commit is contained in:
parent
00448f0f01
commit
c752671453
|
@ -0,0 +1,2 @@
|
|||
// Place all the behaviors and hooks related to the matching controller here.
|
||||
// All this logic will automatically be available in application.js.
|
|
@ -0,0 +1,3 @@
|
|||
// Place all the styles related to the api/pm/issue_links controller here.
|
||||
// They will automatically be included in application.css.
|
||||
// You can use Sass (SCSS) here: http://sass-lang.com/
|
|
@ -31,7 +31,7 @@ class Api::Pm::BaseController < ApplicationController
|
|||
|
||||
def load_issue
|
||||
return render_parameter_missing if params[:pm_project_id].blank?
|
||||
@issue = @project.issues.issue_issue.where(pm_project_id: params[:pm_project_id]).find_by_id(params[:id])
|
||||
@issue = @project.issues.issue_issue.where(pm_project_id: params[:pm_project_id]).find_by_id(params[:issue_id])
|
||||
render_not_found('疑修不存在!') if @issue.blank?
|
||||
end
|
||||
# 具有对仓库的管理权限
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
class Api::Pm::IssueLinksController < Api::Pm::BaseController
|
||||
before_action :load_project
|
||||
before_action :load_issue
|
||||
def index
|
||||
@links = @issue.pm_links.where(be_linkable_type: 'Issue')
|
||||
end
|
||||
|
||||
def create
|
||||
@link = @issue.pm_links.find_or_create_by(be_linkable_type: 'Issue', be_linkable_id: params[:link_id])
|
||||
data = {
|
||||
data: {
|
||||
id: @link.id,
|
||||
issue_id: @link.linkable_id,
|
||||
linked_issue_id: @link.be_linkable_id
|
||||
}
|
||||
}
|
||||
render_ok(data)
|
||||
end
|
||||
|
||||
def destroy
|
||||
@link = @issue.pm_links.find params[:id]
|
||||
@link.destroy
|
||||
render_ok
|
||||
end
|
||||
end
|
|
@ -1,7 +1,7 @@
|
|||
class Api::Pm::IssuesController < Api::Pm::BaseController
|
||||
before_action :require_login, except: [:index]
|
||||
before_action :load_project
|
||||
before_action :load_issue, only: %i[show update destroy]
|
||||
before_action :load_issue, only: %i[show update destroy link_index]
|
||||
before_action :load_issues, only: %i[batch_update batch_destroy]
|
||||
before_action :check_issue_operate_permission, only: %i[update destroy]
|
||||
|
||||
|
@ -19,6 +19,12 @@ class Api::Pm::IssuesController < Api::Pm::BaseController
|
|||
render 'api/v1/issues/index'
|
||||
end
|
||||
|
||||
def link_index
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
def show
|
||||
@issue.associate_attachment_container
|
||||
render 'api/v1/issues/show'
|
||||
|
@ -91,6 +97,13 @@ class Api::Pm::IssuesController < Api::Pm::BaseController
|
|||
return if params[:project_id].to_i.zero?
|
||||
render_forbidden('您没有操作权限!') unless @project.member?(current_user) || current_user.admin? || @issue.user == current_user
|
||||
end
|
||||
|
||||
def load_issue
|
||||
return render_parameter_missing if params[:pm_project_id].blank?
|
||||
@issue = @project.issues.issue_issue.where(pm_project_id: params[:pm_project_id]).find_by_id(params[:id])
|
||||
render_not_found('疑修不存在!') if @issue.blank?
|
||||
end
|
||||
|
||||
def load_issues
|
||||
return render_error('请输入正确的ID数组!') unless params[:ids].is_a?(Array)
|
||||
params[:ids].each do |id|
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
module Api::Pm::IssueLinksHelper
|
||||
end
|
|
@ -60,16 +60,16 @@ class Issue < ApplicationRecord
|
|||
has_many :project_trends, as: :trend, dependent: :destroy
|
||||
has_one :pull_request
|
||||
# belongs_to :issue_tag,optional: true
|
||||
belongs_to :priority, :class_name => 'IssuePriority', foreign_key: :priority_id,optional: true
|
||||
belongs_to :priority, class_name: 'IssuePriority', foreign_key: :priority_id,optional: true
|
||||
belongs_to :version, foreign_key: :fixed_version_id,optional: true, counter_cache: 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, :as => :journalized, :dependent => :destroy
|
||||
has_many :journals, as: :journalized, dependent: :destroy
|
||||
has_many :journal_details, through: :journals
|
||||
has_many :claims, :dependent => :destroy
|
||||
has_many :claims, dependent: :destroy
|
||||
has_many :claim_users, through: :claims, source: :user
|
||||
has_many :issue_tags_relates, dependent: :destroy
|
||||
has_many :issue_tags, through: :issue_tags_relates
|
||||
|
@ -79,19 +79,21 @@ class Issue < ApplicationRecord
|
|||
has_many :assigners, through: :issue_assigners
|
||||
has_many :issue_participants, dependent: :destroy
|
||||
has_many :participants, through: :issue_participants
|
||||
has_many :show_participants, -> {joins(:issue_participants).where.not(issue_participants: {participant_type: "atme"}).distinct}, through: :issue_participants, source: :participant
|
||||
has_many :show_participants, -> {joins(:issue_participants).where.not(issue_participants: {participant_type: 'atme'}).distinct}, through: :issue_participants, source: :participant
|
||||
has_many :show_assigners, -> {joins(:issue_assigners).distinct}, through: :issue_assigners, source: :assigner
|
||||
has_many :show_issue_tags, -> {joins(:issue_tags_relates).distinct}, through: :issue_tags_relates, source: :issue_tag
|
||||
|
||||
has_many :comment_journals, -> {where.not(notes: nil)}, class_name: "Journal", :as => :journalized
|
||||
has_many :operate_journals, -> {where(notes: nil)}, class_name: "Journal", :as => :journalized
|
||||
has_many :pull_attached_issues, dependent: :destroy
|
||||
has_many :comment_journals, -> {where.not(notes: nil)}, class_name: 'Journal', as: :journalized
|
||||
has_many :operate_journals, -> {where(notes: nil)}, class_name: 'Journal', as: :journalized
|
||||
has_many :pull_attached_issues, dependent: :destroy
|
||||
has_many :attach_pull_requests, through: :pull_attached_issues, source: :pull_request
|
||||
# PM 关联工作项目
|
||||
has_many :pm_links, as: :linkable, dependent: :destroy
|
||||
|
||||
scope :issue_includes, ->{includes(:user)}
|
||||
scope :issue_many_includes, ->{includes(journals: :user)}
|
||||
scope :issue_issue, ->{where(issue_classify: [nil,"issue"])}
|
||||
scope :issue_pull_request, ->{where(issue_classify: "pull_request")}
|
||||
scope :issue_issue, ->{where(issue_classify: [nil, 'issue'])}
|
||||
scope :issue_pull_request, ->{where(issue_classify: 'pull_request')}
|
||||
scope :issue_index_includes, ->{includes(:tracker, :priority, :version, :issue_status, :journals,:issue_tags,user: :user_extension)}
|
||||
scope :closed, ->{where(status_id: 5)}
|
||||
scope :opened, ->{where.not(status_id: 5)}
|
||||
|
@ -100,27 +102,27 @@ class Issue < ApplicationRecord
|
|||
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic
|
||||
|
||||
def incre_project_common
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {issues: 1}, self.project_id)
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: 1}, self.project_id)
|
||||
end
|
||||
|
||||
def decre_project_common
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {issues: -1}, self.project_id)
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: -1}, self.project_id)
|
||||
end
|
||||
|
||||
def incre_user_statistic
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {issue_count: 1}, self.author_id)
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: 1}, self.author_id)
|
||||
end
|
||||
|
||||
def decre_user_statistic
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {issue_count: -1}, self.author_id)
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: -1}, self.author_id)
|
||||
end
|
||||
|
||||
def incre_platform_statistic
|
||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {issue_count: 1})
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: 1})
|
||||
end
|
||||
|
||||
def decre_platform_statistic
|
||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {issue_count: -1})
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: -1})
|
||||
end
|
||||
|
||||
def get_assign_user
|
||||
|
@ -129,20 +131,20 @@ class Issue < ApplicationRecord
|
|||
|
||||
def create_journal_detail(change_files, issue_files, issue_file_ids, user_id)
|
||||
journal_params = {
|
||||
journalized_id: self.id, journalized_type: "Issue", user_id: user_id
|
||||
journalized_id: self.id, journalized_type: 'Issue', user_id: user_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)
|
||||
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 branch_name)
|
||||
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))
|
||||
journal.journal_details.create(property: 'attr', prop_key: "#{at}", old_value: self.send("#{at}_before_last_save"), value: self.send(at))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -150,11 +152,11 @@ class Issue < ApplicationRecord
|
|||
|
||||
def custom_journal_detail(prop_key, old_value, value, user_id)
|
||||
journal_params = {
|
||||
journalized_id: self.id, journalized_type: "Issue", user_id: user_id
|
||||
journalized_id: self.id, journalized_type: 'Issue', user_id: user_id
|
||||
}
|
||||
journal = Journal.new journal_params
|
||||
if journal.save
|
||||
journal.journal_details.create(property: "attr", prop_key: prop_key, old_value: old_value, value: value)
|
||||
journal.journal_details.create(property: 'attr', prop_key: prop_key, old_value: old_value, value: value)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -180,14 +182,14 @@ class Issue < ApplicationRecord
|
|||
|
||||
def get_issue_tags_name
|
||||
if issue_tags.present?
|
||||
issue_tags.select(:name).uniq.pluck(:name).join(",")
|
||||
issue_tags.select(:name).uniq.pluck(:name).join(',')
|
||||
else
|
||||
nil
|
||||
end
|
||||
end
|
||||
|
||||
def only_reply_journals
|
||||
journals.where.not(notes: [nil, ""]).journal_includes.limit(2)
|
||||
journals.where.not(notes: [nil, '']).journal_includes.limit(2)
|
||||
end
|
||||
|
||||
def change_versions_count
|
||||
|
@ -232,15 +234,15 @@ class Issue < ApplicationRecord
|
|||
att_ids += self.description.to_s.scan(/\/api\/attachments\/.+\"/).map{|s|s.match(/\d+/)[0]}
|
||||
att_ids += self.description.to_s.scan(/\/api\/attachments\/\d+/).map{|s|s.match(/\d+/)[0]}
|
||||
if att_ids.present?
|
||||
Attachment.where(id: att_ids).where("container_type IS NULL OR container_type = 'Issue'").update_all(container_id: self.project_id, container_type: "Project")
|
||||
Attachment.where(id: att_ids).where("container_type IS NULL OR container_type = 'Issue'").update_all(container_id: self.project_id, container_type: 'Project')
|
||||
end
|
||||
end
|
||||
|
||||
def to_builder
|
||||
Jbuilder.new do |issue|
|
||||
issue.(self, :id, :project_issues_index, :subject, :description, :branch_name, :start_date, :due_date)
|
||||
issue.created_at self.created_on.strftime("%Y-%m-%d %H:%M")
|
||||
issue.updated_at self.updated_on.strftime("%Y-%m-%d %H:%M")
|
||||
issue.created_at self.created_on.strftime('%Y-%m-%d %H:%M')
|
||||
issue.updated_at self.updated_on.strftime('%Y-%m-%d %H:%M')
|
||||
issue.tags self.show_issue_tags.map{|t| JSON.parse(t.to_builder.target!)}
|
||||
issue.status self.issue_status.to_builder
|
||||
if self.priority.present?
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
# == Schema Information
|
||||
#
|
||||
# Table name: pm_links
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# be_linkable_type :string(255) not null
|
||||
# be_linkable_id :integer not null
|
||||
# linkable_type :string(255) not null
|
||||
# linkable_id :integer not null
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_pm_links_on_linkable_id (linkable_id)
|
||||
# index_pm_links_on_linkable_type (linkable_type)
|
||||
#
|
||||
|
||||
class PmLink < ApplicationRecord
|
||||
belongs_to :linkable, polymorphic: true
|
||||
|
||||
def be_linkable
|
||||
be_linkable_type.constantize.find be_linkable_id
|
||||
end
|
||||
end
|
|
@ -70,8 +70,10 @@ class Api::V1::Issues::ListService < ApplicationService
|
|||
issues = issues.where(fixed_version_id: milestone_id) if milestone_id.present?
|
||||
|
||||
#pm相关
|
||||
# root_id,
|
||||
issues = issues.where(root_id: root_id) if root_id.present?
|
||||
# root_id
|
||||
if pm_project_id.present?
|
||||
issues = issues.where(root_id: root_id.present? ? nil : root_id)
|
||||
end
|
||||
|
||||
# pm_issue_type
|
||||
issues = issues.where(pm_issue_type: pm_issue_type) if pm_issue_type.present?
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
|
||||
json.links @links.each do |link|
|
||||
json.id link.id
|
||||
json.issue do
|
||||
json.partial! "api/v1/issues/simple_detail", locals: {issue: link.be_linkable}
|
||||
end
|
||||
end
|
|
@ -9,6 +9,7 @@ defaults format: :json do
|
|||
get :tags
|
||||
get :statues
|
||||
end
|
||||
resources :issue_links
|
||||
|
||||
resources :journals do
|
||||
member do
|
||||
|
|
|
@ -0,0 +1,12 @@
|
|||
class CreatePmLinks < ActiveRecord::Migration[5.2]
|
||||
def change
|
||||
create_table :pm_links do |t|
|
||||
t.string :be_linkable_type, null: false
|
||||
t.integer :be_linkable_id, null: false
|
||||
|
||||
t.string :linkable_type, null: false, index: true
|
||||
t.integer :linkable_id, null: false, index: true
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Api::Pm::IssueLinksController, type: :controller do
|
||||
|
||||
end
|
|
@ -0,0 +1,15 @@
|
|||
require 'rails_helper'
|
||||
|
||||
# Specs in this file have access to a helper object that includes
|
||||
# the Api::Pm::IssueLinksHelper. For example:
|
||||
#
|
||||
# describe Api::Pm::IssueLinksHelper do
|
||||
# describe "string concat" do
|
||||
# it "concats two strings with spaces" do
|
||||
# expect(helper.concat_strings("this","that")).to eq("this that")
|
||||
# end
|
||||
# end
|
||||
# end
|
||||
RSpec.describe Api::Pm::IssueLinksHelper, type: :helper do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
|
@ -0,0 +1,5 @@
|
|||
require 'rails_helper'
|
||||
|
||||
RSpec.describe PmLink, type: :model do
|
||||
pending "add some examples to (or delete) #{__FILE__}"
|
||||
end
|
Loading…
Reference in New Issue