Project

General

Profile

Feature #3058 » 0005-load-changesets-and-time-entries-tabs-async.patch

Marius BĂLTEANU, 2018-12-16 15:59

View differences:

app/controllers/issues_controller.rb
18 18
class IssuesController < ApplicationController
19 19
  default_search_scope :issues
20 20

  
21
  before_action :find_issue, :only => [:show, :edit, :update]
21
  before_action :find_issue, :only => [:show, :edit, :update, :issue_tab]
22 22
  before_action :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
23 23
  before_action :authorize, :except => [:index, :new, :create]
24 24
  before_action :find_optional_project, :only => [:index, :new, :create]
......
84 84

  
85 85
  def show
86 86
    @journals = @issue.visible_journals_with_index
87
    @changesets = @issue.changesets.visible.preload(:repository, :user).to_a
87
    @has_changesets = @issue.changesets.visible.preload(:repository, :user).exists?
88 88
    @relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
89 89

  
90
    if User.current.wants_comments_in_reverse_order?
91
      @journals.reverse!
92
      @changesets.reverse!
93
    end
90
    @journals.reverse! if User.current.wants_comments_in_reverse_order?
94 91

  
95 92
    if User.current.allowed_to?(:view_time_entries, @project)
96 93
      Issue.load_visible_spent_hours([@issue])
......
107 104
        retrieve_previous_and_next_issue_ids
108 105
        render :template => 'issues/show'
109 106
      }
110
      format.api
107
      format.api {
108
        @changesets = @issue.changesets.visible.preload(:repository, :user).to_a
109
        @changesets.reverse! if User.current.wants_comments_in_reverse_order?
110
      }
111 111
      format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
112 112
      format.pdf  {
113 113
        send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf"
......
192 192
    end
193 193
  end
194 194

  
195
  def issue_tab
196
    return render_error :status => 422 unless request.xhr?
197
    tab = params[:name]
198

  
199
    case tab
200
    when 'time_entries'
201
      @time_entries = @issue.time_entries.visible.preload(:activity, :user).to_a
202
      render :partial => 'issues/tabs/time_entries', :locals => {:time_entries => @time_entries}
203
    when 'changesets'
204
      @changesets = @issue.changesets.visible.preload(:repository, :user).to_a
205
      changesets.reverse! if User.current.wants_comments_in_reverse_order?
206
      render :partial => 'issues/tabs/changesets', :locals => {:changesets => @changesets}
207
    end
208
  end
209

  
195 210
  # Bulk edit/copy a set of issues
196 211
  def bulk_edit
197 212
    @issues.sort!
app/helpers/issues_helper.rb
554 554
      tabs << {:name => 'notes', :label => :label_issue_history_notes, :onclick => 'showIssueHistory("notes", this.href)'} if journals_with_notes.any?
555 555
      tabs << {:name => 'properties', :label => :label_issue_history_properties, :onclick => 'showIssueHistory("properties", this.href)'} if journals_without_notes.any?
556 556
    end
557
    tabs << {:name => 'time_entries', :label => :label_time_entry_plural, :partial => 'issues/tabs/time_entries', :locals => {:time_entries => @time_entries}} if User.current.allowed_to?(:view_time_entries, @project) && @issue.spent_hours > 0
558
    tabs << {:name => 'changesets', :label => :label_associated_revisions, :partial => 'issues/tabs/changesets', :locals => {:changesets => @changesets}} if @changesets.present?
557
    tabs << {:name => 'time_entries', :label => :label_time_entry_plural, :remote => true, :onclick => "getRemoteTab('time_entries', '#{tab_issue_path(@issue, :name => 'time_entries')}', '#{issue_path(@issue, :tab => 'time_entries')}')"} if User.current.allowed_to?(:view_time_entries, @project) && @issue.spent_hours > 0
558
    tabs << {:name => 'changesets', :label => :label_associated_revisions, :remote => true, :onclick => "getRemoteTab('changesets', '#{tab_issue_path(@issue, :name => 'changesets')}', '#{issue_path(@issue, :tab => 'changesets')}')"} if @has_changesets
559 559
    tabs
560 560
  end
561

  
561 562
end
app/views/common/_tabs.html.erb
18 18
</div>
19 19

  
20 20
<% tabs.each do |tab| -%>
21
  <%= content_tag('div', render(:partial => tab[:partial], :locals => {:tab => tab} ),
21
  <%= content_tag('div', (render(:partial => tab[:partial], :locals => {:tab => tab}) if tab[:partial]) ,
22 22
                       :id => "tab-content-#{tab[:name]}",
23 23
                       :style => (tab[:name] != selected_tab ? 'display:none' : nil),
24
                       :class => 'tab-content') if tab[:partial] %>
24
                       :class => 'tab-content') if tab[:partial] || tab[:remote] %>
25 25
<% end -%>
26 26

  
27 27
<%= javascript_tag default_action if default_action %>
app/views/issues/_changesets.html.erb
1
<% changesets.each do |changeset| %>
2
    <div class="changeset">
3
    <p><%= link_to_revision(changeset, changeset.repository,
4
                            :text => "#{l(:label_revision)} #{changeset.format_identifier}") %>
5
        <% if changeset.filechanges.any? && User.current.allowed_to?(:browse_repository, changeset.project) %>
6
        (<%= link_to(l(:label_diff),
7
               :controller => 'repositories',
8
               :action => 'diff',
9
               :id     => changeset.project,
10
               :repository_id => changeset.repository.identifier_param,
11
               :path   => "",
12
               :rev    => changeset.identifier) %>)
13
        <% end %>
14
        <br />
15
        <span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
16
    <div class="wiki changeset-comments">
17
        <%= format_changeset_comments changeset %>
18
    </div>
19
    </div>
20
<% end %>
app/views/issues/tabs/_changesets.html.erb
1
<% tab[:locals][:changesets].each do |changeset| %>
1
<% @changesets.each do |changeset| %>
2 2
  <div id="changeset-<%= changeset.id %>" class="changeset journal">
3 3
    <h4>
4 4
      <%= avatar(changeset.user, :size => "24") %>
app/views/issues/tabs/_time_entries.html.erb
1
<% for time_entry in tab[:locals][:time_entries] %>
1
<% for time_entry in time_entries%>
2 2
  <div id="time-entry-<%= time_entry.id %>" class="time_entry journal">
3 3
    <% if time_entry.editable_by?(User.current) -%>
4 4
      <div class="contextual">
config/routes.rb
184 184
    member do
185 185
      # Used when updating the form of an existing issue
186 186
      patch 'edit', :to => 'issues#edit'
187
      get 'tab/:name', :action => 'issue_tab', :as => 'tab'
187 188
    end
188 189
    collection do
189 190
      match 'bulk_edit', :via => [:get, :post]
lib/redmine.rb
90 90

  
91 91
  map.project_module :issue_tracking do |map|
92 92
    # Issues
93
    map.permission :view_issues, {:issues => [:index, :show],
93
    map.permission :view_issues, {:issues => [:index, :show, :issue_tab],
94 94
                                  :auto_complete => [:issues],
95 95
                                  :context_menus => [:issues],
96 96
                                  :versions => [:index, :show, :status_by],
public/javascripts/application.js
377 377
  return false;
378 378
}
379 379

  
380
function getRemoteTab(name, remote_url, url) {
381
  $('#tab-content-' + name).parent().find('.tab-content').hide();
382
  $('#tab-content-' + name).parent().find('div.tabs a').removeClass('selected');
383
  $('#tab-' + name).addClass('selected')
384

  
385
  replaceInHistory(url)
386

  
387
  $.ajax({
388
    url: remote_url,
389
    type: 'get',
390
    success: function(data){
391
      $('#tab-content-' + name).html(data).show();
392
    }
393
  });
394

  
395
  return false;
396
}
397

  
380 398
//replaces current URL with the "href" attribute of the current link
381 399
//(only triggered if supported by browser)
382 400
function replaceInHistory(url) {
test/functional/issues_controller_test.rb
2108 2108
    project.disable_module! :repository
2109 2109

  
2110 2110
    @request.session[:user_id] = 2
2111
    get :show, :params => {
2112
        :id => issue.id
2113
      }
2111
    get :issue_tab, :params => {
2112
        :id => issue.id,
2113
        :name => 'changesets'
2114
      },
2115
      :xhr => true
2114 2116

  
2115 2117
    assert_select 'a[href=?]', '/projects/ecookbook/repository/10/revisions/3'
2116 2118
  end
......
2503 2505
      assert_select 'div.tabs a[id=?]', 'tab-time_entries', :text => 'Spent time'
2504 2506
    end
2505 2507

  
2508
    get :issue_tab, :params => {
2509
        :id => 3,
2510
        :name => 'time_entries'
2511
      },
2512
      :xhr => true
2513
    assert_response :success
2514

  
2506 2515
    assert_select 'div[id=?]', 'time-entry-3' do
2507 2516
      assert_select 'a[title=?][href=?]', 'Edit', '/time_entries/3/edit'
2508 2517
      assert_select 'a[title=?][href=?]', 'Delete', '/time_entries/3'
test/integration/routing/issues_test.rb
33 33
    should_route 'GET /issues/64/edit' => 'issues#edit', :id => '64'
34 34
    should_route 'PUT /issues/64' => 'issues#update', :id => '64'
35 35
    should_route 'DELETE /issues/64' => 'issues#destroy', :id => '64'
36

  
37
    should_route "GET /issues/3/tab/time_entries" => 'issues#issue_tab', :id => '3', :name => 'time_entries'
36 38
  end
37 39

  
38 40
  def test_issues_bulk_edit
(20-20/28)