Commit 942091f9 authored by Jean-Philippe Lang's avatar Jean-Philippe Lang

Display links to Atom feeds (closes #496, #750).

git-svn-id: http://redmine.rubyforge.org/svn/trunk@1185 e93f8b46-1217-0410-a6f0-8f06a7374b81
parent 8ea2ecb9
...@@ -49,7 +49,13 @@ class IssuesController < ApplicationController ...@@ -49,7 +49,13 @@ class IssuesController < ApplicationController
sort_update sort_update
retrieve_query retrieve_query
if @query.valid? if @query.valid?
limit = %w(pdf csv).include?(params[:format]) ? Setting.issues_export_limit.to_i : per_page_option limit = per_page_option
respond_to do |format|
format.html { }
format.atom { }
format.csv { limit = Setting.issues_export_limit.to_i }
format.pdf { limit = Setting.issues_export_limit.to_i }
end
@issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement) @issue_count = Issue.count(:include => [:status, :project], :conditions => @query.statement)
@issue_pages = Paginator.new self, @issue_count, limit, params['page'] @issue_pages = Paginator.new self, @issue_count, limit, params['page']
@issues = Issue.find :all, :order => sort_clause, @issues = Issue.find :all, :order => sort_clause,
...@@ -74,7 +80,7 @@ class IssuesController < ApplicationController ...@@ -74,7 +80,7 @@ class IssuesController < ApplicationController
sort_update sort_update
retrieve_query retrieve_query
if @query.valid? if @query.valid?
@changes = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ], @journals = Journal.find :all, :include => [ :details, :user, {:issue => [:project, :author, :tracker, :status]} ],
:conditions => @query.statement, :conditions => @query.statement,
:limit => 25, :limit => 25,
:order => "#{Journal.table_name}.created_on DESC" :order => "#{Journal.table_name}.created_on DESC"
...@@ -92,6 +98,7 @@ class IssuesController < ApplicationController ...@@ -92,6 +98,7 @@ class IssuesController < ApplicationController
@priorities = Enumeration::get_values('IPRI') @priorities = Enumeration::get_values('IPRI')
respond_to do |format| respond_to do |format|
format.html { render :template => 'issues/show.rhtml' } format.html { render :template => 'issues/show.rhtml' }
format.atom { render :action => 'changes', :layout => false, :content_type => 'application/atom+xml' }
format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") } format.pdf { send_data(render(:template => 'issues/show.rfpdf', :layout => false), :type => 'application/pdf', :filename => "#{@project.identifier}-#{@issue.id}.pdf") }
end end
end end
......
...@@ -11,7 +11,7 @@ ...@@ -11,7 +11,7 @@
<tbody> <tbody>
<% issues.each do |issue| -%> <% issues.each do |issue| -%>
<tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>"> <tr id="issue-<%= issue.id %>" class="issue hascontextmenu <%= cycle('odd', 'even') %> <%= "status-#{issue.status.position} priority-#{issue.priority.position}" %>">
<td class="checkbox"><%= check_box_tag("ids[]", issue.id, false) %></td> <td class="checkbox"><%= check_box_tag("ids[]", issue.id, false, :id => nil) %></td>
<td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td> <td><%= link_to issue.id, :controller => 'issues', :action => 'show', :id => issue %></td>
<% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %> <% query.columns.each do |column| %><%= content_tag 'td', column_content(column, issue), :class => column.name %><% end %>
</tr> </tr>
......
xml.instruct! xml.instruct!
xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do xml.feed "xmlns" => "http://www.w3.org/2005/Atom" do
xml.title @title xml.title @title
xml.link "rel" => "self", "href" => url_for(:controller => 'feeds', :action => 'history', :format => 'atom', :only_path => false) xml.link "rel" => "self", "href" => url_for(:format => 'atom', :key => User.current.rss_key, :only_path => false)
xml.link "rel" => "alternate", "href" => url_for(:controller => 'welcome', :only_path => false) xml.link "rel" => "alternate", "href" => home_url(:only_path => false)
xml.id url_for(:controller => 'welcome', :only_path => false) xml.id url_for(:controller => 'welcome', :only_path => false)
xml.updated((@changes.first ? @changes.first.event_datetime : Time.now).xmlschema) xml.updated((@journals.first ? @journals.first.event_datetime : Time.now).xmlschema)
xml.author { xml.name "#{Setting.app_title}" } xml.author { xml.name "#{Setting.app_title}" }
@changes.each do |change| @journals.each do |change|
issue = change.issue issue = change.issue
xml.entry do xml.entry do
xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}" xml.title "#{issue.project.name} - #{issue.tracker.name} ##{issue.id}: #{issue.subject}"
......
...@@ -41,12 +41,14 @@ ...@@ -41,12 +41,14 @@
<p class="nodata"><%= l(:label_no_data) %></p> <p class="nodata"><%= l(:label_no_data) %></p>
<% else %> <% else %>
<%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %> <%= render :partial => 'issues/list', :locals => {:issues => @issues, :query => @query} %>
<div class="contextual">
<%= l(:label_export_to) %>
<%= link_to 'CSV', {:format => 'csv'}, :class => 'icon icon-csv' %>,
<%= link_to 'PDF', {:format => 'pdf'}, :class => 'icon icon-pdf' %>
</div>
<p class="pagination"><%= pagination_links_full @issue_pages, @issue_count %></p> <p class="pagination"><%= pagination_links_full @issue_pages, @issue_count %></p>
<p class="other-formats">
<%= l(:label_export_to) %>
<span><%= link_to 'Atom', {:format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
<span><%= link_to 'CSV', {:format => 'csv'}, :class => 'csv' %></span>
<span><%= link_to 'PDF', {:format => 'pdf'}, :class => 'pdf' %></span>
</p>
<% end %> <% end %>
<% end %> <% end %>
......
...@@ -95,13 +95,18 @@ end %> ...@@ -95,13 +95,18 @@ end %>
</div> </div>
<% end %> <% end %>
<div class="contextual"> <p class="other-formats">
<%= l(:label_export_to) %><%= link_to 'PDF', {:format => 'pdf'}, :class => 'icon icon-pdf' %> <%= l(:label_export_to) %>
</div> <span><%= link_to 'Atom', {:format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
&nbsp; <span><%= link_to 'PDF', {:format => 'pdf'}, :class => 'pdf' %></span>
</p>
<% html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %> <% html_title "#{@issue.tracker.name} ##{@issue.id}: #{@issue.subject}" %>
<% content_for :sidebar do %> <% content_for :sidebar do %>
<%= render :partial => 'issues/sidebar' %> <%= render :partial => 'issues/sidebar' %>
<% end %> <% end %>
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, {:format => 'atom', :key => User.current.rss_key}, :title => "#{@issue.project} - #{@issue.tracker} ##{@issue.id}: #{@issue.subject}") %>
<% end %>
...@@ -39,6 +39,11 @@ ...@@ -39,6 +39,11 @@
<% end %> <% end %>
<p class="pagination"><%= pagination_links_full @news_pages %></p> <p class="pagination"><%= pagination_links_full @news_pages %></p>
<p class="other-formats">
<%= l(:label_export_to) %>
<span><%= link_to 'Atom', {:format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
</p>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %> <%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :page => nil, :key => User.current.rss_key})) %>
<% end %> <% end %>
......
...@@ -27,12 +27,15 @@ ...@@ -27,12 +27,15 @@
<% next_params = params.clone.update :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1) %> <% next_params = params.clone.update :year => (@month==12 ? @year+1 : @year), :month =>(@month==12 ? 1 : @month+1) %>
<%= link_to_remote ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' &#187;'), <%= link_to_remote ((@month==12 ? "#{month_name(1)} #{@year+1}" : "#{month_name(@month+1)}") + ' &#187;'),
{:update => "content", :url => next_params}, {:href => url_for(next_params)} %> {:update => "content", :url => next_params}, {:href => url_for(next_params)} %>
&nbsp;
</div> </div>
<br /> &nbsp;
<p class="other-formats">
<%= l(:label_export_to) %>
<%= link_to 'Atom', params.merge(:format => :atom, :key => User.current.rss_key).delete_if{|k,v|k=="commit"}, :class => 'feed' %>
</p>
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, params.merge({:format => 'atom', :year => nil, :month => nil, :key => User.current.rss_key})) %> <%= auto_discovery_link_tag(:atom, params.merge(:format => 'atom', :year => nil, :month => nil, :key => User.current.rss_key).delete_if{|k,v|k=="commit"}) %>
<% end %> <% end %>
<% content_for :sidebar do %> <% content_for :sidebar do %>
......
...@@ -223,10 +223,11 @@ if Date.today >= @date_from and Date.today <= @date_to %> ...@@ -223,10 +223,11 @@ if Date.today >= @date_from and Date.today <= @date_to %>
</tr> </tr>
</table> </table>
<div class="contextual"><%= l(:label_export_to) %> <p class="other-formats">
<%= link_to 'PDF', {:zoom => @zoom, :year => @year_from, :month => @month_from, :months => @months, :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects], :format => 'pdf'}, :class => 'icon icon-pdf' %> <%= l(:label_export_to) %>
<%= link_to 'PNG', {:zoom => @zoom, :year => @year_from, :month => @month_from, :months => @months, :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects], :format => 'png'}, :class => 'icon icon-image' if respond_to?('gantt_image') %> <span><%= link_to 'PDF', {:zoom => @zoom, :year => @year_from, :month => @month_from, :months => @months, :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects], :format => 'pdf'}, :class => 'pdf' %></span>
</div> <%= content_tag('span', link_to('PNG', {:zoom => @zoom, :year => @year_from, :month => @month_from, :months => @months, :tracker_ids => @selected_tracker_ids, :with_subprojects => params[:with_subprojects], :format => 'png'}, :class => 'image')) if respond_to?('gantt_image') %>
</p>
<% content_for :sidebar do %> <% content_for :sidebar do %>
<h3><%= l(:label_gantt) %></h3> <h3><%= l(:label_gantt) %></h3>
......
...@@ -37,11 +37,12 @@ ...@@ -37,11 +37,12 @@
<% unless @entries.empty? %> <% unless @entries.empty? %>
<%= render :partial => 'list', :locals => { :entries => @entries }%> <%= render :partial => 'list', :locals => { :entries => @entries }%>
<div class="contextual">
<%= l(:label_export_to) %>
<%= link_to 'CSV', params.merge(:format => 'csv'), :class => 'icon icon-csv' %>
</div>
<p class="pagination"><%= pagination_links_full @entry_pages, @entry_count %></p> <p class="pagination"><%= pagination_links_full @entry_pages, @entry_count %></p>
<p class="other-formats">
<%= l(:label_export_to) %>
<span><%= link_to 'CSV', params.merge(:format => 'csv'), :class => 'csv' %></span>
</p>
<% end %> <% end %>
<% content_for :header_tags do %> <% content_for :header_tags do %>
......
...@@ -36,12 +36,11 @@ ...@@ -36,12 +36,11 @@
<% end %> <% end %>
<% end %> <% end %>
<div class="contextual"> <p class="other-formats">
<%= l(:label_export_to) %> <%= l(:label_export_to) %>
<%= link_to 'HTML', {:page => @page.title, :export => 'html', :version => @content.version}, :class => 'icon icon-html' %>, <span><%= link_to 'HTML', {:page => @page.title, :export => 'html', :version => @content.version}, :class => 'html' %></span>
<%= link_to 'TXT', {:page => @page.title, :export => 'txt', :version => @content.version}, :class => 'icon icon-txt' %> <span><%= link_to 'TXT', {:page => @page.title, :export => 'txt', :version => @content.version}, :class => 'text' %></span>
</div> </p>
&nbsp;
<% content_for :header_tags do %> <% content_for :header_tags do %>
<%= stylesheet_link_tag 'scm' %> <%= stylesheet_link_tag 'scm' %>
......
...@@ -17,9 +17,14 @@ ...@@ -17,9 +17,14 @@
<%= render :partial => 'sidebar' %> <%= render :partial => 'sidebar' %>
<% end %> <% end %>
<div class="contextual">
<% unless @pages.empty? %> <% unless @pages.empty? %>
<%= l(:label_export_to) %> <%= link_to 'HTML', {:action => 'special', :page => 'export'}, :class => 'icon icon-html' %> <p class="other-formats">
<%= l(:label_export_to) %>
<span><%= link_to 'Atom', {:controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
<span><%= link_to 'HTML', {:action => 'special', :page => 'export'}, :class => 'html' %></span>
</p>
<% end %>
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key) %>
<% end %> <% end %>
</div>
&nbsp;
...@@ -14,9 +14,14 @@ ...@@ -14,9 +14,14 @@
<%= render :partial => 'sidebar' %> <%= render :partial => 'sidebar' %>
<% end %> <% end %>
<div class="contextual">
<% unless @pages.empty? %> <% unless @pages.empty? %>
<%= l(:label_export_to) %> <%= link_to 'HTML', {:action => 'special', :page => 'export'}, :class => 'icon icon-html' %> <p class="other-formats">
<%= l(:label_export_to) %>
<span><%= link_to 'Atom', {:controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key}, :class => 'feed' %></span>
<span><%= link_to 'HTML', {:action => 'special', :page => 'export'} %></span>
</p>
<% end %>
<% content_for :header_tags do %>
<%= auto_discovery_link_tag(:atom, :controller => 'projects', :action => 'activity', :id => @project, :show_wiki_pages => 1, :format => 'atom', :key => User.current.rss_key) %>
<% end %> <% end %>
</div>
&nbsp;
...@@ -320,7 +320,7 @@ label_version: Version ...@@ -320,7 +320,7 @@ label_version: Version
label_version_new: New version label_version_new: New version
label_version_plural: Versions label_version_plural: Versions
label_confirmation: Confirmation label_confirmation: Confirmation
label_export_to: Export to label_export_to: 'Also available in:'
label_read: Read... label_read: Read...
label_public_projects: Public projects label_public_projects: Public projects
label_open_issues: open label_open_issues: open
......
...@@ -320,7 +320,7 @@ label_version: Version ...@@ -320,7 +320,7 @@ label_version: Version
label_version_new: Nouvelle version label_version_new: Nouvelle version
label_version_plural: Versions label_version_plural: Versions
label_confirmation: Confirmation label_confirmation: Confirmation
label_export_to: Exporter en label_export_to: 'Formats disponibles:'
label_read: Lire... label_read: Lire...
label_public_projects: Projets publics label_public_projects: Projets publics
label_open_issues: ouvert label_open_issues: ouvert
......
public/images/feed.png

359 Bytes | W: | H:

public/images/feed.png

524 Bytes | W: | H:

public/images/feed.png
public/images/feed.png
public/images/feed.png
public/images/feed.png
  • 2-up
  • Swipe
  • Onion skin
...@@ -80,7 +80,7 @@ a img{ border: 0; } ...@@ -80,7 +80,7 @@ a img{ border: 0; }
/***** Tables *****/ /***** Tables *****/
table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; } table.list { border: 1px solid #e4e4e4; border-collapse: collapse; width: 100%; margin-bottom: 4px; }
table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; } table.list th { background-color:#EEEEEE; padding: 4px; white-space:nowrap; }
table.list td { overflow: hidden; text-overflow: ellipsis; vertical-align: top;} table.list td { overflow: hidden; vertical-align: top;}
table.list td.id { width: 2%; text-align: center;} table.list td.id { width: 2%; text-align: center;}
table.list td.checkbox { width: 15px; padding: 0px;} table.list td.checkbox { width: 15px; padding: 0px;}
...@@ -228,6 +228,11 @@ div.attachments p { margin:4px 0 2px 0; } ...@@ -228,6 +228,11 @@ div.attachments p { margin:4px 0 2px 0; }
div.attachments img { vertical-align: middle; } div.attachments img { vertical-align: middle; }
div.attachments span.author { font-size: 0.9em; color: #888; } div.attachments span.author { font-size: 0.9em; color: #888; }
p.other-formats { text-align: right; font-size:0.9em; color: #666; }
.other-formats span + span:before { content: "| "; }
a.feed { background: url(../images/feed.png) no-repeat 1px 50%; padding: 2px 0px 3px 16px; }
/***** Flash & error messages ****/ /***** Flash & error messages ****/
#errorExplanation, div.flash, .nodata { #errorExplanation, div.flash, .nodata {
padding: 4px 4px 4px 30px; padding: 4px 4px 4px 30px;
...@@ -275,7 +280,6 @@ padding:0.6em; ...@@ -275,7 +280,6 @@ padding:0.6em;
z-index:100; z-index:100;
filter:alpha(opacity=50); filter:alpha(opacity=50);
opacity: 0.5; opacity: 0.5;
-khtml-opacity: 0.5;
} }
html>body #ajax-indicator { position: fixed; } html>body #ajax-indicator { position: fixed; }
...@@ -518,11 +522,6 @@ vertical-align: middle; ...@@ -518,11 +522,6 @@ vertical-align: middle;
.icon-move { background-image: url(../images/move.png); } .icon-move { background-image: url(../images/move.png); }
.icon-save { background-image: url(../images/save.png); } .icon-save { background-image: url(../images/save.png); }
.icon-cancel { background-image: url(../images/cancel.png); } .icon-cancel { background-image: url(../images/cancel.png); }
.icon-pdf { background-image: url(../images/pdf.png); }
.icon-csv { background-image: url(../images/csv.png); }
.icon-html { background-image: url(../images/html.png); }
.icon-image { background-image: url(../images/image.png); }
.icon-txt { background-image: url(../images/txt.png); }
.icon-file { background-image: url(../images/file.png); } .icon-file { background-image: url(../images/file.png); }
.icon-folder { background-image: url(../images/folder.png); } .icon-folder { background-image: url(../images/folder.png); }
.open .icon-folder { background-image: url(../images/folder_open.png); } .open .icon-folder { background-image: url(../images/folder_open.png); }
...@@ -537,7 +536,6 @@ vertical-align: middle; ...@@ -537,7 +536,6 @@ vertical-align: middle;
.icon-attachment { background-image: url(../images/attachment.png); } .icon-attachment { background-image: url(../images/attachment.png); }
.icon-index { background-image: url(../images/index.png); } .icon-index { background-image: url(../images/index.png); }
.icon-history { background-image: url(../images/history.png); } .icon-history { background-image: url(../images/history.png); }
.icon-feed { background-image: url(../images/feed.png); }
.icon-time { background-image: url(../images/time.png); } .icon-time { background-image: url(../images/time.png); }
.icon-stats { background-image: url(../images/stats.png); } .icon-stats { background-image: url(../images/stats.png); }
.icon-warning { background-image: url(../images/warning.png); } .icon-warning { background-image: url(../images/warning.png); }
......
...@@ -96,7 +96,7 @@ class IssuesControllerTest < Test::Unit::TestCase ...@@ -96,7 +96,7 @@ class IssuesControllerTest < Test::Unit::TestCase
def test_changes def test_changes
get :changes, :project_id => 1 get :changes, :project_id => 1
assert_response :success assert_response :success
assert_not_nil assigns(:changes) assert_not_nil assigns(:journals)
assert_equal 'application/atom+xml', @response.content_type assert_equal 'application/atom+xml', @response.content_type
end end
......
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