diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index 2baffa1a..2364ea97 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -163,6 +163,7 @@ class ProjectsController < ApplicationController end 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 diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb index 5aa985ba..387c7689 100644 --- a/app/controllers/users_controller.rb +++ b/app/controllers/users_controller.rb @@ -71,9 +71,17 @@ class UsersController < ApplicationController render :action => "nosignup", :layout => "login" return end - + user = User.new(params['user']) + if Tracks::Config.auth_schemes.include?('ldap') && + user.auth_type == 'ldap' && + !SimpleLdapAuthenticator.valid?(user.login, params['user']['password']) + notify :warning, "Incorrect password" + redirect_to :action => 'new' + return + end + if Tracks::Config.auth_schemes.include?('cas') if user.auth_type.eql? "cas" user.crypted_password = "cas" diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 76622c50..a6b51172 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -196,17 +196,21 @@ module ApplicationHelper # do not change string; URL is alreay linked href else - content_tag(:a, h(href), :href => h(href)) + content = content_tag(:a, h(href), :href => h(href)) end end end def format_note(note) - note.gsub!(/, '<') # eliminate tags - note.gsub!(/>/, '>') - note = markdown(note) note = auto_link_message(note) - note = auto_link(note) + note = markdown(note) + note = auto_link(note, :link => :urls) + + # add onenote and message protocols + Sanitize::Config::RELAXED[:protocols]['a']['href'] << 'onenote' + Sanitize::Config::RELAXED[:protocols]['a']['href'] << 'message' + + note = Sanitize.clean(note, Sanitize::Config::RELAXED) return note end end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index 6c8703c6..994fb305 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -122,7 +122,7 @@ module TodosHelper :title => 'Drag onto another action to make it depend on that action', :class => 'grip') + image_tag('blank.png', :width => 16, :height => 16, :border => 0, - :title => "Drop an action to make it depend on this action", :class => 'successor_target') + :title => "Drop an action to make it depend on this action", :class => 'successor_target drop_target') end end diff --git a/app/models/context.rb b/app/models/context.rb index 41d27a53..a7d79f72 100644 --- a/app/models/context.rb +++ b/app/models/context.rb @@ -1,6 +1,7 @@ class Context < ActiveRecord::Base has_many :todos, :dependent => :delete_all, :include => :project, :order => "todos.completed_at DESC" + has_many :recurring_todos, :dependent => :delete_all belongs_to :user named_scope :active, :conditions => { :hide => false } diff --git a/app/models/project.rb b/app/models/project.rb index 88053a1c..20a75f97 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -27,6 +27,7 @@ class Project < ActiveRecord::Base :order => "show_from" has_many :notes, :dependent => :delete_all, :order => "created_at DESC" + has_many :recurring_todos belongs_to :default_context, :class_name => "Context", :foreign_key => "default_context_id" belongs_to :user diff --git a/app/models/recurring_todo.rb b/app/models/recurring_todo.rb index 353ce0ca..86c549f1 100644 --- a/app/models/recurring_todo.rb +++ b/app/models/recurring_todo.rb @@ -6,6 +6,9 @@ class RecurringTodo < ActiveRecord::Base has_many :todos + named_scope :active, :conditions => { :state => 'active'} + named_scope :completed, :conditions => { :state => 'completed'} + attr_protected :user acts_as_state_machine :initial => :active, :column => 'state' @@ -15,22 +18,91 @@ class RecurringTodo < ActiveRecord::Base t.occurences_count = 0 } state :completed, :enter => Proc.new { |t| t.completed_at = Time.zone.now }, :exit => Proc.new { |t| t.completed_at = nil } + + event :complete do + transitions :to => :completed, :from => [:active] + end + + event :activate do + transitions :to => :active, :from => [:completed] + end validates_presence_of :description + validates_presence_of :recurring_period validates_length_of :description, :maximum => 100 validates_length_of :notes, :maximum => 60000, :allow_nil => true validates_presence_of :context - named_scope :active, :conditions => { :state => 'active'} - named_scope :completed, :conditions => { :state => 'completed'} - - event :complete do - transitions :to => :completed, :from => [:active] - end + validate :period_specific_validations + validate :starts_and_ends_on_validations - event :activate do - transitions :to => :active, :from => [:completed] + def period_specific_validations + periods = %W[daily weekly monthly yearly] + if periods.include?(recurring_period) + self.send("validate_#{recurring_period}") + else + errors.add(:recurring_period, "is an unknown recurrence pattern: '#{self.recurring_period}'") + end + end + + def validate_daily + if (!only_work_days) && (daily_every_x_days.nil? || daily_every_x_days.blank?) + errors.add_to_base("Every other nth day may not be empty for recurrence setting") + end + end + + def validate_weekly + if weekly_every_x_week.nil? || weekly_every_x_week.blank? + errors.add_to_base("Every other nth week may not be empty for recurrence setting") + end + something_set = false + %w{sunday monday tuesday wednesday thursday friday}.each do |day| + something_set ||= self.send("on_#{day}") + + end + errors.add_to_base("You must specify at least one day on which the todo recurs") if !something_set + end + + def validate_monthly + case recurrence_selector + when 0 # 'monthly_every_x_day' + errors.add_to_base("The day of the month may not be empty for recurrence setting") if monthly_every_x_day.nil? || monthly_every_x_day.blank? + errors.add_to_base("Every other nth month may not be empty for recurrence setting") if monthly_every_x_month.nil? || monthly_every_x_month.blank? + when 1 # 'monthly_every_xth_day' + errors.add_to_base("Every other nth month may not be empty for recurrence setting") if monthly_every_x_month2.nil? || monthly_every_x_month2.blank? + errors.add_to_base("The nth day of the month may not be empty for recurrence setting") if monthly_every_xth_day.nil? || monthly_every_xth_day.blank? + errors.add_to_base("The day of the month may not be empty for recurrence setting") if monthly_day_of_week.nil? || monthly_day_of_week.blank? + else + raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'" + end + end + + def validate_yearly + case recurrence_selector + when 0 # 'yearly_every_x_day' + errors.add_to_base("The month of the year may not be empty for recurrence setting") if yearly_month_of_year.nil? || yearly_month_of_year.blank? + errors.add_to_base("The day of the month may not be empty for recurrence setting") if yearly_every_x_day.nil? || yearly_every_x_day.blank? + when 1 # 'yearly_every_xth_day' + errors.add_to_base("The month of the year may not be empty for recurrence setting") if yearly_month_of_year2.nil? || yearly_month_of_year2.blank? + errors.add_to_base("The nth day of the month may not be empty for recurrence setting") if yearly_every_xth_day.nil? || yearly_every_xth_day.blank? + errors.add_to_base("The day of the week may not be empty for recurrence setting") if yearly_day_of_week.nil? || yearly_day_of_week.blank? + else + raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'" + end + end + + + def starts_and_ends_on_validations + errors.add_to_base("The start date needs to be filled in") if start_from.nil? || start_from.blank? + case self.ends_on + when 'ends_on_number_of_times' + errors.add_to_base("The number of recurrences needs to be filled in for 'Ends on'") if number_of_occurences.nil? || number_of_occurences.blank? + when "ends_on_end_date" + errors.add_to_base("The end date needs to be filled in for 'Ends on'") if end_date.nil? || end_date.blank? + else + errors.add_to_base("The end of the recurrence is not selected") unless ends_on == "no_end_date" + end end # the following recurrence patterns can be stored: @@ -64,7 +136,7 @@ class RecurringTodo < ActiveRecord::Base when 'daily_every_work_day' self.only_work_days = true else - raise Exception.new, "unknown daily recurrence pattern: '#{selector}'" + raise Exception.new, "unknown daily recurrence pattern: '#{selector}'" end end @@ -199,7 +271,7 @@ class RecurringTodo < ActiveRecord::Base end end - def monthly_every_x_month2=(x) + def monthly_every_x_month2=(x) self.every_other2 = x if recurring_period=='monthly' && recurrence_selector == 1 end @@ -214,7 +286,7 @@ class RecurringTodo < ActiveRecord::Base end def monthly_every_xth_day=(x) - self.every_other3 = x if recurring_period=='monthly' + self.every_other3 = x if recurring_period=='monthly' end def monthly_every_xth_day(default=nil) @@ -318,6 +390,7 @@ class RecurringTodo < ActiveRecord::Base def recurrence_pattern case recurring_period when 'daily' + return "invalid repeat pattern" if every_other1.nil? if only_work_days return "on work days" else @@ -328,18 +401,21 @@ class RecurringTodo < ActiveRecord::Base end end when 'weekly' + return "invalid repeat pattern" if every_other1.nil? if every_other1 > 1 return "every #{every_other1} weeks" else return 'weekly' end when 'monthly' + return "invalid repeat pattern" if every_other1.nil? || every_other2.nil? if self.recurrence_selector == 0 return "every #{self.every_other2} month#{self.every_other2>1?'s':''} on day #{self.every_other1}" else return "every #{self.xth} #{self.day_of_week} of every #{self.every_other2} month#{self.every_other2>1?'s':''}" end when 'yearly' + return "invalid repeat pattern" if every_other1.nil? if self.recurrence_selector == 0 return "every year on #{self.month_of_year} #{self.every_other1}" else @@ -348,7 +424,7 @@ class RecurringTodo < ActiveRecord::Base else return 'unknown recurrence pattern: period unknown' end - end + end def xth xth_day = ['first','second','third','fourth','last'] @@ -382,9 +458,9 @@ class RecurringTodo < ActiveRecord::Base end def get_show_from_date(previous) - case self.target + case self.target when 'due_date' - # so set show from date relative to due date unless show_always is true or show_from_delta is nil + # so set show from date relative to due date unless show_always is true or show_from_delta is nil if self.show_always? or self.show_from_delta.nil? nil else @@ -400,17 +476,17 @@ class RecurringTodo < ActiveRecord::Base def get_next_date(previous) case self.recurring_period - when 'daily' + when 'daily' return get_daily_date(previous) - when 'weekly' + when 'weekly' return get_weekly_date(previous) - when 'monthly' + when 'monthly' return get_monthly_date(previous) when 'yearly' return get_yearly_date(previous) else raise Exception.new, "unknown recurrence pattern: '#{self.recurring_period}'" - end + end end def get_daily_date(previous) @@ -430,7 +506,7 @@ class RecurringTodo < ActiveRecord::Base unless self.start_from.nil? # check if the start_from date is later than previous. If so, use # start_from as start to search for next date - start = self.start_from if self.start_from > previous + start = self.start_from if self.start_from > previous end end @@ -457,7 +533,7 @@ class RecurringTodo < ActiveRecord::Base start = self.start_from.nil? ? Time.zone.now : self.start_from else start = previous + 1.day - if start.wday() == 0 + if start.wday() == 0 # we went to a new week , go to the nth next week and find first match # that week start += self.every_other1.week @@ -465,7 +541,7 @@ class RecurringTodo < ActiveRecord::Base unless self.start_from.nil? # check if the start_from date is later than previous. If so, use # start_from as start to search for next date - start = self.start_from if self.start_from > previous + start = self.start_from if self.start_from > previous end end @@ -483,7 +559,7 @@ class RecurringTodo < ActiveRecord::Base return start + (i-start.wday()).days unless self.every_day[i,1] == ' ' end - raise Exception.new, "unable to find next weekly date (#{self.every_day})" + raise Exception.new, "unable to find next weekly date (#{self.every_day})" end def get_monthly_date(previous) @@ -531,7 +607,7 @@ class RecurringTodo < ActiveRecord::Base end return the_next else - raise Exception.new, "unknown monthly recurrence selection (#{self.recurrence_selector})" + raise Exception.new, "unknown monthly recurrence selection (#{self.recurrence_selector})" end return nil end @@ -557,7 +633,7 @@ class RecurringTodo < ActiveRecord::Base start+= 1.day end n -= 1 - start += 1.day unless n==0 + start += 1.day unless n==0 end # convert back to local timezone return Time.zone.local(start.year, start.month, start.day) @@ -574,10 +650,10 @@ class RecurringTodo < ActiveRecord::Base if start.month > month || (start.month == month && start.day >= day) # if there is no next month n and day m in this year, search in next # year - start = Time.zone.local(start.year+1, month, 1) + start = Time.zone.local(start.year+1, month, 1) else # if there is a next month n, stay in this year - start = Time.zone.local(start.year, month, 1) + start = Time.zone.local(start.year, month, 1) end return Time.zone.local(start.year, month, day) @@ -594,7 +670,7 @@ class RecurringTodo < ActiveRecord::Base return the_next else - raise Exception.new, "unknown monthly recurrence selection (#{self.recurrence_selector})" + raise Exception.new, "unknown monthly recurrence selection (#{self.recurrence_selector})" end return nil end @@ -635,10 +711,15 @@ class RecurringTodo < ActiveRecord::Base else _add_tags(Todo::STARRED_TAG_NAME) tags.reload - end - starred? + end + starred? end + def remove_from_project! + self.project = nil + self.save + end + def inc_occurences self.occurences_count += 1 self.save @@ -659,7 +740,7 @@ class RecurringTodo < ActiveRecord::Base unless self.start_from.nil? # check if the start_from date is later than previous. If so, use # start_from as start to search for next date - start = self.start_from if self.start_from > previous + start = self.start_from if self.start_from > previous end end return start diff --git a/app/models/todo.rb b/app/models/todo.rb index 82c19cb2..7fd64628 100644 --- a/app/models/todo.rb +++ b/app/models/todo.rb @@ -286,7 +286,15 @@ class Todo < ActiveRecord::Base def active_to_block return successors.find_all {|t| t.active? or t.deferred?} end - + + def notes=(value) + super(value.try(:gsub, /, '<').try(:gsub, />/, '>')) + end + + def raw_notes=(value) + self[:notes] = value + end + # Rich Todo API def self.from_rich_message(user, default_context_id, description, notes) @@ -324,7 +332,7 @@ class Todo < ActiveRecord::Base todo = user.todos.build todo.description = description - todo.notes = notes + todo.raw_notes = notes todo.context_id = context_id todo.project_id = project_id unless project_id.nil? return todo diff --git a/app/views/contexts/_context.rhtml b/app/views/contexts/_context.rhtml index c95c93b9..7b33ee9a 100644 --- a/app/views/contexts/_context.rhtml +++ b/app/views/contexts/_context.rhtml @@ -16,4 +16,5 @@ <%= render :partial => "todos/todo", :collection => @not_done, :locals => { :parent_container_type => "context" } %> +
diff --git a/app/views/contexts/_context_listing.rhtml b/app/views/contexts/_context_listing.rhtml index f8c80b48..df90a138 100644 --- a/app/views/contexts/_context_listing.rhtml +++ b/app/views/contexts/_context_listing.rhtml @@ -35,7 +35,8 @@ :method => 'get', :with => "'_source_view=#{@source_view}'", :before => "$('#{dom_id(context)}').block({message:null});", - :complete => "$('#{dom_id(context)}').unblock();" + :complete => "$('#{dom_id(context)}').unblock();", + :html => {:id => "edit_context_#{context.id}_link"} ) %> diff --git a/app/views/login/login.html.erb b/app/views/login/login.html.erb index b4a1dda5..c651165a 100644 --- a/app/views/login/login.html.erb +++ b/app/views/login/login.html.erb @@ -1,5 +1,5 @@ <% auth_schemes = Tracks::Config.auth_schemes - show_database_form = auth_schemes.include?('database') + show_database_form = auth_schemes.include?('database') || auth_schemes.include?('ldap') show_openid_form = auth_schemes.include?('open_id') show_cas_form = auth_schemes.include?('cas') -%> diff --git a/app/views/todos/update.js.rjs b/app/views/todos/update.js.rjs index 6cdf7367..d15595f5 100644 --- a/app/views/todos/update.js.rjs +++ b/app/views/todos/update.js.rjs @@ -153,3 +153,5 @@ else page.show 'error_status' page.replace_html 'error_status', "#{error_messages_for('todo')}" end + +page << "enable_rich_interaction();" diff --git a/config/environment.rb b/config/environment.rb index 0b26e5eb..981ebeb2 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -23,6 +23,7 @@ Rails::Initializer.run do |config| config.gem "RedCloth" config.gem "soap4r", :lib => false config.gem 'datanoise-actionwebservice', :lib => 'actionwebservice' + config.gem 'sanitize' config.action_controller.use_accept_header = true diff --git a/features/step_definitions/context_steps.rb b/features/step_definitions/context_steps.rb index 58813a63..9bab68a5 100644 --- a/features/step_definitions/context_steps.rb +++ b/features/step_definitions/context_steps.rb @@ -23,7 +23,7 @@ Then /^he should see that a context named "([^\"]*)" is present$/ do |context_na end Then /^he should see that a context named "([^\"]*)" is not present$/ do |context_name| - Then "I should not see \"#{context_name}\"" + Then "I should not see \"#{context_name} (\"" end Given /^I have a context "([^\"]*)" with (.*) actions$/ do |context_name, number_of_actions| @@ -38,10 +38,16 @@ When /^I delete the context "([^\"]*)"$/ do |context_name| context.should_not be_nil click_link "delete_context_#{context.id}" selenium.get_confirmation.should == "Are you sure that you want to delete the context '#{context_name}'?" + wait_for do + !selenium.is_element_present("delete_context_#{context.id}") + end end When /^I edit the context to rename it to "([^\"]*)"$/ do |new_name| click_link "edit_context_#{@context.id}" fill_in "context_name", :with => new_name click_button "submit_context_#{@context.id}" + wait_for do + selenium.is_visible("flash") + end end diff --git a/features/step_definitions/generic_steps.rb b/features/step_definitions/generic_steps.rb index 5e1b684f..506bb493 100644 --- a/features/step_definitions/generic_steps.rb +++ b/features/step_definitions/generic_steps.rb @@ -3,7 +3,7 @@ Then /the badge should show (.*)/ do |number| badge = -1 xpath= "//span[@id='badge_count']" - if Rails.env == 'selenium' + if response.respond_to? :selenium response.should have_xpath(xpath) badge = response.selenium.get_text("xpath=#{xpath}").to_i else diff --git a/features/step_definitions/note_steps.rb b/features/step_definitions/note_steps.rb index 93fab0f6..630f974d 100644 --- a/features/step_definitions/note_steps.rb +++ b/features/step_definitions/note_steps.rb @@ -26,8 +26,10 @@ When /^I add note "([^\"]*)" from the "([^\"]*)" project page$/ do |note, projec end When /^I delete the first note$/ do + title = selenium.get_text("css=div.container h2") + id = title.split(' ').last click_link "delete note" - selenium.get_confirmation.should == "Are you sure that you want to delete the note '1'?" + selenium.get_confirmation.should == "Are you sure that you want to delete the note '#{id}'?" end When /^I click the icon next to the note$/ do @@ -53,8 +55,11 @@ Then /^I should see note "([^\"]*)" on the notes page$/ do |note| end Then /^the first note should disappear$/ do - # the first note contains "A note 1", generated by the Given def above - Then "I should not see \"A note 1\"" + title = selenium.get_text("css=div.container h2") + id = title.split(' ').last + wait_for :timeout => 15 do + !selenium.is_visible("note_#{id}") + end end diff --git a/features/step_definitions/project_steps.rb b/features/step_definitions/project_steps.rb index f08d349d..801104c9 100644 --- a/features/step_definitions/project_steps.rb +++ b/features/step_definitions/project_steps.rb @@ -33,7 +33,6 @@ Then /^I should see the bold text "([^\"]*)" in the project description$/ do |bo response.should have_xpath(xpath) bold_text = response.selenium.get_text("xpath=#{xpath}") - puts "bt=#{bold_text}" bold_text.should =~ /#{bold}/ end @@ -43,6 +42,5 @@ Then /^I should see the italic text "([^\"]*)" in the project description$/ do | response.should have_xpath(xpath) italic_text = response.selenium.get_text("xpath=#{xpath}") - puts "it=#{italic_text}" italic_text.should =~ /#{italic}/ -end \ No newline at end of file +end diff --git a/lib/login_system.rb b/lib/login_system.rb index 4ad9312c..e3c5a779 100644 --- a/lib/login_system.rb +++ b/lib/login_system.rb @@ -189,7 +189,7 @@ module LoginSystem end def basic_auth_denied - response.headers["Status"] = "Unauthorized" + response.headers["Status"] = "401 Unauthorized" response.headers["WWW-Authenticate"] = "Basic realm=\"'Tracks Login Required'\"" render :text => "401 Unauthorized: You are not authorized to interact with Tracks.", :status => 401 end diff --git a/public/javascripts/application.js b/public/javascripts/application.js index 522081d8..cfe11d2e 100644 --- a/public/javascripts/application.js +++ b/public/javascripts/application.js @@ -14,16 +14,14 @@ var TracksForm = { toggleDiv.toggleClass('hide_form'); }, hide_all_recurring: function () { - $('#recurring_daily').hide(); - $('#recurring_weekly').hide(); - $('#recurring_monthly').hide(); - $('#recurring_yearly').hide(); + $.each(['daily', 'weekly', 'monthly', 'yearly'], function(){ + $('#recurring_'+this).hide(); + }); }, hide_all_edit_recurring: function () { - $('#recurring_edit_daily').hide(); - $('#recurring_edit_weekly').hide(); - $('#recurring_edit_monthly').hide(); - $('#recurring_edit_yearly').hide(); + $.each(['daily', 'weekly', 'monthly', 'yearly'], function(){ + $('#recurring_edit_'+this).hide(); + }); }, toggle_overlay: function () { el = document.getElementById("overlay"); @@ -141,6 +139,17 @@ function setup_container_toggles(){ function askIfNewContextProvided() { var givenContextName = $('#todo_context_name').val(); + var contextNames = []; + var contextNamesRequest = $.ajax({url: relative_to_root('contexts.autocomplete'), + async: false, + dataType: "text", + data: "q="+givenContextName, + success: function(result){ + lines = result.split("\n"); + for(var i = 0; i < lines.length; i++){ + contextNames.push(lines[i].split("|")[0]); + } + }}); if (givenContextName.length == 0) return true; // do nothing and depend on rails validation error for (var i = 0; i < contextNames.length; ++i) { if (contextNames[i] == givenContextName) return true; @@ -221,21 +230,46 @@ function enable_rich_interaction(){ function drop_todo(evt, ui) { dragged_todo = ui.draggable[0].id.split('_')[2]; dropped_todo = $(this).parents('.item-show').get(0).id.split('_')[2]; - ui.draggable.hide(); + ui.draggable.remove(); $(this).block({message: null}); $.post(relative_to_root('todos/add_predecessor'), {successor: dragged_todo, predecessor: dropped_todo}, null, 'script'); } + function drag_todo(){ + $('.drop_target').show(); + $(this).parents(".container").find(".context_target").hide(); + } + $('.item-show').draggable({handle: '.grip', revert: 'invalid', - start: function() {$('.successor_target').show();}, - stop: function() {$('.successor_target').hide();}}); + start: drag_todo, + stop: function() {$('.drop_target').hide();}}); $('.successor_target').droppable({drop: drop_todo, tolerance: 'pointer', hoverClass: 'hover'}); + + /* Drag & drop for changing contexts */ + function drop_todo_on_context(evt, ui) { + target = $(this); + dragged_todo = ui.draggable[0].id.split('_')[2]; + context_id = this.id.split('_')[1]; + ui.draggable.remove(); + target.block({message: null}); + setTimeout(function() {target.show()}, 0); + $.post(relative_to_root('todos/update'), + {id: dragged_todo, + "todo[id]": dragged_todo, + "todo[context_id]": context_id}, + function(){target.unblock(); target.hide();}, 'script'); + } + + $('.context_target').droppable({ + drop: drop_todo_on_context, + tolerance: 'pointer', + hoverClass: 'hover'}); /* Reset auto updater */ field_touched = false; @@ -399,16 +433,12 @@ $(document).ready(function() { TracksForm.toggle_overlay(); }); $("#recurring_edit_period input").live('click', function(){ - $.each(['daily', 'weekly', 'monthly', 'yearly'], function(){ - $('#recurring_edit_'+this).hide(); - }); + TracksForm.hide_all_edit_recurring(); $('#recurring_edit_'+this.id.split('_')[5]).show(); }); $("#recurring_period input").live('click', function(){ - $.each(['daily', 'weekly', 'monthly', 'yearly', 'target'], function(){ - $('#recurring_'+this).hide(); - }); + TracksForm.hide_all_recurring(); $('#recurring_'+this.id.split('_')[4]).show(); }); diff --git a/public/stylesheets/standard.css b/public/stylesheets/standard.css index b326652d..d214f861 100644 --- a/public/stylesheets/standard.css +++ b/public/stylesheets/standard.css @@ -939,11 +939,14 @@ div.message { cursor: move; } +.drop_target { + display:none; +} + .successor_target { background-image:url("../images/add_successor_off.png"); background-repeat: no-repeat; background-position: center right; - display: none; } .successor_target.hover { @@ -952,6 +955,15 @@ div.message { background-position: center right; } +.context_target { + height: 15px; + margin: 4px; + border: thick dotted #CCC; +} + +.context_target.hover { +} + /* Error message styles */ .fieldWithErrors { padding: 2px; diff --git a/spec/models/message_gateway_spec.rb b/spec/models/message_gateway_spec.rb index 2f0f5efc..188093ee 100644 --- a/spec/models/message_gateway_spec.rb +++ b/spec/models/message_gateway_spec.rb @@ -2,7 +2,7 @@ require File.dirname(__FILE__) + '/../spec_helper' describe MessageGateway do before :each do - todo = mock_model(Todo, :description= => nil, :notes= => nil, :context_id= => nil, :save! => nil) + todo = mock_model(Todo, :description= => nil, :raw_notes= => nil, :context_id= => nil, :save! => nil) @user = mock_model(User, :prefs => mock_model(Preference, :sms_context => mock_model(Context)), diff --git a/test/fixtures/contexts.yml b/test/fixtures/contexts.yml index 87ea5dba..49ce9d2f 100644 --- a/test/fixtures/contexts.yml +++ b/test/fixtures/contexts.yml @@ -131,21 +131,3 @@ anothercontext: user_id: 4 created_at: <%= today %> updated_at: <%= today %> - -inbox: - id: 15 - name: Inbox - position: 1 - hide: false - user_id: 5 - created_at: <%= today %> - updated_at: <%= today %> - -anothercontext: - id: 16 - name: anothercontext - position: 2 - hide: false - user_id: 5 - created_at: <%= today %> - updated_at: <%= today %> \ No newline at end of file diff --git a/test/fixtures/preferences.yml b/test/fixtures/preferences.yml index 77129787..b047f8d6 100644 --- a/test/fixtures/preferences.yml +++ b/test/fixtures/preferences.yml @@ -54,21 +54,3 @@ sms_user_prefs: show_project_on_todo_done: true sms_email: 5555555555@tmomail.net sms_context_id: 13 - -other_user_prefs: - id: 4 - user_id: 5 - staleness_starts: 7 - date_format: "%d/%m/%Y" - title_date_format: "%A, %d %B %Y" - show_number_completed: 5 - show_completed_projects_in_sidebar: true - show_hidden_contexts_in_sidebar: true - show_hidden_projects_in_sidebar: true - admin_email: butshesagirl@rousette.org.uk - week_starts: 1 - due_style: 0 - refresh: 0 - time_zone: "Los_Angeles" - verbose_action_descriptors: false - show_project_on_todo_done: true diff --git a/test/functional/todos_controller_test.rb b/test/functional/todos_controller_test.rb index 855b8397..0035f291 100644 --- a/test/functional/todos_controller_test.rb +++ b/test/functional/todos_controller_test.rb @@ -542,10 +542,9 @@ class TodosControllerTest < ActionController::TestCase def test_format_note_link_message login_as(:admin_user) todo = users(:admin_user).todos.first - todo.notes = "A Mail.app message://