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]
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])
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"
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!
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
</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 %>
+++ /dev/null
-<% 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">
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]
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],
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) {
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
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'
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