diff --git a/app/controllers/issue_statuses_controller.rb b/app/controllers/issue_statuses_controller.rb
index 5c74fbd..9180533 100644
--- a/app/controllers/issue_statuses_controller.rb
+++ b/app/controllers/issue_statuses_controller.rb
@@ -19,13 +19,16 @@ class IssueStatusesController < ApplicationController
layout 'base'
before_filter :require_admin
+ verify :method => :post, :only => [ :destroy, :create, :update, :move ],
+ :redirect_to => { :action => :list }
+
def index
list
render :action => 'list' unless request.xhr?
end
def list
- @issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 10
+ @issue_status_pages, @issue_statuses = paginate :issue_statuses, :per_page => 25, :order => "position"
render :action => "list", :layout => false if request.xhr?
end
@@ -55,6 +58,21 @@ class IssueStatusesController < ApplicationController
else
render :action => 'edit'
end
+ end
+
+ def move
+ @issue_status = IssueStatus.find(params[:id])
+ case params[:position]
+ when 'highest'
+ @issue_status.move_to_top
+ when 'higher'
+ @issue_status.move_higher
+ when 'lower'
+ @issue_status.move_lower
+ when 'lowest'
+ @issue_status.move_to_bottom
+ end if params[:position]
+ redirect_to :action => 'list'
end
def destroy
diff --git a/app/controllers/issues_controller.rb b/app/controllers/issues_controller.rb
index 6ac8bc7..491062e 100644
--- a/app/controllers/issues_controller.rb
+++ b/app/controllers/issues_controller.rb
@@ -25,7 +25,7 @@ class IssuesController < ApplicationController
include IfpdfHelper
def show
- @status_options = @issue.status.workflows.find(:all, :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
+ @status_options = @issue.status.workflows.find(:all, :order => 'position', :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
@custom_values = @issue.custom_values.find(:all, :include => :custom_field)
@journals_count = @issue.journals.count
@journals = @issue.journals.find(:all, :include => [:user, :details], :limit => 15, :order => "journals.created_on desc")
@@ -83,7 +83,7 @@ class IssuesController < ApplicationController
def change_status
#@history = @issue.histories.build(params[:history])
- @status_options = @issue.status.workflows.find(:all, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
+ @status_options = @issue.status.workflows.find(:all, :order => 'position', :include => :new_status, :conditions => ["role_id=? and tracker_id=?", self.logged_in_user.role_for_project(@project.id), @issue.tracker.id]).collect{ |w| w.new_status } if self.logged_in_user
@new_status = IssueStatus.find(params[:new_status_id])
if params[:confirm]
begin
diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb
index b27eb19..2e2f0fc 100644
--- a/app/controllers/reports_controller.rb
+++ b/app/controllers/reports_controller.rb
@@ -20,7 +20,7 @@ class ReportsController < ApplicationController
before_filter :find_project, :authorize
def issue_report
- @statuses = IssueStatus.find :all
+ @statuses = IssueStatus.find(:all, :order => 'position')
case params[:detail]
when "tracker"
diff --git a/app/controllers/roles_controller.rb b/app/controllers/roles_controller.rb
index ed7c6c2..9e26a69 100644
--- a/app/controllers/roles_controller.rb
+++ b/app/controllers/roles_controller.rb
@@ -79,6 +79,6 @@ class RolesController < ApplicationController
end
@roles = Role.find :all
@trackers = Tracker.find :all
- @statuses = IssueStatus.find(:all, :include => :workflows)
+ @statuses = IssueStatus.find(:all, :include => :workflows, :order => 'position')
end
end
diff --git a/app/models/issue_status.rb b/app/models/issue_status.rb
index aafafec..1a690b4 100644
--- a/app/models/issue_status.rb
+++ b/app/models/issue_status.rb
@@ -18,6 +18,7 @@
class IssueStatus < ActiveRecord::Base
before_destroy :check_integrity
has_many :workflows, :foreign_key => "old_status_id"
+ acts_as_list
validates_presence_of :name
validates_uniqueness_of :name
diff --git a/app/models/query.rb b/app/models/query.rb
index dbde65a..5594e5c 100644
--- a/app/models/query.rb
+++ b/app/models/query.rb
@@ -69,7 +69,7 @@ class Query < ActiveRecord::Base
def available_filters
return @available_filters if @available_filters
- @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all).collect{|s| [s.name, s.id.to_s] } },
+ @available_filters = { "status_id" => { :type => :list_status, :order => 1, :values => IssueStatus.find(:all, :order => 'position').collect{|s| [s.name, s.id.to_s] } },
"tracker_id" => { :type => :list, :order => 2, :values => Tracker.find(:all).collect{|s| [s.name, s.id.to_s] } },
"priority_id" => { :type => :list, :order => 3, :values => Enumeration.find(:all, :conditions => ['opt=?','IPRI']).collect{|s| [s.name, s.id.to_s] } },
"subject" => { :type => :text, :order => 8 },
diff --git a/app/views/issue_statuses/list.rhtml b/app/views/issue_statuses/list.rhtml
index bde9b1e..01617c3 100644
--- a/app/views/issue_statuses/list.rhtml
+++ b/app/views/issue_statuses/list.rhtml
@@ -9,6 +9,7 @@
<%=l(:field_status)%> |
<%=l(:field_is_default)%> |
<%=l(:field_is_closed)%> |
+ <%=l(:button_sort)%> |
|
@@ -18,6 +19,12 @@
<%= image_tag 'true.png' if status.is_default? %> |
<%= image_tag 'true.png' if status.is_closed? %> |
+ <%= link_to image_tag('2uparrow.png', :alt => l(:label_sort_highest)), {:action => 'move', :id => status, :position => 'highest'}, :method => :post, :title => l(:label_sort_highest) %>
+ <%= link_to image_tag('1uparrow.png', :alt => l(:label_sort_higher)), {:action => 'move', :id => status, :position => 'higher'}, :method => :post, :title => l(:label_sort_higher) %> -
+ <%= link_to image_tag('1downarrow.png', :alt => l(:label_sort_lower)), {:action => 'move', :id => status, :position => 'lower'}, :method => :post, :title => l(:label_sort_lower) %>
+ <%= link_to image_tag('2downarrow.png', :alt => l(:label_sort_lowest)), {:action => 'move', :id => status, :position => 'lowest'}, :method => :post, :title => l(:label_sort_lowest) %>
+ |
+
<%= button_to l(:button_delete), { :action => 'destroy', :id => status }, :confirm => l(:text_are_you_sure), :class => "button-small" %>
|
diff --git a/db/migrate/019_add_issue_status_position.rb b/db/migrate/019_add_issue_status_position.rb
new file mode 100644
index 0000000..1c65e52
--- /dev/null
+++ b/db/migrate/019_add_issue_status_position.rb
@@ -0,0 +1,10 @@
+class AddIssueStatusPosition < ActiveRecord::Migration
+ def self.up
+ add_column :issue_statuses, :position, :integer, :default => 1, :null => false
+ IssueStatus.find(:all).each_with_index {|status, i| status.update_attribute(:position, i+1)}
+ end
+
+ def self.down
+ remove_column :issue_statuses, :position
+ end
+end
diff --git a/doc/CHANGELOG b/doc/CHANGELOG
index 05aaa80..34381a0 100644
--- a/doc/CHANGELOG
+++ b/doc/CHANGELOG
@@ -11,6 +11,7 @@ http://redmine.rubyforge.org/
* settings are now stored in the database and editable through the application in: Admin -> Settings (config_custom.rb is no longer used)
* mail notifications added when a document, a file or an attachment is added
* tooltips added on Gantt chart and calender to view the details of the issues
+* ability to set the sort order for issue statuses
* added missing fields to csv export: priority, start date, due date, done ratio
* all icons replaced (new icons are based on GPL icon set: "KDE Crystal Diamond 2.5" -by paolino- and "kNeu! Alpha v0.1" -by Pablo Fabregat-)
* added back "fixed version" field on issue screen and in filters
diff --git a/lang/de.yml b/lang/de.yml
index f1cc3ba..ffc1f7f 100644
--- a/lang/de.yml
+++ b/lang/de.yml
@@ -309,6 +309,10 @@ label_latest_revision: Neueste Neuausgabe
label_view_revisions: Die Neuausgaben ansehen
label_max_size: Maximale Größe
label_on: auf
+label_sort_highest: Erste
+label_sort_higher: Aufzurichten
+label_sort_lower: Herabzusteigen
+label_sort_lowest: Letzter
button_login: Einloggen
button_submit: Einreichen
@@ -332,6 +336,7 @@ button_move: Bewegen
button_back: Rückkehr
button_cancel: Annullieren
button_activate: Aktivieren
+button_sort: Sortieren
text_select_mail_notifications: Aktionen für die Mailbenachrichtigung aktiviert werden soll.
text_regexp_info: eg. ^[A-Z0-9]+$
diff --git a/lang/en.yml b/lang/en.yml
index 85df4e1..824bb21 100644
--- a/lang/en.yml
+++ b/lang/en.yml
@@ -309,6 +309,10 @@ label_latest_revision: Latest revision
label_view_revisions: View revisions
label_max_size: Maximum size
label_on: 'on'
+label_sort_highest: Move to top
+label_sort_higher: Move up
+label_sort_lower: Move down
+label_sort_lowest: Move to bottom
button_login: Login
button_submit: Submit
@@ -332,6 +336,7 @@ button_move: Move
button_back: Back
button_cancel: Cancel
button_activate: Activate
+button_sort: Sort
text_select_mail_notifications: Select actions for which mail notifications should be sent.
text_regexp_info: eg. ^[A-Z0-9]+$
diff --git a/lang/es.yml b/lang/es.yml
index cff537b..ea07a50 100644
--- a/lang/es.yml
+++ b/lang/es.yml
@@ -309,6 +309,10 @@ label_latest_revision: La revisión más última
label_view_revisions: Ver las revisiones
label_max_size: Tamaño máximo
label_on: en
+label_sort_highest: Primero
+label_sort_higher: Subir
+label_sort_lower: Bajar
+label_sort_lowest: Último
button_login: Conexión
button_submit: Someter
@@ -332,6 +336,7 @@ button_move: Mover
button_back: Atrás
button_cancel: Cancelar
button_activate: Activar
+button_sort: Clasificar
text_select_mail_notifications: Seleccionar las actividades que necesitan la activación de la notificación por mail.
text_regexp_info: eg. ^[A-Z0-9]+$
diff --git a/lang/fr.yml b/lang/fr.yml
index 2c34755..6925a72 100644
--- a/lang/fr.yml
+++ b/lang/fr.yml
@@ -309,6 +309,10 @@ label_latest_revision: Dernière révision
label_view_revisions: Voir les révisions
label_max_size: Taille maximale
label_on: sur
+label_sort_highest: Remonter en premier
+label_sort_higher: Remonter
+label_sort_lower: Descendre
+label_sort_lowest: Descendre en dernier
button_login: Connexion
button_submit: Soumettre
@@ -332,6 +336,7 @@ button_move: Déplacer
button_back: Retour
button_cancel: Annuler
button_activate: Activer
+button_sort: Trier
text_select_mail_notifications: Sélectionner les actions pour lesquelles la notification par mail doit être activée.
text_regexp_info: ex. ^[A-Z0-9]+$
diff --git a/public/images/1downarrow.png b/public/images/1downarrow.png
new file mode 100644
index 0000000000000000000000000000000000000000..caa1d2b1ea3df7ca194613eec21e63661f35684e
GIT binary patch
literal 461
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE(~Ds(|LD2km4-xh%5%u
z9$@TtGTV-UfzjU6#WBRJ`DVo%R)8x0}jko^lj=$^U}@I!r9ouL5`Y*66-
zm;6Kf)UW>44iEYlIsDXIR=DQy%&(CMA5UiRp
zVeXkfy?>8iUVr|z-`?2$zdp}5=ee}!6_3%MS3LRqZPG1Ds_$-Ue}DfPXQ%Ps2Fv-4
zKp=UObyH!zq($9^e-$5|9z5xPf8HzYk5bzE{{87mJlDBOmOWqgq^Mw0RqgAa_HFBz
zZ(vd4sd$@`@Zk69vmf66505o=+`rU*|KFb*{~y~XVW-y@T|Vzm!j8~(Ww8m3x24$F
z?yY~rbKkN~^55UHA7)RV{qxk~^m+-u)XVyn7X%p?DlaxWon88V8ZbKYix3o}ZtN$JNvNUhE8JH`pQsf=|VOV#U+d&t;ucLK6T>SI)2i
literal 0
Hc$@tP0iB;k_y;|Deb&ucvRUT*g7`|&*cb9zMia&DD(
zKdca27L``QIR7pW&!#n-c)H^2Z&;piIY0f`l`pqSUmeiQbbPp6=h%J8xHm_W9S(T1
zu`#O2wejoZZ^=F4lzx20_SLVuZgKDb^&{f{ldr|?Ejw@CH_G^*T2U|4%_zCOQo=&w
zhGgBQx`~FOA7)Cb-A__Ixbn<_!+Iwa^cSf9eRbIO>gw|RcjAwe|LdflJoDknhj=y+
zP)ia2^YqUd?NgdpmmW-i{pag-_O|T&euJ3G%9e+}=bz{KW%TV`l8sVqe*E7jfB&;D
zY-hd6V8-S*?f(D$^7p=HUEBF~e)^yPU!U3^Ua!x?vwz>8^dFyFCw@G>{(bz;8#4pH
z@Gvtl{C|_`ZN4$U6BuqvRUr{2!TD(=<%vb93=9>wwDt9`pFVS1&(BZCAxC?bMO7wh04;y<7`w2L7A0}i2Ee~g_vw1`86QoD*-41o?&=}_t*=MR!-
z5}Hd$y&%9RM|nyC-G@GQ@Vm-l^u|KfbJanTO|qU(6cJGDvlh6_stth+zs
z=^O&Kz*vjB<~UfnH!T2w&`xteBOyNa_Q~k8+3@ffvn?0Q^5EG#%E}E%pMLsQGwZ8j
zpr`6*?g7H)gQ`x-uZ7;8oyGV@JS0Q_02*!JL-s|Hy2i_g6Ul0!aEp!rJyeVdZtwi}
zUuo59+K6%qFv~-!md9!SNabB&;rgoZgAk&01W+`!D58<4BhMdA_b-Dn2G0e!IFFb(
zKDAqWmHDaYT2vx`GrVu!P3Rz|NJ~Z~bzJ-MS#uP`rAZ_rlc?(zWaa(6LZhA<9O0>d
zKmZ`^8zj~lf;2$$dj427OVdedc3jcQc%R!o%*tQ4h6Z^>uDCExI=s=>QW^-eKA4{I
zcy3_jqh&fYbAGTE4h7}QTM9Y#j~=vZaUYNj5zSz0hS{*CK5|wpJ2=_wQaih=-vF
z?%ml$KmY&$B6?I2D?NY%?PN(TTo*alb-Q_5Tb
O00008b1
literal 0
Hc$@RBxwMKf5#%n$I;tpgxn9C%PbHRGCyQORAQolp@kba5mAg
z=