@@ -0,0 +1,20 | |||||
|
1 | <table class="list"> | |||
|
2 | <thead><tr> | |||
|
3 | <th></th> | |||
|
4 | <%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %> | |||
|
5 | <% query.columns.each do |column| %> | |||
|
6 | <%= column_header(column) %> | |||
|
7 | <% end %> | |||
|
8 | </tr></thead> | |||
|
9 | <tbody> | |||
|
10 | <% issues.each do |issue| %> | |||
|
11 | <tr class="issue <%= cycle('odd', 'even') %>"> | |||
|
12 | <th class="checkbox"><%= check_box_tag "issue_ids[]", issue.id, false, :id => "issue_#{issue.id}" %></th> | |||
|
13 | <td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td> | |||
|
14 | <% query.columns.each do |column| %> | |||
|
15 | <%= content_tag 'td', column_content(column, issue), :class => column.name %> | |||
|
16 | <% end %> | |||
|
17 | </tr> | |||
|
18 | <% end %> | |||
|
19 | </tbody> | |||
|
20 | </table> |
@@ -0,0 +1,9 | |||||
|
1 | class AddQueriesColumnNames < ActiveRecord::Migration | |||
|
2 | def self.up | |||
|
3 | add_column :queries, :column_names, :text | |||
|
4 | end | |||
|
5 | ||||
|
6 | def self.down | |||
|
7 | remove_column :queries, :column_names | |||
|
8 | end | |||
|
9 | end |
@@ -1,6 +1,45 | |||||
1 | module QueriesHelper |
|
1 | # redMine - project management software | |
|
2 | # Copyright (C) 2006-2007 Jean-Philippe Lang | |||
|
3 | # | |||
|
4 | # This program is free software; you can redistribute it and/or | |||
|
5 | # modify it under the terms of the GNU General Public License | |||
|
6 | # as published by the Free Software Foundation; either version 2 | |||
|
7 | # of the License, or (at your option) any later version. | |||
|
8 | # | |||
|
9 | # This program is distributed in the hope that it will be useful, | |||
|
10 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
11 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
12 | # GNU General Public License for more details. | |||
|
13 | # | |||
|
14 | # You should have received a copy of the GNU General Public License | |||
|
15 | # along with this program; if not, write to the Free Software | |||
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |||
2 |
|
17 | |||
|
18 | module QueriesHelper | |||
|
19 | ||||
3 | def operators_for_select(filter_type) |
|
20 | def operators_for_select(filter_type) | |
4 | Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]} |
|
21 | Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]} | |
5 | end |
|
22 | end | |
|
23 | ||||
|
24 | def column_header(column) | |||
|
25 | if column.sortable | |||
|
26 | sort_header_tag(column.sortable, :caption => l("field_#{column.name}")) | |||
|
27 | else | |||
|
28 | content_tag('th', l("field_#{column.name}")) | |||
|
29 | end | |||
|
30 | end | |||
|
31 | ||||
|
32 | def column_content(column, issue) | |||
|
33 | value = issue.send(column.name) | |||
|
34 | if value.is_a?(Date) | |||
|
35 | format_date(value) | |||
|
36 | elsif value.is_a?(Time) | |||
|
37 | format_time(value) | |||
|
38 | elsif column.name == :subject | |||
|
39 | ((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') + | |||
|
40 | link_to(h(value), :controller => 'issues', :action => 'show', :id => issue) | |||
|
41 | else | |||
|
42 | h(value) | |||
|
43 | end | |||
|
44 | end | |||
6 | end |
|
45 | end |
@@ -37,6 +37,8 class Enumeration < ActiveRecord::Base | |||||
37 | OPTIONS[self.opt] |
|
37 | OPTIONS[self.opt] | |
38 | end |
|
38 | end | |
39 |
|
39 | |||
|
40 | def to_s; name end | |||
|
41 | ||||
40 | private |
|
42 | private | |
41 | def check_integrity |
|
43 | def check_integrity | |
42 | case self.opt |
|
44 | case self.opt |
@@ -34,4 +34,6 class IssueCategory < ActiveRecord::Base | |||||
34 | end |
|
34 | end | |
35 | destroy_without_reassign |
|
35 | destroy_without_reassign | |
36 | end |
|
36 | end | |
|
37 | ||||
|
38 | def to_s; name end | |||
37 | end |
|
39 | end |
@@ -51,7 +51,9 class IssueStatus < ActiveRecord::Base | |||||
51 | :conditions => ["role_id=? and tracker_id=?", role.id, tracker.id]).collect{ |w| w.new_status }.compact if role && tracker |
|
51 | :conditions => ["role_id=? and tracker_id=?", role.id, tracker.id]).collect{ |w| w.new_status }.compact if role && tracker | |
52 | new_statuses ? new_statuses.sort{|x, y| x.position <=> y.position } : [] |
|
52 | new_statuses ? new_statuses.sort{|x, y| x.position <=> y.position } : [] | |
53 | end |
|
53 | end | |
54 |
|
54 | |||
|
55 | def to_s; name end | |||
|
56 | ||||
55 | private |
|
57 | private | |
56 | def check_integrity |
|
58 | def check_integrity | |
57 | raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id]) |
|
59 | raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id]) |
@@ -15,10 +15,23 | |||||
15 | # along with this program; if not, write to the Free Software |
|
15 | # along with this program; if not, write to the Free Software | |
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
|
16 | # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. | |
17 |
|
17 | |||
|
18 | class QueryColumn | |||
|
19 | attr_accessor :name, :sortable, :default | |||
|
20 | ||||
|
21 | def initialize(name, options={}) | |||
|
22 | self.name = name | |||
|
23 | self.sortable = options[:sortable] | |||
|
24 | self.default = options[:default] | |||
|
25 | end | |||
|
26 | ||||
|
27 | def default?; default end | |||
|
28 | end | |||
|
29 | ||||
18 | class Query < ActiveRecord::Base |
|
30 | class Query < ActiveRecord::Base | |
19 | belongs_to :project |
|
31 | belongs_to :project | |
20 | belongs_to :user |
|
32 | belongs_to :user | |
21 | serialize :filters |
|
33 | serialize :filters | |
|
34 | serialize :column_names | |||
22 |
|
35 | |||
23 | attr_protected :project, :user |
|
36 | attr_protected :project, :user | |
24 | attr_accessor :executed_by |
|
37 | attr_accessor :executed_by | |
@@ -59,6 +72,22 class Query < ActiveRecord::Base | |||||
59 |
|
72 | |||
60 | cattr_reader :operators_by_filter_type |
|
73 | cattr_reader :operators_by_filter_type | |
61 |
|
74 | |||
|
75 | @@available_columns = [ | |||
|
76 | QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.position", :default => true), | |||
|
77 | QueryColumn.new(:status, :sortable => "#{IssueStatus.table_name}.position", :default => true), | |||
|
78 | QueryColumn.new(:priority, :sortable => "#{Issue.table_name}.priority_id", :default => true), | |||
|
79 | QueryColumn.new(:subject, :default => true), | |||
|
80 | QueryColumn.new(:assigned_to, :sortable => "#{User.table_name}.lastname", :default => true), | |||
|
81 | QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on", :default => true), | |||
|
82 | QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name"), | |||
|
83 | QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"), | |||
|
84 | QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"), | |||
|
85 | QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"), | |||
|
86 | QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio"), | |||
|
87 | QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on"), | |||
|
88 | ] | |||
|
89 | cattr_reader :available_columns | |||
|
90 | ||||
62 | def initialize(attributes = nil) |
|
91 | def initialize(attributes = nil) | |
63 | super attributes |
|
92 | super attributes | |
64 | self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} } |
|
93 | self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} } | |
@@ -173,7 +202,30 class Query < ActiveRecord::Base | |||||
173 | label = @available_filters[field][:name] if @available_filters.has_key?(field) |
|
202 | label = @available_filters[field][:name] if @available_filters.has_key?(field) | |
174 | label ||= field.gsub(/\_id$/, "") |
|
203 | label ||= field.gsub(/\_id$/, "") | |
175 | end |
|
204 | end | |
|
205 | ||||
|
206 | def available_columns | |||
|
207 | cols = Query.available_columns | |||
|
208 | end | |||
176 |
|
209 | |||
|
210 | def columns | |||
|
211 | if column_names && !column_names.empty? | |||
|
212 | available_columns.select {|c| column_names.include?(c.name) } | |||
|
213 | else | |||
|
214 | # default columns | |||
|
215 | available_columns.select {|c| c.default? } | |||
|
216 | end | |||
|
217 | end | |||
|
218 | ||||
|
219 | def column_names=(names) | |||
|
220 | names = names.select {|n| n.is_a?(Symbol) || !n.blank? } if names | |||
|
221 | names = names.collect {|n| n.is_a?(Symbol) ? n : n.to_sym } if names | |||
|
222 | write_attribute(:column_names, names) | |||
|
223 | end | |||
|
224 | ||||
|
225 | def has_column?(column) | |||
|
226 | column_names && column_names.include?(column.name) | |||
|
227 | end | |||
|
228 | ||||
177 | def statement |
|
229 | def statement | |
178 | # project/subprojects clause |
|
230 | # project/subprojects clause | |
179 | clause = '' |
|
231 | clause = '' |
@@ -27,6 +27,8 class Tracker < ActiveRecord::Base | |||||
27 | validates_length_of :name, :maximum => 30 |
|
27 | validates_length_of :name, :maximum => 30 | |
28 | validates_format_of :name, :with => /^[\w\s\'\-]*$/i |
|
28 | validates_format_of :name, :with => /^[\w\s\'\-]*$/i | |
29 |
|
29 | |||
|
30 | def to_s; name end | |||
|
31 | ||||
30 | private |
|
32 | private | |
31 | def check_integrity |
|
33 | def check_integrity | |
32 | raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id]) |
|
34 | raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id]) |
@@ -23,32 +23,8 | |||||
23 | <p><i><%= l(:label_no_data) %></i></p> |
|
23 | <p><i><%= l(:label_no_data) %></i></p> | |
24 | <% else %> |
|
24 | <% else %> | |
25 | |
|
25 | | |
26 | <table class="list"> |
|
26 | <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> | |
27 | <thead><tr> |
|
27 | ||
28 | <%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %> |
|
|||
29 | <%= sort_header_tag("#{Project.table_name}.name", :caption => l(:field_project)) %> |
|
|||
30 | <%= sort_header_tag("#{Issue.table_name}.tracker_id", :caption => l(:field_tracker)) %> |
|
|||
31 | <%= sort_header_tag("#{IssueStatus.table_name}.name", :caption => l(:field_status)) %> |
|
|||
32 | <%= sort_header_tag("#{Issue.table_name}.priority_id", :caption => l(:field_priority)) %> |
|
|||
33 | <th><%=l(:field_subject)%></th> |
|
|||
34 | <%= sort_header_tag("#{User.table_name}.lastname", :caption => l(:field_assigned_to)) %> |
|
|||
35 | <%= sort_header_tag("#{Issue.table_name}.updated_on", :caption => l(:field_updated_on)) %> |
|
|||
36 | </tr></thead> |
|
|||
37 | <tbody> |
|
|||
38 | <% for issue in @issues %> |
|
|||
39 | <tr class="<%= cycle("odd", "even") %>"> |
|
|||
40 | <td align="center" valign="top"><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td> |
|
|||
41 | <td align="center" valign="top" nowrap><%=h issue.project.name %></td> |
|
|||
42 | <td align="center" valign="top" nowrap><%= issue.tracker.name %></td> |
|
|||
43 | <td valign="top"nowrap><%= issue.status.name %></td> |
|
|||
44 | <td align="center" valign="top"><%= issue.priority.name %></td> |
|
|||
45 | <td><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></td> |
|
|||
46 | <td align="center" valign="top" nowrap><%= issue.assigned_to.name if issue.assigned_to %></td> |
|
|||
47 | <td align="center" valign="top" nowrap><%= format_time(issue.updated_on) %></td> |
|
|||
48 | </tr> |
|
|||
49 | <% end %> |
|
|||
50 | </tbody> |
|
|||
51 | </table> |
|
|||
52 | <p><%= pagination_links_full @issue_pages %> |
|
28 | <p><%= pagination_links_full @issue_pages %> | |
53 | [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p> |
|
29 | [ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p> | |
54 | <% end %> |
|
30 | <% end %> |
@@ -45,32 +45,7 | |||||
45 | <% else %> |
|
45 | <% else %> | |
46 | |
|
46 | | |
47 | <% form_tag({:controller => 'projects', :action => 'move_issues', :id => @project}, :id => 'issues_form' ) do %> |
|
47 | <% form_tag({:controller => 'projects', :action => 'move_issues', :id => @project}, :id => 'issues_form' ) do %> | |
48 | <table class="list"> |
|
48 | <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> | |
49 | <thead><tr> |
|
|||
50 | <th></th> |
|
|||
51 | <%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %> |
|
|||
52 | <%= sort_header_tag("#{Issue.table_name}.tracker_id", :caption => l(:field_tracker)) %> |
|
|||
53 | <%= sort_header_tag("#{IssueStatus.table_name}.name", :caption => l(:field_status)) %> |
|
|||
54 | <%= sort_header_tag("#{Issue.table_name}.priority_id", :caption => l(:field_priority)) %> |
|
|||
55 | <th><%=l(:field_subject)%></th> |
|
|||
56 | <%= sort_header_tag("#{User.table_name}.lastname", :caption => l(:field_assigned_to)) %> |
|
|||
57 | <%= sort_header_tag("#{Issue.table_name}.updated_on", :caption => l(:field_updated_on)) %> |
|
|||
58 | </tr></thead> |
|
|||
59 | <tbody> |
|
|||
60 | <% for issue in @issues %> |
|
|||
61 | <tr class="<%= cycle("odd", "even") %>"> |
|
|||
62 | <th style="width:15px;"><%= check_box_tag "issue_ids[]", issue.id, false, :id => "issue_#{issue.id}" %></th> |
|
|||
63 | <td align="center"><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td> |
|
|||
64 | <td align="center"><%= issue.tracker.name %></td> |
|
|||
65 | <td><%= issue.status.name %></td> |
|
|||
66 | <td align="center"><%= issue.priority.name %></td> |
|
|||
67 | <td><%= "#{issue.project.name} - " unless @project && @project == issue.project %><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></td> |
|
|||
68 | <td align="center"><%= issue.assigned_to.name if issue.assigned_to %></td> |
|
|||
69 | <td align="center"><%= format_time(issue.updated_on) %></td> |
|
|||
70 | </tr> |
|
|||
71 | <% end %> |
|
|||
72 | </tbody> |
|
|||
73 | </table> |
|
|||
74 | <div class="contextual"> |
|
49 | <div class="contextual"> | |
75 | <%= l(:label_export_to) %> |
|
50 | <%= l(:label_export_to) %> | |
76 | <%= link_to 'CSV', {:action => 'export_issues_csv', :id => @project}, :class => 'icon icon-csv' %>, |
|
51 | <%= link_to 'CSV', {:action => 'export_issues_csv', :id => @project}, :class => 'icon icon-csv' %>, |
@@ -9,6 +9,13 | |||||
9 | <p><label for="query_is_public"><%=l(:field_is_public)%></label> |
|
9 | <p><label for="query_is_public"><%=l(:field_is_public)%></label> | |
10 | <%= check_box 'query', 'is_public' %></p> |
|
10 | <%= check_box 'query', 'is_public' %></p> | |
11 | <% end %> |
|
11 | <% end %> | |
|
12 | ||||
|
13 | <p><label for="query_column_names"><%=l(:field_column_names)%></label> | |||
|
14 | <% @query.available_columns.each do |column| %> | |||
|
15 | <%= check_box_tag 'query[column_names][]', column.name, @query.has_column?(column) %> <%= l("field_#{column.name}") %><br /> | |||
|
16 | <% end %> | |||
|
17 | <%= hidden_field_tag 'query[column_names][]', '' %> | |||
|
18 | </p> | |||
12 | </div> |
|
19 | </div> | |
13 |
|
20 | |||
14 | <%= render :partial => 'queries/filters', :locals => {:query => query}%> |
|
21 | <%= render :partial => 'queries/filters', :locals => {:query => query}%> |
@@ -511,3 +511,4 enumeration_doc_categories: Категории документи | |||||
511 | enumeration_activities: Дейности (time tracking) |
|
511 | enumeration_activities: Дейности (time tracking) | |
512 | label_file_plural: Files |
|
512 | label_file_plural: Files | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -511,3 +511,4 text_issue_category_destroy_assignments: Remove category assignments | |||||
511 | label_added_time_by: Added by %s %s ago |
|
511 | label_added_time_by: Added by %s %s ago | |
512 | field_estimated_hours: Estimated time |
|
512 | field_estimated_hours: Estimated time | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -511,3 +511,4 enumeration_doc_categories: Dokumentenkategorien | |||||
511 | enumeration_activities: Aktivitäten (Zeiterfassung) |
|
511 | enumeration_activities: Aktivitäten (Zeiterfassung) | |
512 | label_file_plural: Files |
|
512 | label_file_plural: Files | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -159,6 +159,7 field_delay: Delay | |||||
159 | field_assignable: Issues can be assigned to this role |
|
159 | field_assignable: Issues can be assigned to this role | |
160 | field_redirect_existing_links: Redirect existing links |
|
160 | field_redirect_existing_links: Redirect existing links | |
161 | field_estimated_hours: Estimated time |
|
161 | field_estimated_hours: Estimated time | |
|
162 | field_column_names: Columns | |||
162 |
|
163 | |||
163 | setting_app_title: Application title |
|
164 | setting_app_title: Application title | |
164 | setting_app_subtitle: Application subtitle |
|
165 | setting_app_subtitle: Application subtitle |
@@ -511,3 +511,4 enumeration_doc_categories: Categorías del documento | |||||
511 | enumeration_activities: Activities (time tracking) |
|
511 | enumeration_activities: Activities (time tracking) | |
512 | label_file_plural: Files |
|
512 | label_file_plural: Files | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -159,6 +159,7 field_delay: Retard | |||||
159 | field_assignable: Demandes assignables à ce rôle |
|
159 | field_assignable: Demandes assignables à ce rôle | |
160 | field_redirect_existing_links: Rediriger les liens existants |
|
160 | field_redirect_existing_links: Rediriger les liens existants | |
161 | field_estimated_hours: Temps estimé |
|
161 | field_estimated_hours: Temps estimé | |
|
162 | field_column_names: Colonnes | |||
162 |
|
163 | |||
163 | setting_app_title: Titre de l'application |
|
164 | setting_app_title: Titre de l'application | |
164 | setting_app_subtitle: Sous-titre de l'application |
|
165 | setting_app_subtitle: Sous-titre de l'application |
@@ -511,3 +511,4 enumeration_doc_categories: Categorie di documenti | |||||
511 | enumeration_activities: Attività (time tracking) |
|
511 | enumeration_activities: Attività (time tracking) | |
512 | label_file_plural: Files |
|
512 | label_file_plural: Files | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -512,3 +512,4 enumeration_doc_categories: 文書カテゴリ | |||||
512 | enumeration_activities: 作業分類 (時間トラッキング) |
|
512 | enumeration_activities: 作業分類 (時間トラッキング) | |
513 | label_file_plural: Files |
|
513 | label_file_plural: Files | |
514 | label_changeset_plural: Changesets |
|
514 | label_changeset_plural: Changesets | |
|
515 | field_column_names: Columns |
@@ -512,3 +512,4 enumeration_activities: Activiteiten (tijd tracking) | |||||
512 | text_comma_separated: Multiple values allowed (comma separated). |
|
512 | text_comma_separated: Multiple values allowed (comma separated). | |
513 | label_file_plural: Files |
|
513 | label_file_plural: Files | |
514 | label_changeset_plural: Changesets |
|
514 | label_changeset_plural: Changesets | |
|
515 | field_column_names: Columns |
@@ -511,3 +511,4 label_added_time_by: Dodane przez %s %s temu | |||||
511 | field_estimated_hours: Szacowany czas |
|
511 | field_estimated_hours: Szacowany czas | |
512 | label_file_plural: Pliki |
|
512 | label_file_plural: Pliki | |
513 | label_changeset_plural: Zestawienia zmian |
|
513 | label_changeset_plural: Zestawienia zmian | |
|
514 | field_column_names: Columns |
@@ -511,3 +511,4 enumeration_doc_categories: Categorias de documento | |||||
511 | enumeration_activities: Atividades (time tracking) |
|
511 | enumeration_activities: Atividades (time tracking) | |
512 | label_file_plural: Files |
|
512 | label_file_plural: Files | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -511,3 +511,4 enumeration_doc_categories: Categorias de documento | |||||
511 | enumeration_activities: Atividades (time tracking) |
|
511 | enumeration_activities: Atividades (time tracking) | |
512 | label_file_plural: Files |
|
512 | label_file_plural: Files | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -511,3 +511,4 label_index_by_date: Index by date | |||||
511 | label_index_by_title: Index by title |
|
511 | label_index_by_title: Index by title | |
512 | label_file_plural: Files |
|
512 | label_file_plural: Files | |
513 | label_changeset_plural: Changesets |
|
513 | label_changeset_plural: Changesets | |
|
514 | field_column_names: Columns |
@@ -512,3 +512,4 enumeration_activities: Aktiviteter (tidsspårning) | |||||
512 | field_comments: Comment |
|
512 | field_comments: Comment | |
513 | label_file_plural: Files |
|
513 | label_file_plural: Files | |
514 | label_changeset_plural: Changesets |
|
514 | label_changeset_plural: Changesets | |
|
515 | field_column_names: Columns |
@@ -514,3 +514,4 enumeration_activities: Activities (time tracking) | |||||
514 | label_wiki_page: Wiki page |
|
514 | label_wiki_page: Wiki page | |
515 | label_file_plural: Files |
|
515 | label_file_plural: Files | |
516 | label_changeset_plural: Changesets |
|
516 | label_changeset_plural: Changesets | |
|
517 | field_column_names: Columns |
@@ -133,6 +133,12 margin*/ | |||||
133 |
|
133 | |||
134 | div.attachments p { margin:4px 0 2px 0; } |
|
134 | div.attachments p { margin:4px 0 2px 0; } | |
135 |
|
135 | |||
|
136 | /***** Issue list ****/ | |||
|
137 | tr.issue { text-align: center; white-space: nowrap; } | |||
|
138 | tr.issue th.checkbox { width: 15px; } | |||
|
139 | tr.issue td.subject, tr.issue td.category { white-space: normal; } | |||
|
140 | tr.issue td.subject { text-align: left; } | |||
|
141 | ||||
136 | /***** Flash & error messages ****/ |
|
142 | /***** Flash & error messages ****/ | |
137 | #flash div, #errorExplanation, .nodata { |
|
143 | #flash div, #errorExplanation, .nodata { | |
138 | padding: 4px 4px 4px 30px; |
|
144 | padding: 4px 4px 4px 30px; |
@@ -28,4 +28,17 class QueryTest < Test::Unit::TestCase | |||||
28 | assert_equal 1, issues.length |
|
28 | assert_equal 1, issues.length | |
29 | assert_equal Issue.find(3), issues.first |
|
29 | assert_equal Issue.find(3), issues.first | |
30 | end |
|
30 | end | |
|
31 | ||||
|
32 | def test_default_columns | |||
|
33 | q = Query.new | |||
|
34 | assert !q.columns.empty? | |||
|
35 | end | |||
|
36 | ||||
|
37 | def test_set_column_names | |||
|
38 | q = Query.new | |||
|
39 | q.column_names = ['tracker', :subject, '', 'unknonw_column'] | |||
|
40 | assert_equal [:tracker, :subject], q.columns.collect {|c| c.name} | |||
|
41 | c = q.columns.first | |||
|
42 | assert q.has_column?(c) | |||
|
43 | end | |||
31 | end |
|
44 | end |
General Comments 0
You need to be logged in to leave comments.
Login now