Commit d8263b28 authored by Thijs Wouters's avatar Thijs Wouters Committed by Alfredo Sumaran

Sort by label priority

Signed-off-by: default avatarRémy Coutable <remy@rymai.me>
parent 0e2f26dd
...@@ -100,7 +100,7 @@ class Projects::LabelsController < Projects::ApplicationController ...@@ -100,7 +100,7 @@ class Projects::LabelsController < Projects::ApplicationController
end end
def label_params def label_params
params.require(:label).permit(:title, :description, :color) params.require(:label).permit(:title, :description, :color, :priority)
end end
def label def label
......
...@@ -224,7 +224,7 @@ class IssuableFinder ...@@ -224,7 +224,7 @@ class IssuableFinder
def sort(items) def sort(items)
# Ensure we always have an explicit sort order (instead of inheriting # Ensure we always have an explicit sort order (instead of inheriting
# multiple orders when combining ActiveRecord::Relation objects). # multiple orders when combining ActiveRecord::Relation objects).
params[:sort] ? items.sort(params[:sort]) : items.reorder(id: :desc) params[:sort] ? items.sort(params[:sort], label_names) : items.reorder(id: :desc)
end end
def by_assignee(items) def by_assignee(items)
...@@ -318,7 +318,11 @@ class IssuableFinder ...@@ -318,7 +318,11 @@ class IssuableFinder
end end
def label_names def label_names
if labels?
params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name] params[:label_name].is_a?(String) ? params[:label_name].split(',') : params[:label_name]
else
[]
end
end end
def current_user_related? def current_user_related?
......
...@@ -14,7 +14,8 @@ module SortingHelper ...@@ -14,7 +14,8 @@ module SortingHelper
sort_value_recently_signin => sort_title_recently_signin, sort_value_recently_signin => sort_title_recently_signin,
sort_value_oldest_signin => sort_title_oldest_signin, sort_value_oldest_signin => sort_title_oldest_signin,
sort_value_downvotes => sort_title_downvotes, sort_value_downvotes => sort_title_downvotes,
sort_value_upvotes => sort_title_upvotes sort_value_upvotes => sort_title_upvotes,
sort_value_priority => sort_title_priority
} }
end end
...@@ -28,6 +29,10 @@ module SortingHelper ...@@ -28,6 +29,10 @@ module SortingHelper
} }
end end
def sort_title_priority
'Priority'
end
def sort_title_oldest_updated def sort_title_oldest_updated
'Oldest updated' 'Oldest updated'
end end
...@@ -84,6 +89,10 @@ module SortingHelper ...@@ -84,6 +89,10 @@ module SortingHelper
'Most popular' 'Most popular'
end end
def sort_value_priority
'priority'
end
def sort_value_oldest_updated def sort_value_oldest_updated
'updated_asc' 'updated_asc'
end end
......
...@@ -48,6 +48,12 @@ module Issuable ...@@ -48,6 +48,12 @@ module Issuable
scope :non_archived, -> { join_project.where(projects: { archived: false }) } scope :non_archived, -> { join_project.where(projects: { archived: false }) }
def self.order_priority(labels)
select("#{table_name}.*, (#{Label.high_priority(name, table_name, labels).to_sql}) AS highest_priority")
.group("#{table_name}.id")
.reorder(nulls_last('highest_priority', 'ASC'))
end
delegate :name, delegate :name,
:email, :email,
to: :author, to: :author,
...@@ -105,12 +111,13 @@ module Issuable ...@@ -105,12 +111,13 @@ module Issuable
where(t[:title].matches(pattern).or(t[:description].matches(pattern))) where(t[:title].matches(pattern).or(t[:description].matches(pattern)))
end end
def sort(method) def sort(method, labels = [])
case method.to_s case method.to_s
when 'milestone_due_asc' then order_milestone_due_asc when 'milestone_due_asc' then order_milestone_due_asc
when 'milestone_due_desc' then order_milestone_due_desc when 'milestone_due_desc' then order_milestone_due_desc
when 'downvotes_desc' then order_downvotes_desc when 'downvotes_desc' then order_downvotes_desc
when 'upvotes_desc' then order_upvotes_desc when 'upvotes_desc' then order_upvotes_desc
when 'priority' then order_priority(labels)
else else
order_by(method) order_by(method)
end end
......
...@@ -27,11 +27,28 @@ class Label < ActiveRecord::Base ...@@ -27,11 +27,28 @@ class Label < ActiveRecord::Base
format: { with: /\A[^&\?,]+\z/ }, format: { with: /\A[^&\?,]+\z/ },
uniqueness: { scope: :project_id } uniqueness: { scope: :project_id }
before_save :nillify_priority
default_scope { order(title: :asc) } default_scope { order(title: :asc) }
scope :templates, -> { where(template: true) } scope :templates, -> { where(template: true) }
scope :prioritized, ->(value = true) { where(priority: value) } scope :prioritized, ->(value = true) { where(priority: value) }
def self.high_priority(name, table_name, labels)
unfiltered = unscoped
.select("MIN(labels.priority)")
.joins("INNER JOIN label_links ON label_links.label_id = labels.id")
.where("label_links.target_type = '#{name}'")
.where("label_links.target_id = #{table_name}.id")
.where("labels.project_id = #{table_name}.project_id")
if labels.empty?
unfiltered
else
unfiltered.where("labels.title NOT IN (?)", labels)
end
end
alias_attribute :name, :title alias_attribute :name, :title
def self.reference_prefix def self.reference_prefix
...@@ -120,4 +137,10 @@ class Label < ActiveRecord::Base ...@@ -120,4 +137,10 @@ class Label < ActiveRecord::Base
id id
end end
end end
def nillify_priority
unless self.priority.present?
self.priority = nil
end
end
end end
...@@ -24,6 +24,10 @@ ...@@ -24,6 +24,10 @@
- suggested_colors.each do |color| - suggested_colors.each do |color|
= link_to '#', style: "background-color: #{color}", data: { color: color } do = link_to '#', style: "background-color: #{color}", data: { color: color } do
&nbsp; &nbsp;
.form-group
= f.label :priority, "Priority", class: 'control-label'
.col-sm-10
= f.text_field :priority, class: "form-control"
.form-actions .form-actions
- if @label.persisted? - if @label.persisted?
......
...@@ -8,6 +8,8 @@ ...@@ -8,6 +8,8 @@
%b.caret %b.caret
%ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort %ul.dropdown-menu.dropdown-menu-align-right.dropdown-menu-sort
%li %li
= link_to page_filter_path(sort: sort_value_priority) do
= sort_title_priority
= link_to page_filter_path(sort: sort_value_recently_created) do = link_to page_filter_path(sort: sort_value_recently_created) do
= sort_title_recently_created = sort_title_recently_created
= link_to page_filter_path(sort: sort_value_oldest_created) do = link_to page_filter_path(sort: sort_value_oldest_created) do
......
module ActiveRecord
class Base
def self.nulls_last(field, direction = 'ASC')
if Gitlab::Database.postgresql?
"#{field} #{direction} NULLS LAST"
else
if direction.upcase == 'ASC'
"-#{field} DESC"
else
"#{field} DESC"
end
end
end
end
end
class AddPriorityToLabel < ActiveRecord::Migration
def change
add_column :labels, :priority, :integer
add_index :labels, :priority
end
end
...@@ -496,8 +496,10 @@ ActiveRecord::Schema.define(version: 20160530150109) do ...@@ -496,8 +496,10 @@ ActiveRecord::Schema.define(version: 20160530150109) do
t.datetime "updated_at" t.datetime "updated_at"
t.boolean "template", default: false t.boolean "template", default: false
t.string "description" t.string "description"
t.integer "priority"
end end
add_index "labels", ["priority"], name: "index_labels_on_priority", using: :btree
add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree add_index "labels", ["project_id"], name: "index_labels_on_project_id", using: :btree
create_table "lfs_objects", force: :cascade do |t| create_table "lfs_objects", force: :cascade do |t|
......
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