Prioritize labels functionality
This commit is contained in:
parent
4d4a9b7c8a
commit
0e2f26dd2a
8 changed files with 146 additions and 12 deletions
79
app/assets/javascripts/LabelManager.js.coffee
Normal file
79
app/assets/javascripts/LabelManager.js.coffee
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
class @LabelManager
|
||||||
|
constructor: (opts = {}) ->
|
||||||
|
# Defaults
|
||||||
|
{
|
||||||
|
@togglePriorityButton = $('.js-toggle-priority')
|
||||||
|
@prioritizedLabels = $('.js-prioritized-labels')
|
||||||
|
@otherLabels = $('.js-other-labels')
|
||||||
|
} = opts
|
||||||
|
|
||||||
|
@prioritizedLabels.sortable(
|
||||||
|
items: 'li'
|
||||||
|
update: @onPrioritySortUpdate.bind(@)
|
||||||
|
)
|
||||||
|
|
||||||
|
@bindEvents()
|
||||||
|
|
||||||
|
bindEvents: ->
|
||||||
|
@togglePriorityButton.on 'click', @, @onTogglePriorityClick
|
||||||
|
|
||||||
|
onTogglePriorityClick: (e) ->
|
||||||
|
e.preventDefault()
|
||||||
|
_this = e.data
|
||||||
|
$btn = $(e.currentTarget)
|
||||||
|
$label = $("##{$btn.data('domId')}")
|
||||||
|
action = if $btn.parents('.js-prioritized-labels').length then 'remove' else 'add'
|
||||||
|
_this.toggleLabelPriority($label, action)
|
||||||
|
|
||||||
|
toggleLabelPriority: ($label, action, pasive = false) ->
|
||||||
|
_this = @
|
||||||
|
url = $label.find('.js-toggle-priority').data 'url'
|
||||||
|
|
||||||
|
$target = @prioritizedLabels
|
||||||
|
$from = @otherLabels
|
||||||
|
|
||||||
|
# Optimistic update
|
||||||
|
if action is 'remove'
|
||||||
|
$target = @otherLabels
|
||||||
|
$from = @prioritizedLabels
|
||||||
|
|
||||||
|
if $from.find('li').length is 1
|
||||||
|
$from.find('.empty-message').show()
|
||||||
|
|
||||||
|
if not $target.find('li').length
|
||||||
|
$target.find('.empty-message').hide()
|
||||||
|
|
||||||
|
$label.detach().appendTo($target)
|
||||||
|
|
||||||
|
# Return if we are not persisting state
|
||||||
|
return if pasive
|
||||||
|
|
||||||
|
xhr = $.post url
|
||||||
|
|
||||||
|
# If request fails, put label back to Other labels group
|
||||||
|
xhr.fail ->
|
||||||
|
_this.toggleLabelPriority($label, 'remove', true)
|
||||||
|
|
||||||
|
# Show a message
|
||||||
|
new Flash('Unable to update label prioritization at this time' , 'alert')
|
||||||
|
|
||||||
|
onPrioritySortUpdate: ->
|
||||||
|
@savePrioritySort()
|
||||||
|
|
||||||
|
savePrioritySort: ->
|
||||||
|
xhr = $.post
|
||||||
|
url: @prioritizedLabels.data('url')
|
||||||
|
data:
|
||||||
|
label_ids: @getSortedLabelsIds()
|
||||||
|
|
||||||
|
xhr.done ->
|
||||||
|
console.log 'done'
|
||||||
|
|
||||||
|
xhr.fail ->
|
||||||
|
console.log 'fail'
|
||||||
|
|
||||||
|
getSortedLabelsIds: ->
|
||||||
|
sortedIds = []
|
||||||
|
@prioritizedLabels.find('li').each ->
|
||||||
|
sortedIds.push $(@).data 'id'
|
||||||
|
sortedIds
|
|
@ -100,6 +100,8 @@ class Dispatcher
|
||||||
shortcut_handler = new ShortcutsNavigation()
|
shortcut_handler = new ShortcutsNavigation()
|
||||||
when 'projects:labels:new', 'projects:labels:edit'
|
when 'projects:labels:new', 'projects:labels:edit'
|
||||||
new Labels()
|
new Labels()
|
||||||
|
when 'projects:labels:index'
|
||||||
|
new LabelManager()
|
||||||
when 'projects:network:show'
|
when 'projects:network:show'
|
||||||
# Ensure we don't create a particular shortcut handler here. This is
|
# Ensure we don't create a particular shortcut handler here. This is
|
||||||
# already created, where the network graph is created.
|
# already created, where the network graph is created.
|
||||||
|
|
|
@ -138,3 +138,15 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.prioritized-labels {
|
||||||
|
.add-priority {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.other-labels {
|
||||||
|
.remove-priority {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -11,7 +11,8 @@ class Projects::LabelsController < Projects::ApplicationController
|
||||||
respond_to :js, :html
|
respond_to :js, :html
|
||||||
|
|
||||||
def index
|
def index
|
||||||
@labels = @project.labels.page(params[:page])
|
@labels = @project.labels.prioritized(false).page(params[:page])
|
||||||
|
@prioritized = @project.labels.prioritized
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
|
@ -71,6 +72,25 @@ class Projects::LabelsController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def toggle_priority
|
||||||
|
priority = label.priority
|
||||||
|
|
||||||
|
respond_to do |format|
|
||||||
|
if label.update_attributes(priority: !priority)
|
||||||
|
format.json { render json: label }
|
||||||
|
else
|
||||||
|
message = label.errors.full_messages.uniq.join('. ')
|
||||||
|
format.json { render json: { message: message }, status: :unprocessable_entity }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def set_sorting
|
||||||
|
respond_to do |format|
|
||||||
|
format.json { render json: {message: 'success'}}
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
protected
|
protected
|
||||||
|
|
||||||
def module_enabled
|
def module_enabled
|
||||||
|
|
|
@ -19,6 +19,7 @@ class Label < ActiveRecord::Base
|
||||||
|
|
||||||
validates :color, color: true, allow_blank: false
|
validates :color, color: true, allow_blank: false
|
||||||
validates :project, presence: true, unless: Proc.new { |service| service.template? }
|
validates :project, presence: true, unless: Proc.new { |service| service.template? }
|
||||||
|
validates :priority, presence: false, default: false
|
||||||
|
|
||||||
# Don't allow '?', '&', and ',' for label titles
|
# Don't allow '?', '&', and ',' for label titles
|
||||||
validates :title,
|
validates :title,
|
||||||
|
@ -29,6 +30,7 @@ class Label < ActiveRecord::Base
|
||||||
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) }
|
||||||
|
|
||||||
alias_attribute :name, :title
|
alias_attribute :name, :title
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
%li{ id: dom_id(label), data: { id: label.id } }
|
- label_css_id = dom_id(label)
|
||||||
|
%li{id: label_css_id, :"data-id" => label.id}
|
||||||
|
%a.js-toggle-priority{:href => "#",
|
||||||
|
:"data-url" => toggle_priority_namespace_project_label_path(@project.namespace, @project, label),
|
||||||
|
:"data-dom-id" => "#{label_css_id}" }
|
||||||
|
%span.add-priority
|
||||||
|
(+)
|
||||||
|
%span.remove-priority
|
||||||
|
(-)
|
||||||
= render "shared/label_row", label: label
|
= render "shared/label_row", label: label
|
||||||
.pull-info-right
|
.pull-info-right
|
||||||
%span.append-right-20
|
%span.append-right-20
|
||||||
|
@ -24,4 +32,4 @@
|
||||||
|
|
||||||
- if current_user
|
- if current_user
|
||||||
:javascript
|
:javascript
|
||||||
new Subscription('##{dom_id(label)} .label-subscription');
|
new Subscription('##{label_css_id} .label-subscription');
|
||||||
|
|
|
@ -10,13 +10,22 @@
|
||||||
New label
|
New label
|
||||||
|
|
||||||
.labels
|
.labels
|
||||||
- if @labels.present?
|
.prioritized-labels
|
||||||
%ul.content-list.manage-labels-list
|
%h5 Prioritized Label
|
||||||
= render @labels
|
%ul.content-list.manage-labels-list.js-prioritized-labels{ "data-url" => set_sorting_namespace_project_labels_path(@project.namespace, @project) }
|
||||||
= paginate @labels, theme: 'gitlab'
|
- if @prioritized.present?
|
||||||
- else
|
= render @prioritized
|
||||||
.nothing-here-block
|
|
||||||
- if can? current_user, :admin_label, @project
|
|
||||||
Create a label or #{link_to 'generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post}.
|
|
||||||
- else
|
- else
|
||||||
No labels created
|
%p.empty-message No prioritized labels yet
|
||||||
|
.other-labels
|
||||||
|
%h5 Other Labels
|
||||||
|
- if @labels.present?
|
||||||
|
%ul.content-list.manage-labels-list.js-other-labels
|
||||||
|
= render @labels
|
||||||
|
= paginate @labels, theme: 'gitlab'
|
||||||
|
- else
|
||||||
|
.nothing-here-block
|
||||||
|
- if can? current_user, :admin_label, @project
|
||||||
|
Create a label or #{link_to 'generate a default set of labels', generate_namespace_project_labels_path(@project.namespace, @project), method: :post}.
|
||||||
|
- else
|
||||||
|
No labels created
|
||||||
|
|
|
@ -719,10 +719,12 @@ Rails.application.routes.draw do
|
||||||
resources :labels, constraints: { id: /\d+/ } do
|
resources :labels, constraints: { id: /\d+/ } do
|
||||||
collection do
|
collection do
|
||||||
post :generate
|
post :generate
|
||||||
|
post :set_sorting
|
||||||
end
|
end
|
||||||
|
|
||||||
member do
|
member do
|
||||||
post :toggle_subscription
|
post :toggle_subscription
|
||||||
|
post :toggle_priority
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue