33-add_versions_inheritance-0.4.0.patch

Vitaliy Ischenko, 2009-07-06 15:00

Download (27.8 KB)

View differences:

app/controllers/issues_controller.rb
19 19
  menu_item :new_issue, :only => :new
20 20
  
21 21
  before_filter :find_issue, :only => [:show, :edit, :reply]
22
  before_filter :check_issue_perms, :only => [:show, :edit]
22 23
  before_filter :find_issues, :only => [:bulk_edit, :move, :destroy]
23 24
  before_filter :find_project, :only => [:new, :update_form, :preview]
24 25
  before_filter :authorize, :except => [:index, :changes, :gantt, :calendar, :preview, :update_form, :context_menu]
......
63 64
                           :conditions => @query.statement,
64 65
                           :limit  =>  limit,
65 66
                           :offset =>  @issue_pages.current.offset
67
      @issues.map!{ |issue| issue_without_hidden_fields(issue) } # don't show forbidden fields
66 68
      respond_to do |format|
67 69
        format.html { 
68 70
          if @query.grouped?
......
113 115
    @changesets.reverse! if User.current.wants_comments_in_reverse_order?
114 116
    @allowed_statuses = @issue.new_statuses_allowed_to(User.current)
115 117
    @edit_allowed = User.current.allowed_to?(:edit_issues, @project)
118
    @issue = issue_without_hidden_fields(@issue)
119
    @journals = journals_without_hidden_entries(@journals)
116 120
    @priorities = IssuePriority.all
117 121
    @time_entry = TimeEntry.new
118 122
    respond_to do |format|
......
355 359
      events += Version.find(:all, :include => :project,
356 360
                                   :conditions => ["(#{@query.project_statement}) AND effective_date BETWEEN ? AND ?", @gantt.date_from, @gantt.date_to])
357 361
                                   
362

  
363
      events += @project.related_versions.select { |v| ((v.project.id != @project.id) && (@gantt.date_from..@gantt.date_to).include?(v.effective_date)) }
364

  
358 365
      @gantt.events = events
359 366
    end
360 367
    
......
387 394
                           )
388 395
      events += Version.find(:all, :include => :project,
389 396
                                   :conditions => ["(#{@query.project_statement}) AND effective_date BETWEEN ? AND ?", @calendar.startdt, @calendar.enddt])
390
                                     
397

  
398
      events += @project.related_versions.select { |v| ((v.project.id != @project.id) && (@calendar.startdt..@calendar.enddt).include?(v.effective_date)) }
399
                               
391 400
      @calendar.events = events
392 401
    end
393 402
    
......
471 480
    render_404
472 481
  end
473 482
  
483
  def issue_fixed_version_allowed?(issue)
484
    ((not issue.fixed_version) ||
485
     (User.current.allowed_to?(:view_issues,
486
                               issue.fixed_version.project)))
487
  end
488

  
489
  def check_issue_perms
490
    @forbidden_fixed_version = (not issue_fixed_version_allowed?(@issue))
491
  end
492

  
493
  ## Filter journals to remove non allowed entries. We want here
494
  ## to handle the _specific case_ of a user 'Joe' browsing 'Project
495
  ## B' issues. 'Project B' is a subproject of 'Project A' and
496
  ## inherits its versions. Joe can't see 'Project A, but issue
497
  ## fixed_versions has been set at some point to a version belonging
498
  ## to 'Project A', by an other member of 'Project B'. Joe should not
499
  ## see this sensitive information.
500
  def journals_without_hidden_entries(journals)
501
    p = @project
502
    forbidden_parents = []
503
    while p = p.parent do
504
      forbidden_parents.push p.id unless User.current.allowed_to?(:view_issues, p)
505
    end
506

  
507
    unless (journals.empty? || forbidden_parents.empty?)
508
      journals = journals.dup
509
      journals.delete_if do |j|
510
        j.details.map{ |d| (d.property == 'attr' &&
511
                            d.prop_key == 'fixed_version_id' &&
512
                            (
513
                             (d.old_value && forbidden_parents.include?(Version.find(d.old_value.to_i).project_id)) ||
514
                             (d.value && forbidden_parents.include?(Version.find(d.value.to_i).project_id))
515
                            )
516
                           ) }.include?(true)
517
      end
518
    end
519
    journals
520
  end
521

  
522
  ## Filter issue to remove non allowed fields. For more information,
523
  ## see documentation of journals_without_hidden_entries
524
  def issue_without_hidden_fields(issue)
525
    unless issue_fixed_version_allowed?(issue)
526
      issue = issue.dup
527
      issue.fixed_version = nil
528
    end
529
    issue
530
  end
531
  
474 532
  # Retrieve query from session or build a new query
475 533
  def retrieve_query
476 534
    if !params[:query_id].blank?
app/controllers/projects_controller.rb
221 221

  
222 222
  def add_file
223 223
    if request.post?
224
      container = (params[:version_id].blank? ? @project : @project.versions.find_by_id(params[:version_id]))
224
      container = (params[:version_id].blank? ? @project : @project.related_versions.find { |v| v.id.to_s == params[:version_id] })
225 225
      attachments = attach_files(container, params[:attachments])
226 226
      if !attachments.empty? && Setting.notified_events.include?('file_added')
227 227
        Mailer.deliver_attachments_added(attachments)
......
229 229
      redirect_to :controller => 'projects', :action => 'list_files', :id => @project
230 230
      return
231 231
    end
232
    @versions = @project.versions.sort
232
    @versions = @project.related_versions.sort
233 233
  end
234 234
  
235 235
  def list_files
......
240 240
                'downloads' => "#{Attachment.table_name}.downloads"
241 241
                
242 242
    @containers = [ Project.find(@project.id, :include => :attachments, :order => sort_clause)]
243
    @containers += @project.versions.find(:all, :include => :attachments, :order => sort_clause).sort.reverse
243
    @containers += Version.find(:all, :include => :attachments, :order => sort_clause, :conditions => ['versions.id IN (?)', @project.related_versions.map {|v| v.id}]).sort.reverse
244 244
    render :layout => !request.xhr?
245 245
  end
246 246
  
......
248 248
  def changelog
249 249
    @trackers = @project.trackers.find(:all, :conditions => ["is_in_chlog=?", true], :order => 'position')
250 250
    retrieve_selected_tracker_ids(@trackers)    
251
    @versions = @project.versions.sort
251
    @versions = @project.related_versions.sort
252 252
  end
253 253

  
254 254
  def roadmap
255 255
    @trackers = @project.trackers.find(:all, :conditions => ["is_in_roadmap=?", true])
256 256
    retrieve_selected_tracker_ids(@trackers)
257
    @versions = @project.versions.sort
258
    @versions = @versions.select {|v| !v.completed? } unless params[:completed]
257
    @versions = retrieve_related_versions
259 258
  end
260 259
  
261 260
  def activity
......
316 315
    render_404
317 316
  end
318 317

  
318
  def retrieve_related_versions
319
    related_versions=@project.related_versions
320
    # should this test be moved to projects_helper.rb : version_visible_issues ?
321
    params[:completed] ? related_versions : related_versions.select {|v| !v.completed? }
322
  end
323

  
319 324
  def retrieve_selected_tracker_ids(selectable_trackers)
320 325
    if ids = params[:tracker_ids]
321 326
      @selected_tracker_ids = (ids.is_a? Array) ? ids.collect { |id| id.to_i.to_s } : ids.split('/').collect { |id| id.to_i.to_s }
app/controllers/reports_controller.rb
31 31
      render :template => "reports/issue_report_details"
32 32
    when "version"
33 33
      @field = "fixed_version_id"
34
      @rows = @project.versions.sort
34
      @rows = @project.related_versions.sort
35 35
      @data = issues_by_version
36 36
      @report_title = l(:field_version)
37 37
      render :template => "reports/issue_report_details"
......
67 67
      render :template => "reports/issue_report_details"  
68 68
    else
69 69
      @trackers = @project.trackers
70
      @versions = @project.versions.sort
70
      @versions = @project.related_versions.sort
71 71
      @priorities = IssuePriority.all
72 72
      @categories = @project.issue_categories
73 73
      @assignees = @project.members.collect { |m| m.user }
app/controllers/versions_controller.rb
19 19
  menu_item :roadmap
20 20
  before_filter :find_project, :authorize
21 21

  
22
  helper :projects
23
  include ProjectsHelper
24

  
22 25
  def show
26
    @issues = version_visible_issues(@version,@project,@project.trackers.collect { |x| x.id.to_s })
23 27
  end
24 28
  
25 29
  def edit
app/helpers/projects_helper.rb
33 33
            ]
34 34
    tabs.select {|tab| User.current.allowed_to?(tab[:action], @project)}     
35 35
  end
36

  
37
  ## return an array of the issues attached to version that a user should see
38
  ## As a convenience, allow limitation by trackers with Array of tracker_ids
39
  def version_visible_issues(version,project,tracker_ids=[],user=User.current)
40
    # Returns void when user can not see issues or if tracker_ids is void
41
    return [] if ((not user.allowed_to?(:view_issues,
42
                                        version.project)) or
43
                  tracker_ids.empty?)
44
    # user can see project issues, carry on, retrieve them ...
45
    issues = version.
46
      fixed_issues.find(:all,
47
                        :include => [:status, :tracker],
48
                        :conditions => ["tracker_id in (#{tracker_ids.join(',')})"],
49
                        :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id")
50
    # Only keep issues from self, parent or children,
51
    related_projects = project.self_and_descendants.map { |t_item| t_item.id }
52

  
53
    # do we need parents at all?
54
    p = project
55
    while p = p.parent do
56
        related_projects.push p.id
57
    end
58
    related_projects = related_projects.select{|x| user.allowed_to?(:view_issues, Project.find(x))}
59
    
60
    # now only keep related issues. (issues from brother projects are discarded)
61
    issues.select {|x| related_projects.include?(x.project.id) }
62
  end
63

  
64
  def grouped_versions_for_select(versions_list)
65
    return [] if versions_list == nil
66

  
67
    grouped_structure = []
68
    versions_list.each do |prj, ver|
69
      grouped_structure.push [prj.name, ver.collect { |v| [v.name, v.id] }]
70
    end
71
    grouped_structure
72
  end
36 73
  
37 74
  def parent_project_select_tag(project)
38 75
    options = '<option></option>' + project_tree_options_for_select(project.possible_parents, :selected => project.parent)
app/models/project.rb
274 274
    members.select {|m| m.mail_notification? || m.user.mail_notification?}.collect {|m| m.user.mail}
275 275
  end
276 276
  
277
  ## Return versions attached to self, and to parents if relevant.
278
  ## Sorting is done in the SQL request to take advantage of cache
279
  def related_versions(user=User.current)
280
    p = self 
281
    parent_ids = [self.id]
282
    while p = p.parent do
283
      parent_ids.push p.id if user.allowed_to?(:view_issues, p)
284
    end
285

  
286
    Version.find(:all,
287
                 :conditions => {:project_id => parent_ids},
288
                 :order => "effective_date ASC, name ASC ")
289
  end
290
  
291
  def grouped_versions(version_list=nil, user=User.current)
292
    version_list ||= related_versions(user)
293

  
294
    p, i = self, 0
295
    parent_nesting = {}
296
    parent_nesting[p.id] = i
297

  
298
    while p = p.parent do
299
      i += 1
300
      parent_nesting[p.id] = i
301
    end
302

  
303
    version_list.group_by(&:project).sort_by { |item| parent_nesting[item.first.id] }
304
  end
305

  
277 306
  # Returns an array of all custom fields enabled for project issues
278 307
  # (explictly associated custom fields and custom fields enabled for all projects)
279 308
  def all_issue_custom_fields
app/models/query.rb
89 89
  @@operators_by_filter_type = { :list => [ "=", "!" ],
90 90
                                 :list_status => [ "o", "=", "!", "c", "*" ],
91 91
                                 :list_optional => [ "=", "!", "!*", "*" ],
92
                                 :list_grouped => [ "=", "!", "!*", "*" ],
92 93
                                 :list_subprojects => [ "*", "!*", "=" ],
93 94
                                 :date => [ "<t+", ">t+", "t+", "t", "w", ">t-", "<t-", "t-" ],
94 95
                                 :date_past => [ ">t-", "<t-", "t-", "t", "w" ],
......
117 118
  ]
118 119
  cattr_reader :available_columns
119 120
  
121
  include ProjectsHelper
122

  
120 123
  def initialize(attributes = nil)
121 124
    super attributes
122 125
    self.filters ||= { 'status_id' => {:operator => "o", :values => [""]} }
......
181 184
      unless @project.issue_categories.empty?
182 185
        @available_filters["category_id"] = { :type => :list_optional, :order => 6, :values => @project.issue_categories.collect{|s| [s.name, s.id.to_s] } }
183 186
      end
184
      unless @project.versions.empty?
185
        @available_filters["fixed_version_id"] = { :type => :list_optional, :order => 7, :values => @project.versions.sort.collect{|s| [s.name, s.id.to_s] } }
187
      unless @project.related_versions.empty?
188
        @available_filters["fixed_version_id"] = { :type => :list_grouped,
189
                                                   :order => 7,
190
                                                   :values => grouped_versions_for_select(@project.grouped_versions) }
186 191
      end
187 192
      unless @project.descendants.active.empty?
188 193
        @available_filters["subproject_id"] = { :type => :list_subprojects, :order => 13, :values => @project.descendants.visible.collect{|s| [s.name, s.id.to_s] } }
app/views/issues/_form.rhtml
32 32
                     {:controller => 'projects', :action => 'add_issue_category', :id => @project},
33 33
                     :class => 'small', :tabindex => 199) if authorize_for('projects', 'add_issue_category') %></p>
34 34
<% end %>
35
<%= content_tag('p', f.select(:fixed_version_id, 
36
                              (@project.versions.sort.collect {|v| [v.name, v.id]}),
37
                              { :include_blank => true })) unless @project.versions.empty? %>
35
<% unless (@project.related_versions.empty? || @forbidden_fixed_version) then %>
36
    <%= content_tag('p', f.select_ex(:fixed_version_id,
37
                                     grouped_versions_for_select(@project.grouped_versions),
38
                                     { :include_blank => true})) %>
39
<% end %>
38 40
</div>
39 41

  
40 42
<div class="splitcontentright">
app/views/issues/_form_update.rhtml
5 5
</div>
6 6
<div class="splitcontentright">
7 7
<p><%= f.select :done_ratio, ((0..10).to_a.collect {|r| ["#{r*10} %", r*10] }) %></p>
8
<%= content_tag('p', f.select(:fixed_version_id, 
9
                          (@project.versions.sort.collect {|v| [v.name, v.id]}),
10
                          { :include_blank => true })) unless @project.versions.empty? %>
8
<%= unless (@issue.fixed_version &&
9
            (not User.current.allowed_to?(:view_issues,
10
                                          @issue.fixed_version.project)) ||
11
            @project.related_versions.empty?) then
12
      content_tag('p', f.select_ex(:fixed_version_id, 
13
                                grouped_versions_for_select(@project.grouped_versions),
14
                                { :include_blank => true }))
15
    end %>
11 16
</div>
12 17
</div>
app/views/issues/bulk_edit.rhtml
27 27
<label><%= l(:field_fixed_version) %>: 
28 28
<%= select_tag('fixed_version_id', content_tag('option', l(:label_no_change_option), :value => '') +
29 29
                                   content_tag('option', l(:label_none), :value => 'none') +
30
                                   options_from_collection_for_select(@project.versions.sort, :id, :name)) %></label>
30
                                   grouped_options_for_select(grouped_versions_for_select(@project.grouped_versions))) %></label>
31 31
</p>
32 32

  
33 33
<p>
app/views/issues/context_menu.rhtml
27 27
		<% end -%>
28 28
		</ul>
29 29
	</li>
30
	<% unless @project.nil? || @project.versions.empty? -%>
30
	<% unless @project.nil? || @project.related_versions.empty? -%>
31 31
	<li class="folder">			
32 32
		<a href="#" class="submenu"><%= l(:field_fixed_version) %></a>
33 33
		<ul>
34
		<% @project.versions.sort.each do |v| -%>
35
		    <li><%= context_menu_link v.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => v, :back_to => @back}, :method => :post,
36
		                              :selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %></li>
37
		<% end -%>
34
                <% @project.grouped_versions.each do |p, vv| -%>
35
                   <li class="<%= "folder" unless @project.id == p.id %>">
36
                   <% unless @project.id == p.id %>
37
                   <a href="#" class="submenu"><%= p.name %></a>
38
                   <ul>
39
                   <% end %>
40
                   <% vv.each do |v| %>
41
                   <li><%= context_menu_link v.name, {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => v, :back_to => @back}, :method => :post, :selected => (@issue && v == @issue.fixed_version), :disabled => !@can[:update] %></li>
42
                   <% end %>
43
                   <% unless @project.id == p.id %>
44
                   </ul>
45
                   <% end %>
46
                   </li>
47
                <% end -%>
38 48
		    <li><%= context_menu_link l(:label_none), {:controller => 'issues', :action => 'bulk_edit', :ids => @issues.collect(&:id), 'fixed_version_id' => 'none', :back_to => @back}, :method => :post,
39 49
		                              :selected => (@issue && @issue.fixed_version.nil?), :disabled => !@can[:update] %></li>
40 50
		</ul>
app/views/projects/add_file.rhtml
7 7
<% if @versions.any? %>
8 8
<p><label for="version_id"><%=l(:field_version)%></label>
9 9
<%= select_tag "version_id", content_tag('option', '') +
10
														 options_from_collection_for_select(@versions, "id", "name") %></p>
10
														 grouped_options_for_select(grouped_versions_for_select(@project.grouped_versions)) %></p>
11 11
<% end %>
12 12

  
13 13
<p><label><%=l(:label_attachment_plural)%></label><%= render :partial => 'attachments/form' %></p>
app/views/projects/roadmap.rhtml
4 4
<p class="nodata"><%= l(:label_no_data) %></p>
5 5
<% else %>
6 6
<div id="roadmap">
7
<% @versions.each do |version| %>   
7
<% grouped_versions = @project.grouped_versions(@versions) %>
8
<% grouped_versions.each do |projects, versions_in_project| %>
9
    <% unless @project.id == projects.id %>
10
        <fieldset>
11
        <legend><h3><%= l(:label_project) %>: <%= link_to h(projects.name), :controller => 'projects', :action => 'show', :id => projects, :jump => 'roadmap' %></h3></legend>
12
    <% end %>
13
    <% versions_in_project.each do |version| %>
14

  
15
    <% issues = version_visible_issues(version,@project,@selected_tracker_ids) %>
16

  
8 17
    <%= tag 'a', :name => version.name %>
9 18
    <h3 class="icon22 icon22-package"><%= link_to h(version.name), :controller => 'versions', :action => 'show', :id => version %></h3>
10 19
    <%= render :partial => 'versions/overview', :locals => {:version => version} %>
11 20
    <%= render(:partial => "wiki/content", :locals => {:content => version.wiki_page.content}) if version.wiki_page %>
12 21

  
13
    <% issues = version.fixed_issues.find(:all,
14
                                          :include => [:status, :tracker],
15
                                          :conditions => ["tracker_id in (#{@selected_tracker_ids.join(',')})"],
16
                                          :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") unless @selected_tracker_ids.empty?
17
       issues ||= []
18
    %>
19 22
    <% if issues.size > 0 %>
20 23
    <fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend>
21 24
    <ul>
22 25
    <%- issues.each do |issue| -%>
23
        <li><%= link_to_issue(issue) %>: <%=h issue.subject %></li>
26
        <li><%= link_to_issue(issue) %>: <%=h issue.subject %> <%= (" <em>(<b>" + l(:label_project) + "</b>: " + issue.project.name + ")</em>") unless issue.project.id == @project.id %></li>
24 27
    <%- end -%>
25 28
    </ul>
26 29
    </fieldset>
27 30
    <% end %>
28 31
    <%= call_hook :view_projects_roadmap_version_bottom, :version => version %>
32
    <% end %>
33

  
34
    <% unless @project.id == projects.id %>
35
        </fieldset>
36
    <% end %>
29 37
<% end %>
30 38
</div>
31 39
<% end %>
app/views/queries/_filters.rhtml
74 74
    <td>    
75 75
    <div id="div_values_<%= field %>" style="display:none;">
76 76
    <% case options[:type]
77
    when :list, :list_optional, :list_status, :list_subprojects %>
77
    when :list, :list_optional, :list_grouped, :list_status, :list_subprojects %>
78 78
        <select <%= "multiple=true" if query.values_for(field) and query.values_for(field).length > 1 %> name="values[<%= field %>][]" id="values_<%= field %>" class="select-small" style="vertical-align: top;">
79
        <% if options[:type] == :list_grouped %>
80
        <%= grouped_options_for_select options[:values], query.values_for(field) %>
81
        <% else %>
79 82
        <%= options_for_select options[:values], query.values_for(field) %>        
83
        <% end %>
80 84
        </select>
81 85
        <%= link_to_function image_tag('bullet_toggle_plus.png'), "toggle_multi_select('#{field}');", :style => "vertical-align: bottom;" %>
82 86
    <% when :date, :date_past %>
app/views/versions/show.rhtml
32 32
<%= render :partial => 'versions/overview', :locals => {:version => @version} %>
33 33
<%= render(:partial => "wiki/content", :locals => {:content => @version.wiki_page.content}) if @version.wiki_page %>
34 34

  
35
<% issues = @version.fixed_issues.find(:all,
36
                                       :include => [:status, :tracker],
37
                                       :order => "#{Tracker.table_name}.position, #{Issue.table_name}.id") %>
38
<% if issues.size > 0 %>
35
<% if @issues.size > 0 %>
39 36
<fieldset class="related-issues"><legend><%= l(:label_related_issues) %></legend>
40 37
<ul>
41
<% issues.each do |issue| -%>
42
    <li><%= link_to_issue(issue) %>: <%=h issue.subject %></li>
38
<% @issues.each do |issue| -%>
39
    <li><%= link_to_issue(issue) %>: <%=h issue.subject %> <%= (" <em>(" + issue.project.name + ")</em>") unless issue.project.id == @project.id %></li>
43 40
<% end -%>
44 41
</ul>
45 42
</fieldset>
lib/redmine.rb
133 133
  menu.push :overview, { :controller => 'projects', :action => 'show' }
134 134
  menu.push :activity, { :controller => 'projects', :action => 'activity' }
135 135
  menu.push :roadmap, { :controller => 'projects', :action => 'roadmap' }, 
136
              :if => Proc.new { |p| p.versions.any? }
136
              :if => Proc.new { |p| p.related_versions.any? }
137 137
  menu.push :issues, { :controller => 'issues', :action => 'index' }, :param => :project_id, :caption => :label_issue_plural
138 138
  menu.push :new_issue, { :controller => 'issues', :action => 'new' }, :param => :project_id, :caption => :label_issue_new,
139 139
              :html => { :accesskey => Redmine::AccessKeys.key_for(:new_issue) }
lib/redmine/core_ext/form_builder.rb
1
require 'action_view/helpers/form_helper'
2

  
3
module ActionView::Helpers
4
    module FormOptionsHelper
5
      def select_ex(object, method, choices, options = {}, html_options = {})
6
        InstanceTag.new(object, method, self, options.delete(:object)).to_select_tag_ex(choices, options, html_options)
7
      end
8

  
9
      def grouped_options_for_select(grouped_options, selected_key = nil, prompt = nil)
10
        body = ''
11
        body << content_tag(:option, prompt, :value => "") if prompt
12

  
13
        grouped_options = grouped_options.sort if grouped_options.is_a?(Hash)
14

  
15
        grouped_options.each do |group|
16
          body << content_tag(:optgroup, options_for_select(group[1], selected_key), :label => group[0])
17
        end
18

  
19
        body
20
      end
21
    end
22

  
23
    class InstanceTag
24
      def to_select_tag_ex(choices, options, html_options)
25
        html_options = html_options.stringify_keys
26
        add_default_name_and_id(html_options)
27
        value = value(object)
28
        selected_value = options.has_key?(:selected) ? options[:selected] : value
29

  
30
        content_tag(
31
          "select",
32
          add_options(
33
            grouped_options_for_select(choices, selected_value),
34
            options,
35
            selected_value
36
          ),
37
          html_options
38
        )
39
      end
40
    end
41

  
42
    class FormBuilder
43
      def select_ex(method, choices, options = {}, html_options = {})
44
        @template.select_ex(@object_name, method, choices, objectify_options(options), @default_options.merge(html_options))
45
      end
46
    end
47
end
lib/redmine/export/pdf.rb
260 260
        pdf.SetFontStyle('B',9)
261 261
        pdf.Cell(190,5, l(:label_history), "B")
262 262
        pdf.Ln  
263
        for journal in issue.journals.find(:all, :include => [:user, :details], :order => "#{Journal.table_name}.created_on ASC")
263
        for journal in @journals
264 264
          pdf.SetFontStyle('B',8)
265 265
          pdf.Cell(190,5, format_time(journal.created_on) + " - " + journal.user.name)
266 266
          pdf.Ln
lib/tabular_form_builder.rb
37 37
  def select(field, choices, options = {}, html_options = {}) 
38 38
    label_for_field(field, options) + super
39 39
  end
40

  
41
  def select_ex(field, choices, options = {}, html_options = {})
42
    label_for_field(field, options) + super
43
  end
40 44
  
41 45
  # Returns a label tag for the given field
42 46
  def label_for_field(field, options = {})