@@ -27,7 +27,7 class AdminController < ApplicationController | |||||
27 |
|
27 | |||
28 | def projects |
|
28 | def projects | |
29 | sort_init 'name', 'asc' |
|
29 | sort_init 'name', 'asc' | |
30 | sort_update |
|
30 | sort_update %w(name is_public created_on) | |
31 |
|
31 | |||
32 | @status = params[:status] ? params[:status].to_i : 1 |
|
32 | @status = params[:status] ? params[:status].to_i : 1 | |
33 | c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status]) |
|
33 | c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status]) |
@@ -35,8 +35,10 class BoardsController < ApplicationController | |||||
35 | end |
|
35 | end | |
36 |
|
36 | |||
37 | def show |
|
37 | def show | |
38 |
sort_init |
|
38 | sort_init 'updated_on', 'desc' | |
39 | sort_update |
|
39 | sort_update 'created_on' => "#{Message.table_name}.created_on", | |
|
40 | 'replies' => "#{Message.table_name}.replies_count", | |||
|
41 | 'updated_on' => "#{Message.table_name}.updated_on" | |||
40 |
|
42 | |||
41 | @topic_count = @board.topics.count |
|
43 | @topic_count = @board.topics.count | |
42 | @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page'] |
|
44 | @topic_pages = Paginator.new self, @topic_count, per_page_option, params['page'] |
@@ -45,9 +45,10 class IssuesController < ApplicationController | |||||
45 | helper :timelog |
|
45 | helper :timelog | |
46 |
|
46 | |||
47 | def index |
|
47 | def index | |
48 | sort_init "#{Issue.table_name}.id", "desc" |
|
|||
49 | sort_update |
|
|||
50 | retrieve_query |
|
48 | retrieve_query | |
|
49 | sort_init 'id', 'desc' | |||
|
50 | sort_update({'id' => "#{Issue.table_name}.id"}.merge(@query.columns.inject({}) {|h, c| h[c.name.to_s] = c.sortable; h})) | |||
|
51 | ||||
51 | if @query.valid? |
|
52 | if @query.valid? | |
52 | limit = per_page_option |
|
53 | limit = per_page_option | |
53 | respond_to do |format| |
|
54 | respond_to do |format| | |
@@ -78,9 +79,10 class IssuesController < ApplicationController | |||||
78 | end |
|
79 | end | |
79 |
|
80 | |||
80 | def changes |
|
81 | def changes | |
81 | sort_init "#{Issue.table_name}.id", "desc" |
|
|||
82 | sort_update |
|
|||
83 | retrieve_query |
|
82 | retrieve_query | |
|
83 | sort_init 'id', 'desc' | |||
|
84 | sort_update({'id' => "#{Issue.table_name}.id"}.merge(@query.columns.inject({}) {|h, c| h[c.name.to_s] = c.sortable; h})) | |||
|
85 | ||||
84 | if @query.valid? |
|
86 | if @query.valid? | |
85 | @journals = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ], |
|
87 | @journals = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ], | |
86 | :conditions => @query.statement, |
|
88 | :conditions => @query.statement, |
@@ -197,8 +197,12 class ProjectsController < ApplicationController | |||||
197 | end |
|
197 | end | |
198 |
|
198 | |||
199 | def list_files |
|
199 | def list_files | |
200 |
sort_init |
|
200 | sort_init 'filename', 'asc' | |
201 | sort_update |
|
201 | sort_update 'filename' => "#{Attachment.table_name}.filename", | |
|
202 | 'created_on' => "#{Attachment.table_name}.created_on", | |||
|
203 | 'size' => "#{Attachment.table_name}.filesize", | |||
|
204 | 'downloads' => "#{Attachment.table_name}.downloads" | |||
|
205 | ||||
202 | @versions = @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse |
|
206 | @versions = @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse | |
203 | render :layout => !request.xhr? |
|
207 | render :layout => !request.xhr? | |
204 | end |
|
208 | end |
@@ -138,7 +138,12 class TimelogController < ApplicationController | |||||
138 |
|
138 | |||
139 | def details |
|
139 | def details | |
140 | sort_init 'spent_on', 'desc' |
|
140 | sort_init 'spent_on', 'desc' | |
141 | sort_update |
|
141 | sort_update 'spent_on' => 'spent_on', | |
|
142 | 'user' => 'user_id', | |||
|
143 | 'activity' => 'activity_id', | |||
|
144 | 'project' => "#{Project.table_name}.name", | |||
|
145 | 'issue' => 'issue_id', | |||
|
146 | 'hours' => 'hours' | |||
142 |
|
147 | |||
143 | cond = ARCondition.new |
|
148 | cond = ARCondition.new | |
144 | if @project.nil? |
|
149 | if @project.nil? |
@@ -30,7 +30,7 class UsersController < ApplicationController | |||||
30 |
|
30 | |||
31 | def list |
|
31 | def list | |
32 | sort_init 'login', 'asc' |
|
32 | sort_init 'login', 'asc' | |
33 | sort_update |
|
33 | sort_update %w(login firstname lastname mail admin created_on last_login_on) | |
34 |
|
34 | |||
35 | @status = params[:status] ? params[:status].to_i : 1 |
|
35 | @status = params[:status] ? params[:status].to_i : 1 | |
36 | c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status]) |
|
36 | c = ARCondition.new(@status == 0 ? "status <> 0" : ["status = ?", @status]) |
@@ -22,8 +22,8 module QueriesHelper | |||||
22 | end |
|
22 | end | |
23 |
|
23 | |||
24 | def column_header(column) |
|
24 | def column_header(column) | |
25 |
column.sortable ? sort_header_tag(column. |
|
25 | column.sortable ? sort_header_tag(column.name.to_s, :caption => column.caption, | |
26 | :default_order => column.default_order) : |
|
26 | :default_order => column.default_order) : | |
27 | content_tag('th', column.caption) |
|
27 | content_tag('th', column.caption) | |
28 | end |
|
28 | end | |
29 |
|
29 |
@@ -67,23 +67,31 module SortHelper | |||||
67 |
|
67 | |||
68 | # Updates the sort state. Call this in the controller prior to calling |
|
68 | # Updates the sort state. Call this in the controller prior to calling | |
69 | # sort_clause. |
|
69 | # sort_clause. | |
70 | # |
|
70 | # sort_keys can be either an array or a hash of allowed keys | |
71 | def sort_update() |
|
71 | def sort_update(sort_keys) | |
72 |
|
|
72 | sort_key = params[:sort_key] | |
73 | sort = {:key => params[:sort_key], :order => params[:sort_order]} |
|
73 | sort_key = nil unless (sort_keys.is_a?(Array) ? sort_keys.include?(sort_key) : sort_keys[sort_key]) | |
|
74 | ||||
|
75 | sort_order = (params[:sort_order] == 'desc' ? 'DESC' : 'ASC') | |||
|
76 | ||||
|
77 | if sort_key | |||
|
78 | sort = {:key => sort_key, :order => sort_order} | |||
74 | elsif session[@sort_name] |
|
79 | elsif session[@sort_name] | |
75 | sort = session[@sort_name] # Previous sort. |
|
80 | sort = session[@sort_name] # Previous sort. | |
76 | else |
|
81 | else | |
77 | sort = @sort_default |
|
82 | sort = @sort_default | |
78 | end |
|
83 | end | |
79 | session[@sort_name] = sort |
|
84 | session[@sort_name] = sort | |
|
85 | ||||
|
86 | sort_column = (sort_keys.is_a?(Hash) ? sort_keys[sort[:key]] : sort[:key]) | |||
|
87 | @sort_clause = (sort_column.blank? ? '' : "#{sort_column} #{sort[:order]}") | |||
80 | end |
|
88 | end | |
81 |
|
89 | |||
82 | # Returns an SQL sort clause corresponding to the current sort state. |
|
90 | # Returns an SQL sort clause corresponding to the current sort state. | |
83 | # Use this to sort the controller's table items collection. |
|
91 | # Use this to sort the controller's table items collection. | |
84 | # |
|
92 | # | |
85 | def sort_clause() |
|
93 | def sort_clause() | |
86 |
|
|
94 | @sort_clause || '' #session[@sort_name][:key] + ' ' + (session[@sort_name][:order] || 'ASC') | |
87 | end |
|
95 | end | |
88 |
|
96 | |||
89 | # Returns a link which sorts by the named column. |
|
97 | # Returns a link which sorts by the named column. |
@@ -57,7 +57,7 class Mailer < ActionMailer::Base | |||||
57 | subject l(:mail_subject_reminder, issues.size) |
|
57 | subject l(:mail_subject_reminder, issues.size) | |
58 | body :issues => issues, |
|
58 | body :issues => issues, | |
59 | :days => days, |
|
59 | :days => days, | |
60 |
:issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => ' |
|
60 | :issues_url => url_for(:controller => 'issues', :action => 'index', :set_filter => 1, :assigned_to_id => user.id, :sort_key => 'due_date', :sort_order => 'asc') | |
61 | end |
|
61 | end | |
62 |
|
62 | |||
63 | def document_added(document) |
|
63 | def document_added(document) |
@@ -33,9 +33,9 | |||||
33 | <thead><tr> |
|
33 | <thead><tr> | |
34 | <th><%= l(:field_subject) %></th> |
|
34 | <th><%= l(:field_subject) %></th> | |
35 | <th><%= l(:field_author) %></th> |
|
35 | <th><%= l(:field_author) %></th> | |
36 |
<%= sort_header_tag( |
|
36 | <%= sort_header_tag('created_on', :caption => l(:field_created_on)) %> | |
37 |
<%= sort_header_tag( |
|
37 | <%= sort_header_tag('replies', :caption => l(:label_reply_plural)) %> | |
38 |
<%= sort_header_tag( |
|
38 | <%= sort_header_tag('updated_on', :caption => l(:label_message_last)) %> | |
39 | </tr></thead> |
|
39 | </tr></thead> | |
40 | <tbody> |
|
40 | <tbody> | |
41 | <% @topics.each do |topic| %> |
|
41 | <% @topics.each do |topic| %> |
@@ -4,7 +4,7 | |||||
4 | <th><%= link_to image_tag('toggle_check.png'), {}, :onclick => 'toggleIssuesSelection(Element.up(this, "form")); return false;', |
|
4 | <th><%= link_to image_tag('toggle_check.png'), {}, :onclick => 'toggleIssuesSelection(Element.up(this, "form")); return false;', | |
5 | :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %> |
|
5 | :title => "#{l(:button_check_all)}/#{l(:button_uncheck_all)}" %> | |
6 | </th> |
|
6 | </th> | |
7 |
<%= sort_header_tag( |
|
7 | <%= sort_header_tag('id', :caption => '#', :default_order => 'desc') %> | |
8 | <% query.columns.each do |column| %> |
|
8 | <% query.columns.each do |column| %> | |
9 | <%= column_header(column) %> |
|
9 | <%= column_header(column) %> | |
10 | <% end %> |
|
10 | <% end %> |
@@ -20,7 +20,7 | |||||
20 | <h3><%= l(:label_query_plural) %></h3> |
|
20 | <h3><%= l(:label_query_plural) %></h3> | |
21 |
|
21 | |||
22 | <% sidebar_queries.each do |query| -%> |
|
22 | <% sidebar_queries.each do |query| -%> | |
23 |
<%= link_to |
|
23 | <%= link_to(h(query.name), :controller => 'issues', :action => 'index', :project_id => @project, :query_id => query) %><br /> | |
24 | <% end -%> |
|
24 | <% end -%> | |
25 | <%= call_hook(:view_issues_sidebar_queries_bottom) %> |
|
25 | <%= call_hook(:view_issues_sidebar_queries_bottom) %> | |
26 | <% end -%> |
|
26 | <% end -%> |
@@ -9,10 +9,10 | |||||
9 | <table class="list"> |
|
9 | <table class="list"> | |
10 | <thead><tr> |
|
10 | <thead><tr> | |
11 | <th><%=l(:field_version)%></th> |
|
11 | <th><%=l(:field_version)%></th> | |
12 |
<%= sort_header_tag( |
|
12 | <%= sort_header_tag('filename', :caption => l(:field_filename)) %> | |
13 |
<%= sort_header_tag( |
|
13 | <%= sort_header_tag('created_on', :caption => l(:label_date), :default_order => 'desc') %> | |
14 |
<%= sort_header_tag( |
|
14 | <%= sort_header_tag('size', :caption => l(:field_filesize), :default_order => 'desc') %> | |
15 |
<%= sort_header_tag( |
|
15 | <%= sort_header_tag('downloads', :caption => l(:label_downloads_abbr), :default_order => 'desc') %> | |
16 | <th>MD5</th> |
|
16 | <th>MD5</th> | |
17 | <% if delete_allowed %><th></th><% end %> |
|
17 | <% if delete_allowed %><th></th><% end %> | |
18 | </tr></thead> |
|
18 | </tr></thead> |
@@ -2,10 +2,10 | |||||
2 | <thead> |
|
2 | <thead> | |
3 | <tr> |
|
3 | <tr> | |
4 | <%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %> |
|
4 | <%= sort_header_tag('spent_on', :caption => l(:label_date), :default_order => 'desc') %> | |
5 |
<%= sort_header_tag('user |
|
5 | <%= sort_header_tag('user', :caption => l(:label_member)) %> | |
6 |
<%= sort_header_tag('activity |
|
6 | <%= sort_header_tag('activity', :caption => l(:label_activity)) %> | |
7 |
<%= sort_header_tag( |
|
7 | <%= sort_header_tag('project', :caption => l(:label_project)) %> | |
8 |
<%= sort_header_tag('issue |
|
8 | <%= sort_header_tag('issue', :caption => l(:label_issue), :default_order => 'desc') %> | |
9 | <th><%= l(:field_comments) %></th> |
|
9 | <th><%= l(:field_comments) %></th> | |
10 | <%= sort_header_tag('hours', :caption => l(:field_hours)) %> |
|
10 | <%= sort_header_tag('hours', :caption => l(:field_hours)) %> | |
11 | <th></th> |
|
11 | <th></th> |
@@ -20,7 +20,7 | |||||
20 | <th class="line-num"><%= line_num %></th> |
|
20 | <th class="line-num"><%= line_num %></th> | |
21 | <td class="revision"><%= link_to line[0], :controller => 'wiki', :action => 'index', :id => @project, :page => @page.title, :version => line[0] %></td> |
|
21 | <td class="revision"><%= link_to line[0], :controller => 'wiki', :action => 'index', :id => @project, :page => @page.title, :version => line[0] %></td> | |
22 | <td class="author"><%= h(line[1]) %></td> |
|
22 | <td class="author"><%= h(line[1]) %></td> | |
23 | <td class="line-code"><pre><%= line[2] %></pre></td> |
|
23 | <td class="line-code"><pre><%=h line[2] %></pre></td> | |
24 | </tr> |
|
24 | </tr> | |
25 | <% line_num += 1 %> |
|
25 | <% line_num += 1 %> | |
26 | <% end -%> |
|
26 | <% end -%> |
@@ -408,7 +408,7 class RedCloth3 < String | |||||
408 | # [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing |
|
408 | # [ /"(?=[#{PUNCT_Q}]*[\s#{PUNCT_NOQ}])/, '”' ], # double closing | |
409 | # [ /"/, '“' ], # double opening |
|
409 | # [ /"/, '“' ], # double opening | |
410 | # [ /\b( )?\.{3}/, '\1…' ], # ellipsis |
|
410 | # [ /\b( )?\.{3}/, '\1…' ], # ellipsis | |
411 |
|
|
411 | # [ /\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/, '<acronym title="\2">\1</acronym>' ], # 3+ uppercase acronym | |
412 | # [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^<A-Za-z0-9]|$)/, '\1<span class="caps">\2</span>\3', :no_span_caps ], # 3+ uppercase caps |
|
412 | # [ /(^|[^"][>\s])([A-Z][A-Z0-9 ]+[A-Z0-9])([^<A-Za-z0-9]|$)/, '\1<span class="caps">\2</span>\3', :no_span_caps ], # 3+ uppercase caps | |
413 | # [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash |
|
413 | # [ /(\.\s)?\s?--\s?/, '\1—' ], # em dash | |
414 | # [ /\s->\s/, ' → ' ], # right arrow |
|
414 | # [ /\s->\s/, ' → ' ], # right arrow | |
@@ -448,9 +448,12 class RedCloth3 < String | |||||
448 |
|
448 | |||
449 | # Search and replace for Textile glyphs (quotes, dashes, other symbols) |
|
449 | # Search and replace for Textile glyphs (quotes, dashes, other symbols) | |
450 | def pgl( text ) |
|
450 | def pgl( text ) | |
451 | GLYPHS.each do |re, resub, tog| |
|
451 | #GLYPHS.each do |re, resub, tog| | |
452 | next if tog and method( tog ).call |
|
452 | # next if tog and method( tog ).call | |
453 | text.gsub! re, resub |
|
453 | # text.gsub! re, resub | |
|
454 | #end | |||
|
455 | text.gsub!(/\b([A-Z][A-Z0-9]{2,})\b(?:[(]([^)]*)[)])/) do |m| | |||
|
456 | "<acronym title=\"#{htmlesc $2}\">#{$1}</acronym>" | |||
454 | end |
|
457 | end | |
455 | end |
|
458 | end | |
456 |
|
459 | |||
@@ -467,7 +470,7 class RedCloth3 < String | |||||
467 | style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN |
|
470 | style << "vertical-align:#{ v_align( $& ) };" if text =~ A_VLGN | |
468 | end |
|
471 | end | |
469 |
|
472 | |||
470 | style << "#{ $1 };" if not filter_styles and |
|
473 | style << "#{ htmlesc $1 };" if not filter_styles and | |
471 | text.sub!( /\{([^}]*)\}/, '' ) |
|
474 | text.sub!( /\{([^}]*)\}/, '' ) | |
472 |
|
475 | |||
473 | lang = $1 if |
|
476 | lang = $1 if | |
@@ -810,7 +813,7 class RedCloth3 < String | |||||
810 | end |
|
813 | end | |
811 | atts = pba( atts ) |
|
814 | atts = pba( atts ) | |
812 | atts = " href=\"#{ url }#{ slash }\"#{ atts }" |
|
815 | atts = " href=\"#{ url }#{ slash }\"#{ atts }" | |
813 | atts << " title=\"#{ title }\"" if title |
|
816 | atts << " title=\"#{ htmlesc title }\"" if title | |
814 | atts = shelve( atts ) if atts |
|
817 | atts = shelve( atts ) if atts | |
815 |
|
818 | |||
816 | external = (url =~ /^https?:\/\//) ? ' class="external"' : '' |
|
819 | external = (url =~ /^https?:\/\//) ? ' class="external"' : '' |
@@ -137,6 +137,16 class IssuesControllerTest < Test::Unit::TestCase | |||||
137 | assert_not_nil assigns(:issues) |
|
137 | assert_not_nil assigns(:issues) | |
138 | assert_equal 'application/pdf', @response.content_type |
|
138 | assert_equal 'application/pdf', @response.content_type | |
139 | end |
|
139 | end | |
|
140 | ||||
|
141 | def test_index_sort | |||
|
142 | get :index, :sort_key => 'tracker' | |||
|
143 | assert_response :success | |||
|
144 | ||||
|
145 | sort_params = @request.session['issuesindex_sort'] | |||
|
146 | assert sort_params.is_a?(Hash) | |||
|
147 | assert_equal 'tracker', sort_params[:key] | |||
|
148 | assert_equal 'ASC', sort_params[:order] | |||
|
149 | end | |||
140 |
|
150 | |||
141 | def test_gantt |
|
151 | def test_gantt | |
142 | get :gantt, :project_id => 1 |
|
152 | get :gantt, :project_id => 1 |
@@ -76,6 +76,15 class ApplicationHelperTest < HelperTestCase | |||||
76 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } |
|
76 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } | |
77 | end |
|
77 | end | |
78 |
|
78 | |||
|
79 | def test_acronyms | |||
|
80 | to_test = { | |||
|
81 | 'this is an acronym: GPL(General Public License)' => 'this is an acronym: <acronym title="General Public License">GPL</acronym>', | |||
|
82 | 'GPL(This is a double-quoted "title")' => '<acronym title="This is a double-quoted "title"">GPL</acronym>', | |||
|
83 | } | |||
|
84 | to_test.each { |text, result| assert_equal "<p>#{result}</p>", textilizable(text) } | |||
|
85 | ||||
|
86 | end | |||
|
87 | ||||
79 | def test_attached_images |
|
88 | def test_attached_images | |
80 | to_test = { |
|
89 | to_test = { | |
81 | 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />', |
|
90 | 'Inline image: !logo.gif!' => 'Inline image: <img src="/attachments/download/3" title="This is a logo" alt="This is a logo" />', | |
@@ -90,6 +99,7 class ApplicationHelperTest < HelperTestCase | |||||
90 | 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>', |
|
99 | 'This is a "link":http://foo.bar' => 'This is a <a href="http://foo.bar" class="external">link</a>', | |
91 | 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>', |
|
100 | 'This is an intern "link":/foo/bar' => 'This is an intern <a href="/foo/bar">link</a>', | |
92 | '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>', |
|
101 | '"link (Link title)":http://foo.bar' => '<a href="http://foo.bar" title="Link title" class="external">link</a>', | |
|
102 | '"link (Link title with "double-quotes")":http://foo.bar' => '<a href="http://foo.bar" title="Link title with "double-quotes"" class="external">link</a>', | |||
93 | "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph", |
|
103 | "This is not a \"Link\":\n\nAnother paragraph" => "This is not a \"Link\":</p>\n\n\n\t<p>Another paragraph", | |
94 | # no multiline link text |
|
104 | # no multiline link text | |
95 | "This is a double quote \"on the first line\nand another on a second line\":test" => "This is a double quote \"on the first line<br />\nand another on a second line\":test" |
|
105 | "This is a double quote \"on the first line\nand another on a second line\":test" => "This is a double quote \"on the first line<br />\nand another on a second line\":test" |
General Comments 0
You need to be logged in to leave comments.
Login now