From 6dd0f51dbda4e856fc833c7c45426a657c7d5eab Mon Sep 17 00:00:00 2001 From: bsag Date: Sun, 26 Feb 2006 11:36:25 +0000 Subject: [PATCH] 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 --- tracks/app/controllers/feed_controller.rb | 79 ++++++++++++++++--- tracks/app/controllers/todo_controller.rb | 5 ++ tracks/app/helpers/feed_helper.rb | 12 ++- tracks/app/helpers/todo_helper.rb | 13 +++ tracks/app/models/user.rb | 2 +- tracks/app/views/feed/na_text.rhtml | 6 -- .../app/views/feed/{na_feed.rxml => rss.rxml} | 9 ++- tracks/app/views/feed/text.rhtml | 5 ++ tracks/app/views/layouts/standard.rhtml | 3 +- tracks/app/views/todo/feeds.rhtml | 67 ++++++++++++++++ tracks/config/routes.rb | 2 +- tracks/doc/CHANGELOG | 2 + tracks/public/stylesheets/standard.css | 36 ++++++++- 13 files changed, 209 insertions(+), 32 deletions(-) delete mode 100644 tracks/app/views/feed/na_text.rhtml rename tracks/app/views/feed/{na_feed.rxml => rss.rxml} (74%) create mode 100644 tracks/app/views/feed/text.rhtml create mode 100644 tracks/app/views/todo/feeds.rhtml diff --git a/tracks/app/controllers/feed_controller.rb b/tracks/app/controllers/feed_controller.rb index 1f6bec1d..f4d511d4 100644 --- a/tracks/app/controllers/feed_controller.rb +++ b/tracks/app/controllers/feed_controller.rb @@ -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 diff --git a/tracks/app/controllers/todo_controller.rb b/tracks/app/controllers/todo_controller.rb index 8e7269c0..fea42763 100644 --- a/tracks/app/controllers/todo_controller.rb +++ b/tracks/app/controllers/todo_controller.rb @@ -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 diff --git a/tracks/app/helpers/feed_helper.rb b/tracks/app/helpers/feed_helper.rb index 28de48e1..263ff2f5 100644 --- a/tracks/app/helpers/feed_helper.rb +++ b/tracks/app/helpers/feed_helper.rb @@ -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 diff --git a/tracks/app/helpers/todo_helper.rb b/tracks/app/helpers/todo_helper.rb index 4dc72976..2ab9c19f 100644 --- a/tracks/app/helpers/todo_helper.rb +++ b/tracks/app/helpers/todo_helper.rb @@ -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('TXT', linkoptions, :title => "Plain text feed" ) + end + end diff --git a/tracks/app/models/user.rb b/tracks/app/models/user.rb index aa3b059c..7db65399 100644 --- a/tracks/app/models/user.rb +++ b/tracks/app/models/user.rb @@ -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 diff --git a/tracks/app/views/feed/na_text.rhtml b/tracks/app/views/feed/na_text.rhtml deleted file mode 100644 index d02dd48e..00000000 --- a/tracks/app/views/feed/na_text.rhtml +++ /dev/null @@ -1,6 +0,0 @@ -<% -for @context in @contexts - @not_done = @context.find_not_done_todos --%> - <%= build_text_page( @not_done, @context ) %> -<% end -%> diff --git a/tracks/app/views/feed/na_feed.rxml b/tracks/app/views/feed/rss.rxml similarity index 74% rename from tracks/app/views/feed/na_feed.rxml rename to tracks/app/views/feed/rss.rxml index 4772b5f0..edf21681 100644 --- a/tracks/app/views/feed/na_feed.rxml +++ b/tracks/app/views/feed/rss.rxml @@ -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 = "
Due: #{format_date(i.due)}
\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 "none" end - xml.description("#{item_notes||''}\n
Project: #{project_link}
\n
Context: #{context_link}
") + xml.description("#{due||''}#{item_notes||''}\n
Project: #{project_link}
\n
Context: #{context_link}
") end } end diff --git a/tracks/app/views/feed/text.rhtml b/tracks/app/views/feed/text.rhtml new file mode 100644 index 00000000..f19c0f57 --- /dev/null +++ b/tracks/app/views/feed/text.rhtml @@ -0,0 +1,5 @@ +<% +for @context in @contexts +-%> + <%= build_text_page( @todos, @context ) %> +<% end -%> diff --git a/tracks/app/views/layouts/standard.rhtml b/tracks/app/views/layouts/standard.rhtml index 13ce47e8..52169707 100644 --- a/tracks/app/views/layouts/standard.rhtml +++ b/tracks/app/views/layouts/standard.rhtml @@ -35,8 +35,7 @@
  • <%= link_to( "Preferences", {:controller => "user", :action => "preferences"}, :title => "Show my preferences" ) %>
  • Show
  • Hide
  • -
  • <%= 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" ) %>
  • -
  • <%= link_to("TXT", {:controller => "feed", :action => "na_text", :name => "#{@session['user']['login']}", :token => "#{@session['user']['word']}"}, :title => "View a plain text feed of your next actions" ) %>
  • +
  • <%= link_to(image_tag("feed-icon", :size => "16X16", :border => 0), {:controller => "todo", :action => "feeds"}, :title => "See a list of available feeds" ) %>
  • <%= link_to "Logout (#{@session['user']['login']}) »", :controller => "login", :action=>"logout"%>
  • diff --git a/tracks/app/views/todo/feeds.rhtml b/tracks/app/views/todo/feeds.rhtml new file mode 100644 index 00000000..9ecb0744 --- /dev/null +++ b/tracks/app/views/todo/feeds.rhtml @@ -0,0 +1,67 @@ +
    + + <% for name in ["notice", "warning", "message"] %> + <% if flash[name] %> + <%= "
    #{flash[name]}
    " %> + <% end %> + <% end %> + +
    +
    +

    Legend:

    +
    +
    <%= image_tag("feed-icon", :size => "16X16", :border => 0)%>
    RSS Feed
    +
    TXT
    Plain Text Feed
    +
    +

    Note: All feeds show only actions that have not been marked as done.

    +
    +
      +
    • + <%= rss_feed_link({ :limit => 15 }) %> + <%= text_feed_link({ :limit => 15 }) %> + Last 15 actions +
    • +
    • + <%= rss_feed_link %> + <%= text_feed_link %> + All actions +
    • +
    • + <%= rss_feed_link({ :due => 0 }) %> + <%= text_feed_link({ :due => 0 }) %> + Actions due today or earlier +
    • +
    • + <%= rss_feed_link({ :due => 6 }) %> + <%= text_feed_link({ :due => 6 }) %> + Actions due in 7 days or earlier +
    • +
    • Feeds for uncompleted actions in a specific context:

      +
        + <% for context in @contexts %> +
      • + <%= rss_feed_link({ :context => context }) %> + <%= text_feed_link({ :context => context }) %> + Next actions in <%=h context.name %> +
      • + <% end %> +
      +
    • +
    • Feeds for uncompleted actions in a specific project:

      +
        + <% for project in @projects %> +
      • + <%= rss_feed_link({ :project => project }) %> + <%= text_feed_link({ :project => project }) %> + Next actions for <%=h project.name %> +
      • + <% end %> +
      +
    • +
    +
    +
    + +
    + <%= render "shared/sidebar" %> +
    \ No newline at end of file diff --git a/tracks/config/routes.rb b/tracks/config/routes.rb index aabc08a5..ceaf1289 100644 --- a/tracks/config/routes.rb +++ b/tracks/config/routes.rb @@ -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' diff --git a/tracks/doc/CHANGELOG b/tracks/doc/CHANGELOG index ff587b55..883f082c 100644 --- a/tracks/doc/CHANGELOG +++ b/tracks/doc/CHANGELOG @@ -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 http://0.0.0.0:3000/user/preferences 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 diff --git a/tracks/public/stylesheets/standard.css b/tracks/public/stylesheets/standard.css index 646b5762..88f5dac4 100644 --- a/tracks/public/stylesheets/standard.css +++ b/tracks/public/stylesheets/standard.css @@ -579,4 +579,38 @@ div.message { list-style: disc; } -ul#prefs {list-style-type: disc; margin-left: 5px;} \ No newline at end of file +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; +} \ No newline at end of file