Project

General

Profile

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

Marius BĂLTEANU, 2019-06-20 08:19

View differences:

app/controllers/issues_controller.rb
20 20
class IssuesController < ApplicationController
21 21
  default_search_scope :issues
22 22

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

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

  
92
    if User.current.wants_comments_in_reverse_order?
93
      @journals.reverse!
94
      @changesets.reverse!
95
    end
92
    @journals.reverse! if User.current.wants_comments_in_reverse_order?
96 93

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

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

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

  
197 212
  # Bulk edit/copy a set of issues
198 213
  def bulk_edit
199 214
    @issues.sort!
app/helpers/issues_helper.rb
557 557
      tabs << {:name => 'notes', :label => :label_issue_history_notes, :onclick => 'showIssueHistory("notes", this.href)'} if journals_with_notes.any?
558 558
      tabs << {:name => 'properties', :label => :label_issue_history_properties, :onclick => 'showIssueHistory("properties", this.href)'} if journals_without_notes.any?
559 559
    end
560
    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
561
    tabs << {:name => 'changesets', :label => :label_associated_revisions, :partial => 'issues/tabs/changesets', :locals => {:changesets => @changesets}} if @changesets.present?
560
    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
561
    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
562 562
    tabs
563 563
  end
564

  
564 565
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
188 188
    member do
189 189
      # Used when updating the form of an existing issue
190 190
      patch 'edit', :to => 'issues#edit'
191
      get 'tab/:name', :action => 'issue_tab', :as => 'tab'
191 192
    end
192 193
    collection do
193 194
      match 'bulk_edit', :via => [:get, :post]
lib/redmine.rb
94 94

  
95 95
  map.project_module :issue_tracking do |map|
96 96
    # Issues
97
    map.permission :view_issues, {:issues => [:index, :show],
97
    map.permission :view_issues, {:issues => [:index, :show, :issue_tab],
98 98
                                  :auto_complete => [:issues],
99 99
                                  :context_menus => [:issues],
100 100
                                  :versions => [:index, :show, :status_by],
public/javascripts/application.js
385 385
  return false;
386 386
}
387 387

  
388
function getRemoteTab(name, remote_url, url) {
389
  $('#tab-content-' + name).parent().find('.tab-content').hide();
390
  $('#tab-content-' + name).parent().find('div.tabs a').removeClass('selected');
391
  $('#tab-' + name).addClass('selected')
392

  
393
  replaceInHistory(url)
394

  
395
  $.ajax({
396
    url: remote_url,
397
    type: 'get',
398
    success: function(data){
399
      $('#tab-content-' + name).html(data).show();
400
    }
401
  });
402

  
403
  return false;
404
}
405

  
388 406
//replaces current URL with the "href" attribute of the current link
389 407
//(only triggered if supported by browser)
390 408
function replaceInHistory(url) {
test/functional/issues_controller_test.rb
2146 2146
    project.disable_module! :repository
2147 2147

  
2148 2148
    @request.session[:user_id] = 2
2149
    get :show, :params => {
2150
        :id => issue.id
2151
      }
2149
    get :issue_tab, :params => {
2150
        :id => issue.id,
2151
        :name => 'changesets'
2152
      },
2153
      :xhr => true
2152 2154

  
2153 2155
    assert_select 'a[href=?]', '/projects/ecookbook/repository/10/revisions/3'
2154 2156
  end
......
2538 2540
      assert_select 'div.tabs a[id=?]', 'tab-time_entries', :text => 'Spent time'
2539 2541
    end
2540 2542

  
2543
    get :issue_tab, :params => {
2544
        :id => 3,
2545
        :name => 'time_entries'
2546
      },
2547
      :xhr => true
2548
    assert_response :success
2549

  
2541 2550
    assert_select 'div[id=?]', 'time-entry-3' do
2542 2551
      assert_select 'a[title=?][href=?]', 'Edit', '/time_entries/3/edit'
2543 2552
      assert_select 'a[title=?][href=?]', 'Delete', '/time_entries/3'
test/integration/routing/issues_test.rb
35 35
    should_route 'GET /issues/64/edit' => 'issues#edit', :id => '64'
36 36
    should_route 'PUT /issues/64' => 'issues#update', :id => '64'
37 37
    should_route 'DELETE /issues/64' => 'issues#destroy', :id => '64'
38

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

  
40 42
  def test_issues_bulk_edit
(26-26/28)