summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrandx <dmitriy.zaporozhets@gmail.com>2012-07-28 03:35:24 +0300
committerrandx <dmitriy.zaporozhets@gmail.com>2012-07-28 03:35:43 +0300
commit00b280c3f9521f3e001b2ffc8a8a52f2a93a69d9 (patch)
tree6d2a452f6ec6309ec46804d217285bc4baa56ad5
parentd63706d72c8a52625bf1e892484261378936e240 (diff)
downloadgitlab-ce-00b280c3f9521f3e001b2ffc8a8a52f2a93a69d9.tar.gz
Feature: Bulk Issues update
-rw-r--r--app/assets/javascripts/application.js8
-rw-r--r--app/assets/javascripts/issues.js29
-rw-r--r--app/assets/stylesheets/sections/issues.scss32
-rw-r--r--app/contexts/base_context.rb12
-rw-r--r--app/contexts/issues_bulk_update_context.rb24
-rw-r--r--app/controllers/issues_controller.rb5
-rw-r--r--app/views/issues/_issues.html.haml1
-rw-r--r--app/views/issues/_show.html.haml6
-rw-r--r--app/views/issues/index.html.haml58
-rw-r--r--config/routes.rb1
10 files changed, 144 insertions, 32 deletions
diff --git a/app/assets/javascripts/application.js b/app/assets/javascripts/application.js
index 527b5c795e1..56e26a06f18 100644
--- a/app/assets/javascripts/application.js
+++ b/app/assets/javascripts/application.js
@@ -52,14 +52,6 @@ $(document).ready(function(){
}
});
- $("#issues-table .issue").live('click', function(e){
- if(e.target.nodeName != "A" && e.target.nodeName != "INPUT") {
- location.href = $(this).attr("url");
- e.stopPropagation();
- return false;
- }
- });
-
/**
* Focus search field by pressing 's' key
*/
diff --git a/app/assets/javascripts/issues.js b/app/assets/javascripts/issues.js
index 0acf9ec8aef..bc0569654e1 100644
--- a/app/assets/javascripts/issues.js
+++ b/app/assets/javascripts/issues.js
@@ -67,6 +67,10 @@ function initIssuesSearch() {
*/
function issuesPage(){
initIssuesSearch();
+ $("#update_status").chosen();
+ $("#update_assignee_id").chosen();
+ $("#update_milestone_id").chosen();
+
$("#label_name").chosen();
$("#assignee_id").chosen();
$("#milestone_id").chosen();
@@ -94,4 +98,29 @@ function issuesPage(){
});
});
+
+ $(".check_all_issues").click(function () {
+ $('.selected_issue').attr('checked', this.checked);
+ issuesCheckChanged();
+ });
+
+ $('.selected_issue').bind('change', issuesCheckChanged);
+}
+
+function issuesCheckChanged() {
+ var checked_issues = $('.selected_issue:checked');
+
+ if(checked_issues.length > 0) {
+ var ids = []
+ $.each(checked_issues, function(index, value) {
+ ids.push($(value).attr("data-id"));
+ })
+ $('#update_issues_ids').val(ids);
+ $('.issues_filters').hide();
+ $('.issues_bulk_update').show();
+ } else {
+ $('#update_issues_ids').val([]);
+ $('.issues_bulk_update').hide();
+ $('.issues_filters').show();
+ }
}
diff --git a/app/assets/stylesheets/sections/issues.scss b/app/assets/stylesheets/sections/issues.scss
index 12926d3fdb1..82f180c5bd1 100644
--- a/app/assets/stylesheets/sections/issues.scss
+++ b/app/assets/stylesheets/sections/issues.scss
@@ -30,6 +30,13 @@
.issue {
padding:7px 10px;
+ .issue_check {
+ float:left;
+ padding: 8px 0;
+ padding-right: 8px;
+ min-width: 15px;
+ }
+
p {
padding-top:0;
padding-bottom:2px;
@@ -41,3 +48,28 @@
}
}
}
+
+input.check_all_issues {
+ float:left;
+ padding: 8px 0;
+ margin: 14px 0;
+ margin-right: 10px;
+}
+
+#issues-table-holder {
+ .issues_bulk_update {
+ padding: 0 5px;
+ margin: 0;
+ form {
+ margin:0;
+ padding-bottom:5px;
+ }
+ .update_selected_issues {
+ position:relative;
+ top:-2px;
+ margin-left:3px;
+ }
+
+
+ }
+}
diff --git a/app/contexts/base_context.rb b/app/contexts/base_context.rb
index 6eb8ee46c80..101be50d54b 100644
--- a/app/contexts/base_context.rb
+++ b/app/contexts/base_context.rb
@@ -4,5 +4,17 @@ class BaseContext
def initialize(project, user, params)
@project, @current_user, @params = project, user, params.dup
end
+
+ def abilities
+ @abilities ||= begin
+ abilities = Six.new
+ abilities << Ability
+ abilities
+ end
+ end
+
+ def can?(object, action, subject)
+ abilities.allowed?(object, action, subject)
+ end
end
diff --git a/app/contexts/issues_bulk_update_context.rb b/app/contexts/issues_bulk_update_context.rb
new file mode 100644
index 00000000000..0ba779de5ce
--- /dev/null
+++ b/app/contexts/issues_bulk_update_context.rb
@@ -0,0 +1,24 @@
+class IssuesBulkUpdateContext < BaseContext
+ def execute
+ update_data = params[:update]
+
+ issues_ids = update_data[:issues_ids].split(",")
+ milestone_id = update_data[:milestone_id]
+ assignee_id = update_data[:assignee_id]
+ status = update_data[:status]
+
+ opts = {}
+ opts[:milestone_id] = milestone_id if milestone_id.present?
+ opts[:assignee_id] = assignee_id if assignee_id.present?
+ opts[:closed] = (status == "closed") if status.present?
+
+ issues = Issue.where(:id => issues_ids).all
+ issues = issues.select { |issue| can?(current_user, :modify_issue, issue) }
+ issues.each { |issue| issue.update_attributes(opts) }
+ {
+ :count => issues.count,
+ :success => !issues.count.zero?
+ }
+ end
+end
+
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index c36258c818a..85333b85e3c 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -113,6 +113,11 @@ class IssuesController < ApplicationController
render :partial => 'issues'
end
+ def bulk_update
+ result = IssuesBulkUpdateContext.new(project, current_user, params).execute
+ redirect_to :back, :notice => "#{result[:count]} issues updated"
+ end
+
protected
def issue
diff --git a/app/views/issues/_issues.html.haml b/app/views/issues/_issues.html.haml
index 17141cc453c..fc515ec3b49 100644
--- a/app/views/issues/_issues.html.haml
+++ b/app/views/issues/_issues.html.haml
@@ -12,3 +12,4 @@
- else
%li
%h4.nothing_here_message Nothing to show here
+
diff --git a/app/views/issues/_show.html.haml b/app/views/issues/_show.html.haml
index 18294af40a9..574777be384 100644
--- a/app/views/issues/_show.html.haml
+++ b/app/views/issues/_show.html.haml
@@ -1,6 +1,6 @@
%li.wll{ :id => dom_id(issue), :class => issue_css_classes(issue), :url => project_issue_path(issue.project, issue) }
- .list_legend
- .icon
+ .issue_check
+ = check_box_tag dom_id(issue,"selected"), nil, false, 'data-id' => issue.id, :class => "selected_issue", :disabled => !can?(current_user, :modify_issue, issue)
.right
- issue.labels.each do |label|
%span.label.label-issue.grouped
@@ -34,4 +34,4 @@
&nbsp;
- if issue.upvotes > 0
- %span.badge.badge-success= "+#{issue.upvotes}" \ No newline at end of file
+ %span.badge.badge-success= "+#{issue.upvotes}"
diff --git a/app/views/issues/index.html.haml b/app/views/issues/index.html.haml
index fb8b9f8ee8e..f033536e686 100644
--- a/app/views/issues/index.html.haml
+++ b/app/views/issues/index.html.haml
@@ -14,35 +14,51 @@
= search_field_tag :issue_search, nil, { :placeholder => 'Search', :class => 'issue_search span3 right neib' }
.clearfix
+
%div#issues-table-holder.ui-box
.title
- .left
- %ul.nav.nav-pills.left
- %li{:class => ("active" if (params[:f] == issues_filter[:open] || !params[:f]))}
- = link_to project_issues_path(@project, :f => issues_filter[:open], :milestone_id => params[:milestone_id]) do
- Open
- %li{:class => ("active" if params[:f] == issues_filter[:closed])}
- = link_to project_issues_path(@project, :f => issues_filter[:closed], :milestone_id => params[:milestone_id]) do
- Closed
- %li{:class => ("active" if params[:f] == issues_filter[:to_me])}
- = link_to project_issues_path(@project, :f => issues_filter[:to_me], :milestone_id => params[:milestone_id]) do
- To Me
- %li{:class => ("active" if params[:f] == issues_filter[:all])}
- = link_to project_issues_path(@project, :f => issues_filter[:all], :milestone_id => params[:milestone_id]) do
- All
+ = check_box_tag "check_all_issues", nil, false, :class => "check_all_issues left"
+
- .right
- = form_tag project_issues_path(@project), :method => :get, :class => :right do
- = select_tag(:label_name, options_for_select(issue_tags, params[:label_name]), :prompt => "Labels")
- = select_tag(:assignee_id, options_from_collection_for_select(@project.users.all, "id", "name", params[:assignee_id]), :prompt => "Assignee")
- = select_tag(:milestone_id, options_from_collection_for_select(@project.milestones.order("id desc").all, "id", "title", params[:milestone_id]), :prompt => "Milestone")
+ .issues_bulk_update.hide
+ = form_tag bulk_update_project_issues_path(@project), :method => :post do
+ %span Update selected issues with
+ &nbsp;
+ = select_tag('update[status]', options_for_select(['open', 'closed']), :prompt => "Status")
+ = select_tag('update[assignee_id]', options_from_collection_for_select(@project.users.all, "id", "name", params[:assignee_id]), :prompt => "Assignee")
+ = select_tag('update[milestone_id]', options_from_collection_for_select(@project.milestones.order("id desc").all, "id", "title", params[:milestone_id]), :prompt => "Milestone")
+ = hidden_field_tag 'update[issues_ids]', []
= hidden_field_tag :f, params[:f]
- .clearfix
+ = button_tag "Save", :class => "btn update_selected_issues"
+ .issues_filters
+ .left
+ %ul.nav.nav-pills.left
+ %li{:class => ("active" if (params[:f] == issues_filter[:open] || !params[:f]))}
+ = link_to project_issues_path(@project, :f => issues_filter[:open], :milestone_id => params[:milestone_id]) do
+ Open
+ %li{:class => ("active" if params[:f] == issues_filter[:closed])}
+ = link_to project_issues_path(@project, :f => issues_filter[:closed], :milestone_id => params[:milestone_id]) do
+ Closed
+ %li{:class => ("active" if params[:f] == issues_filter[:to_me])}
+ = link_to project_issues_path(@project, :f => issues_filter[:to_me], :milestone_id => params[:milestone_id]) do
+ To Me
+ %li{:class => ("active" if params[:f] == issues_filter[:all])}
+ = link_to project_issues_path(@project, :f => issues_filter[:all], :milestone_id => params[:milestone_id]) do
+ All
+
+ .right
+ = form_tag project_issues_path(@project), :method => :get, :class => :right do
+ = select_tag(:label_name, options_for_select(issue_tags, params[:label_name]), :prompt => "Labels")
+ = select_tag(:assignee_id, options_from_collection_for_select(@project.users.all, "id", "name", params[:assignee_id]), :prompt => "Assignee")
+ = select_tag(:milestone_id, options_from_collection_for_select(@project.milestones.order("id desc").all, "id", "title", params[:milestone_id]), :prompt => "Milestone")
+ = hidden_field_tag :f, params[:f]
+ .clearfix
%ul#issues-table.unstyled.issues_table
= render "issues"
+
:javascript
$(function(){
issuesPage();
- }) \ No newline at end of file
+ })
diff --git a/config/routes.rb b/config/routes.rb
index dea4df46a30..664f4649e8c 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -194,6 +194,7 @@ Gitlab::Application.routes.draw do
resources :issues do
collection do
post :sort
+ post :bulk_update
get :search
end
end