mirror of
https://github.com/TracksApp/tracks.git
synced 2026-01-31 05:05:18 +01:00
Added the beginnings of a tickler to Tracks. It's fairly rudimentary at the moment, but it's designed to set the foundations for more kinds of deferred tasks.The current system works, but isn't very DRY: it will need refactoring for speed.
It has these features: * The todos table and model has been altered (run rake migrate to update) to create two sub-classes of the todo model: Immediate and Deferred. Fairly obviously, Immediate actions are those shown immediately, and Deferred are those shown when certain conditions are fulfilled. At the moment, this is when the 'show_from' date arrives. * Deferred actions are created on a separate page: /todo/tickler. You can view the show_from date here and delete or edit the actions. Deferred actions don't show on the home page (their handling on project and context pages is still to be fixed). * A periodically called method (every 10 minutes) checks whether any of the deferred actions is due to be show, and if so, a warning message is shown on the home page to tell you how many deferred actions are to be shown. You need to refresh the page to see them (again, this is to be fixed). * When deferred actions become due, their type is changed from "Deferred" to "Immediate". The handling of their staleness is still to be fixed. There's a way to go before it's really smooth, but it's a start. At least partially fixes #270 and #78, but will be improved with time too. git-svn-id: http://www.rousette.org.uk/svn/tracks-repos/trunk@232 a4c988fc-2ded-0310-b66e-134b36920a42
This commit is contained in:
parent
4de6537af8
commit
03ff56d703
24 changed files with 399 additions and 16 deletions
|
|
@ -56,7 +56,7 @@ class TodoController < ApplicationController
|
|||
else
|
||||
@item.due = ""
|
||||
end
|
||||
|
||||
|
||||
@saved = @item.save
|
||||
|
||||
@on_page = "home"
|
||||
|
|
@ -82,6 +82,44 @@ class TodoController < ApplicationController
|
|||
render :action => 'list'
|
||||
end
|
||||
end
|
||||
|
||||
# Adding deferred actions from form on todo/tickler
|
||||
#
|
||||
def add_deferred_item
|
||||
self.init
|
||||
@tickle = Deferred.create(@params["todo"])
|
||||
|
||||
if @tickle.due?
|
||||
@tickle.due = Date.strptime(@params["todo"]["due"], @user.preferences["date_format"])
|
||||
else
|
||||
@tickle.due = ""
|
||||
end
|
||||
|
||||
@saved = @tickle.save
|
||||
|
||||
@on_page = "home"
|
||||
if @saved
|
||||
@up_count = @todos.collect { |x| ( !x.done? and !x.context.hide? ) ? x:nil }.compact.size.to_s
|
||||
end
|
||||
return if request.xhr?
|
||||
|
||||
# fallback for standard requests
|
||||
if @saved
|
||||
flash["notice"] = 'Added new next action.'
|
||||
redirect_to :action => 'tickler'
|
||||
else
|
||||
flash["warning"] = 'The next action was not added. Please try again.'
|
||||
redirect_to :action => 'tickler'
|
||||
end
|
||||
|
||||
rescue
|
||||
if request.xhr? # be sure to include an error.rjs
|
||||
render :action => 'error'
|
||||
else
|
||||
flash["warning"] = 'An error occurred on the server.'
|
||||
render :action => 'tickler'
|
||||
end
|
||||
end
|
||||
|
||||
def edit_action
|
||||
self.init
|
||||
|
|
@ -90,6 +128,13 @@ class TodoController < ApplicationController
|
|||
render :partial => 'action_edit_form', :object => item
|
||||
end
|
||||
|
||||
def edit_deferred_action
|
||||
self.init
|
||||
item = check_user_return_item
|
||||
|
||||
render :partial => 'action_edit_deferred_form', :object => item
|
||||
end
|
||||
|
||||
# Toggles the 'done' status of the action
|
||||
#
|
||||
def toggle_check
|
||||
|
|
@ -133,6 +178,21 @@ class TodoController < ApplicationController
|
|||
@saved = @item.save
|
||||
end
|
||||
|
||||
def deferred_update_action
|
||||
#self.init
|
||||
@tickle = check_user_return_item
|
||||
@original_item_context_id = @tickle.context_id
|
||||
@tickle.attributes = @params["item"]
|
||||
|
||||
if @tickle.due?
|
||||
@tickle.due = Date.strptime(@params["item"]["due"], @user.preferences["date_format"])
|
||||
else
|
||||
@tickle.due = ""
|
||||
end
|
||||
|
||||
@saved = @tickle.save
|
||||
end
|
||||
|
||||
# Delete a next action
|
||||
#
|
||||
def destroy_action
|
||||
|
|
@ -191,7 +251,31 @@ class TodoController < ApplicationController
|
|||
self.init
|
||||
@page_title = "TRACKS::Feeds"
|
||||
end
|
||||
|
||||
def tickler
|
||||
self.init
|
||||
@page_title = "TRACKS::Tickler"
|
||||
@tickles = @user.todos.find(:all, :conditions => ['type = ?', "Deferred"], :order => "show_from ASC")
|
||||
@count = @tickles.size
|
||||
end
|
||||
|
||||
# Called by periodically_call_remote
|
||||
# Check for any due tickler items, change them to type Immediate and show
|
||||
# on the page
|
||||
#
|
||||
def check_tickler
|
||||
self.init
|
||||
now = Date.today()
|
||||
@due_tickles = @user.todos.find(:all, :conditions => ['type = ? AND (show_from < ? OR show_from = ?)', "Deferred", now, now ], :order => "show_from ASC")
|
||||
unless @due_tickles.empty?
|
||||
# Change the due tickles to type "Immediate"
|
||||
@due_tickles.each do |t|
|
||||
t[:type] = "Immediate"
|
||||
t.show_from = nil
|
||||
t.save
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
|
|
@ -208,8 +292,9 @@ class TodoController < ApplicationController
|
|||
def init
|
||||
@projects = @user.projects
|
||||
@contexts = @user.contexts
|
||||
@todos = @user.todos
|
||||
@done = @todos.find(:all, :conditions => ["done = ?", true])
|
||||
@todos = Todo.find(:all, :conditions => ['user_id = ? and type = ?', @user.id, "Immediate"])
|
||||
@done = Todo.find(:all, :conditions => ['user_id = ? and done = ?', @user.id, true])
|
||||
# @todos = @todos.collect { |x| (x.class == Immediate) ? x : nil }.compact
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,13 +7,20 @@ module TodoHelper
|
|||
count = Todo.find_all("done=0 AND context_id=#{context.id}").length
|
||||
end
|
||||
|
||||
def form_remote_tag_edit_todo( item )
|
||||
form_remote_tag( :url => { :controller => 'todo', :action => 'update_action', :id => item.id },
|
||||
def form_remote_tag_edit_todo( item, type )
|
||||
(type == "deferred") ? act = 'deferred_update_action' : act = 'update_action'
|
||||
form_remote_tag( :url => { :controller => 'todo', :action => act, :id => item.id },
|
||||
:html => { :id => "form-action-#{item.id}", :class => "inline-form" }
|
||||
)
|
||||
end
|
||||
|
||||
def link_to_remote_todo( item, handled_by)
|
||||
def link_to_remote_todo( item, handled_by, type)
|
||||
if type == "deferred"
|
||||
act = "edit_deferred_action"
|
||||
else
|
||||
act = "edit_action"
|
||||
end
|
||||
|
||||
str = link_to_remote( image_tag("blank", :title =>"Delete action", :class=>"delete_item"),
|
||||
{:url => { :controller => handled_by, :action => "destroy_action", :id => item.id },
|
||||
:confirm => "Are you sure that you want to delete the action, \'#{item.description}\'?"},
|
||||
|
|
@ -23,7 +30,7 @@ module TodoHelper
|
|||
{
|
||||
:update => "form-action-#{item.id}",
|
||||
:loading => visual_effect(:pulsate, "action-#{item.id}-edit-icon"),
|
||||
:url => { :controller => "todo", :action => "edit_action", :id => item.id },
|
||||
:url => { :controller => "todo", :action => act, :id => item.id },
|
||||
:success => "Element.toggle('item-#{item.id}','action-#{item.id}-edit-form'); new Effect.Appear('action-#{item.id}-edit-form', { duration: .2 }); Form.focusFirstElement('form-action-#{item.id}')"
|
||||
},
|
||||
{
|
||||
|
|
@ -88,6 +95,38 @@ module TodoHelper
|
|||
end
|
||||
end
|
||||
|
||||
# Check show_from date in comparison to today's date
|
||||
# Flag up date appropriately with a 'traffic light' colour code
|
||||
#
|
||||
def show_date(due)
|
||||
if due == nil
|
||||
return ""
|
||||
end
|
||||
|
||||
@now = Date.today
|
||||
@days = due-@now
|
||||
|
||||
case @days
|
||||
# overdue or due very soon! sound the alarm!
|
||||
when -1000..-1
|
||||
"<a title='" + format_date(due) + "'><span class=\"red\">Shown on " + (@days * -1).to_s + " days</span></a> "
|
||||
when 0
|
||||
"<a title='" + format_date(due) + "'><span class=\"amber\">Show Today</span></a> "
|
||||
when 1
|
||||
"<a title='" + format_date(due) + "'><span class=\"amber\">Show Tomorrow</span></a> "
|
||||
# due 2-7 days away
|
||||
when 2..7
|
||||
if @user.preferences["due_style"] == "1"
|
||||
"<a title='" + format_date(due) + "'><span class=\"orange\">Show on " + due.strftime("%A") + "</span></a> "
|
||||
else
|
||||
"<a title='" + format_date(due) + "'><span class=\"orange\">Show in " + @days.to_s + " days</span></a> "
|
||||
end
|
||||
# more than a week away - relax
|
||||
else
|
||||
"<a title='" + format_date(due) + "'><span class=\"green\">Show in " + @days.to_s + " days</span></a> "
|
||||
end
|
||||
end
|
||||
|
||||
def toggle_show_notes( item )
|
||||
str = "<a href=\"javascript:Element.toggle('"
|
||||
str << item.id.to_s
|
||||
|
|
|
|||
|
|
@ -17,13 +17,13 @@ class Context < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def find_not_done_todos
|
||||
todos = Todo.find :all, :conditions => ["todos.context_id = #{id} AND todos.done = ?", false],
|
||||
todos = Todo.find :all, :conditions => ["todos.context_id = #{id} AND todos.done = ? AND type = ?", false, "Immediate"],
|
||||
:include => [:context, :project],
|
||||
:order => "due IS NULL, due ASC, created_at ASC"
|
||||
end
|
||||
|
||||
def find_done_todos
|
||||
todos = Todo.find :all, :conditions => ["todos.context_id = #{id} AND todos.done = ?", true],
|
||||
todos = Todo.find :all, :conditions => ["todos.context_id = #{id} AND todos.done = ? AND type = ?", true, "Immediate"],
|
||||
:include => [:context, :project],
|
||||
:order => "due IS NULL, due ASC, created_at ASC",
|
||||
:limit => @user.preferences["no_completed"].to_i
|
||||
|
|
|
|||
2
tracks/app/models/deferred.rb
Normal file
2
tracks/app/models/deferred.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
class Deferred < Todo
|
||||
end
|
||||
2
tracks/app/models/immediate.rb
Normal file
2
tracks/app/models/immediate.rb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
class Immediate < Todo
|
||||
end
|
||||
|
|
@ -1 +1 @@
|
|||
page.replace_html "status", "A server error has occurred"
|
||||
page.replace_html "status", content_tag("div", "A server error has occurred", "class" => "warning")
|
||||
|
|
@ -31,6 +31,7 @@
|
|||
<li><%= navigation_link("Home", {:controller => "todo", :action => "list"}, {:accesskey => "t", :title => "Home"} ) %></li>
|
||||
<li><%= navigation_link( "Contexts", {:controller => "context", :action => "list"}, {:accesskey=>"c", :title=>"Contexts"} ) %></li>
|
||||
<li><%= navigation_link( "Projects", {:controller => "project", :action => "list"}, {:accesskey=>"p", :title=>"Projects"} ) %></li>
|
||||
<li><%= navigation_link( "Tickler", {:controller => "todo", :action => "tickler"}, :title => "Ticker" ) %></li>
|
||||
<li><%= navigation_link( "Done", {:controller => "todo", :action => "completed"}, {:accesskey=>"d", :title=>"Completed"} ) %></li>
|
||||
<li><%= navigation_link( "Notes", {:controller => "note", :action => "index"}, {:accesskey => "o", :title => "Show all notes"} ) %></li>
|
||||
<li><%= navigation_link( "Preferences", {:controller => "user", :action => "preferences"}, {:accesskey => "u", :title => "Show my preferences"} ) %></li>
|
||||
|
|
@ -47,7 +48,9 @@
|
|||
<% unless @controller_name == 'feed' or session['noexpiry'] == "on" -%>
|
||||
<%= periodically_call_remote( :url => {:controller => "login", :action => "check_expiry"},
|
||||
:frequency => (5*60)) %>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
<%= periodically_call_remote( :url => {:controller => "todo", :action => "check_tickler"},
|
||||
:frequency => (10*60)) %>
|
||||
<%= @content_for_layout %>
|
||||
|
||||
<div id="footer">
|
||||
|
|
|
|||
|
|
@ -7,6 +7,10 @@
|
|||
else
|
||||
add_string = "Add a next action »"
|
||||
end
|
||||
|
||||
if request.request_uri == "/todo/tickler"
|
||||
add_string = "Add a deferred action »"
|
||||
end
|
||||
%>
|
||||
|
||||
<% hide_link ||= false %>
|
||||
|
|
@ -21,6 +25,12 @@
|
|||
<div id="status">
|
||||
</div>
|
||||
<!--[form:todo]-->
|
||||
<% if request.request_uri == "/todo/tickler" -%>
|
||||
<%= form_remote_tag(
|
||||
:url => { :controller => controller.controller_name, :action => "add_deferred_item" },
|
||||
:html=> { :id=>'todo-form-new-action', :name=>'todo', :class => 'inline-form' }) %>
|
||||
<% end -%>
|
||||
|
||||
<%= form_remote_tag(
|
||||
:url => { :controller => controller.controller_name, :action => "add_item" },
|
||||
:html=> { :id=>'todo-form-new-action', :name=>'todo', :class => 'inline-form' }) %>
|
||||
|
|
@ -43,7 +53,7 @@
|
|||
{ :include_blank => true }, {"tabindex" => 4}) %><br />
|
||||
<% end -%>
|
||||
|
||||
<label for="item_due">Due</label><br />
|
||||
<label for="todo_due">Due</label><br />
|
||||
<%= text_field("todo", "due", "size" => 10, "class" => "Date", "onFocus" => "Calendar.setup", "tabindex" => 5, "autocomplete" => "off") %>
|
||||
|
||||
<% if controller.controller_name == "project" -%>
|
||||
|
|
@ -51,6 +61,12 @@
|
|||
<% elsif controller.controller_name == "context" -%>
|
||||
<%= hidden_field( "todo", "context_id", "value" => "#{@context.id}") %>
|
||||
<% end -%>
|
||||
|
||||
<% if request.request_uri == "/todo/tickler" -%>
|
||||
<br /> <label for="todo_show_from">Show from</label><br />
|
||||
<%= date_select( "todo", "show_from", :start_year => Date.today.year, :order => [:year, :month, :day] ) %>
|
||||
<% end -%>
|
||||
|
||||
<br /><br />
|
||||
<input type="submit" value="Add item" tabindex="6">
|
||||
<%= end_form_tag %><!--[eoform:todo]-->
|
||||
|
|
|
|||
62
tracks/app/views/todo/_action_edit_deferred_form.rhtml
Normal file
62
tracks/app/views/todo/_action_edit_deferred_form.rhtml
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
<%
|
||||
@item = action_edit_deferred_form
|
||||
%>
|
||||
<%= error_messages_for("item") %>
|
||||
|
||||
<%= hidden_field( "item", "id" ) %>
|
||||
<table>
|
||||
<tr>
|
||||
<td class="label"><label for="item_description">Next action</label></td>
|
||||
<td><%= text_field( "item", "description", "tabindex" => 1) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><label for="item_notes">Notes</label></td>
|
||||
<td><%= text_area( "item", "notes", "cols" => 20, "rows" => 5, "tabindex" => 2) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><label for="item_context_id">Context</label></td>
|
||||
<td><select name="item[context_id]" id="item_context_id" tabindex="3">
|
||||
<% for @place in @contexts %>
|
||||
<% if @item %>
|
||||
<% if @place.id == @item.context_id %>
|
||||
<option value="<%= @place.id %>" selected="selected"><%= @place.name %></option>
|
||||
<% else %>
|
||||
<option value="<%= @place.id %>"><%= @place.name %></option>
|
||||
<% end %>
|
||||
<% else %>
|
||||
<option value="<%= @place.id %>"><%= @place.name %></option>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</select></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><label for="item_project_id">Project</label></td>
|
||||
<td>
|
||||
<select name="item[project_id]" id="item_project_id" tabindex="4">
|
||||
<% if !@item.project_id? %>
|
||||
<option selected="selected"></option>
|
||||
<%= options_from_collection_for_select(@projects, "id", "name") %>
|
||||
<% else %>
|
||||
<option></option>
|
||||
<%= options_from_collection_for_select(@projects, "id", "name", @item.project_id) %>
|
||||
<% end %>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><label for="item_due">Due</td>
|
||||
<td><input name="item[due]" id="due_<%= @item.id %>" type="text" value="<%= format_date(@item.due) %>" tabindex="5" size="10" onFocus="Calendar.setup" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="label"><label for="item_show_from">Show from</label></td>
|
||||
<td><%= date_select( "item", "show_from", :start_year => Date.today.year,
|
||||
:order => [:year, :month, :day]) %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="hidden" name="on_project_page" value="true" /></td>
|
||||
<td><input type="submit" value="Update" tabindex="6" />
|
||||
<a href="javascript:void(0);" onclick="Element.toggle('item-<%= @item.id %>','action-<%= @item.id %>-edit-form');Form.reset('form-action-<%= @item.id %>');">Cancel</a></td>
|
||||
</tr>
|
||||
</table>
|
||||
<%= calendar_setup( "due_#{@item.id}" ) %>
|
||||
<% @item = nil %>
|
||||
46
tracks/app/views/todo/_add_new_tickle_form.rhtml
Normal file
46
tracks/app/views/todo/_add_new_tickle_form.rhtml
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
<%
|
||||
add_string = "Add a deferred action »"
|
||||
|
||||
%>
|
||||
|
||||
<% hide_link ||= false %>
|
||||
<% unless hide_link -%>
|
||||
<%= link_to_function(
|
||||
add_string,
|
||||
"Element.toggle('todo_new_action');Form.focusFirstElement('todo-form-new-action');",
|
||||
{:title => "Add the next action", :accesskey => "n"}) %>
|
||||
<% end -%>
|
||||
|
||||
<div id="todo_new_action" class="context_new" style="display:<%= hide_link ? 'block' : 'none'%>">
|
||||
<div id="status">
|
||||
</div>
|
||||
<!--[form:todo]-->
|
||||
<%= form_remote_tag(
|
||||
:url => { :controller => "todo", :action => "add_deferred_item" },
|
||||
:html=> { :id=>'todo-form-new-action', :name=>'todo', :class => 'inline-form' }) %>
|
||||
|
||||
<label for="todo_description">Description</label><br />
|
||||
<%= text_field( "todo", "description", "size" => 25, "tabindex" => 1) %><br />
|
||||
|
||||
<label for="todo_notes">Notes</label><br />
|
||||
<%= text_area( "todo", "notes", "cols" => 25, "rows" => 10, "tabindex" => 2) %><br />
|
||||
|
||||
<label for="todo_context_id">Context</label><br />
|
||||
<%= collection_select( "todo", "context_id", @contexts, "id", "name",
|
||||
{}, {"tabindex" => 3}) %><br />
|
||||
|
||||
<label for="todo_project_id">Project</label><br />
|
||||
<%= collection_select( "todo", "project_id", @projects, "id", "name",
|
||||
{ :include_blank => true }, {"tabindex" => 4}) %><br />
|
||||
|
||||
<label for="todo_due">Due</label><br />
|
||||
<%= text_field("todo", "due", "size" => 10, "class" => "Date", "onFocus" => "Calendar.setup", "tabindex" => 5, "autocomplete" => "off") %><br />
|
||||
|
||||
<label for="todo_show_from">Show from</label><br />
|
||||
<%= date_select( "todo", "show_from", :start_year => Date.today.year, :order => [:year, :month, :day] ) %>
|
||||
|
||||
<br /><br />
|
||||
<input type="submit" value="Add item" tabindex="6">
|
||||
<%= end_form_tag %><!--[eoform:todo]-->
|
||||
<%= calendar_setup( "todo_due" ) %>
|
||||
</div><!-- [end:todo-new-action] -->
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
<div id="item-<%= item.id %>-container" class="item-container">
|
||||
|
||||
<div id="item-<%= item.id %>">
|
||||
<%= link_to_remote_todo( item, controller.controller_name ) %>
|
||||
<%= link_to_remote_todo( item, controller.controller_name, "immediate" ) %>
|
||||
<input type="checkbox" class="item-checkbox"
|
||||
onclick="new Ajax.Request('<%= url_for :controller => controller.controller_name, :action => 'toggle_check', :id => item.id %>', {asynchronous:true, evalScripts:true});"
|
||||
name="item_id" value="<%= item.id %>"<% if item.done? %> checked="checked" <% end %> />
|
||||
|
|
@ -28,7 +28,7 @@
|
|||
</div>
|
||||
</div><!-- [end:item-item.id] -->
|
||||
<div id="action-<%= item.id %>-edit-form" class="edit-form" style="display:none;">
|
||||
<%= form_remote_tag_edit_todo( item ) -%>
|
||||
<%= form_remote_tag_edit_todo( item, "immediate" ) -%>
|
||||
<% #note: edit form will load here remotely -%>
|
||||
<%= end_form_tag -%>
|
||||
</div><!-- [end:action-item.id-edit-form] -->
|
||||
|
|
|
|||
26
tracks/app/views/todo/_tickle.rhtml
Normal file
26
tracks/app/views/todo/_tickle.rhtml
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
<div id="item-<%= tickle.id %>-container" class="item-container">
|
||||
|
||||
<div id="item-<%= tickle.id %>">
|
||||
<%= link_to_remote_todo( tickle, controller.controller_name, "deferred" ) %>
|
||||
<div class="description">
|
||||
<%= show_date( tickle.show_from ) -%>
|
||||
|
||||
<%= sanitize(tickle.description) %>
|
||||
<% if tickle.due -%>
|
||||
(action due on <%= tickle.due.to_s %>)
|
||||
<% end -%>
|
||||
<%= link_to( "[C]", { :controller => "context", :action => "show", :name => urlize(tickle.context.name) }, :title => "View context: #{tickle.context.name}" ) %>
|
||||
<% if tickle.project_id -%>
|
||||
<%= link_to( "[P]", { :controller => "project", :action => "show", :name => urlize(tickle.project.name) }, :title => "View project: #{tickle.project.name}" ) %>
|
||||
<% end -%>
|
||||
<% if tickle.notes? -%>
|
||||
<%= toggle_show_notes( tickle ) %>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div><!-- [end:item-tickle.id] -->
|
||||
<div id="action-<%= tickle.id %>-edit-form" class="edit-form" style="display:none;">
|
||||
<%= form_remote_tag_edit_todo( tickle, "deferred" ) -%>
|
||||
<% #note: edit form will load here remotely -%>
|
||||
<%= end_form_tag -%>
|
||||
</div><!-- [end:action-tickle.id-edit-form] -->
|
||||
</div><!-- [end:item-tickle.id-container] -->
|
||||
12
tracks/app/views/todo/_tickler_items.rhtml
Normal file
12
tracks/app/views/todo/_tickler_items.rhtml
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
<div id="tickler" class="container project">
|
||||
<h2>Deferred actions</h2>
|
||||
|
||||
<div class="items toggle_target">
|
||||
<div id="empty-nd" style="display:<%= @tickles.empty? ? 'block' : 'none'%>;">
|
||||
<div class="message"><p>Currently there are no deferred actions</p></div>
|
||||
</div>
|
||||
|
||||
<%= render :partial => "tickle", :collection => @tickles %>
|
||||
|
||||
</div><!-- [end:items] -->
|
||||
</div><!-- [end:tickler] -->
|
||||
13
tracks/app/views/todo/add_deferred_item.rjs
Normal file
13
tracks/app/views/todo/add_deferred_item.rjs
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
if @saved
|
||||
page.hide "status"
|
||||
page.replace_html "status", content_tag("div", "Added new next action", "class" => "confirmation")
|
||||
page.visual_effect :appear, 'status', :duration => 0.5
|
||||
page.replace_html "badge_count", @up_count
|
||||
page.send :record, "Form.reset('todo-form-new-action');Form.focusFirstElement('todo-form-new-action')"
|
||||
page.insert_html :bottom, "tickler", :partial => 'todo/tickle'
|
||||
page.visual_effect :highlight, "item-#{@tickle.id}-container", :duration => 3
|
||||
else
|
||||
page.hide "status"
|
||||
page.replace_html "status", content_tag("div", content_tag("h2", "#{pluralize(@tickle.errors.count, "error")} prohibited this record from being saved") + content_tag("p", "There were problems with the following fields:") + content_tag("ul", @tickle.errors.each_full { |msg| content_tag("li", msg) }), "id" => "ErrorExplanation", "class" => "ErrorExplanation")
|
||||
page.visual_effect :appear, 'status', :duration => 0.5
|
||||
end
|
||||
3
tracks/app/views/todo/check_tickler.rjs
Normal file
3
tracks/app/views/todo/check_tickler.rjs
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
unless @due_tickles.empty?
|
||||
page.replace_html "info", content_tag("div", "#{@due_tickles.length.to_s} tickler items are now due - refresh the page to see them.", "class" => "warning")
|
||||
end
|
||||
14
tracks/app/views/todo/deferred_update_action.rjs
Normal file
14
tracks/app/views/todo/deferred_update_action.rjs
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
if @saved
|
||||
if @tickle.context_id == @original_item_context_id
|
||||
page.replace_html "item-#{@tickle.id}-container", :partial => 'todo/tickle'
|
||||
page.visual_effect :highlight, "item-#{@tickle.id}-container", :duration => 3
|
||||
else
|
||||
page["item-#{@tickle.id}-container"].remove
|
||||
page.insert_html :bottom, "c#{@tickle.context_id}items", :partial => 'todo/tickle'
|
||||
page.visual_effect :highlight, "item-#{@tickle.id}-container", :duration => 3
|
||||
end
|
||||
else
|
||||
page.hide "info"
|
||||
page.replace_html "info", content_tag("div", content_tag("div", "#{pluralize(@tickle.errors.count, "error")} prohibited this record from being saved", "id" => "warning", "class" => "warning") + content_tag("p", "There were problems with the following fields:") + content_tag("ul", @tickle.errors.each_full { |msg| content_tag("li", msg) }))
|
||||
page.visual_effect :appear, 'info', :duration => 0.5
|
||||
end
|
||||
16
tracks/app/views/todo/tickler.rhtml
Normal file
16
tracks/app/views/todo/tickler.rhtml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<div id="display_box">
|
||||
|
||||
<% for name in ["notice", "warning", "message"] %>
|
||||
<% if flash[name] %>
|
||||
<%= "<div id=\"#{name}\">#{flash[name]}</div>" %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<%= render :partial => "tickler_items" %>
|
||||
|
||||
</div><!-- End of display_box -->
|
||||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form", :locals => {:hide_link => false, :msg => ""} %>
|
||||
<%= render "shared/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
12
tracks/db/migrate/008_add_subclass_attr_to_todos.rb
Normal file
12
tracks/db/migrate/008_add_subclass_attr_to_todos.rb
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
class AddSubclassAttrToTodos < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :todos, :type, :string, :null => false, :default => "Immediate"
|
||||
add_column :todos, :show_from, :date
|
||||
Todo.find(:all).each { |todo| todo.type = "Immediate" }
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :todos, :type
|
||||
remove_column :todos, :show_from
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
# migrations feature of ActiveRecord to incrementally modify your database, and
|
||||
# then regenerate this schema definition.
|
||||
|
||||
ActiveRecord::Schema.define(:version => 7) do
|
||||
ActiveRecord::Schema.define(:version => 8) do
|
||||
|
||||
create_table "contexts", :force => true do |t|
|
||||
t.column "name", :string, :default => "", :null => false
|
||||
|
|
@ -45,6 +45,8 @@ ActiveRecord::Schema.define(:version => 7) do
|
|||
t.column "completed", :datetime
|
||||
t.column "project_id", :integer
|
||||
t.column "user_id", :integer, :default => 1
|
||||
t.column "type", :string, :default => "Immediate", :null => false
|
||||
t.column "show_from", :date
|
||||
end
|
||||
|
||||
create_table "users", :force => true do |t|
|
||||
|
|
|
|||
|
|
@ -289,7 +289,7 @@ a.footer_link:hover {color: #fff; background-color: #cc3334 !important;}
|
|||
text-align: center;
|
||||
}
|
||||
|
||||
#message {
|
||||
#message, .message {
|
||||
padding: 2px;
|
||||
border: 1px solid #CCC;
|
||||
background-color: #D2D3D6;
|
||||
|
|
|
|||
5
tracks/test/fixtures/deferreds.yml
vendored
Normal file
5
tracks/test/fixtures/deferreds.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
first:
|
||||
id: 1
|
||||
another:
|
||||
id: 2
|
||||
5
tracks/test/fixtures/immediates.yml
vendored
Normal file
5
tracks/test/fixtures/immediates.yml
vendored
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
# Read about fixtures at http://ar.rubyonrails.org/classes/Fixtures.html
|
||||
first:
|
||||
id: 1
|
||||
another:
|
||||
id: 2
|
||||
10
tracks/test/unit/deferred_test.rb
Normal file
10
tracks/test/unit/deferred_test.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
|
||||
class DeferredTest < Test::Unit::TestCase
|
||||
fixtures :deferreds
|
||||
|
||||
# Replace this with your real tests.
|
||||
def test_truth
|
||||
assert true
|
||||
end
|
||||
end
|
||||
10
tracks/test/unit/immediate_test.rb
Normal file
10
tracks/test/unit/immediate_test.rb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
require File.dirname(__FILE__) + '/../test_helper'
|
||||
|
||||
class ImmediateTest < Test::Unit::TestCase
|
||||
fixtures :immediates
|
||||
|
||||
# Replace this with your real tests.
|
||||
def test_truth
|
||||
assert true
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Add a link
Reference in a new issue