Commit 946a0f4a authored by jplang's avatar jplang

Load changesets and time entries tabs async (#3058).

Patch by Marius BALTEANU.

git-svn-id: https://svn.redmine.org/redmine/trunk@18275 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent e212ef87
......@@ -20,7 +20,7 @@
class IssuesController < ApplicationController
default_search_scope :issues
before_action :find_issue, :only => [:show, :edit, :update]
before_action :find_issue, :only => [:show, :edit, :update, :issue_tab]
before_action :find_issues, :only => [:bulk_edit, :bulk_update, :destroy]
before_action :authorize, :except => [:index, :new, :create]
before_action :find_optional_project, :only => [:index, :new, :create]
......@@ -86,13 +86,10 @@ class IssuesController < ApplicationController
def show
@journals = @issue.visible_journals_with_index
@changesets = @issue.changesets.visible.preload(:repository, :user).to_a
@has_changesets = @issue.changesets.visible.preload(:repository, :user).exists?
@relations = @issue.relations.select {|r| r.other_issue(@issue) && r.other_issue(@issue).visible? }
if User.current.wants_comments_in_reverse_order?
@journals.reverse!
@changesets.reverse!
end
@journals.reverse! if User.current.wants_comments_in_reverse_order?
if User.current.allowed_to?(:view_time_entries, @project)
Issue.load_visible_spent_hours([@issue])
......@@ -109,7 +106,10 @@ class IssuesController < ApplicationController
retrieve_previous_and_next_issue_ids
render :template => 'issues/show'
}
format.api
format.api {
@changesets = @issue.changesets.visible.preload(:repository, :user).to_a
@changesets.reverse! if User.current.wants_comments_in_reverse_order?
}
format.atom { render :template => 'journals/index', :layout => false, :content_type => 'application/atom+xml' }
format.pdf {
send_file_headers! :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf"
......@@ -194,6 +194,21 @@ class IssuesController < ApplicationController
end
end
def issue_tab
return render_error :status => 422 unless request.xhr?
tab = params[:name]
case tab
when 'time_entries'
@time_entries = @issue.time_entries.visible.preload(:activity, :user).to_a
render :partial => 'issues/tabs/time_entries', :locals => {:time_entries => @time_entries}
when 'changesets'
@changesets = @issue.changesets.visible.preload(:repository, :user).to_a
changesets.reverse! if User.current.wants_comments_in_reverse_order?
render :partial => 'issues/tabs/changesets', :locals => {:changesets => @changesets}
end
end
# Bulk edit/copy a set of issues
def bulk_edit
@issues.sort!
......
......@@ -557,8 +557,9 @@ module IssuesHelper
tabs << {:name => 'notes', :label => :label_issue_history_notes, :onclick => 'showIssueHistory("notes", this.href)'} if journals_with_notes.any?
tabs << {:name => 'properties', :label => :label_issue_history_properties, :onclick => 'showIssueHistory("properties", this.href)'} if journals_without_notes.any?
end
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
tabs << {:name => 'changesets', :label => :label_associated_revisions, :partial => 'issues/tabs/changesets', :locals => {:changesets => @changesets}} if @changesets.present?
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
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
tabs
end
end
......@@ -18,10 +18,10 @@
</div>
<% tabs.each do |tab| -%>
<%= content_tag('div', render(:partial => tab[:partial], :locals => {:tab => tab} ),
<%= content_tag('div', (render(:partial => tab[:partial], :locals => {:tab => tab}) if tab[:partial]) ,
:id => "tab-content-#{tab[:name]}",
:style => (tab[:name] != selected_tab ? 'display:none' : nil),
:class => 'tab-content') if tab[:partial] %>
:class => 'tab-content') if tab[:partial] || tab[:remote] %>
<% end -%>
<%= javascript_tag default_action if default_action %>
<% changesets.each do |changeset| %>
<div class="changeset">
<p><%= link_to_revision(changeset, changeset.repository,
:text => "#{l(:label_revision)} #{changeset.format_identifier}") %>
<% if changeset.filechanges.any? && User.current.allowed_to?(:browse_repository, changeset.project) %>
(<%= link_to(l(:label_diff),
:controller => 'repositories',
:action => 'diff',
:id => changeset.project,
:repository_id => changeset.repository.identifier_param,
:path => "",
:rev => changeset.identifier) %>)
<% end %>
<br />
<span class="author"><%= authoring(changeset.committed_on, changeset.author) %></span></p>
<div class="wiki changeset-comments">
<%= format_changeset_comments changeset %>
</div>
</div>
<% end %>
<% tab[:locals][:changesets].each do |changeset| %>
<% @changesets.each do |changeset| %>
<div id="changeset-<%= changeset.id %>" class="changeset journal">
<h4>
<%= avatar(changeset.user, :size => "24") %>
......
<% for time_entry in tab[:locals][:time_entries] %>
<% for time_entry in time_entries%>
<div id="time-entry-<%= time_entry.id %>" class="time_entry journal">
<% if time_entry.editable_by?(User.current) -%>
<div class="contextual">
......
......@@ -188,6 +188,7 @@ Rails.application.routes.draw do
member do
# Used when updating the form of an existing issue
patch 'edit', :to => 'issues#edit'
get 'tab/:name', :action => 'issue_tab', :as => 'tab'
end
collection do
match 'bulk_edit', :via => [:get, :post]
......
......@@ -94,7 +94,7 @@ Redmine::AccessControl.map do |map|
map.project_module :issue_tracking do |map|
# Issues
map.permission :view_issues, {:issues => [:index, :show],
map.permission :view_issues, {:issues => [:index, :show, :issue_tab],
:auto_complete => [:issues],
:context_menus => [:issues],
:versions => [:index, :show, :status_by],
......
......@@ -385,6 +385,24 @@ function showIssueHistory(journal, url) {
return false;
}
function getRemoteTab(name, remote_url, url) {
$('#tab-content-' + name).parent().find('.tab-content').hide();
$('#tab-content-' + name).parent().find('div.tabs a').removeClass('selected');
$('#tab-' + name).addClass('selected')
replaceInHistory(url)
$.ajax({
url: remote_url,
type: 'get',
success: function(data){
$('#tab-content-' + name).html(data).show();
}
});
return false;
}
//replaces current URL with the "href" attribute of the current link
//(only triggered if supported by browser)
function replaceInHistory(url) {
......
......@@ -2168,9 +2168,11 @@ class IssuesControllerTest < Redmine::ControllerTest
project.disable_module! :repository
@request.session[:user_id] = 2
get :show, :params => {
:id => issue.id
}
get :issue_tab, :params => {
:id => issue.id,
:name => 'changesets'
},
:xhr => true
assert_select 'a[href=?]', '/projects/ecookbook/repository/10/revisions/3'
end
......@@ -2560,6 +2562,13 @@ class IssuesControllerTest < Redmine::ControllerTest
assert_select 'div.tabs a[id=?]', 'tab-time_entries', :text => 'Spent time'
end
get :issue_tab, :params => {
:id => 3,
:name => 'time_entries'
},
:xhr => true
assert_response :success
assert_select 'div[id=?]', 'time-entry-3' do
assert_select 'a[title=?][href=?]', 'Edit', '/time_entries/3/edit'
assert_select 'a[title=?][href=?]', 'Delete', '/time_entries/3'
......
......@@ -35,6 +35,8 @@ class RoutingIssuesTest < Redmine::RoutingTest
should_route 'GET /issues/64/edit' => 'issues#edit', :id => '64'
should_route 'PUT /issues/64' => 'issues#update', :id => '64'
should_route 'DELETE /issues/64' => 'issues#destroy', :id => '64'
should_route "GET /issues/3/tab/time_entries" => 'issues#issue_tab', :id => '3', :name => 'time_entries'
end
def test_issues_bulk_edit
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment