Added the ability to customize columns of a saved query.
git-svn-id: http://redmine.rubyforge.org/svn/trunk@782 e93f8b46-1217-0410-a6f0-8f06a7374b81
This commit is contained in:
parent
427b47b4d7
commit
e5f5671d66
|
@ -1,6 +1,45 @@
|
||||||
module QueriesHelper
|
# redMine - project management software
|
||||||
|
# Copyright (C) 2006-2007 Jean-Philippe Lang
|
||||||
|
#
|
||||||
|
# This program is free software; you can redistribute it and/or
|
||||||
|
# modify it under the terms of the GNU General Public License
|
||||||
|
# as published by the Free Software Foundation; either version 2
|
||||||
|
# of the License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program; if not, write to the Free Software
|
||||||
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
module QueriesHelper
|
||||||
|
|
||||||
def operators_for_select(filter_type)
|
def operators_for_select(filter_type)
|
||||||
Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]}
|
Query.operators_by_filter_type[filter_type].collect {|o| [l(Query.operators[o]), o]}
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def column_header(column)
|
||||||
|
if column.sortable
|
||||||
|
sort_header_tag(column.sortable, :caption => l("field_#{column.name}"))
|
||||||
|
else
|
||||||
|
content_tag('th', l("field_#{column.name}"))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def column_content(column, issue)
|
||||||
|
value = issue.send(column.name)
|
||||||
|
if value.is_a?(Date)
|
||||||
|
format_date(value)
|
||||||
|
elsif value.is_a?(Time)
|
||||||
|
format_time(value)
|
||||||
|
elsif column.name == :subject
|
||||||
|
((@project.nil? || @project != issue.project) ? "#{issue.project.name} - " : '') +
|
||||||
|
link_to(h(value), :controller => 'issues', :action => 'show', :id => issue)
|
||||||
|
else
|
||||||
|
h(value)
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -37,6 +37,8 @@ class Enumeration < ActiveRecord::Base
|
||||||
OPTIONS[self.opt]
|
OPTIONS[self.opt]
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s; name end
|
||||||
|
|
||||||
private
|
private
|
||||||
def check_integrity
|
def check_integrity
|
||||||
case self.opt
|
case self.opt
|
||||||
|
|
|
@ -34,4 +34,6 @@ class IssueCategory < ActiveRecord::Base
|
||||||
end
|
end
|
||||||
destroy_without_reassign
|
destroy_without_reassign
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s; name end
|
||||||
end
|
end
|
||||||
|
|
|
@ -51,7 +51,9 @@ class IssueStatus < ActiveRecord::Base
|
||||||
:conditions => ["role_id=? and tracker_id=?", role.id, tracker.id]).collect{ |w| w.new_status }.compact if role && tracker
|
:conditions => ["role_id=? and tracker_id=?", role.id, tracker.id]).collect{ |w| w.new_status }.compact if role && tracker
|
||||||
new_statuses ? new_statuses.sort{|x, y| x.position <=> y.position } : []
|
new_statuses ? new_statuses.sort{|x, y| x.position <=> y.position } : []
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def to_s; name end
|
||||||
|
|
||||||
private
|
private
|
||||||
def check_integrity
|
def check_integrity
|
||||||
raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id])
|
raise "Can't delete status" if Issue.find(:first, :conditions => ["status_id=?", self.id])
|
||||||
|
|
|
@ -15,10 +15,23 @@
|
||||||
# along with this program; if not, write to the Free Software
|
# along with this program; if not, write to the Free Software
|
||||||
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
class QueryColumn
|
||||||
|
attr_accessor :name, :sortable, :default
|
||||||
|
|
||||||
|
def initialize(name, options={})
|
||||||
|
self.name = name
|
||||||
|
self.sortable = options[:sortable]
|
||||||
|
self.default = options[:default]
|
||||||
|
end
|
||||||
|
|
||||||
|
def default?; default end
|
||||||
|
end
|
||||||
|
|
||||||
class Query < ActiveRecord::Base
|
class Query < ActiveRecord::Base
|
||||||
belongs_to :project
|
belongs_to :project
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
serialize :filters
|
serialize :filters
|
||||||
|
serialize :column_names
|
||||||
|
|
||||||
attr_protected :project, :user
|
attr_protected :project, :user
|
||||||
attr_accessor :executed_by
|
attr_accessor :executed_by
|
||||||
|
@ -59,6 +72,22 @@ class Query < ActiveRecord::Base
|
||||||
|
|
||||||
cattr_reader :operators_by_filter_type
|
cattr_reader :operators_by_filter_type
|
||||||
|
|
||||||
|
@@available_columns = [
|
||||||
|
QueryColumn.new(:tracker, :sortable => "#{Tracker.table_name}.position", :default => true),
|
||||||
|
QueryColumn.new(:status, :sortable => "#{IssueStatus.table_name}.position", :default => true),
|
||||||
|
QueryColumn.new(:priority, :sortable => "#{Issue.table_name}.priority_id", :default => true),
|
||||||
|
QueryColumn.new(:subject, :default => true),
|
||||||
|
QueryColumn.new(:assigned_to, :sortable => "#{User.table_name}.lastname", :default => true),
|
||||||
|
QueryColumn.new(:updated_on, :sortable => "#{Issue.table_name}.updated_on", :default => true),
|
||||||
|
QueryColumn.new(:category, :sortable => "#{IssueCategory.table_name}.name"),
|
||||||
|
QueryColumn.new(:start_date, :sortable => "#{Issue.table_name}.start_date"),
|
||||||
|
QueryColumn.new(:due_date, :sortable => "#{Issue.table_name}.due_date"),
|
||||||
|
QueryColumn.new(:estimated_hours, :sortable => "#{Issue.table_name}.estimated_hours"),
|
||||||
|
QueryColumn.new(:done_ratio, :sortable => "#{Issue.table_name}.done_ratio"),
|
||||||
|
QueryColumn.new(:created_on, :sortable => "#{Issue.table_name}.created_on"),
|
||||||
|
]
|
||||||
|
cattr_reader :available_columns
|
||||||
|
|
||||||
def initialize(attributes = nil)
|
def initialize(attributes = nil)
|
||||||
super attributes
|
super attributes
|
||||||
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
|
self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
|
||||||
|
@ -173,7 +202,30 @@ class Query < ActiveRecord::Base
|
||||||
label = @available_filters[field][:name] if @available_filters.has_key?(field)
|
label = @available_filters[field][:name] if @available_filters.has_key?(field)
|
||||||
label ||= field.gsub(/\_id$/, "")
|
label ||= field.gsub(/\_id$/, "")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def available_columns
|
||||||
|
cols = Query.available_columns
|
||||||
|
end
|
||||||
|
|
||||||
|
def columns
|
||||||
|
if column_names && !column_names.empty?
|
||||||
|
available_columns.select {|c| column_names.include?(c.name) }
|
||||||
|
else
|
||||||
|
# default columns
|
||||||
|
available_columns.select {|c| c.default? }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def column_names=(names)
|
||||||
|
names = names.select {|n| n.is_a?(Symbol) || !n.blank? } if names
|
||||||
|
names = names.collect {|n| n.is_a?(Symbol) ? n : n.to_sym } if names
|
||||||
|
write_attribute(:column_names, names)
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_column?(column)
|
||||||
|
column_names && column_names.include?(column.name)
|
||||||
|
end
|
||||||
|
|
||||||
def statement
|
def statement
|
||||||
# project/subprojects clause
|
# project/subprojects clause
|
||||||
clause = ''
|
clause = ''
|
||||||
|
|
|
@ -27,6 +27,8 @@ class Tracker < ActiveRecord::Base
|
||||||
validates_length_of :name, :maximum => 30
|
validates_length_of :name, :maximum => 30
|
||||||
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
|
validates_format_of :name, :with => /^[\w\s\'\-]*$/i
|
||||||
|
|
||||||
|
def to_s; name end
|
||||||
|
|
||||||
private
|
private
|
||||||
def check_integrity
|
def check_integrity
|
||||||
raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id])
|
raise "Can't delete tracker" if Issue.find(:first, :conditions => ["tracker_id=?", self.id])
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
<table class="list">
|
||||||
|
<thead><tr>
|
||||||
|
<th></th>
|
||||||
|
<%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %>
|
||||||
|
<% query.columns.each do |column| %>
|
||||||
|
<%= column_header(column) %>
|
||||||
|
<% end %>
|
||||||
|
</tr></thead>
|
||||||
|
<tbody>
|
||||||
|
<% issues.each do |issue| %>
|
||||||
|
<tr class="issue <%= cycle('odd', 'even') %>">
|
||||||
|
<th class="checkbox"><%= check_box_tag "issue_ids[]", issue.id, false, :id => "issue_#{issue.id}" %></th>
|
||||||
|
<td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
|
||||||
|
<% query.columns.each do |column| %>
|
||||||
|
<%= content_tag 'td', column_content(column, issue), :class => column.name %>
|
||||||
|
<% end %>
|
||||||
|
</tr>
|
||||||
|
<% end %>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
|
@ -23,32 +23,8 @@
|
||||||
<p><i><%= l(:label_no_data) %></i></p>
|
<p><i><%= l(:label_no_data) %></i></p>
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|
||||||
<table class="list">
|
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
|
||||||
<thead><tr>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %>
|
|
||||||
<%= sort_header_tag("#{Project.table_name}.name", :caption => l(:field_project)) %>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.tracker_id", :caption => l(:field_tracker)) %>
|
|
||||||
<%= sort_header_tag("#{IssueStatus.table_name}.name", :caption => l(:field_status)) %>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.priority_id", :caption => l(:field_priority)) %>
|
|
||||||
<th><%=l(:field_subject)%></th>
|
|
||||||
<%= sort_header_tag("#{User.table_name}.lastname", :caption => l(:field_assigned_to)) %>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.updated_on", :caption => l(:field_updated_on)) %>
|
|
||||||
</tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<% for issue in @issues %>
|
|
||||||
<tr class="<%= cycle("odd", "even") %>">
|
|
||||||
<td align="center" valign="top"><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
|
|
||||||
<td align="center" valign="top" nowrap><%=h issue.project.name %></td>
|
|
||||||
<td align="center" valign="top" nowrap><%= issue.tracker.name %></td>
|
|
||||||
<td valign="top"nowrap><%= issue.status.name %></td>
|
|
||||||
<td align="center" valign="top"><%= issue.priority.name %></td>
|
|
||||||
<td><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></td>
|
|
||||||
<td align="center" valign="top" nowrap><%= issue.assigned_to.name if issue.assigned_to %></td>
|
|
||||||
<td align="center" valign="top" nowrap><%= format_time(issue.updated_on) %></td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<p><%= pagination_links_full @issue_pages %>
|
<p><%= pagination_links_full @issue_pages %>
|
||||||
[ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p>
|
[ <%= @issue_pages.current.first_item %> - <%= @issue_pages.current.last_item %> / <%= @issue_count %> ]</p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -45,32 +45,7 @@
|
||||||
<% else %>
|
<% else %>
|
||||||
|
|
||||||
<% form_tag({:controller => 'projects', :action => 'move_issues', :id => @project}, :id => 'issues_form' ) do %>
|
<% form_tag({:controller => 'projects', :action => 'move_issues', :id => @project}, :id => 'issues_form' ) do %>
|
||||||
<table class="list">
|
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
|
||||||
<thead><tr>
|
|
||||||
<th></th>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.id", :caption => '#') %>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.tracker_id", :caption => l(:field_tracker)) %>
|
|
||||||
<%= sort_header_tag("#{IssueStatus.table_name}.name", :caption => l(:field_status)) %>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.priority_id", :caption => l(:field_priority)) %>
|
|
||||||
<th><%=l(:field_subject)%></th>
|
|
||||||
<%= sort_header_tag("#{User.table_name}.lastname", :caption => l(:field_assigned_to)) %>
|
|
||||||
<%= sort_header_tag("#{Issue.table_name}.updated_on", :caption => l(:field_updated_on)) %>
|
|
||||||
</tr></thead>
|
|
||||||
<tbody>
|
|
||||||
<% for issue in @issues %>
|
|
||||||
<tr class="<%= cycle("odd", "even") %>">
|
|
||||||
<th style="width:15px;"><%= check_box_tag "issue_ids[]", issue.id, false, :id => "issue_#{issue.id}" %></th>
|
|
||||||
<td align="center"><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
|
|
||||||
<td align="center"><%= issue.tracker.name %></td>
|
|
||||||
<td><%= issue.status.name %></td>
|
|
||||||
<td align="center"><%= issue.priority.name %></td>
|
|
||||||
<td><%= "#{issue.project.name} - " unless @project && @project == issue.project %><%= link_to h(issue.subject), :controller => 'issues', :action => 'show', :id => issue %></td>
|
|
||||||
<td align="center"><%= issue.assigned_to.name if issue.assigned_to %></td>
|
|
||||||
<td align="center"><%= format_time(issue.updated_on) %></td>
|
|
||||||
</tr>
|
|
||||||
<% end %>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
<div class="contextual">
|
<div class="contextual">
|
||||||
<%= l(:label_export_to) %>
|
<%= l(:label_export_to) %>
|
||||||
<%= link_to 'CSV', {:action => 'export_issues_csv', :id => @project}, :class => 'icon icon-csv' %>,
|
<%= link_to 'CSV', {:action => 'export_issues_csv', :id => @project}, :class => 'icon icon-csv' %>,
|
||||||
|
|
|
@ -9,6 +9,13 @@
|
||||||
<p><label for="query_is_public"><%=l(:field_is_public)%></label>
|
<p><label for="query_is_public"><%=l(:field_is_public)%></label>
|
||||||
<%= check_box 'query', 'is_public' %></p>
|
<%= check_box 'query', 'is_public' %></p>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
|
<p><label for="query_column_names"><%=l(:field_column_names)%></label>
|
||||||
|
<% @query.available_columns.each do |column| %>
|
||||||
|
<%= check_box_tag 'query[column_names][]', column.name, @query.has_column?(column) %> <%= l("field_#{column.name}") %><br />
|
||||||
|
<% end %>
|
||||||
|
<%= hidden_field_tag 'query[column_names][]', '' %>
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<%= render :partial => 'queries/filters', :locals => {:query => query}%>
|
<%= render :partial => 'queries/filters', :locals => {:query => query}%>
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
class AddQueriesColumnNames < ActiveRecord::Migration
|
||||||
|
def self.up
|
||||||
|
add_column :queries, :column_names, :text
|
||||||
|
end
|
||||||
|
|
||||||
|
def self.down
|
||||||
|
remove_column :queries, :column_names
|
||||||
|
end
|
||||||
|
end
|
|
@ -511,3 +511,4 @@ enumeration_doc_categories: Категории документи
|
||||||
enumeration_activities: Дейности (time tracking)
|
enumeration_activities: Дейности (time tracking)
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -511,3 +511,4 @@ text_issue_category_destroy_assignments: Remove category assignments
|
||||||
label_added_time_by: Added by %s %s ago
|
label_added_time_by: Added by %s %s ago
|
||||||
field_estimated_hours: Estimated time
|
field_estimated_hours: Estimated time
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -511,3 +511,4 @@ enumeration_doc_categories: Dokumentenkategorien
|
||||||
enumeration_activities: Aktivitäten (Zeiterfassung)
|
enumeration_activities: Aktivitäten (Zeiterfassung)
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -159,6 +159,7 @@ field_delay: Delay
|
||||||
field_assignable: Issues can be assigned to this role
|
field_assignable: Issues can be assigned to this role
|
||||||
field_redirect_existing_links: Redirect existing links
|
field_redirect_existing_links: Redirect existing links
|
||||||
field_estimated_hours: Estimated time
|
field_estimated_hours: Estimated time
|
||||||
|
field_column_names: Columns
|
||||||
|
|
||||||
setting_app_title: Application title
|
setting_app_title: Application title
|
||||||
setting_app_subtitle: Application subtitle
|
setting_app_subtitle: Application subtitle
|
||||||
|
|
|
@ -511,3 +511,4 @@ enumeration_doc_categories: Categorías del documento
|
||||||
enumeration_activities: Activities (time tracking)
|
enumeration_activities: Activities (time tracking)
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -159,6 +159,7 @@ field_delay: Retard
|
||||||
field_assignable: Demandes assignables à ce rôle
|
field_assignable: Demandes assignables à ce rôle
|
||||||
field_redirect_existing_links: Rediriger les liens existants
|
field_redirect_existing_links: Rediriger les liens existants
|
||||||
field_estimated_hours: Temps estimé
|
field_estimated_hours: Temps estimé
|
||||||
|
field_column_names: Colonnes
|
||||||
|
|
||||||
setting_app_title: Titre de l'application
|
setting_app_title: Titre de l'application
|
||||||
setting_app_subtitle: Sous-titre de l'application
|
setting_app_subtitle: Sous-titre de l'application
|
||||||
|
|
|
@ -511,3 +511,4 @@ enumeration_doc_categories: Categorie di documenti
|
||||||
enumeration_activities: Attività (time tracking)
|
enumeration_activities: Attività (time tracking)
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -512,3 +512,4 @@ enumeration_doc_categories: 文書カテゴリ
|
||||||
enumeration_activities: 作業分類 (時間トラッキング)
|
enumeration_activities: 作業分類 (時間トラッキング)
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -512,3 +512,4 @@ enumeration_activities: Activiteiten (tijd tracking)
|
||||||
text_comma_separated: Multiple values allowed (comma separated).
|
text_comma_separated: Multiple values allowed (comma separated).
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -511,3 +511,4 @@ label_added_time_by: Dodane przez %s %s temu
|
||||||
field_estimated_hours: Szacowany czas
|
field_estimated_hours: Szacowany czas
|
||||||
label_file_plural: Pliki
|
label_file_plural: Pliki
|
||||||
label_changeset_plural: Zestawienia zmian
|
label_changeset_plural: Zestawienia zmian
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -511,3 +511,4 @@ enumeration_doc_categories: Categorias de documento
|
||||||
enumeration_activities: Atividades (time tracking)
|
enumeration_activities: Atividades (time tracking)
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -511,3 +511,4 @@ enumeration_doc_categories: Categorias de documento
|
||||||
enumeration_activities: Atividades (time tracking)
|
enumeration_activities: Atividades (time tracking)
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -511,3 +511,4 @@ label_index_by_date: Index by date
|
||||||
label_index_by_title: Index by title
|
label_index_by_title: Index by title
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -512,3 +512,4 @@ enumeration_activities: Aktiviteter (tidsspårning)
|
||||||
field_comments: Comment
|
field_comments: Comment
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -514,3 +514,4 @@ enumeration_activities: Activities (time tracking)
|
||||||
label_wiki_page: Wiki page
|
label_wiki_page: Wiki page
|
||||||
label_file_plural: Files
|
label_file_plural: Files
|
||||||
label_changeset_plural: Changesets
|
label_changeset_plural: Changesets
|
||||||
|
field_column_names: Columns
|
||||||
|
|
|
@ -133,6 +133,12 @@ margin*/
|
||||||
|
|
||||||
div.attachments p { margin:4px 0 2px 0; }
|
div.attachments p { margin:4px 0 2px 0; }
|
||||||
|
|
||||||
|
/***** Issue list ****/
|
||||||
|
tr.issue { text-align: center; white-space: nowrap; }
|
||||||
|
tr.issue th.checkbox { width: 15px; }
|
||||||
|
tr.issue td.subject, tr.issue td.category { white-space: normal; }
|
||||||
|
tr.issue td.subject { text-align: left; }
|
||||||
|
|
||||||
/***** Flash & error messages ****/
|
/***** Flash & error messages ****/
|
||||||
#flash div, #errorExplanation, .nodata {
|
#flash div, #errorExplanation, .nodata {
|
||||||
padding: 4px 4px 4px 30px;
|
padding: 4px 4px 4px 30px;
|
||||||
|
|
|
@ -28,4 +28,17 @@ class QueryTest < Test::Unit::TestCase
|
||||||
assert_equal 1, issues.length
|
assert_equal 1, issues.length
|
||||||
assert_equal Issue.find(3), issues.first
|
assert_equal Issue.find(3), issues.first
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_default_columns
|
||||||
|
q = Query.new
|
||||||
|
assert !q.columns.empty?
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_set_column_names
|
||||||
|
q = Query.new
|
||||||
|
q.column_names = ['tracker', :subject, '', 'unknonw_column']
|
||||||
|
assert_equal [:tracker, :subject], q.columns.collect {|c| c.name}
|
||||||
|
c = q.columns.first
|
||||||
|
assert q.has_column?(c)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue