migrate edit update and destroy to jQuery and refactor it

test for changing state is wip, forgot to mark it with @wip
This commit is contained in:
Reinier Balt 2010-10-07 23:24:50 +02:00
parent ee4ef4ad42
commit 35453acd57
12 changed files with 198 additions and 105 deletions

View file

@ -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
@ -202,6 +201,15 @@ class ProjectsController < ApplicationController
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')

View file

@ -111,6 +111,12 @@ module ApplicationHelper
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} )
end

View file

@ -13,24 +13,15 @@ suppress_edit_button ||= false
<%= link_to_project( project ) %><%= " (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %>
</div>
<div class="buttons">
<span class="grey"><%= t('states.' + project.current_state.to_s).upcase %></span>
<a class="delete_project_button"
href="<%= project_path(project, :format => 'js') %>"
title="<%= t('projects.delete_project_title') %> '<%= project.name %>'"><%= image_tag( "blank.png",
:title => t('projects.delete_project'),
:class=>"delete_item") %></a>
<span class="grey"><%= project.current_state.to_s.upcase %></span>
<a class="delete_project_button" id="delete_project_<%= project.id%> " href="<%= project_path(project, :format => 'js') %>"
title="<%= t('projects.delete_project_title') %> '<%= project.name %>'">
<%= image_tag( "blank.png", :title => t('projects.delete_project'), :class=>"delete_item") %>
</a>
<% unless suppress_edit_button -%>
<%= link_to_remote(
image_tag( "blank.png", :title => t('projects.edit_project_title'), :class=>"edit_item"),
: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, image_tag( "blank.png", :title => t('projects.edit_project_title'), :class=>"edit_item")) %>
<% end -%>
</div>
</div>

View file

@ -14,16 +14,7 @@
<% else -%>
'<%= project.default_tags -%>' as the default tags.
<% end -%>
<a class ="project_edit_settings" id="link_edit_<%=dom_id(project)-%>" href="<%=url_for(:controller => 'projects', :action => 'edit', :id => project.id)%>">Edit Project Settings</a>
<%#= 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") %>
</div>
<% unless project.description.blank? -%>
<div class="project_description"><%= format_note(project.description) %></div>

View file

@ -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()
});
}

View file

@ -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"

View file

@ -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();

View file

@ -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%>
function show_errors() {
$('div#error_status').html(html_for_error_messages());
$('div#error_status').show();
}
function remove_project_edit_form() {
$('#<%=dom_id(@project, 'edit')%>').hide(500);
}
function update_and_show_project_settings() {
$('#<%=dom_id(@project, 'container')%>').html(html_for_project_settings());
$('#<%=dom_id(@project)%>').show();
}
function update_sidebar() {
$('#sidebar').html();
}
function update_sortable() {
<%#* 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%>
console.log("Pending: update_sortable() on update project");
}
<%#*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 replace_project() {
$('#<%=dom_id(@project, 'container')%>').fadeOut(500, function() {
$('#<%=dom_id(@project, 'container')%>').html(html_for_project_listing());
$('#<%=dom_id(@project, 'container')%>').fadeIn(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 remove_project() {
$('#<%=dom_id(@project, 'container')%>').slideUp(500, function() {
$('#<%=dom_id(@project, 'container')%>').remove();});
}
<%# *page['default_project_name_id'].value = @project.name%>
<%# *page['todo_project_name'].value = @project.name%>
<%# *page.replace_html "project_name", @project.name%>
function add_project() {
$('#list-<%=@project.state%>-projects').append(html_for_project_listing);
}
<%# *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();"%>
<%
# 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')) %>";
}

View file

@ -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

View file

@ -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

View file

@ -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)/

View file

@ -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(); }
}
}
@ -286,6 +317,7 @@ function enable_rich_interaction(){
$("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("<h4 id=\'flash\' class=\'alert "+type+"\'>"+message+"</h4>");
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; }