diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb
index 41d2b80e..163263c9 100644
--- a/app/controllers/projects_controller.rb
+++ b/app/controllers/projects_controller.rb
@@ -125,9 +125,7 @@ class ProjectsController < ApplicationController
@project_not_done_counts[@project.id] = @project.reload().not_done_todos_including_hidden.count
end
@contexts = current_user.contexts
- @active_projects_count = current_user.projects.active.count
- @hidden_projects_count = current_user.projects.hidden.count
- @completed_projects_count = current_user.projects.completed.count
+ update_state_counts
init_data_for_sidebar
render :template => 'projects/update.js.erb'
return
@@ -166,11 +164,12 @@ class ProjectsController < ApplicationController
def destroy
@project.recurring_todos.each {|rt| rt.remove_from_project!}
@project.destroy
- @active_projects_count = current_user.projects.active.count
- @hidden_projects_count = current_user.projects.hidden.count
- @completed_projects_count = current_user.projects.completed.count
+
respond_to do |format|
- format.js { @down_count = current_user.projects.size }
+ format.js {
+ @down_count = current_user.projects.size
+ update_state_counts
+ }
format.xml { render :text => "Deleted project #{@project.name}" }
end
end
@@ -201,7 +200,16 @@ class ProjectsController < ApplicationController
end
protected
-
+
+ def update_state_counts
+ @active_projects_count = current_user.projects.active.count
+ @hidden_projects_count = current_user.projects.hidden.count
+ @completed_projects_count = current_user.projects.completed.count
+ @show_active_projects = @active_projects_count > 0
+ @show_hidden_projects = @hidden_projects_count > 0
+ @show_completed_projects = @completed_projects_count > 0
+ end
+
def render_projects_html
lambda do
@page_title = t('projects.list_projects')
diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb
index 8ab0f8f6..75d110be 100644
--- a/app/helpers/application_helper.rb
+++ b/app/helpers/application_helper.rb
@@ -110,6 +110,12 @@ module ApplicationHelper
def link_to_project(project, descriptor = sanitize(project.name))
link_to( descriptor, project_path(project), :title => "View project: #{project.name}" )
end
+
+ def link_to_edit_project (project, descriptor = sanitize(project.name))
+ link_to(descriptor,
+ url_for({:controller => 'projects', :action => 'edit', :id => project.id}),
+ {:id => "link_edit_#{dom_id(project)}", :class => "project_edit_settings"})
+ end
def link_to_project_mobile(project, accesskey, descriptor = sanitize(project.name))
link_to( descriptor, project_path(project, :format => 'm'), {:title => "View project: #{project.name}", :accesskey => accesskey} )
diff --git a/app/views/projects/_project_listing.rhtml b/app/views/projects/_project_listing.rhtml
index b6742ee5..e4e4880d 100644
--- a/app/views/projects/_project_listing.rhtml
+++ b/app/views/projects/_project_listing.rhtml
@@ -13,24 +13,15 @@ suppress_edit_button ||= false
<%= link_to_project( project ) %><%= " (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %>
diff --git a/app/views/projects/_project_settings.rhtml b/app/views/projects/_project_settings.rhtml
index cf3e18a1..954a486e 100644
--- a/app/views/projects/_project_settings.rhtml
+++ b/app/views/projects/_project_settings.rhtml
@@ -14,16 +14,7 @@
<% else -%>
'<%= project.default_tags -%>' as the default tags.
<% end -%>
- Edit Project Settings
- <%#= link_to_remote(
- "",
- :url => {:controller => 'projects', :action => 'edit', :id => project.id},
- :method => 'get',
- :with => "'_source_view=#{@source_view}'",
- :before => "$('#{dom_id(project)}').block({message: null});",
- :complete => "$('#{dom_id(project)}').unblock();enable_rich_interaction();",
- :html => {:id => "link_edit_#{dom_id(project)}"}
- ) %>
+ <%= link_to_edit_project(project, "Edit Project Settings") %>
<% unless project.description.blank? -%>
<%= format_note(project.description) %>
diff --git a/app/views/projects/destroy.js.erb b/app/views/projects/destroy.js.erb
new file mode 100644
index 00000000..38494a21
--- /dev/null
+++ b/app/views/projects/destroy.js.erb
@@ -0,0 +1,12 @@
+remove_deleted_project();
+ProjectListPage.update_state_count(<%=@active_projects_count%>, <%=@hidden_projects_count%>, <%=@completed_projects_count%>)
+ProjectListPage.show_or_hide_state_container(<%= @show_active_projects %>, <%= @show_hidden_projects %>, <%= @show_completed_projects %>);
+page_notify('notice', "Deleted project '#{@project.name}'", 5);
+set_page_badge(<%=@down_count%>);
+
+function remove_deleted_project() {
+ $('div#<%=dom_id(@project, "container")%>').slideUp(1000,
+ function() {
+ $('div#<%=dom_id(@project, "container")%>').remove()
+ });
+}
diff --git a/app/views/projects/destroy.js.rjs b/app/views/projects/destroy.js.rjs
deleted file mode 100644
index 18e22540..00000000
--- a/app/views/projects/destroy.js.rjs
+++ /dev/null
@@ -1,13 +0,0 @@
-page.visual_effect :fade, dom_id(@project, "container"), :duration => 0.5
-page.delay(0.5) do
- page[dom_id(@project, "container")].remove
- page.replace_html "active-projects-count", @active_projects_count
- page.replace_html "hidden-projects-count", @hidden_projects_count
- page.replace_html "completed-projects-count", @completed_projects_count
- page.set_element_visible("list-hidden-projects-container", @hidden_projects_count > 0)
- page.set_element_visible("list-active-projects-container", @active_projects_count > 0)
- page.set_element_visible("list-completed-projects-container", @completed_projects_count > 0)
-end
-page.notify :notice, "Deleted project '#{@project.name}'", 5.0
-page['badge_count'].replace_html @down_count
-page.hide "busy"
diff --git a/app/views/projects/edit.js.erb b/app/views/projects/edit.js.erb
index 2d2e7cd2..6c4d3875 100644
--- a/app/views/projects/edit.js.erb
+++ b/app/views/projects/edit.js.erb
@@ -1,5 +1,5 @@
newHtml = "<%= escape_javascript(render(:partial => 'project_form', :locals => { :project_form => @project })) %>"
$('div#<%=dom_id(@project, 'edit')%>').html(newHtml);
$('div#<%=dom_id(@project)%>').hide();
-$('div#<%=dom_id(@project, 'edit')%>').show();
+$('div#<%=dom_id(@project, 'edit')%>').show(500);
$('input.project-name').focus();
diff --git a/app/views/projects/update.js.erb b/app/views/projects/update.js.erb
index c97de018..fb4c7aeb 100644
--- a/app/views/projects/update.js.erb
+++ b/app/views/projects/update.js.erb
@@ -1,69 +1,101 @@
<% if @saved -%>
+
pageNotify('notice', '<%=t('projects.project_saved_status')%>', 5);
+
<% if source_view_is :project_list -%>
+
<% if @state_changed -%>
- <% else # TODO!!!-%>
+ remove_project();
+ add_project();
+ <% else -%>
+ replace_project();
<% end -%>
- <% else # source_view must be :project %>
- $('#<%=dom_id(@project, 'edit')%>').hide();
- $('#<%=dom_id(@project, 'container')%>').html("<%= escape_javascript(render(:partial => 'project_settings', :locals => { :project => @project })) %> ");
- $('#<%=dom_id(@project)%>').show();
- $('input#todo_project_name').val("<%= escape_javascript(@project.name)%>");
+
+ update_sortable();
+ ProjectListPage.update_state_count(<%=@active_projects_count%>, <%=@hidden_projects_count%>, <%=@completed_projects_count%>)
+ ProjectListPage.show_or_hide_state_container(<%= @show_active_projects %>, <%= @show_hidden_projects %>, <%= @show_completed_projects %>);
+
+ <% else # assume source_view :project %>
+
+ remove_project_edit_form();
+ update_and_show_project_settings();
+
+ TracksForm.set_project_name("<%= escape_javascript(@project.name)%>");
<% if @project.default_context %>
- $('input#todo_context_name').val("<%= escape_javascript(@project.default_context.name)%>");
- $('input[name=default_context_name]').val('<%= escape_javascript(@project.default_context.name)%>');
+ TracksForm.set_context_name_and_default_context_name("<%= escape_javascript(@project.default_context.name)%>");
<% end %>
<% if @project.default_tags %>
- $('input#tag_list').val("<%= escape_javascript(@project.default_tags)%>");
+ TracksForm.set_tag_list("<%= escape_javascript(@project.default_tags)%>");
<% end %>
+
+ update_sidebar();
+
<% end %>
- $('#default_project_name_id').val('<%= escape_javascript(@project.name)%>');
- $('input#todo_project_name').val("<%= escape_javascript(@project.name)%>");
- $('#project_name').html("<%= escape_javascript(@project.name)%>");
- $('#sidebar').html("<%= escape_javascript(render(:file => 'sidebar/sidebar.html.erb')) %>");
+
+ TracksForm.set_project_name_and_default_project_name("<%= escape_javascript(@project.name)%>");
+
<% else -%>
- $('div#error_status').html("<%= escape_javascript(error_messages_for('project')) %>");
- $('div#error_status').show();
+ show_errors();
<% end %>
+
enable_rich_interaction();
-<%# *page << "console.log(\"hello\");"%>
-<%# *if @saved%>
-<%# *status_message = 'Project saved'%>
-<%# *page.notify :notice, status_message, 5.0%>
-<%# *if source_view_is :project_list%>
-<%# *if @state_changed%>
-<%#*page[dom_id(@project, 'container')].remove%>
-<%#*page.insert_html :bottom, "list-#{@project.state}-projects", :partial => 'project_listing', :object => @project%>
-<%# *else%>
-<%#*page.replace_html dom_id(@project, 'container'), :partial => 'project_listing', :object => @project%>
-<%# *end%>
-<%#*page.sortable "list-#{@project.state}-projects", get_listing_sortable_options("list-#{@project.state}-projects")%>
-<%#*page.replace_html "active-projects-count", @active_projects_count%>
-<%#*page.replace_html "hidden-projects-count", @hidden_projects_count%>
-<%#*page.replace_html "completed-projects-count", @completed_projects_count%>
+function show_errors() {
+ $('div#error_status').html(html_for_error_messages());
+ $('div#error_status').show();
+}
-<%#*page.set_element_visible("list-hidden-projects-container", @hidden_projects_count > 0)%>
-<%#*page.set_element_visible("list-active-projects-container", @active_projects_count > 0)%>
-<%#*page.set_element_visible("list-completed-projects-container", @completed_projects_count > 0)%>
-<%# *else%>
-<%# *page[dom_id(@project, 'edit')].hide%>
-<%# *page.replace_html dom_id(@project, 'container'), :partial => 'project_settings', :locals => { :project => @project }%>
-<%# *page[dom_id(@project)].show%>
+function remove_project_edit_form() {
+ $('#<%=dom_id(@project, 'edit')%>').hide(500);
+}
-<%# *page['todo_context_name'].value = @project.default_context.name if @project.default_context%>
-<%# *page['#todo_project_name'].value = @project.name%>
-<%# *page['tag_list'].value = @project.default_tags if @project.default_tags%>
-<%# *page << "$('input[name=default_context_name]').val('#{@project.default_context.name}');" if @project.default_context%>
-<%# *end%>
+function update_and_show_project_settings() {
+ $('#<%=dom_id(@project, 'container')%>').html(html_for_project_settings());
+ $('#<%=dom_id(@project)%>').show();
+}
-<%# *page['default_project_name_id'].value = @project.name%>
-<%# *page['todo_project_name'].value = @project.name%>
-<%# *page.replace_html "project_name", @project.name%>
+function update_sidebar() {
+ $('#sidebar').html();
+}
-<%# *page.replace_html "sidebar", :file => 'sidebar/sidebar.html.erb'%>
-<%# *else%>
-<%# *page.show 'error_status'%>
-<%# *page.replace_html 'error_status', "#{error_messages_for('project')}"%>
-<%# *end%>
-<%# *page << "enable_rich_interaction();"%>
+function update_sortable() {
+ <%#* page.sortable "list-#{@project.state}-projects", get_listing_sortable_options("list-#{@project.state}-projects")%>
+ console.log("Pending: update_sortable() on update project");
+}
+
+function replace_project() {
+ $('#<%=dom_id(@project, 'container')%>').fadeOut(500, function() {
+ $('#<%=dom_id(@project, 'container')%>').html(html_for_project_listing());
+ $('#<%=dom_id(@project, 'container')%>').fadeIn(500);
+ });
+}
+
+function remove_project() {
+ $('#<%=dom_id(@project, 'container')%>').slideUp(500, function() {
+ $('#<%=dom_id(@project, 'container')%>').remove();});
+}
+
+function add_project() {
+ $('#list-<%=@project.state%>-projects').append(html_for_project_listing);
+}
+
+<%
+# the following functions return empty string if rendering the partial is not
+# necessary, for example the sidebar is not on the project list page, so do not
+# render it into the function.
+-%>
+function html_for_project_listing() {
+ return "<%= source_view_is(:project_list) ? escape_javascript(render(:partial => 'project_listing', :locals => { :project_listing => @project })) : "" %>";
+}
+
+function html_for_sidebar() {
+ return "<%= source_view_is(:project) ? escape_javascript(render(:file => 'sidebar/sidebar.html.erb')) : "" %>";
+}
+
+function html_for_project_settings() {
+ return "<%= source_view_is(:project) ? escape_javascript(render(:partial => 'project_settings', :locals => { :project => @project })) : "" %>";
+}
+
+function html_for_error_messages() {
+ return "<%= escape_javascript(error_messages_for('project')) %>";
+}
diff --git a/features/manage_list_of_projects.feature b/features/manage_list_of_projects.feature
index 14822f4a..e39cb6b7 100644
--- a/features/manage_list_of_projects.feature
+++ b/features/manage_list_of_projects.feature
@@ -17,7 +17,7 @@ Feature: Manage the list of projects
When I go to the projects page
Then I should see "manage me"
And I should see "upgrade jquery"
- And the badge should show 2
+ And the badge should show 3
Scenario: Clicking on a project takes me to the project page
When I go to the projects page
@@ -27,12 +27,26 @@ Feature: Manage the list of projects
@selenium
Scenario: Editing a project name will update the list
When I go to the projects page
- And I edit the project name for "manage me" to "manage him"
+ And I edit the project name of "manage me" to "manage him"
Then I should see "manage him"
- Scenario: Dragging a project to change list order of projects
+ @selenium
Scenario: Deleting a project will remove it from the list
+ When I go to the projects page
+ And I delete project "manage me"
+ Then I should not see "manage me"
+ And the badge should show 2
+ And the project list badge for "active" projects should show 2
+
+ @selenium
Scenario: Changing project state will move project to other state list
+ When I go to the projects page
+ Then the project "manage me" should be in state list "active"
+ When I edit the project state of "manage me" to "hidden"
+ Then the project "manage me" should not be in state list "active"
+ And the project "manage me" should be in state list "hidden"
+
+ Scenario: Dragging a project to change list order of projects
Scenario: Adding a new project
Scenario: Adding a new project and take me to the project page
Scenario: Hiding and unhiding the new project form
diff --git a/features/step_definitions/project_list_steps.rb b/features/step_definitions/project_list_steps.rb
new file mode 100644
index 00000000..4390112f
--- /dev/null
+++ b/features/step_definitions/project_list_steps.rb
@@ -0,0 +1,14 @@
+When /^I delete project "([^"]*)"$/ do |project_name|
+ # from the project list page
+ project = @current_user.projects.find_by_name(project_name)
+ project.should_not be_nil
+ click_link "delete_project_#{project.id}"
+ selenium.get_confirmation.should == "Are you sure that you want to delete the project '#{project_name}'?"
+ wait_for do
+ !selenium.is_element_present("delete_project_#{project.id}")
+ end
+end
+
+Then /^the project list badge for "([^"]*)" projects should show (\d+)$/ do |state_name, count|
+ selenium.get_text("css=span##{state_name}-projects-count").should == count
+end
\ No newline at end of file
diff --git a/features/step_definitions/project_steps.rb b/features/step_definitions/project_steps.rb
index d1733bfa..d380bc1a 100644
--- a/features/step_definitions/project_steps.rb
+++ b/features/step_definitions/project_steps.rb
@@ -42,12 +42,14 @@ end
When /^I edit the project name to "([^\"]*)"$/ do |new_title|
click_link "link_edit_project_#{@project.id}"
+
+ # no need to wait for the form because the AJAX loading should not be async!
fill_in "project[name]", :with => new_title
# changed to make sure selenium waits until the saving has a result either
# positive or negative. Was: :element=>"flash", :text=>"Project saved"
# we may need to change it back if you really need a positive outcome, i.e.
- # this step needs to fail if the project was not saved succesfully
+ # this step needs to fail if the project was not saved successfully
selenium.click "submit_project_#{@project.id}",
:wait_for => :text,
:text => /(Project saved|1 error prohibited this project from being saved)/
diff --git a/public/javascripts/application.js b/public/javascripts/application.js
index c5f2334b..1ccf4919 100644
--- a/public/javascripts/application.js
+++ b/public/javascripts/application.js
@@ -26,6 +26,37 @@ var TracksForm = {
toggle_overlay: function () {
el = document.getElementById("overlay");
el.style.visibility = (el.style.visibility == "visible") ? "hidden" : "visible";
+ },
+ set_project_name: function (name) {
+ $('input#todo_project_name').val(name);
+ },
+ set_context_name_and_default_context_name: function (name) {
+ $('input#todo_context_name').val(name);
+ $('input[name=default_context_name]').val(name);
+ },
+ set_project_name_and_default_project_name: function (name) {
+ $('#default_project_name_id').val(name);
+ $('input#todo_project_name').val();
+ $('#project_name').html(name);
+ },
+ set_tag_list: function (name) {
+ $('input#tag_list').val(name);
+ }
+}
+
+var ProjectListPage = {
+ update_state_count: function (active, hidden, completed) {
+ $('#active-projects-count').html(active);
+ $('#hidden-projects-count').html(hidden);
+ $('#completed-projects-count').html(completed);
+ },
+ show_or_hide_state_container: function (show_active, show_hidden, show_completed) {
+ active = $('#list-active-projects-container');
+ hidden = $('#list-hidden-projects-container');
+ completed = $('#list-completed-projects-container');
+ if (show_active) { active.show(); } else { active.hide(); }
+ if (show_hidden) { hidden.show(); } else { hidden.hide(); }
+ if (show_completed) { completed.show(); } else { completed.hide(); }
}
}
@@ -282,10 +313,11 @@ function enable_rich_interaction(){
$('h2#project_name').editable(save_project_name, {style: 'padding:0px', submit: "OK"});
- /* set behavior for edit project settings link */
+ /* set behavior for edit project settings link */
$("a.project_edit_settings").live('click', function (ev) {
$.ajax({
url: this.href,
+ async: true,
project_dom_id: 'project_'+this.id,
dataType: 'script',
beforeSend: function() {$(this.project_dom_id).block({message: null});},
@@ -314,7 +346,7 @@ function setup_auto_refresh(interval){
});
}
-function pageNotify(type, message, fade_duration_in_sec) {
+function page_notify(type, message, fade_duration_in_sec) {
flash = $('h4#flash');
flash.html(""+message+"
");
flash = $('h4#flash');
@@ -322,6 +354,10 @@ function pageNotify(type, message, fade_duration_in_sec) {
flash.fadeOut(fade_duration_in_sec*1000);
}
+function set_page_badge(count) {
+ $('#badge_count').html(count);
+}
+
function setup_periodic_check(url_for_check, interval_in_sec, method) {
ajaxMethod = "GET"
if (method) { ajaxMethod = method; }