From 42bea2490bfbf12797c9e0beb7294b13b11b16d1 Mon Sep 17 00:00:00 2001 From: Eric Allen Date: Sun, 1 Mar 2009 18:07:25 -0500 Subject: [PATCH 1/2] Fix #592 be able to set default tags for a project. Default tags can now be specified when creating or editing a project, and they will be applied to any new todos created in that project. --- app/controllers/todos_controller.rb | 10 ++++- app/views/projects/_project_form.rhtml | 4 ++ app/views/projects/index.html.erb | 4 ++ app/views/projects/show.html.erb | 43 ++++++++++++++----- ...90301154745_add_default_tags_to_project.rb | 9 ++++ public/stylesheets/standard.css | 3 ++ spec/controllers/projects_controller_spec.rb | 21 +++++++++ spec/controllers/todos_controller_spec.rb | 41 ++++++++++++++++++ 8 files changed, 122 insertions(+), 13 deletions(-) create mode 100644 db/migrate/20090301154745_add_default_tags_to_project.rb create mode 100644 spec/controllers/projects_controller_spec.rb create mode 100644 spec/controllers/todos_controller_spec.rb diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb index 12b2dbd4..8442763f 100644 --- a/app/controllers/todos_controller.rb +++ b/app/controllers/todos_controller.rb @@ -49,6 +49,7 @@ class TodosController < ApplicationController @source_view = params['_source_view'] || 'todo' p = TodoCreateParamsHelper.new(params, prefs) p.parse_dates() unless mobile? + tag_list = p.tag_list @todo = current_user.todos.build(p.attributes) @@ -56,6 +57,11 @@ class TodosController < ApplicationController project = current_user.projects.find_or_create_by_name(p.project_name) @new_project_created = project.new_record_before_save? @todo.project_id = project.id + if tag_list.blank? + tag_list = project.default_tags unless project.default_tags.blank? + else + tag_list += ','+project.default_tags unless project.default_tags.blank? + end end if p.context_specified_by_name? @@ -67,8 +73,8 @@ class TodosController < ApplicationController @todo.update_state_from_project @saved = @todo.save - unless (@saved == false) || p.tag_list.blank? - @todo.tag_with(p.tag_list) + unless (@saved == false) || tag_list.blank? + @todo.tag_with(tag_list) @todo.tags.reload end diff --git a/app/views/projects/_project_form.rhtml b/app/views/projects/_project_form.rhtml index 8aab07b9..10aa601a 100644 --- a/app/views/projects/_project_form.rhtml +++ b/app/views/projects/_project_form.rhtml @@ -19,6 +19,10 @@ <%= render :partial => 'default_context_autocomplete' %>
+
+ <%= text_field_tag("project[default_tags]", project.default_tags, {:tabindex=>2,:size=> 25}) %> +
+
diff --git a/app/views/projects/index.html.erb b/app/views/projects/index.html.erb index e8c7ec54..a694b5ed 100644 --- a/app/views/projects/index.html.erb +++ b/app/views/projects/index.html.erb @@ -44,6 +44,10 @@
<% end -%> +
+ <%= text_field_tag("project[default_tags]", @project.default_tags, :tabindex => 4) %> +
+
diff --git a/app/views/projects/show.html.erb b/app/views/projects/show.html.erb index a4abee09..121f2e5e 100644 --- a/app/views/projects/show.html.erb +++ b/app/views/projects/show.html.erb @@ -57,20 +57,41 @@

Default Context

<% form_remote_tag( :url => project_path(@project), :method => :put, - :html=> { :id => 'set-default-context-action', - :name => 'default_context', - :class => 'inline-form' }) do -%> - <%= hidden_field_tag("update_default_context", true) %> - <%= text_field_tag("project[default_context_name]", - @project.default_context.name, - { :tabindex => 9,:size => 25 }) %> - <%= submit_tag "Set Default Context for this Project", { :tabindex => 10 } %> - <%= render :partial => 'default_context_autocomplete' %> - <% end -%> + :html=> { :id => 'set-default-context-action', + :name => 'default_context', + :class => 'inline-form' }) do -%> + <%= hidden_field_tag("update_default_context", true) %> + <%= text_field_tag("project[default_context_name]", + @project.default_context.name, + { :tabindex => 9,:size => 25 }) %> + <%= submit_tag "Set Default Context for this Project", { :tabindex => 10 } %> + <%= render :partial => 'default_context_autocomplete' %> + <% end -%>
-
+ +
+
+

Default Tags

+
+ <% form_remote_tag( :url => project_path(@project), :method => :put, + :html=> { :id => 'set-default-tags-action', + :name => 'default_tags', + :class => 'inline-form' }) do -%> + <%= hidden_field_tag("update_default_tags", true) %> + <%= text_field_tag("project[default_tags]", + @project.default_tags, + { :tabindex => 11,:size => 25 }) %> + <%= submit_tag "Set Default Tags for this Project", { :tabindex => 12 } %> + <% end -%> +
+
+
+ + + +
<%= render :partial => "shared/add_new_item_form" %> diff --git a/db/migrate/20090301154745_add_default_tags_to_project.rb b/db/migrate/20090301154745_add_default_tags_to_project.rb new file mode 100644 index 00000000..378edbd7 --- /dev/null +++ b/db/migrate/20090301154745_add_default_tags_to_project.rb @@ -0,0 +1,9 @@ +class AddDefaultTagsToProject < ActiveRecord::Migration + def self.up + add_column :projects, :default_tags, :string + end + + def self.down + remove_column :projects, :default_tags + end +end diff --git a/public/stylesheets/standard.css b/public/stylesheets/standard.css index 8ad037b7..fbc7ded0 100644 --- a/public/stylesheets/standard.css +++ b/public/stylesheets/standard.css @@ -480,6 +480,9 @@ div#project_status > div { div#default_context > div{ padding:10px; } +div#default_tags > div{ + padding:10px; +} a.footer_link {color: #cc3334; font-style: normal;} a.footer_link:hover {color: #fff; background-color: #cc3334 !important;} diff --git a/spec/controllers/projects_controller_spec.rb b/spec/controllers/projects_controller_spec.rb new file mode 100644 index 00000000..98e77093 --- /dev/null +++ b/spec/controllers/projects_controller_spec.rb @@ -0,0 +1,21 @@ +require File.dirname(__FILE__) + '/../spec_helper' + +describe ProjectsController do + it "should save default tags" do + project = Project.new + + projects = mock(:project_list, :build => project, + :active => mock(:meh, :count => 0), :size => 0) + + user = mock_model(User, :projects => projects, :prefs => {}, + :contexts => mock(:context_list, :find => [])) + controller.stub!(:current_user).and_return(user) + controller.stub!(:login_required).and_return(true) + controller.stub!(:set_time_zone).and_return(true) + controller.stub!(:mobile?).and_return(true) + + get 'create', :project => {:name => "fooproject", :default_tags => "a,b"} + + project.default_tags.should == 'a,b' + end +end diff --git a/spec/controllers/todos_controller_spec.rb b/spec/controllers/todos_controller_spec.rb new file mode 100644 index 00000000..3ef2c590 --- /dev/null +++ b/spec/controllers/todos_controller_spec.rb @@ -0,0 +1,41 @@ +require File.dirname(__FILE__) + '/../spec_helper' + +describe TodosController do + it "should add project's default tags to todos" do + p = mock_model(Project, :new_record_before_save? => false) + p.should_receive(:default_tags).twice.and_return('abcd,efgh') + todo = mock_model(Todo, :save => true, :update_state_from_project => nil, + :tags => mock(:tag_list, :reload => nil)) + todo.stub!(:project_id=) + todo.should_receive(:tag_with).with('abcd,efgh') + projects = mock(:project_list, :find_or_create_by_name => p, :find => [p]) + todos = mock(:todo_list, :build => todo) + + user = mock_model(User, :todos => todos, :projects => projects, :prefs => {}, + :contexts => mock(:context_list, :find => [])) + controller.stub!(:current_user).and_return(user) + controller.stub!(:login_required).and_return(true) + controller.stub!(:set_time_zone).and_return(true) + controller.stub!(:mobile?).and_return(true) + get 'create', :project_name => "zzzz", :tag_list => '', :todo => {} + end + + it "should append project's default tags to todos" do + p = mock_model(Project, :new_record_before_save? => false) + p.should_receive(:default_tags).twice.and_return('abcd,efgh') + todo = mock_model(Todo, :save => true, :update_state_from_project => nil, + :tags => mock(:tag_list, :reload => nil)) + todo.stub!(:project_id=) + todo.should_receive(:tag_with).with('111,222,abcd,efgh') + projects = mock(:project_list, :find_or_create_by_name => p, :find => [p]) + todos = mock(:todo_list, :build => todo) + + user = mock_model(User, :todos => todos, :projects => projects, :prefs => {}, + :contexts => mock(:context_list, :find => [])) + controller.stub!(:current_user).and_return(user) + controller.stub!(:login_required).and_return(true) + controller.stub!(:set_time_zone).and_return(true) + controller.stub!(:mobile?).and_return(true) + get 'create', :project_name => "zzzz", :tag_list => '111,222', :todo => {} + end +end From 5b694bdf65b54cdaef458402382498697a6525c8 Mon Sep 17 00:00:00 2001 From: Eric Allen Date: Wed, 15 Apr 2009 23:09:55 -0400 Subject: [PATCH 2/2] Don't allow defer past due date and popup with warning. Fixes #848. --- app/helpers/todos_helper.rb | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 8e1aa83e..1ffd964f 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -60,11 +60,21 @@ module TodosHelper url = {:controller => 'todos', :action => 'defer', :id => todo.id, :days => days, :_source_view => (@source_view.underscore.gsub(/\s+/,'_') rescue "")} url[:_tag_name] = @tag_name if @source_view == 'tag' - return link_to_remote( - image_tag("defer_#{days}_off.png", :mouseover => "defer_#{days}.png", :alt => "", :align => "absmiddle")+" Defer #{pluralize(days, "day")}", - :url => url, - :before => todo_start_waiting_js(todo), - :complete => todo_stop_waiting_js) + + futuredate = (@todo.show_from || @todo.user.date) + days.days + puts "DUE: #{@todo.due}, futuredate: #{futuredate}" + if @todo.due && futuredate > @todo.due + return link_to_function( + image_tag("defer_#{days}_off.png", :mouseover => "defer_#{days}.png", :alt => "", :align => "absmiddle")+" Defer #{pluralize(days, "day")}", + "alert('Defer date is after due date. Please edit and adjust due date before deferring.')" + ) + else + return link_to_remote( + image_tag("defer_#{days}_off.png", :mouseover => "defer_#{days}.png", :alt => "", :align => "absmiddle")+" Defer #{pluralize(days, "day")}", + :url => url, + :before => todo_start_waiting_js(todo), + :complete => todo_stop_waiting_js) + end end def todo_start_waiting_js(todo) @@ -276,13 +286,5 @@ module TodosHelper def image_tag_for_star(todo) class_str = todo.starred? ? "starred_todo" : "unstarred_todo" image_tag("blank.png", :title =>"Star action", :class => class_str) - end - - def defer_link(days) - url = {:controller => 'todos', :action => 'defer', :id => @todo.id, :days => days, - :_source_view => (@source_view.underscore.gsub(/\s+/,'_') rescue "")} - url[:_tag_name] = @tag_name if @source_view == 'tag' - link_to_remote image_tag("defer_#{days}.png", :alt => "Defer #{pluralize(days, 'day')}"), :url => url end - end