mirror of
https://gitlink.org.cn/Gitlink/forgeplus.git
synced 2026-05-03 03:40:49 +08:00
Merge branch 'standalone_develop' into pre_trustie_server
This commit is contained in:
@@ -16,11 +16,12 @@
|
||||
# user_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# label :string(255)
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_action_nodes_on_action_types_id (action_node_types_id)
|
||||
# index_action_nodes_on_user_id (user_id)
|
||||
# index_action_nodes_on_action_node_types_id (action_node_types_id)
|
||||
# index_action_nodes_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class Action::Node < ApplicationRecord
|
||||
@@ -33,39 +34,36 @@ class Action::Node < ApplicationRecord
|
||||
|
||||
belongs_to :user, optional: true
|
||||
|
||||
attr_accessor :cust_name, :run_values, :input_values
|
||||
|
||||
# def content_yaml
|
||||
# "foo".to_yaml
|
||||
# <<~YAML
|
||||
# - name: Set up JDK ${{ matrix.java }}
|
||||
# uses: actions/setup-java@v3
|
||||
# with:
|
||||
# distribution: 'temurin'
|
||||
# java-version: ${{ matrix.java }}
|
||||
# YAML
|
||||
# end
|
||||
validates :name, presence: { message: "不能为空" }
|
||||
validates :full_name, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||
validates :label, length: { maximum: 200, too_long: "不能超过200个字符" }
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
def yaml_hash
|
||||
|
||||
def content_yaml
|
||||
"foo".to_yaml
|
||||
<<~YAML
|
||||
name: Check dist
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
pull_request:
|
||||
paths-ignore:
|
||||
- '**.md'
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
call-check-dist:
|
||||
name: Check dist/
|
||||
uses: actions/reusable-workflows/.github/workflows/check-dist.yml@main
|
||||
with:
|
||||
node-version: '20.x'
|
||||
- name: Set up JDK ${{ matrix.java }}
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: ${{ matrix.java }}
|
||||
YAML
|
||||
end
|
||||
|
||||
def node
|
||||
self
|
||||
end
|
||||
|
||||
def build_yaml
|
||||
yaml = ERB.new(File.read(File.join(Rails.root, "app/views/api/v1/projects/pipelines", "build_node.yaml.erb"))).result(binding)
|
||||
# 删除空行内容
|
||||
yaml = yaml.gsub(/^\s*\n/, "")
|
||||
# Rails.logger.info "========================="
|
||||
# Rails.logger.info yaml
|
||||
yaml
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
# input_type :string(255)
|
||||
# description :string(255)
|
||||
# is_required :boolean default("0")
|
||||
# sort_no :string(255) default("0")
|
||||
# sort_no :integer default("0")
|
||||
# user_id :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
@@ -24,4 +24,7 @@ class Action::NodeInput < ApplicationRecord
|
||||
default_scope { order(sort_no: :asc) }
|
||||
|
||||
belongs_to :action_node, :class_name => 'Action::Node', foreign_key: "action_nodes_id"
|
||||
|
||||
validates :name, presence: { message: "不能为空" }
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
end
|
||||
|
||||
@@ -29,6 +29,9 @@ class Action::NodeSelect < ApplicationRecord
|
||||
belongs_to :action_node, :class_name => 'Action::Node', foreign_key: "action_nodes_id"
|
||||
belongs_to :user, optional: true
|
||||
|
||||
validates :name, presence: { message: "不能为空" }
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
def value
|
||||
if self.val_ext.blank?
|
||||
self.val
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
# id :integer not null, primary key
|
||||
# name :string(255)
|
||||
# description :string(255)
|
||||
# sort_no :integer
|
||||
# sort_no :integer default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
@@ -15,4 +15,7 @@ class Action::NodeType < ApplicationRecord
|
||||
default_scope { order(sort_no: :asc) }
|
||||
|
||||
has_many :action_nodes, :class_name => 'Action::Node', foreign_key: "action_node_types_id"
|
||||
|
||||
validates :name, presence: { message: "不能为空" }
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
end
|
||||
|
||||
39
app/models/action/pipeline.rb
Normal file
39
app/models/action/pipeline.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: action_pipelines
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# project_id :integer
|
||||
# user_id :integer
|
||||
# pipeline_name :string(255)
|
||||
# pipeline_status :string(255)
|
||||
# description :string(255)
|
||||
# file_name :string(255)
|
||||
# is_graphic_design :boolean default("0")
|
||||
# repo_name :string(255)
|
||||
# repo_identifier :string(255)
|
||||
# repo_owner :string(255)
|
||||
# branch :string(255)
|
||||
# event :string(255)
|
||||
# sha :string(255)
|
||||
# json :text(65535)
|
||||
# yaml :text(65535)
|
||||
# disable :boolean default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_action_pipelines_on_project_id (project_id)
|
||||
# index_action_pipelines_on_user_id (user_id)
|
||||
#
|
||||
|
||||
class Action::Pipeline < ApplicationRecord
|
||||
self.table_name = 'action_pipelines'
|
||||
belongs_to :user, optional: true
|
||||
belongs_to :project
|
||||
|
||||
validates :name, presence: { message: "不能为空" }
|
||||
validates :json, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
validates :yaml, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
end
|
||||
@@ -6,7 +6,7 @@
|
||||
# name :string(255)
|
||||
# description :string(255)
|
||||
# img :string(255)
|
||||
# sort_no :string(255) default("0")
|
||||
# sort_no :integer default("0")
|
||||
# json :text(65535)
|
||||
# yaml :text(65535)
|
||||
# created_at :datetime not null
|
||||
@@ -17,4 +17,7 @@ class Action::Template < ApplicationRecord
|
||||
self.table_name = 'action_templates'
|
||||
default_scope { order(sort_no: :asc) }
|
||||
|
||||
validates :name, presence: { message: "不能为空" }
|
||||
validates :description, length: { maximum: 65535, too_long: "不能超过65535个字符"}
|
||||
|
||||
end
|
||||
|
||||
@@ -26,8 +26,6 @@
|
||||
# cloud_url :string(255) default("")
|
||||
# course_second_category_id :integer default("0")
|
||||
# delay_publish :boolean default("0")
|
||||
# memo_image :boolean default("0")
|
||||
# extra_type :integer default("0")
|
||||
# uuid :string(255)
|
||||
#
|
||||
# Indexes
|
||||
@@ -38,12 +36,14 @@
|
||||
# index_attachments_on_created_on (created_on)
|
||||
# index_attachments_on_is_public (is_public)
|
||||
# index_attachments_on_quotes (quotes)
|
||||
# index_attachments_on_uuid (uuid)
|
||||
#
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class Attachment < ApplicationRecord
|
||||
include BaseModel
|
||||
include Publicable
|
||||
@@ -76,6 +76,42 @@ class Attachment < ApplicationRecord
|
||||
|
||||
DCODES = %W(2 3 4 5 6 7 8 9 a b c f e f g h i j k l m n o p q r s t u v w x y z)
|
||||
|
||||
def self.build_from_remote_url(user, name, url, container=nil)
|
||||
ext = name.split('.')[-1]
|
||||
tmp_path = "#{Rails.root}/#{name}"
|
||||
uri = URI(url)
|
||||
size = Net::HTTP.start(uri.host, uri.port, use_ssl: uri.scheme == 'https') do |http|
|
||||
response = http.get(uri.path)
|
||||
File.open(tmp_path, 'wb') do |file|
|
||||
file.write(response.body)
|
||||
end
|
||||
end
|
||||
digest = "#{Digest::MD5.file(tmp_path).hexdigest}_#{(Time.now.to_f * 1000).to_i}.#{ext}"
|
||||
month_folder = "#{Time.now.year}/#{Time.now.month.to_s.rjust(2, '0')}"
|
||||
save_path = "#{Rails.root}#{EduSetting.get("attachment_folder")}#{month_folder}"
|
||||
unless Dir.exists?(save_path)
|
||||
FileUtils.mkdir_p(save_path) ##不成功这里会抛异常
|
||||
end
|
||||
path = File.join(save_path, digest)
|
||||
FileUtils.mv(tmp_path, path)
|
||||
attachment = Attachment.new
|
||||
attachment.filename = name
|
||||
attachment.disk_filename = path[save_path.size+1, path.size]
|
||||
attachment.filesize = size
|
||||
attachment.content_type = 'application/octet-stream'
|
||||
attachment.digest = digest.split('.')[0]
|
||||
attachment.author_id = user.id
|
||||
attachment.disk_directory = month_folder
|
||||
attachment.cloud_url = url
|
||||
attachment.uuid = SecureRandom.uuid
|
||||
attachment.container = container
|
||||
attachment.save!
|
||||
|
||||
return attachment
|
||||
rescue
|
||||
return nil
|
||||
end
|
||||
|
||||
def diskfile
|
||||
File.join(File.join(Rails.root, "files"), disk_directory.to_s, disk_filename.to_s)
|
||||
end
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: gitlink_competition_applies
|
||||
#
|
||||
# id :integer not null, primary key
|
||||
# competition_id :integer
|
||||
# competition_identifier :string(255)
|
||||
# team_id :integer
|
||||
# team_name :string(255)
|
||||
# school_name :string(255)
|
||||
# educoder_login :string(255)
|
||||
# nickname :string(255)
|
||||
# phone :string(255)
|
||||
# email :string(255)
|
||||
# identity :string(255)
|
||||
# role :string(255)
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
# == Schema Information
|
||||
#
|
||||
# Table name: gitlink_competition_applies
|
||||
|
||||
@@ -63,16 +63,17 @@ 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
|
||||
belongs_to :parent_issue, class_name: 'Issue', optional: true, foreign_key: :root_id, counter_cache: :child_count
|
||||
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
|
||||
@@ -82,25 +83,67 @@ 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 :children_issues, class_name: 'Issue', foreign_key: :root_id, dependent: :destroy
|
||||
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
|
||||
|
||||
belongs_to :changer, class_name: 'User', foreign_key: :changer_id, optional: true
|
||||
|
||||
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)}
|
||||
after_create :incre_project_common, :incre_user_statistic, :incre_platform_statistic
|
||||
after_save :incre_or_decre_closed_issues_count, :change_versions_count, :send_update_message_to_notice_system, :associate_attachment_container
|
||||
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic
|
||||
before_save :check_pm_and_update_due_date
|
||||
after_save :incre_or_decre_closed_issues_count, :change_versions_count, :send_update_message_to_notice_system, :associate_attachment_container, :generate_uuid
|
||||
after_destroy :update_closed_issues_count_in_project!, :decre_project_common, :decre_user_statistic, :decre_platform_statistic, :destroy_be_pm_links
|
||||
|
||||
|
||||
def pm_issue_type_string
|
||||
case pm_issue_type
|
||||
when 1
|
||||
"requirement"
|
||||
when 2
|
||||
"task"
|
||||
when 3
|
||||
"bug"
|
||||
else
|
||||
"issue"
|
||||
end
|
||||
end
|
||||
|
||||
def destroy_be_pm_links
|
||||
PmLink.where(be_linkable_type:"Issue",be_linkable_id:self.id).map(&:destroy)
|
||||
end
|
||||
|
||||
def check_pm_and_update_due_date
|
||||
if pm_project_id.present? && pm_issue_type.present? && status_id_changed?
|
||||
status_ids = case pm_issue_type
|
||||
when 1
|
||||
[3,5]
|
||||
when 2
|
||||
[3,5]
|
||||
when 3
|
||||
[5]
|
||||
else
|
||||
[]
|
||||
end
|
||||
if status_ids.include? self.status_id
|
||||
self.due_date = self.due_date || Time.current
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def is_issuely_issue?
|
||||
self.issue_classify.nil? || self.issue_classify == 'issue'
|
||||
@@ -118,27 +161,34 @@ class Issue < ApplicationRecord
|
||||
end
|
||||
|
||||
def incre_project_common
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {issues: 1}, self.project_id) if is_issuely_issue?
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: 1}, self.project_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def decre_project_common
|
||||
CacheAsyncSetJob.perform_later("project_common_service", {issues: -1}, self.project_id) if is_issuely_issue?
|
||||
CacheAsyncSetJob.perform_later('project_common_service', {issues: -1}, self.project_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def incre_user_statistic
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {issue_count: 1}, self.author_id) if is_issuely_issue?
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: 1}, self.author_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def decre_user_statistic
|
||||
CacheAsyncSetJob.perform_later("user_statistic_service", {issue_count: -1}, self.author_id) if is_issuely_issue?
|
||||
CacheAsyncSetJob.perform_later('user_statistic_service', {issue_count: -1}, self.author_id) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def refresh_root_issue_count
|
||||
return if root_id.nil? || root_id.zero?
|
||||
root_issue = Issue.find_by(id: root_id)
|
||||
root_count = Issue.where(root_id: root_id).count
|
||||
root_issue.update(child_count: root_count)
|
||||
end
|
||||
|
||||
def incre_platform_statistic
|
||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {issue_count: 1}) if is_issuely_issue?
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: 1}) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def decre_platform_statistic
|
||||
CacheAsyncSetJob.perform_later("platform_statistic_service", {issue_count: -1}) if is_issuely_issue?
|
||||
CacheAsyncSetJob.perform_later('platform_statistic_service', {issue_count: -1}) if is_issuely_issue?
|
||||
end
|
||||
|
||||
def get_assign_user
|
||||
@@ -147,20 +197,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
|
||||
@@ -168,11 +218,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
|
||||
|
||||
@@ -192,20 +242,29 @@ class Issue < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def generate_uuid
|
||||
# return if pm_project_id.nil?
|
||||
# attachments.map(&:generate_uuid)
|
||||
end
|
||||
|
||||
def is_collaborators?
|
||||
self.assigned_to_id.present? ? self.project.member?(self.assigned_to_id) : false
|
||||
if self.assigned_to_id.present? && self.project.present?
|
||||
self.project.member?(self.assigned_to_id)
|
||||
else
|
||||
false
|
||||
end
|
||||
end
|
||||
|
||||
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
|
||||
@@ -235,7 +294,7 @@ class Issue < ApplicationRecord
|
||||
end
|
||||
|
||||
def update_closed_issues_count_in_project!
|
||||
self.project.decrement!(:closed_issues_count) if self.status_id == 5
|
||||
self.project.decrement!(:closed_issues_count) if self.status_id == 5 && self.project.present?
|
||||
end
|
||||
|
||||
def send_update_message_to_notice_system
|
||||
@@ -267,8 +326,8 @@ class Issue < ApplicationRecord
|
||||
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?
|
||||
@@ -290,4 +349,12 @@ class Issue < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def self.full_children_issues(issue, issues = [])
|
||||
issue.children_issues.each do |i|
|
||||
issues << i
|
||||
full_children_issues(i, issues)
|
||||
end
|
||||
issues
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -38,4 +38,21 @@ class IssuePriority < ApplicationRecord
|
||||
priority.(self, :id, :name)
|
||||
end
|
||||
end
|
||||
|
||||
def pm_color
|
||||
case name
|
||||
when '低'
|
||||
'#13b33e'
|
||||
when '正常'
|
||||
'#0d5ef8'
|
||||
when '高'
|
||||
'#ff6f00'
|
||||
when '紧急'
|
||||
'#d20f0f'
|
||||
# when '立刻'
|
||||
# '#f5222d'
|
||||
else
|
||||
'#13b33e'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -45,9 +45,28 @@ class IssueStatus < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def to_builder
|
||||
def to_builder
|
||||
Jbuilder.new do |status|
|
||||
status.(self, :id, :name)
|
||||
end
|
||||
end
|
||||
|
||||
def pm_color
|
||||
case name
|
||||
when '新增'
|
||||
'#ff6f00'
|
||||
when '正在解决'
|
||||
'#0d5ef8'
|
||||
when '已解决'
|
||||
'#13b33e'
|
||||
when '关闭'
|
||||
'#b1aaa5'
|
||||
# when '反馈'
|
||||
# '#13c2c2'
|
||||
when '拒绝'
|
||||
'#ff0000'
|
||||
else
|
||||
'#ff6f00'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -15,9 +15,11 @@
|
||||
# gitea_url :string(255)
|
||||
# pull_requests_count :integer default("0")
|
||||
# pm_project_id :integer
|
||||
# organization_id :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_issue_tags_on_organization_id (organization_id)
|
||||
# index_issue_tags_on_user_id_and_name_and_project_id (user_id,name,project_id)
|
||||
#
|
||||
|
||||
@@ -29,8 +31,15 @@ class IssueTag < ApplicationRecord
|
||||
has_many :pull_request_issues, -> {where(issue_classify: "pull_request")}, source: :issue, through: :issue_tags_relates
|
||||
belongs_to :project, optional: true, counter_cache: true
|
||||
belongs_to :user, optional: true
|
||||
belongs_to :organization, optional: true
|
||||
|
||||
validates :name, uniqueness: {scope: :project_id, message: "已存在" }
|
||||
scope :pm_able, -> {where(project_id: 0)}
|
||||
|
||||
validates :name, uniqueness: {scope: :project_id, message: "已存在" }, if: :pm_project?
|
||||
|
||||
def pm_project?
|
||||
!project_id.zero?
|
||||
end
|
||||
|
||||
def self.init_data(project_id)
|
||||
data = init_issue_tag_data
|
||||
@@ -41,6 +50,24 @@ class IssueTag < ApplicationRecord
|
||||
$redis_cache.hset("project_init_issue_tags", project_id, 1)
|
||||
end
|
||||
|
||||
def self.pm_init_data(pm_project_id)
|
||||
data = init_issue_tag_data
|
||||
data.each do |item|
|
||||
next if IssueTag.exists?(pm_project_id: pm_project_id, project_id: 0, name: item[0])
|
||||
IssueTag.create!(pm_project_id: pm_project_id, project_id: 0, name: item[0], description: item[1], color: item[2])
|
||||
end
|
||||
$redis_cache.hset("pm_project_init_issue_tags", pm_project_id, 1)
|
||||
end
|
||||
|
||||
def self.pm_org_init_data(organization_id)
|
||||
data = init_issue_tag_data
|
||||
data.each do |item|
|
||||
next if IssueTag.exists?(organization_id: organization_id, project_id: 0, name: item[0])
|
||||
IssueTag.create!(organization_id: organization_id, project_id: 0, name: item[0], description: item[1], color: item[2])
|
||||
end
|
||||
$redis_cache.hset("pm_org_init_issue_tags", organization_id, 1)
|
||||
end
|
||||
|
||||
def reset_counter_field
|
||||
self.update_column(:issues_count, issue_issues.size)
|
||||
self.update_column(:pull_requests_count, pull_request_issues.size)
|
||||
|
||||
@@ -82,15 +82,432 @@ class Journal < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def operate_content
|
||||
def pm_operate_category
|
||||
detail = self.journal_details.take
|
||||
if %w(requirement task bug).include?(detail.property) && detail.prop_key.to_s == "1"
|
||||
return "issue"
|
||||
else
|
||||
return %w(requirement task bug attr).include?(detail.property) ? detail.prop_key : detail.property
|
||||
end
|
||||
end
|
||||
|
||||
def pm_operate_content
|
||||
content = ""
|
||||
detail = self.journal_details.take
|
||||
case detail.property
|
||||
when 'requirement'
|
||||
case detail.prop_key
|
||||
when 'status_id'
|
||||
old_value = IssueStatus.find_by_id(detail.old_value)&.name
|
||||
new_value = IssueStatus.find_by_id(detail.value)&.name
|
||||
content += "将状态"
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "设置为<b>#{new_value}</b>"
|
||||
else
|
||||
new_value = "未设置" if detail.value.blank?
|
||||
content += "由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
content.gsub!('新增', '待评审')
|
||||
content.gsub!('正在解决', '进行中')
|
||||
content.gsub!('已解决', '已完成')
|
||||
content.gsub!('关闭', '已关闭')
|
||||
content.gsub!('拒绝', '已拒绝')
|
||||
return content
|
||||
when 'root_id'
|
||||
old_value = "<b><#{Issue.find_by_id(detail.old_value)&.subject}></b>"
|
||||
new_value = "<b><#{Issue.find_by_id(detail.value)&.subject}></b>"
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了父需求#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的父需求#{old_value}"
|
||||
else
|
||||
content += "将关联的父需求由#{old_value}更改为#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'leaf_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "新建了子需求#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "删除了关联的子需求#{old_value}"
|
||||
else
|
||||
content += "新建了子需求#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'tag_leaf_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了子需求#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的子需求#{old_value}"
|
||||
else
|
||||
content += "关联了子需求#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
else
|
||||
return "创建了需求"
|
||||
end
|
||||
when 'task'
|
||||
case detail.prop_key
|
||||
when 'status_id'
|
||||
old_value = IssueStatus.find_by_id(detail.old_value)&.name
|
||||
new_value = IssueStatus.find_by_id(detail.value)&.name
|
||||
content += "将状态"
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "设置为<b>#{new_value}</b>"
|
||||
else
|
||||
new_value = "未设置" if detail.value.blank?
|
||||
content += "由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
content.gsub!('新增', '待处理')
|
||||
content.gsub!('正在解决', '进行中')
|
||||
content.gsub!('已解决', '已完成')
|
||||
content.gsub!('关闭', '已关闭')
|
||||
content.gsub!('拒绝', '已拒绝')
|
||||
return content
|
||||
when 'root_id'
|
||||
old_value = "<b><#{Issue.find_by_id(detail.old_value)&.subject}></b>"
|
||||
new_value = "<b><#{Issue.find_by_id(detail.value)&.subject}></b>"
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了父任务#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的父任务#{old_value}"
|
||||
else
|
||||
content += "将关联的父任务由#{old_value}>更改为#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'leaf_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "新建了子任务#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "删除了关联的子任务#{old_value}"
|
||||
else
|
||||
content += "新建了子任务#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'tag_leaf_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了子任务#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的子任务#{old_value}"
|
||||
else
|
||||
content += "关联了子任务#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
else
|
||||
return "创建了任务"
|
||||
end
|
||||
when 'bug'
|
||||
case detail.prop_key
|
||||
when 'status_id'
|
||||
old_value = IssueStatus.find_by_id(detail.old_value)&.name
|
||||
new_value = IssueStatus.find_by_id(detail.value)&.name
|
||||
content += "将状态"
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "设置为<b>#{new_value}</b>"
|
||||
else
|
||||
new_value = "未设置" if detail.value.blank?
|
||||
content += "由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
content.gsub!('新增', '待修复')
|
||||
content.gsub!('正在解决', '修复中')
|
||||
content.gsub!('已解决', '已修复')
|
||||
content.gsub!('关闭', '已关闭')
|
||||
content.gsub!('拒绝', '已拒绝')
|
||||
return content
|
||||
when 'root_id'
|
||||
old_value = "<b><#{Issue.find_by_id(detail.old_value)&.subject}></b>"
|
||||
new_value = "<b><#{Issue.find_by_id(detail.value)&.subject}></b>"
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了父缺陷#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的父缺陷#{old_value}"
|
||||
else
|
||||
content += "将关联的父缺陷由#{old_value}更改为#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'leaf_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "新建了子缺陷#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "删除了关联的子缺陷#{old_value}"
|
||||
else
|
||||
content += "新建了子缺陷#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'tag_leaf_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b><#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了子缺陷#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的子缺陷#{old_value}"
|
||||
else
|
||||
content += "关联了子缺陷#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
else
|
||||
return "创建了缺陷"
|
||||
end
|
||||
when 'attr'
|
||||
case detail.prop_key
|
||||
when 'subject'
|
||||
return "修改了<b>标题</b>"
|
||||
when 'description'
|
||||
return "修改了<b>正文</b>"
|
||||
when 'priority_id'
|
||||
old_value = IssuePriority.find_by_id(detail.old_value)&.name
|
||||
new_value = IssuePriority.find_by_id(detail.value)&.name
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "将优先级设置为<b>#{new_value}</b>"
|
||||
else
|
||||
new_value = "未设置" if detail.value.blank?
|
||||
content += "将优先级由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
return content
|
||||
when 'status_id'
|
||||
old_value = IssueStatus.find_by_id(detail.old_value)&.name
|
||||
new_value = IssueStatus.find_by_id(detail.value)&.name
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "将状态设置为<b>#{new_value}</b>"
|
||||
else
|
||||
new_value = "未设置" if detail.value.blank?
|
||||
content += "将状态由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
case self.issue.pm_issue_type.to_i
|
||||
when 1
|
||||
content.gsub!('新增', '待评审')
|
||||
content.gsub!('正在解决', '进行中')
|
||||
content.gsub!('已解决', '已完成')
|
||||
content.gsub!('关闭', '已关闭')
|
||||
content.gsub!('拒绝', '已拒绝')
|
||||
when 2
|
||||
content.gsub!('新增', '待处理')
|
||||
content.gsub!('正在解决', '进行中')
|
||||
content.gsub!('已解决', '已完成')
|
||||
content.gsub!('关闭', '已关闭')
|
||||
content.gsub!('拒绝', '已拒绝')
|
||||
when 3
|
||||
content.gsub!('新增', '待修复')
|
||||
content.gsub!('正在解决', '修复中')
|
||||
content.gsub!('已解决', '已修复')
|
||||
content.gsub!('关闭', '已关闭')
|
||||
content.gsub!('拒绝', '已拒绝')
|
||||
end
|
||||
return content
|
||||
when 'pm_issue_type'
|
||||
old_value = detail.old_value
|
||||
new_value = detail.value
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "将工作项类型设置为<b>#{new_value}</b>"
|
||||
else
|
||||
new_value = "未设置" if detail.value.blank?
|
||||
content += "将工作项类型由<b>#{old_value}</b>更改为<b>#{new_value}</b>"
|
||||
end
|
||||
content.gsub!('1', '需求')
|
||||
content.gsub!('2', '任务')
|
||||
content.gsub!('3', '缺陷')
|
||||
return content
|
||||
when 'pm_sprint_id'
|
||||
old_value = detail.old_value
|
||||
new_value = detail.value
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加了关联迭代"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将关联迭代更改为<b>未设置</b>"
|
||||
else
|
||||
content += "变更了关联迭代"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'project_id'
|
||||
old_value = Project.find_by_id(detail.old_value)&.name
|
||||
new_value = Project.find_by_id(detail.value)&.name
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加关联代码库<b>#{new_value}</b>"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将关联代码库更改为<b>未设置</b>"
|
||||
else
|
||||
content += "将关联代码库由<b>#{old_value}</b>改为<b>#{new_value}</b>"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'branch_name'
|
||||
old_value = detail.old_value
|
||||
new_value = detail.value
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加关联分支<b>#{new_value}</b>"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将关联分支更改为<b>未设置</b>"
|
||||
else
|
||||
content += "将关联分支由<b>#{old_value}</b>改为<b>#{new_value}</b>"
|
||||
end
|
||||
end
|
||||
return content
|
||||
|
||||
when 'start_date'
|
||||
old_value = detail.old_value
|
||||
new_value = detail.value
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加开始时间<b>#{new_value}</b>"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将开始时间更改为<b>未设置</b>"
|
||||
else
|
||||
content += "将开始时间由<b>#{old_value}</b>改为<b>#{new_value}</b>"
|
||||
end
|
||||
end
|
||||
return content
|
||||
|
||||
when 'due_date'
|
||||
old_value = detail.old_value
|
||||
new_value = detail.value
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加结束时间<b>#{new_value}</b>"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将结束时间更改为<b>未设置</b>"
|
||||
else
|
||||
content += "将结束时间由<b>#{old_value}</b>改为<b>#{new_value}</b>"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'time_scale'
|
||||
old_value = detail.old_value
|
||||
new_value = detail.value
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加预估工时<b>#{new_value}</b>"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将预估工时更改为<b>未设置</b>"
|
||||
else
|
||||
content += "将预估工时由<b>#{old_value}</b>改为<b>#{new_value}</b>"
|
||||
end
|
||||
end
|
||||
return content
|
||||
end
|
||||
when 'attachment'
|
||||
old_value = detail.old_value.to_s
|
||||
new_value = detail.value.to_s
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "上传了附件"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "删除了附件"
|
||||
else
|
||||
content += "上传了附件"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'assigner'
|
||||
old_value = User.where(id: detail.old_value.split(",")).map{|u| "<b>#{u.real_name}</b>"}.join("、")
|
||||
new_value = User.where(id: detail.value.split(",")).map{|u| "<b>#{u.real_name}</b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加负责人#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将负责人更改为<b>未设置</b>"
|
||||
else
|
||||
content += "将负责人由#{old_value}更改为#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'issue_tag'
|
||||
old_value = IssueTag.where(id: detail.old_value.split(",")).map{|t| "<b>#{t.name}</b>"}.join("、")
|
||||
new_value = IssueTag.where(id: detail.value.split(",")).map{|t| "<b>#{t.name}</b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "添加标记#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "将标记更改为<b>未设置</b>"
|
||||
else
|
||||
content += "将标记由#{old_value}更改为#{new_value}"
|
||||
end
|
||||
end
|
||||
return content
|
||||
when 'link_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "新建了关联的工作项#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "删除了关联的工作项#{old_value}"
|
||||
else
|
||||
content += "新建了关联的工作项#{new_value}"
|
||||
end
|
||||
end
|
||||
content.gsub!('1', "需求")
|
||||
content.gsub!('2', "任务")
|
||||
content.gsub!('3', "缺陷")
|
||||
return content
|
||||
when 'tag_link_issue'
|
||||
old_value = Issue.where(id: detail.old_value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
new_value = Issue.where(id: detail.value.to_s.split(",")).map{|i| "<b>[#{i.pm_issue_type}]-<#{i.subject}></b>"}.join("、")
|
||||
if detail.old_value.nil? || detail.old_value.blank?
|
||||
content += "关联了工作项#{new_value}"
|
||||
else
|
||||
if detail.value.nil? || detail.value.blank?
|
||||
content += "取消了关联的工作项#{old_value}"
|
||||
else
|
||||
content += "关联了工作项#{new_value}"
|
||||
end
|
||||
end
|
||||
content.gsub!('1', "需求")
|
||||
content.gsub!('2', "任务")
|
||||
content.gsub!('3', "缺陷")
|
||||
return content
|
||||
when 'issue'
|
||||
issue = self.issue
|
||||
case issue.pm_issue_type
|
||||
when 1
|
||||
return "创建了需求"
|
||||
when 2
|
||||
return "创建了任务"
|
||||
when 3
|
||||
return "创建了缺陷"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def operate_content
|
||||
content = ""
|
||||
detail = self.journal_details.take
|
||||
case detail.property
|
||||
when 'issue'
|
||||
return "创建了<b>疑修</b>"
|
||||
when 'attachment'
|
||||
old_value = Attachment.where("id in (?) or uuid in (?)", detail.old_value.to_s.split(","), detail.old_value.to_s.split(",")).pluck(:filename).join("、")
|
||||
new_value = Attachment.where("id in (?) or uuid in (?)", detail.value.to_s.split(","), detail.value.to_s.split(",")).pluck(:filename).join("、")
|
||||
old_value = Attachment.where("BINARY id in (?) or uuid in (?)", detail.old_value.to_s.split(","), detail.old_value.to_s.split(",")).pluck(:filename).join("、")
|
||||
new_value = Attachment.where("BINARY id in (?) or uuid in (?)", detail.value.to_s.split(","), detail.value.to_s.split(",")).pluck(:filename).join("、")
|
||||
if old_value.nil? || old_value.blank?
|
||||
content += "添加了<b>#{new_value}</b>附件"
|
||||
else
|
||||
|
||||
@@ -11,7 +11,6 @@
|
||||
# course_group_id :integer default("0")
|
||||
# is_collect :integer default("1")
|
||||
# graduation_group_id :integer default("0")
|
||||
# is_apply_signature :boolean default("0")
|
||||
# team_user_id :integer
|
||||
#
|
||||
# Indexes
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# id :integer not null, primary key
|
||||
# user_id :integer
|
||||
# organization_id :integer
|
||||
# is_creator :boolean default("0")
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
|
||||
28
app/models/pm_link.rb
Normal file
28
app/models/pm_link.rb
Normal file
@@ -0,0 +1,28 @@
|
||||
# == 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
|
||||
belongs_to :be_linkable, polymorphic: true
|
||||
# belongs_to :linkable_issue, -> {where(pm_links: {linkable_type: 'Issue'})}, foreign_key: 'linkable_id', class_name: 'Issue'
|
||||
# belongs_to :be_linkable_issue, -> {where(pm_links: {be_linkable_type: 'Issue'})}, foreign_key: 'be_linkable_id', class_name: 'Issue'
|
||||
|
||||
def be_linkable
|
||||
be_linkable_type.constantize.find be_linkable_id
|
||||
end
|
||||
end
|
||||
@@ -59,6 +59,7 @@
|
||||
# is_pinned :boolean default("0")
|
||||
# recommend_index :integer default("0")
|
||||
# pr_view_admin :boolean default("0")
|
||||
# has_actions :boolean default("0")
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
@@ -130,9 +131,9 @@ class Project < ApplicationRecord
|
||||
has_many :pinned_projects, dependent: :destroy
|
||||
has_many :has_pinned_users, through: :pinned_projects, source: :owner
|
||||
has_many :webhooks, class_name: "Gitea::Webhook", primary_key: :gpid, foreign_key: :repo_id
|
||||
has_many :user_trace_tasks, dependent: :destroy
|
||||
has_many :user_trace_tasks, dependent: :destroy
|
||||
has_many :project_invite_links, dependent: :destroy
|
||||
has_many :project_topic_ralates, dependent: :destroy
|
||||
has_many :project_topic_ralates, dependent: :destroy
|
||||
has_many :project_topics, through: :project_topic_ralates
|
||||
has_many :commit_logs, dependent: :destroy
|
||||
has_many :daily_project_statistics, dependent: :destroy
|
||||
@@ -149,6 +150,12 @@ class Project < ApplicationRecord
|
||||
scope :recommend, -> { visible.project_statics_select.where(recommend: true) }
|
||||
scope :pinned, -> {where(is_pinned: true)}
|
||||
|
||||
scope :like, lambda { |keywords|
|
||||
# 表情处理
|
||||
keywords = keywords.to_s.each_char.select { |c| c.bytes.first < 240 }.join('')
|
||||
sql = "name LIKE :search OR identifier LIKE :search"
|
||||
where(sql, :search => "%#{keywords.strip}%") unless keywords.blank?
|
||||
}
|
||||
delegate :content, to: :project_detail, allow_nil: true
|
||||
delegate :name, to: :license, prefix: true, allow_nil: true
|
||||
|
||||
@@ -245,11 +252,11 @@ class Project < ApplicationRecord
|
||||
def set_recommend_and_is_pinned
|
||||
self.recommend = self.recommend_index.zero? ? false : true
|
||||
# 私有项目不允许设置精选和推荐
|
||||
unless self.is_public
|
||||
self.recommend = false
|
||||
self.recommend_index = 0
|
||||
self.is_pinned = false
|
||||
end
|
||||
# unless self.is_public
|
||||
# self.recommend = false
|
||||
# self.recommend_index = 0
|
||||
# self.is_pinned = false
|
||||
# end
|
||||
end
|
||||
|
||||
def self.search_project(search)
|
||||
@@ -393,11 +400,13 @@ class Project < ApplicationRecord
|
||||
|
||||
user = Owner.find_by_login namespace_path
|
||||
user = User.new(login: namespace_path) if user.nil?
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
user = User.new(login: namespace_path) if user.nil?
|
||||
if identifier.end_with?('.json')
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
identifier = identifier.sub(/.*\K.json/, '')
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
else
|
||||
else
|
||||
project = user&.projects&.find_by(identifier: identifier) || Project.find_by(identifier: "#{namespace_path}/#{identifier}")
|
||||
end
|
||||
return nil if project.blank?
|
||||
@@ -444,36 +453,46 @@ class Project < ApplicationRecord
|
||||
end
|
||||
|
||||
def get_last_project_issues_index
|
||||
last_issue = self.issues.issue_issue.last
|
||||
last_issue = self.issues.issue_issue.last
|
||||
deleted_issue_count = ($redis_cache.hget("issue_cache_delete_count", self.id) || 0).to_i
|
||||
|
||||
last_issue&.project_issues_index.present? ? last_issue.project_issues_index + deleted_issue_count : 0
|
||||
end
|
||||
|
||||
def incre_project_issue_cache_delete_count(count=1)
|
||||
$redis_cache.hincrby("issue_cache_delete_count", self.id, count)
|
||||
$redis_cache.hincrby("issue_cache_delete_count", self.id, count)
|
||||
end
|
||||
|
||||
def del_project_issue_cache_delete_count
|
||||
$redis_cache.hdel("issue_cache_delete_count", self.id)
|
||||
$redis_cache.hdel("issue_cache_delete_count", self.id)
|
||||
end
|
||||
|
||||
def open_portrait
|
||||
EduSetting.get("open_portrait_projects").present? ? EduSetting.get("open_portrait_projects").split(",").include?(self.id.to_s) : false
|
||||
end
|
||||
|
||||
def actionable
|
||||
return false if EduSetting.get("project_user_actionable").nil?
|
||||
return EduSetting.get("project_user_actionable").split(",").include?(self.owner&.login)
|
||||
end
|
||||
|
||||
def has_pull_request(branch_name)
|
||||
return true if self.pull_requests.opening.where(head: branch_name).present? || self.pull_requests.opening.where(base: branch_name).present?
|
||||
if self.forked_from_project_id.present?
|
||||
return true if self.fork_project.pull_requests.opening.where(head: branch_name).present? || self.fork_project.pull_requests.opening.where(base: branch_name).present?
|
||||
end
|
||||
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def self.mindspore_contributors
|
||||
def is_need_apply
|
||||
return false if EduSetting.get("project_need_apply").nil?
|
||||
return EduSetting.get("project_need_apply").split(",").include?(self.id.to_s)
|
||||
end
|
||||
|
||||
def self.mindspore_contributors
|
||||
cache_result = $redis_cache.get("ProjectMindsporeContributors")
|
||||
if cache_result.nil?
|
||||
if cache_result.nil?
|
||||
contributors = []
|
||||
file = File.open('public/mindspore_authors', 'r')
|
||||
file.each_line do |l|
|
||||
@@ -481,12 +500,12 @@ class Project < ApplicationRecord
|
||||
email = itemArray[0]
|
||||
username = itemArray[1]
|
||||
commits = itemArray[2].to_i
|
||||
user = User.find_by(login: username, mail: email)
|
||||
user = User.find_by(login: username) if user.nil?
|
||||
user = User.find_by(login: username, mail: email)
|
||||
user = User.find_by(login: username) if user.nil?
|
||||
user = User.find_by(mail: email) if user.nil?
|
||||
# next if user.nil?
|
||||
search_contributor = contributors.select{|con| con["id"]==user.id}[0]
|
||||
if search_contributor.present?
|
||||
if search_contributor.present?
|
||||
search_contributor["contributions"] += commits
|
||||
else
|
||||
contributors << {contributions: commits, name: username, login: username, email: email, id: user&.id}.stringify_keys
|
||||
@@ -497,10 +516,15 @@ class Project < ApplicationRecord
|
||||
$redis_cache.set("ProjectMindsporeContributors", contributors.to_json)
|
||||
|
||||
return contributors
|
||||
else
|
||||
else
|
||||
return JSON.parse(cache_result)
|
||||
end
|
||||
end
|
||||
|
||||
def full_url
|
||||
Rails.application.config_for(:configuration)['platform_url'].to_s + '/' + self.owner&.try(:login).to_s + '/' + self.identifier.to_s
|
||||
end
|
||||
|
||||
def to_builder
|
||||
Jbuilder.new do |project|
|
||||
project.id self.id
|
||||
@@ -509,9 +533,9 @@ class Project < ApplicationRecord
|
||||
project.description Nokogiri::HTML(self.description).text
|
||||
project.visits self.visits
|
||||
project.praises_count self.praises_count.to_i
|
||||
project.watchers_count self.watchers_count.to_i
|
||||
project.issues_count self.issues_count.to_i
|
||||
project.pull_requests_count self.pull_requests_count.to_i
|
||||
project.watchers_count self.watchers_count.to_i
|
||||
project.issues_count self.issues_count.to_i
|
||||
project.pull_requests_count self.pull_requests_count.to_i
|
||||
project.forked_count self.forked_count.to_i
|
||||
project.is_public self.is_public
|
||||
project.mirror_url self.repository&.mirror_url
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
# Indexes
|
||||
#
|
||||
# index_project_categories_on_ancestry (ancestry)
|
||||
# index_project_categories_on_id (id)
|
||||
#
|
||||
|
||||
class ProjectCategory < ApplicationRecord
|
||||
|
||||
@@ -9,10 +9,6 @@
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_project_languages_on_id (id)
|
||||
#
|
||||
|
||||
class ProjectLanguage < ApplicationRecord
|
||||
include Projectable
|
||||
|
||||
@@ -27,7 +27,6 @@
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
# index_name (project_id)
|
||||
# index_repositories_on_identifier (identifier)
|
||||
# index_repositories_on_project_id (project_id)
|
||||
# index_repositories_on_user_id (user_id)
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
# sync_direction :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# external_token :string(255)
|
||||
# webhook_gid :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
# sync_direction :integer
|
||||
# created_at :datetime not null
|
||||
# updated_at :datetime not null
|
||||
# external_token :string(255)
|
||||
# webhook_gid :integer
|
||||
#
|
||||
# Indexes
|
||||
#
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#
|
||||
|
||||
|
||||
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or
|
||||
# modify it under the terms of the GNU General Public License
|
||||
@@ -44,7 +45,7 @@ class Token < ActiveRecord::Base
|
||||
|
||||
def self.get_or_create_permanent_login_token(user, type)
|
||||
token = Token.get_token_from_user(user, type)
|
||||
Rails.logger.info "###### Token.get_token_from_user result: #{token&.value}"
|
||||
Rails.logger.info "###### Token.get_token_from_user time:#{Time.new.to_i}, result: #{token&.value}"
|
||||
unless token
|
||||
token = Token.create(:user => user, :action => type)
|
||||
Rails.logger.info "###### Token.get_token_from_user is nul and agine create token: #{token&.value}"
|
||||
@@ -117,8 +118,8 @@ class Token < ActiveRecord::Base
|
||||
|
||||
# Removes obsolete tokens (same user and action)
|
||||
def delete_previous_tokens
|
||||
if user
|
||||
Token.where(['user_id = ? AND action = ?', user.id, action]).delete_all
|
||||
end
|
||||
# if user
|
||||
# Token.where(['user_id = ? AND action = ?', user.id, action]).delete_all
|
||||
# end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,9 +22,9 @@
|
||||
# school_id :integer
|
||||
# description :string(255)
|
||||
# department_id :integer
|
||||
# province :text(65535)
|
||||
# custom_department :string(255)
|
||||
# province :string(255)
|
||||
# city :string(255)
|
||||
# custom_department :string(255)
|
||||
# show_email :boolean default("0")
|
||||
# show_location :boolean default("0")
|
||||
# show_department :boolean default("0")
|
||||
|
||||
Reference in New Issue
Block a user