Added Luke's excellent changes to the feeds (#214). There are now loads of choices for feeds (including ones for individual contexts or projects and for actions due today or in the next 7 days). The list is accessed via the feed icon in the main navigation.

Thanks, Luke!



git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@193 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
bsag 2006-02-26 11:36:25 +00:00
parent aa0760f0ef
commit 6dd0f51dbd
13 changed files with 209 additions and 32 deletions

View file

@ -11,25 +11,84 @@ class FeedController < ApplicationController
def index
end
# Builds an RSS feed for the latest 15 items
# This is fairly basic: it lists the action description as the title
# and the item context as the description
#
def na_feed
@not_done = @user.todos.collect { |x| x.done? ? nil:x }.compact.sort! {|x,y| y.created_at <=> x.created_at }
# Build an RSS feed
def rss
conditions = '(done = 0)'
options = {:conditions => conditions}
limit = @params['limit']
options[:limit] = limit if limit
@description = limit ? "Lists the last #{limit} uncompleted next actions" : "Lists uncompleted next actions"
@title = "Tracks - Next Actions"
if @params['due']
due_within = @params['due'].to_i
due_within_date_s = due_within.days.from_now.strftime("%Y-%m-%d")
conditions << " AND (due <= '#{due_within_date_s}')"
@title << " due today" if (due_within == 0)
@title << " due within a week" if (due_within == 6)
@description << " with a due date #{due_within_date_s} or earlier"
end
context_id = @params['context']
if context_id
conditions << " AND (context_id = #{context_id})"
context = @user.contexts.find(context_id)
@title << " in #{context.name}"
@description << " in context '#{context.name}'"
end
project_id = @params['project']
if project_id
conditions << " AND (project_id = #{project_id})"
project = @user.projects.find(project_id)
@title << " for #{project.name}"
@description << " for project '#{project.name}'"
end
@todos = @user.todos.find_all_by_done(false, options )
@headers["Content-Type"] = "text/xml; charset=utf-8"
end
# Builds a plain text page listing all the next actions,
# sorted by context (contexts are sorted by position, as on the home page).
# Builds a plain text page listing uncompleted next actions,
# grouped by context (contexts are sorted by position, as on the home page).
# Showing notes doesn't make much sense here so they are omitted.
# Hidden contexts are also hidden in the text view
# You can use this with GeekTool to get your next actions
# on the desktop:
# curl [url from "TXT" link on todo/list]
#
def na_text
@contexts = @user.contexts.collect { |x| x.hide? ? nil:x }.compact.sort! { |x,y| x.position <=> y.position }
def text
conditions = '(done = 0)'
options = {:conditions => conditions}
limit = @params['limit']
options[:limit] = limit if limit
if @params['due']
due_within = @params['due'].to_i
due_within_date_s = due_within.days.from_now.strftime("%Y-%m-%d")
conditions << " AND (due <= '#{due_within_date_s}')"
end
context_id = @params['context']
if context_id
conditions << " AND (context_id = #{context_id})"
context = @user.contexts.find(context_id)
@contexts = [context]
end
project_id = @params['project']
if project_id
conditions << " AND (project_id = #{project_id})"
project = @user.projects.find(project_id)
end
@todos = @user.todos.find_all_by_done(false, options )
if (!@contexts)
@contexts = @user.contexts.find_all_by_hide(false)
end
@headers["Content-Type"] = "text/plain; charset=utf-8"
end

View file

@ -189,6 +189,11 @@ class TodoController < ApplicationController
archive_date = Time.now - 32 * (60 * 60 * 24)
@done_archive = @done.collect { |x| archive_date >= x.completed ? x:nil }.compact
end
def feeds
self.init
@page_title = "TRACKS::Feeds"
end
protected

View file

@ -7,11 +7,10 @@ module FeedHelper
#
def build_text_page(list,context)
result_string = ""
result_string << "\n" + context.name.upcase + ":\n"
list.each do |item|
list.each do |item|
if item.context_id == context.id
result_string << "\n" + context.name.upcase + ":\n" if result_string.empty?
if item.due
result_string << " [" + format_date(item.due) + "] "
result_string << item.description + " "
@ -22,10 +21,9 @@ module FeedHelper
if item.project_id
result_string << "(" + item.project.name + ")"
end
result_string << "\n"
end
result_string << "\n"
end
end
return result_string
end

View file

@ -110,4 +110,17 @@ module TodoHelper
javascript_tag str
end
def rss_feed_link(options = {})
image_tag = image_tag("feed-icon", :size => "16X16", :border => 0, :class => "rss-icon")
linkoptions = {:controller => 'feed', :action => 'rss', :name => "#{@session['user']['login']}", :token => "#{@session['user']['word']}"}
linkoptions.merge!(options)
link_to(image_tag, linkoptions, :title => "RSS feed")
end
def text_feed_link(options = {})
linkoptions = {:controller => 'feed', :action => 'text', :name => "#{@session['user']['login']}", :token => "#{@session['user']['word']}"}
linkoptions.merge!(options)
link_to('<span class="feed">TXT</span>', linkoptions, :title => "Plain text feed" )
end
end

View file

@ -4,7 +4,7 @@ require 'digest/sha1'
class User < ActiveRecord::Base
has_many :contexts, :order => "position ASC"
has_many :projects, :order => "position ASC"
has_many :todos, :order => "completed DESC"
has_many :todos, :order => "completed DESC, created_at DESC"
has_many :notes, :order => "created_at DESC"
serialize :preferences

View file

@ -1,6 +0,0 @@
<%
for @context in @contexts
@not_done = @context.find_not_done_todos
-%>
<%= build_text_page( @not_done, @context ) %>
<% end -%>

View file

@ -1,20 +1,21 @@
xml.rss("version" => "2.0", "xmlns:dc" => "http://purl.org/dc/elements/1.1/") do
xml.channel do
xml.title("Tracks - Next Actions")
xml.title(@title)
xml.link("http://#{@request.host}:#{@request.port}/todo/list")
xml.description("Lists the last 15 uncompleted next actions")
@not_done.each { |i|
xml.description(@description)
@todos.each { |i|
xml.item do
xml.title(i.description)
xml.link(url_for(:only_path => false, :controller => 'context', :action => 'show', :name => urlize(i.context.name)))
item_notes = sanitize(markdown( i.notes )) if i.notes?
due = "<div>Due: #{format_date(i.due)}</div>\n" if i.due?
context_link = link_to( i.context.name, { :only_path => false, :controller => "context", :action => "show", :name => urlize(i.context.name) } )
project_link = if i.project_id?
link_to (i.project.name, { :only_path => false, :controller => "project", :action => "show", :name => urlize(i.project.name)} )
else
"<em>none</em>"
end
xml.description("#{item_notes||''}\n<div>Project: #{project_link}</div>\n<div>Context: #{context_link}</div>")
xml.description("#{due||''}#{item_notes||''}\n<div>Project: #{project_link}</div>\n<div>Context: #{context_link}</div>")
end
}
end

View file

@ -0,0 +1,5 @@
<%
for @context in @contexts
-%>
<%= build_text_page( @todos, @context ) %>
<% end -%>

View file

@ -35,8 +35,7 @@
<li><%= link_to( "Preferences", {:controller => "user", :action => "preferences"}, :title => "Show my preferences" ) %></li>
<li><a href="javascript:toggleAll('notes','block')" accesskey="S" title="Show all notes">Show</a></li>
<li><a href="javascript:toggleAll('notes','none')" accesskey="H" title="Hide all notes">Hide</a></li>
<li><%= link_to(image_tag("feed-icon", :size => "16X16", :border => 0), {:controller => "feed", :action => "na_feed", :name => "#{@session['user']['login']}", :token => "#{@session['user']['word']}"}, :title => "Subscribe to an RSS feed of your next actions" ) %></li>
<li><%= link_to("<span class=\"feed\">TXT</span>", {:controller => "feed", :action => "na_text", :name => "#{@session['user']['login']}", :token => "#{@session['user']['word']}"}, :title => "View a plain text feed of your next actions" ) %></li>
<li><%= link_to(image_tag("feed-icon", :size => "16X16", :border => 0), {:controller => "todo", :action => "feeds"}, :title => "See a list of available feeds" ) %></li>
<li><%= link_to "Logout (#{@session['user']['login']}) &#187;", :controller => "login", :action=>"logout"%></li>
</ul>
</div>

View file

@ -0,0 +1,67 @@
<div id="display_box">
<% for name in ["notice", "warning", "message"] %>
<% if flash[name] %>
<%= "<div id=\"#{name}\">#{flash[name]}</div>" %>
<% end %>
<% end %>
<div id="feeds">
<div id="feedlegend">
<h3>Legend:</h3>
<dl>
<dt><%= image_tag("feed-icon", :size => "16X16", :border => 0)%></dt><dd>RSS Feed</dd>
<dt><span class="feed">TXT</span></dt><dd>Plain Text Feed</dd>
</dl>
<p>Note: All feeds show only actions that have not been marked as done.</p>
</div>
<ul>
<li>
<%= rss_feed_link({ :limit => 15 }) %>
<%= text_feed_link({ :limit => 15 }) %>
Last 15 actions
</li>
<li>
<%= rss_feed_link %>
<%= text_feed_link %>
All actions
</li>
<li>
<%= rss_feed_link({ :due => 0 }) %>
<%= text_feed_link({ :due => 0 }) %>
Actions due today or earlier
</li>
<li>
<%= rss_feed_link({ :due => 6 }) %>
<%= text_feed_link({ :due => 6 }) %>
Actions due in 7 days or earlier
</li>
<li><h4>Feeds for uncompleted actions in a specific context:</h4>
<ul>
<% for context in @contexts %>
<li>
<%= rss_feed_link({ :context => context }) %>
<%= text_feed_link({ :context => context }) %>
Next actions in <strong><%=h context.name %></strong>
</li>
<% end %>
</ul>
</li>
<li><h4>Feeds for uncompleted actions in a specific project:</h4>
<ul>
<% for project in @projects %>
<li>
<%= rss_feed_link({ :project => project }) %>
<%= text_feed_link({ :project => project }) %>
Next actions for <strong><%=h project.name %></strong>
</li>
<% end %>
</ul>
</li>
</ul>
</div>
</div><!-- End of display_box -->
<div id="input_box">
<%= render "shared/sidebar" %>
</div><!-- End of input box -->

View file

@ -50,7 +50,7 @@ ActionController::Routing::Routes.draw do |map|
map.connect 'notes', :controller => 'note', :action => 'index'
# Feed Routes
map.connect 'feed/:action/:name/:user', :controller => 'feed'
map.connect 'feed/:action/:name/:token', :controller => 'feed'
#map.connect 'add_item', :controller => 'todo', :action => 'add_item'

View file

@ -37,6 +37,8 @@ Wiki (deprecated - please use Trac): http://www.rousette.org.uk/projects/wiki/
19. There's a rake task (upgrade_sqlite_db) which allows you to safely upgrade databases created with version 1.03, afterwhich you can run rake migrate to complete the process. From there, rake migrate should work OK.
20. Moved settings for Tracks from the file settings.yml to the database. Running 'rake migrate' will update your database appropriately, and add the default settings into it. Then you should be able to visit <tt>http://0.0.0.0:3000/user/preferences</tt> to view and edit your settings. The advantage is that you don't need to mess about with the settings.yml file, and each of the users can have their own settings.
21. Session data is now stored in the database rather than a file in tracks/tmp. This should prevent the tmp directory cluttering up the file system, and give better performance. You need to run rake migrate to add the session table to your database.
22. You can now change the password for the logged in user (user/preferences)
23. Lots of new text and RSS feeds added by Luke Melia. These are accessed via the feed icon on in the main navigation.
== Version 1.03

View file

@ -579,4 +579,38 @@ div.message {
list-style: disc;
}
ul#prefs {list-style-type: disc; margin-left: 5px;}
ul#prefs {list-style-type: disc; margin-left: 5px;}
#feedlegend {
padding: 2px;
border: 1px solid #CCC;
background-color: #D2D3D6;
color: #666;
padding: 5px 20px;
text-align: left;
}
#feedlegend h3, #feedlegend dl, #feedlegend dt, #feedlegend dd {
display: inline;
}
#feedlegend dt {
margin-left: 15px;
}
#feedlegend dd {
margin-left: 3px;
}
#feedlegend p {
margin-bottom: 0px;
}
#feeds img.rss-icon {
margin-bottom: -4px;
}
#feeds li {
font-size:13px;
font-family: "Lucida Grande", Verdana, Geneva, Arial, sans-serif;
}
#feeds li h4 {
margin-top: 12px;
margin-bottom: 4px;
font-weight: normal;
font-style:oblique;
}