get destroying of actions working

This commit is contained in:
Reinier Balt 2010-12-20 18:20:37 +01:00
parent e13e946295
commit 33f68df154
18 changed files with 246 additions and 96 deletions

View file

@ -112,17 +112,17 @@ class RecurringTodosController < ApplicationController
end
if @saved
@message = "The recurring todo was saved"
@status_message = "The recurring todo was saved"
@todo_saved = create_todo_from_recurring_todo(@recurring_todo).nil? == false
if @todo_saved
@message += " / created a new todo"
@status_message += " / created a new todo"
else
@message += " / did not create todo"
@status_message += " / did not create todo"
end
@down_count = current_user.recurring_todos.active.count
@new_recurring_todo = RecurringTodo.new
else
@message = "Error saving recurring todo"
@status_message = "Error saving recurring todo"
end
respond_to do |format|

View file

@ -118,6 +118,11 @@ class TodosController < ApplicationController
@initial_context_name = params['default_context_name']
@initial_project_name = params['default_project_name']
@default_tags = @todo.project.default_tags unless @todo.project.nil?
@status_message = 'Added new next action'
@status_message += ' to tickler' if @todo.deferred?
@status_message += ' in pending state' if @todo.pending?
@status_message = 'Added new project / ' + status_message if @new_project_created
@status_message = 'Added new context / ' + status_message if @new_context_created
render :action => 'create'
end
format.xml do
@ -295,6 +300,7 @@ class TodosController < ApplicationController
respond_to do |format|
format.js
format.xml { render :xml => @todo.to_xml( :except => :user_id ) }
format.html { redirect_to request.referrer}
end
end
@ -452,6 +458,7 @@ class TodosController < ApplicationController
end
def destroy
@source_view = params['_source_view'] || 'todo'
@todo = get_todo_from_params
@original_item_due = @todo.due
@context_id = @todo.context_id

View file

@ -32,15 +32,13 @@ module TodosHelper
:title => t('todos.edit_action_with_description', :description => @todo.description))
end
def remote_delete_menu_item(parameters, todo)
return link_to_remote(
def remote_delete_menu_item(todo)
return link_to(
image_tag("delete_off.png", :mouseover => "delete_on.png", :alt => t('todos.delete'), :align => "absmiddle")+" "+t('todos.delete'),
:url => {:controller => 'todos', :action => 'destroy', :id => todo.id},
:method => 'delete',
:with => "'#{parameters}'",
:before => todo_start_waiting_js(todo),
:complete => todo_stop_waiting_js(todo),
:confirm => t('todos.confirm_delete', :description => todo.description))
{:controller => 'todos', :action => 'destroy', :id => todo.id},
:class => "icon_delete_item",
:id => "delete_#{dom_id(todo)}",
:title => t('todos.confirm_delete', :description => todo.description));
end
def remote_defer_menu_item(days, todo)
@ -264,10 +262,16 @@ module TodosHelper
def empty_container_msg_div_id
todo = @todo || @successor
return "" unless todo # empty id if no todo or successor given
return "tickler-empty-nd" if source_view_is_one_of(:project, :tag) && todo.deferred?
return "tickler-empty-nd" if source_view_is_one_of(:project, :tag, :deferred) && todo.deferred?
return "p#{todo.project_id}empty-nd" if source_view_is :project
return "c#{todo.context_id}empty-nd"
end
def todo_container_is_empty
default_container_empty = ( @down_count == 0 )
deferred_container_empty = ( @todo.deferred? && @deferred_count == 0)
return default_container_empty || deferred_container_empty
end
def default_contexts_for_autocomplete
projects = current_user.projects.find(:all, :conditions => ['default_context_id is not null'])

View file

@ -1,4 +1,5 @@
<% if @saved -%>
TracksPages.page_notify('notice', "<%=@status_message%>", 5);
RecurringTodosPage.toggle_overlay();
add_recurring_todo_to_active_container();
replace_form_with_empty_form();

View file

@ -11,17 +11,15 @@ parameters += "&_tag_name=#{@tag_name}" if @source_view == 'tag'
<div id="<%= dom_id(todo, 'line') %>" class="item-show">
<%= remote_star_icon %>
<%= remote_toggle_checkbox unless source_view_is :deferred %>
<% unless suppress_edit_button %>
<%= remote_edit_button %>
<% end %>
<%= remote_edit_button unless suppress_edit_button %>
<ul class="sf-menu sf-item-menu">
<li style="z-index:<%=@z_index_counter%>"><%= image_tag "downarrow.png", :alt=> "" %>
<ul id="ul<%= dom_id(todo) %>">
<li><%= remote_delete_menu_item(parameters, todo) %></li>
<% unless todo.completed? || todo.deferred? %>
<li><%= remote_delete_menu_item(todo) %></li>
<% unless todo.completed? || todo.deferred? -%>
<li><%= remote_defer_menu_item(1, todo) %></li>
<li><%= remote_defer_menu_item(7, todo) %></li>
<% end %>
<% end -%>
<li><%= remote_promote_to_project_menu_item(todo) %></li>
</ul>
</li>
@ -30,7 +28,6 @@ parameters += "&_tag_name=#{@tag_name}" if @source_view == 'tag'
<%= grip_span %>
<%= date_span -%>
<span class="todo.descr"><%= h todo.description %></span>
<% #= successors_span %>
<%= image_tag_for_recurring_todo(todo) if @todo.from_recurring_todo? %>
<%= tag_list %>
<%= deferred_due_date %>
@ -45,4 +42,4 @@ parameters += "&_tag_name=#{@tag_name}" if @source_view == 'tag'
<div class="placeholder"> </div>
<% end -%>
</div>
</div>
</div>

View file

@ -1,9 +1,6 @@
<%
suppress_button ||= false
%>
<%= link_to(image_tag( 'blank.png', :width=>'16', :height=>'16', :border=>'0' ), "#", {:class => 'show_successors', :title => 'Show successors'}) unless suppress_button %>
<%= link_to(image_tag( 'blank.png', :width=>'16', :height=>'16', :border=>'0' ), "#", {:class => 'show_successors', :title => 'Show successors'}) %>
<div class="todo_successors" id="<%= dom_id(item, 'successors') %>" style=<%= suppress_button ? "display:display" : "display:none" %> >
<div class="todo_successors" id="<%= dom_id(item, 'successors') %>">
<%= render :partial => "todos/successor",
:collection => item.pending_successors,
:locals => { :todo => item,

View file

@ -1,5 +1,5 @@
<% if @saved -%>
set_notification();
TracksPages.page_notify('notice', "<%=@status_message%>", 5);
hide_empty_message();
TracksPages.hide_errors();
TracksPages.set_page_badge(<%= @down_count %>);
@ -16,17 +16,6 @@
TracksPages.show_errors(html_for_error_messages());
<% end -%>
function set_notification() {
<%-
status_message = 'Added new next action'
status_message += ' to tickler' if @todo.deferred?
status_message += ' in pending state' if @todo.pending?
status_message = 'Added new project / ' + status_message if @new_project_created
status_message = 'Added new context / ' + status_message if @new_context_created
-%>
TracksPages.page_notify('notice', "<%=status_message%>", 5);
}
function hide_empty_message() {
<% if @todo %>
$('#<%=empty_container_msg_div_id%>').hide();

View file

@ -16,7 +16,8 @@
<% end -%>
<% if @saved
# the following functions assume a todo is saved or not nil, so leave them out in case of an error
# the following functions assume a todo is saved or at least not nil,
# so leave them out in case of an error
-%>
function set_notification() {

View file

@ -1,36 +1,75 @@
if @saved
page[@todo].remove
page.show "empty_"+@original_item_due_id if @old_due_empty
page['badge_count'].replace_html @down_count
# remove context if empty
page.visual_effect(:fade, "c#{@todo.context_id}", :duration => 0.4) if (@remaining_in_context == 0)
# show message if there are no actions
page[empty_container_msg_div_id].show if !empty_container_msg_div_id.nil? && @down_count == 0
page['tickler-empty-nd'].show if source_view_is(:deferred) && @down_count == 0
# show new todo if the completed todo was recurring
if @todo.from_recurring_todo?
unless @new_recurring_todo.nil? || @new_recurring_todo.deferred?
page.call "todoItems.ensureVisibleWithEffectAppear", item_container_id(@new_recurring_todo)
page.insert_html :bottom, item_container_id(@new_recurring_todo), :partial => 'todos/todo', :locals => { :todo => @new_recurring_todo, :parent_container_type => parent_container_type }
page.visual_effect :highlight, dom_id(@new_recurring_todo, 'line'), {'startcolor' => "'#99ff99'"}
page.notify :notice, t('todos.recurring_action_deleted'), 6.0
else
if @todo.recurring_todo.todos.active.count == 0
page.notify :notice, t('todos.completed_recurrence_completed'), 6.0 if @new_recurring_todo.nil?
end
end
end
# Activate pending todos that are successors of the deleted
@pending_to_activate.each do |t|
logger.debug "#300: Removing #{t.description} from pending block and adding it to active"
page[t].remove if source_view_is(:project) or source_view_is(:tag)
page.insert_html :bottom, item_container_id(t), :partial => 'todos/todo', :locals => { :todo => t, :parent_container_type => parent_container_type }
page.visual_effect :highlight, dom_id(t, 'line'), {'startcolor' => "'#99ff99'", :duration => 2}
end
else
page.notify :error, t('todos.error_deleting_item', :description => @todo.description), 8.0
end
<%- if @saved -%>
TracksPages.page_notify('notice', '<%= escape_javascript("The action was deleted succesfully") %>', 5);
TracksPages.set_page_badge(<%=@down_count%>);
remove_todo_from_page();
show_new_todo_if_todo_was_recurring();
activate_pending_todos();
show_empty_messages();
<%- else -%>
TracksPages.page_notify('error', "<%= t('todos.error_deleting_item', :description => @todo.description) %>", 8);
<%- end -%>
<% if @saved
# do not send the js in case of an error
-%>
function show_empty_messages() {
<% if @old_due_empty -%>
$('#empty_<%=@original_item_due_id%>').slideDown(1000);
<% end -%>
<% if empty_container_msg_div_id && todo_container_is_empty -%>
$('#<%=empty_container_msg_div_id%>').slideDown(1000);
<% end -%>
}
function remove_todo_from_page() {
<% if (@remaining_in_context == 0)
# remove context with deleted todo
-%>
$('#c<%=@todo.context_id%>').fadeOut(1000, function() {
$('#<%=dom_id(@todo)%>').remove();
});
<% else
# remove only the todo
-%>
$('#<%=dom_id(@todo)%>').slideUp(1000, function() {
$('#<%=dom_id(@todo)%>').remove();
});
<% end -%>
}
function show_new_todo_if_todo_was_recurring() {
<% if @todo.from_recurring_todo? -%>
<% unless @new_recurring_todo.nil? || @new_recurring_todo.deferred? -%>
TodoItemsContainer.ensureVisibleWithEffectAppear("<%=item_container_id(@new_recurring_todo)%>");
$('#<%=item_container_id(@new_recurring_todo)%>').append(html_for_new_recurring_todo());
$('#<%= dom_id(@new_recurring_todo, 'line')%>').effect('highlight', {}, 2000 );
TracksPages.page_notify('notice', "Action was deleted. Because this action is recurring, a new action was added", 5);
<% else -%>
<% if @todo.recurring_todo.todos.active.count == 0 && @new_recurring_todo.nil? -%>
TracksPages.page_notify('notice', "There is no next action after the recurring action you just deleted. The recurrence is completed", 5);
<% end -%>
<% end -%>
<% end -%>
}
function activate_pending_todos() {
<% # Activate pending todos that are successors of the deleted -%>
<% @pending_to_activate.each do |t| -%>
<% if source_view_is(:project) or source_view_is(:tag) %>
$('#<%=dom_id(t)%>').remove();
<% end -%>
$('#<%=item_container_id(t)%>').append("<%=escape_javascript(render(:partial => 'todos/todo', :locals => { :todo => t, :parent_container_type => parent_container_type }))%>");
$('#<%= dom_id(t, 'line')%>').effect('highlight', {}, 2000 );
<% end -%>
}
function html_for_new_recurring_todo() {
return "<%= @saved && @new_recurring_todo ? escape_javascript(render(:partial => 'todos/todo', :locals => { :todo => @new_recurring_todo, :parent_container_type => parent_container_type })) : "" %>";
}
<% end
# if @saved
-%>
>>>>>>> get destroying of actions working

View file

@ -1,3 +1,5 @@
<% if @saved -%>
$('div#line_todo_<%= @todo.id %> a.star_item img').toggleClass('starred_todo').toggleClass('unstarred_todo');
<% else -%>
TracksPages.page_notify('error', "Could not toggle the star of this todo", 5);
<% end -%>

19
features/calendar.feature Normal file
View file

@ -0,0 +1,19 @@
Feature: dependencies
As a Tracks user
In order to keep overview of my due todos
I want to manage due todos in a calendar view
Background:
Given the following user record
| login | password | is_admin |
| testuser | secret | false |
And I have logged in as "testuser" with password "secret"
Scenario: Setting due date of a todo will show it in the calendar
Given this is a pending scenario
Scenario: Clearing the due date of a todo will remove it from the calendar
Given this is a pending scenario
Scenario: Changing due date of a todo will move it in the calendar
Given this is a pending scenario

View file

@ -9,7 +9,7 @@ Feature: dependencies
| testuser | secret | false |
And I have logged in as "testuser" with password "secret"
@selenium
@selenium @wip
Scenario: Adding dependency to dependency
Given I have a project "dependencies" with 3 todos
And "Todo 2" depends on "Todo 1"
@ -35,3 +35,6 @@ Feature: dependencies
Then the dependencies of "test me" should include "test,1, 2,3"
When I edit the dependency of "test me" to '"test,1, 2,3" <"@pc"; "dependencies">,"test,1, 2,3" <"@pc"; "dependencies">'
Then there should not be an error
Scenario: Deleting a predecessor will activate successors
Given this scenario is pending

View file

@ -0,0 +1,55 @@
Feature: Edit a next action from every page
In order to manage a next action
As a Tracks user
I want to to be able to change the next action from every page
Background:
Given the following user record
| login | password | is_admin |
| testuser | secret | false |
And I have logged in as "testuser" with password "secret"
Scenario: I can toggle the star of a todo
Given this is a pending scenario
Scenario: I can delete a todo
Given this is a pending scenario
Scenario: Deleting the last todo in context will hide context
Given this is a pending scenario
Scenario: Deleting the last todo in container will show empty message
Given this is a pending scenario
Scenario: I can mark a todo complete
Given this is a pending scenario
Scenario: I can mark a completed todo active
Given this is a pending scenario
Scenario: I can edit a todo to move it to another context
Given this is a pending scenario
Scenario: I can edit a todo to move it to another project
Given this is a pending scenario
Scenario: I can edit a todo to move it to the tickler
Given this is a pending scenario
Scenario: I can defer a todo
Given this is a pending scenario
Scenario: I can make a project from a todo
Given this is a pending scenario
Scenario: I can show the notes of a todo
Given this is a pending scenario
Scenario: I can tag a todo
Given this is a pending scenario
Scenario: Clicking a tag of a todo will go to that tag page
Given this is a pending scenario
Scenario: I can edit the tags of a todo
Given this is a pending scenario

View file

@ -23,7 +23,7 @@ Feature: Manage users
Then I should be on the manage users page
And I should see "new.user"
@selenium
@selenium @wip
Scenario: Delete account from users page
When I go to the manage users page
And I delete the user "testuser"

View file

@ -68,7 +68,7 @@ Feature: Edit a project
Then the badge should show 2 # "manage me" and "test"
When I try to edit the project name of "manage me" to "test"
Then I should see "Name already exists"
@selenium
Scenario: I can add a note to the project
Given I have a project called "test"
@ -89,4 +89,7 @@ Feature: Edit a project
When I visit the "test" project
And I add a note "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890TOO LONG" to the project
Then I should not see "123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890TOO LONG"
And I should see "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456"
And I should see "12345678901234567890123456789012345678901234567890123456789012345678901234567890123456"
Scenario: Cancelling editing a project will restore project settings
Given this scenario is pending

View file

@ -25,7 +25,7 @@ Feature: Manage recurring todos
When I select "Daily" recurrence pattern
Then I should see the form for "Daily" recurrence pattern
@selenium
@selenium
Scenario: I can mark a repeat pattern as starred
When I go to the repeating todos page
And I star the pattern "run tests"
@ -54,10 +54,19 @@ Feature: Manage recurring todos
And the state list "active" should be empty
@selenium
Scenario: I can reactivate a repeat pattern
Scenario: I can reactivate a repeat pattern
Given I have a completed repeat pattern "I'm done"
When I go to the repeating todos page
Then the pattern "I'm done" should be in the state list "completed"
When I mark the pattern "I'm done" as active
Then the pattern "I'm done" should be in the state list "active"
And the state list "completed" should be empty
And the state list "completed" should be empty
Scenario: Following the recurring todo link of a todo takes me to the recurring todos page
Given this is a pending scenario
Scenario: Deleting a recurring todo with ending pattern will show message
Given this is a pending scenario
Scenario: Deleting a recurring todo with active pattern will show new todo
Given this is a pending scenario

View file

@ -119,6 +119,24 @@ Feature: Add new next action from every page
| visit | context page for "test context" | see | 2 | 3 |
| visit | tag page for "starred" | not see | 0 | 3 |
Scenario: Adding a todo to another project does not show the todo
Given this is a pending scenario
Scenario: Adding a todo to a hidden project does not show the todo
Given this is a pending scenario
Scenario: Adding a todo with a new context shows the new context
Given this is a pending scenario
Scenario: Adding a todo to a hidden context does not show the todo
Given this is a pending scenario
Scenario: Adding a todo to an empty container hides the empty message
Given this is a pending scenario
Scenario: Adding a dependency to a todo updated the successor
Given this is a pending scenario
@selenium
Scenario: I need to fill in at least one description and a context
When I go to the home page
@ -133,4 +151,4 @@ Feature: Add new next action from every page
"""
Then I should see "You need to submit at least one next action"
Then I should see "You need to submit at least one next action"

View file

@ -203,7 +203,7 @@ var TracksPages = {
$(".alert").fadeOut(8000);
/* for edit project form and edit todo form
* TODO: refactor to separate calls from project and todo */
* TODO: refactor to separate calls from project and todo */
$('.edit-form a.negative').live('click', function(){
$(this).parents('.edit-form').fadeOut(200, function () {
$(this).parents('.list').find('.project').fadeIn(500);
@ -331,15 +331,14 @@ var TodoItems = {
/* set behavior for star icon */
$(".item-container a.star_item").live('click', function (ev){
$.post(this.href, {
_method: 'put'
}, null, 'script');
put_with_ajax_and_block_element(this.href, $(this));
return false;
});
/* set behavior for toggle checkboxes for Recurring Todos */
$(".item-container input.item-checkbox").live('click', function(ev){
put_with_ajax_and_block_element(this.value, $(this));
return false;
});
/* set behavior for edit icon */
@ -347,6 +346,15 @@ var TodoItems = {
get_with_ajax_and_block_element(this.href, $(this).parents(".item-container"));
return false;
});
/* delete button to delete a project from the list
* :with => "'#{parameters}'",*/
$('.item-container a.icon_delete_item').live('click', function(evt){
if(confirm(this.title)){
delete_with_ajax_and_block_element(this.href, $(this).parents('.project'));
}
return false;
});
}
}
@ -383,7 +391,6 @@ var ProjectListPage = {
return(value);
},
setup_behavior: function() {
/* in-place edit of project name */
$('h2#project_name').editable(ProjectListPage.save_project_name, {
style: 'padding:0px',
@ -726,10 +733,11 @@ function generic_get_script_for_list(element, getter, param){
}
function default_ajax_options_for_submit(ajax_type, element_to_block) {
return {
options = {
type: ajax_type,
async: true,
context: element_to_block,
data: "_source_view=" + encodeURIComponent( SOURCE_VIEW ),
beforeSend: function() {
$(this).block({
message: null
@ -743,6 +751,9 @@ function default_ajax_options_for_submit(ajax_type, element_to_block) {
TracksPages.page_notify('error', 'There was an error retrieving from server: '+status, 8);
}
}
if(typeof(TAG_NAME) !== 'undefined')
options.data += "&_tag_name="+ encodeURIComponent (TAG_NAME);
return options;
}
function default_ajax_options_for_scripts(ajax_type, the_url, element_to_block) {
@ -766,9 +777,7 @@ function post_with_ajax_and_block_element(the_url, element_to_block) {
function put_with_ajax_and_block_element(the_url, element_to_block) {
options = default_ajax_options_for_scripts('POST', the_url, element_to_block);
options.data = '_method=put';
if(typeof(TAG_NAME) !== 'undefined')
options.data += "&_tag_name="+ encodeURIComponent (TAG_NAME);
options.data += '&_method=put';
$.ajax(options);
}
@ -793,10 +802,7 @@ $(document).ajaxSend(function(event, request, settings) {
});
function setup_periodic_check(url_for_check, interval_in_sec, method) {
ajaxMethod = "GET"
if (method) {
ajaxMethod = method;
}
ajaxMethod = (method ? method : "GET");
function check_remote() {
$.ajax({