Add ProjectLabel model

parent e2dd75c0
......@@ -128,7 +128,8 @@ class IssuableFinder
@labels = Label.where(title: label_names)
if projects
@labels = @labels.where(project: projects)
label_ids = LabelsFinder.new(current_user, project_id: projects).execute.select(:id)
@labels = @labels.where(labels: { id: label_ids })
end
else
@labels = Label.none
......
......@@ -57,21 +57,21 @@ module LabelsHelper
def edit_label_path(label)
case label
when GroupLabel then edit_group_label_path(label.group, label)
else edit_namespace_project_label_path(label.project.namespace, label.project, label)
when ProjectLabel then edit_namespace_project_label_path(label.project.namespace, label.project, label)
end
end
def destroy_label_path(label)
case label
when GroupLabel then group_label_path(label.group, label)
else namespace_project_label_path(label.project.namespace, label.project, label)
when ProjectLabel then namespace_project_label_path(label.project.namespace, label.project, label)
end
end
def toggle_subscription_label_path(label)
case label
when GroupLabel then toggle_subscription_group_label_path(label.group, label)
else toggle_subscription_namespace_project_label_path(label.project.namespace, label.project, label)
when ProjectLabel then toggle_subscription_namespace_project_label_path(label.project.namespace, label.project, label)
end
end
......@@ -79,7 +79,7 @@ module LabelsHelper
title, icon =
case label
when GroupLabel then ['Group', 'folder-open']
else ['Project', 'bookmark']
when ProjectLabel then ['Project', 'bookmark']
end
options[:class] ||= ''
......
......@@ -15,15 +15,12 @@ class Label < ActiveRecord::Base
default_value_for :color, DEFAULT_COLOR
belongs_to :project
has_many :lists, dependent: :destroy
has_many :label_links, dependent: :destroy
has_many :issues, through: :label_links, source: :target, source_type: 'Issue'
has_many :merge_requests, through: :label_links, source: :target, source_type: 'MergeRequest'
validates :color, color: true, allow_blank: false
validates :project, presence: true, if: :project_label?
# Don't allow ',' for label titles
validates :title, presence: true, format: { with: /\A[^,]+\z/ }
......@@ -137,10 +134,6 @@ class Label < ActiveRecord::Base
.count
end
def project_label?
type.blank? && !template?
end
def label_format_reference(format = :id)
raise StandardError, 'Unknown format' unless [:id, :name].include?(format)
......
......@@ -107,7 +107,7 @@ class Project < ActiveRecord::Base
# Merge requests from source project should be kept when source project was removed
has_many :fork_merge_requests, foreign_key: 'source_project_id', class_name: MergeRequest
has_many :issues, dependent: :destroy
has_many :labels, dependent: :destroy
has_many :labels, dependent: :destroy, class_name: 'ProjectLabel'
has_many :services, dependent: :destroy
has_many :events, dependent: :destroy
has_many :milestones, dependent: :destroy
......@@ -730,8 +730,10 @@ class Project < ActiveRecord::Base
def create_labels
Label.templates.each do |label|
label = label.dup
label.template = nil
label.template = false
label.project_id = self.id
label.type = 'ProjectLabel'
label.save
end
end
......
class ProjectLabel < Label
belongs_to :project
validates :project, presence: true
end
class LabelPolicy < BasePolicy
class ProjectLabelPolicy < BasePolicy
def rules
return unless @user
can! :admin_label if Ability.allowed?(@user, :admin_label, @subject.project)
end
end
= form_for [@project.namespace.becomes(Namespace), @project, @label], html: { class: 'form-horizontal label-form js-quick-submit js-requires-input' } do |f|
= form_for @label, as: :label, url: url, html: { class: 'form-horizontal label-form js-quick-submit js-requires-input' } do |f|
= form_errors(@label)
.form-group
......
......@@ -7,4 +7,4 @@
= icon('bookmark')
Edit Project Label
%hr
= render 'form'
= render 'form', url: namespace_project_label_path(@project.namespace.becomes(Namespace), @project, @label)
......@@ -7,4 +7,4 @@
= icon('bookmark')
New Project Label
%hr
= render 'form'
= render 'form', url: namespace_project_labels_path(@project.namespace.becomes(Namespace), @project)
class SetProjectLabelTypeOnLabels < ActiveRecord::Migration
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
def up
update_column_in_batches(:labels, :type, 'ProjectLabel') do |table, query|
query.where(table[:project_id].not_eq(nil))
end
end
def down
update_column_in_batches(:labels, :type, nil) do |table, query|
query.where(table[:project_id].not_eq(nil))
end
end
end
......@@ -70,7 +70,7 @@ module Banzai
end
def object_link_text(object, matches)
if object.project.nil? || object.project == context[:project]
if object.is_a?(GroupLabel) || object.project == context[:project]
LabelsHelper.render_colored_label(object)
else
LabelsHelper.render_colored_cross_project_label(object)
......
......@@ -237,7 +237,7 @@ module Gitlab
def create_label(name)
color = nice_label_color(name)
Label.create!(project_id: project.id, name: name, color: color)
project.labels.create!(name: name, color: color)
end
def format_content(raw_content)
......
FactoryGirl.define do
factory :label do
factory :label, class: ProjectLabel do
sequence(:title) { |n| "label#{n}" }
color "#990000"
project
......
require 'spec_helper'
describe Label, models: true do
let(:label) { create(:label) }
describe 'modules' do
it { is_expected.to include_module(Referable) }
it { is_expected.to include_module(Subscribable) }
end
describe 'associations' do
it { is_expected.to belong_to(:project) }
it { is_expected.to have_many(:label_links).dependent(:destroy) }
it { is_expected.to have_many(:issues).through(:label_links).source(:target) }
it { is_expected.to have_many(:label_links).dependent(:destroy) }
it { is_expected.to have_many(:lists).dependent(:destroy) }
end
describe 'modules' do
subject { described_class }
it { is_expected.to include_module(Referable) }
end
describe 'validation' do
it { is_expected.to validate_presence_of(:project) }
it { is_expected.to validate_uniqueness_of(:title) }
it 'validates color code' do
expect(label).not_to allow_value('G-ITLAB').for(:color)
expect(label).not_to allow_value('AABBCC').for(:color)
expect(label).not_to allow_value('#AABBCCEE').for(:color)
expect(label).not_to allow_value('GGHHII').for(:color)
expect(label).not_to allow_value('#').for(:color)
expect(label).not_to allow_value('').for(:color)
expect(label).to allow_value('#AABBCC').for(:color)
expect(label).to allow_value('#abcdef').for(:color)
is_expected.not_to allow_value('G-ITLAB').for(:color)
is_expected.not_to allow_value('AABBCC').for(:color)
is_expected.not_to allow_value('#AABBCCEE').for(:color)
is_expected.not_to allow_value('GGHHII').for(:color)
is_expected.not_to allow_value('#').for(:color)
is_expected.not_to allow_value('').for(:color)
is_expected.to allow_value('#AABBCC').for(:color)
is_expected.to allow_value('#abcdef').for(:color)
end
it 'validates title' do
expect(label).not_to allow_value('G,ITLAB').for(:title)
expect(label).not_to allow_value('').for(:title)
expect(label).to allow_value('GITLAB').for(:title)
expect(label).to allow_value('gitlab').for(:title)
expect(label).to allow_value('G?ITLAB').for(:title)
expect(label).to allow_value('G&ITLAB').for(:title)
expect(label).to allow_value("customer's request").for(:title)
is_expected.not_to allow_value('G,ITLAB').for(:title)
is_expected.not_to allow_value('').for(:title)
is_expected.to allow_value('GITLAB').for(:title)
is_expected.to allow_value('gitlab').for(:title)
is_expected.to allow_value('G?ITLAB').for(:title)
is_expected.to allow_value('G&ITLAB').for(:title)
is_expected.to allow_value("customer's request").for(:title)
end
end
......@@ -53,6 +47,8 @@ describe Label, models: true do
end
describe '#to_reference' do
let(:label) { create(:label) }
context 'using id' do
it 'returns a String reference to the object' do
expect(label.to_reference).to eq "~#{label.id}"
......
require 'spec_helper'
describe ProjectLabel, models: true do
describe 'relationships' do
it { is_expected.to belong_to(:project) }
end
describe 'validations' do
it { is_expected.to validate_presence_of(:project) }
end
end
......@@ -56,7 +56,7 @@ describe Project, models: true do
it { is_expected.to have_many(:runners) }
it { is_expected.to have_many(:variables) }
it { is_expected.to have_many(:triggers) }
it { is_expected.to have_many(:labels).dependent(:destroy) }
it { is_expected.to have_many(:labels).class_name('ProjectLabel').dependent(:destroy) }
it { is_expected.to have_many(:users_star_projects).dependent(:destroy) }
it { is_expected.to have_many(:environments).dependent(:destroy) }
it { is_expected.to have_many(:deployments).dependent(:destroy) }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment