diff --git a/app/controllers/application.rb b/app/controllers/application.rb index df5fcd1f..497c2fa1 100644 --- a/app/controllers/application.rb +++ b/app/controllers/application.rb @@ -27,6 +27,7 @@ class ApplicationController < ActionController::Base helper_method :current_user, :prefs layout proc{ |controller| controller.mobile? ? "mobile" : "standard" } + exempt_from_layout /\.js\.erb$/ before_filter :set_session_expiration before_filter :set_time_zone @@ -129,14 +130,6 @@ class ApplicationController < ActionController::Base RedCloth.new(text).to_html end - def build_default_project_context_name_map(projects) - Hash[*projects.reject{ |p| p.default_context.nil? }.map{ |p| [p.name, p.default_context.name] }.flatten].to_json - end - - def build_default_project_tags_map(projects) - Hash[*projects.reject{ |p| p.default_tags.nil? }.map{ |p| [p.name, p.default_tags] }.flatten].to_json - end - # Here's the concept behind this "mobile content negotiation" hack: In # addition to the main, AJAXy Web UI, Tracks has a lightweight low-feature # 'mobile' version designed to be suitablef or use from a phone or PDA. It diff --git a/app/controllers/contexts_controller.rb b/app/controllers/contexts_controller.rb index 1c399935..5177c399 100644 --- a/app/controllers/contexts_controller.rb +++ b/app/controllers/contexts_controller.rb @@ -92,7 +92,7 @@ class ContextsController < ApplicationController if @context.save if boolean_param('wants_render') - @context_state_changed = (@orgininal_context_hidden != @context.hidden?) + @context_state_changed = (@original_context_hidden != @context.hidden?) @new_state = (@context.hidden? ? "hidden" : "active") if @context_state_changed respond_to do |format| format.js @@ -110,6 +110,13 @@ class ContextsController < ApplicationController end end + def edit + @context = Context.find(params[:id]) + respond_to do |format| + format.js + end + end + # Fairly self-explanatory; deletes the context If the context contains # actions, you'll get a warning dialogue. If you choose to go ahead, any # actions in the context will also be deleted. @@ -124,11 +131,12 @@ class ContextsController < ApplicationController # Methods for changing the sort order of the contexts in the list # def order - list = params["list-contexts-hidden"] || params["list-contexts-active"] - list.each_with_index do |id, position| - current_user.contexts.update(id, :position => position + 1) - end + context_ids = params["container_context"] + @projects = current_user.contexts.update_positions( context_ids ) render :nothing => true + rescue + notify :error, $! + redirect_to :action => 'index' end protected @@ -218,8 +226,6 @@ class ContextsController < ApplicationController @projects = current_user.projects @count = @not_done_todos.size - @default_project_context_name_map = build_default_project_context_name_map(@projects).to_json - @default_project_tags_map = build_default_project_tags_map(@projects).to_json end end diff --git a/app/controllers/projects_controller.rb b/app/controllers/projects_controller.rb index a175d9eb..d62f6aa0 100644 --- a/app/controllers/projects_controller.rb +++ b/app/controllers/projects_controller.rb @@ -53,8 +53,7 @@ class ProjectsController < ApplicationController @down_count = @count + @deferred.size @next_project = current_user.projects.next_from(@project) @previous_project = current_user.projects.previous_from(@project) - @default_project_context_name_map = build_default_project_context_name_map(current_user.projects).to_json - @default_project_tags_map = build_default_project_tags_map(current_user.projects).to_json + @default_tags = @project.default_tags respond_to do |format| format.html format.m &render_project_mobile @@ -127,6 +126,7 @@ class ProjectsController < ApplicationController @active_projects_count = current_user.projects.active.count @hidden_projects_count = current_user.projects.hidden.count @completed_projects_count = current_user.projects.completed.count + init_data_for_sidebar render :template => 'projects/update.js.rjs' return elsif boolean_param('update_status') @@ -173,7 +173,7 @@ class ProjectsController < ApplicationController end def order - project_ids = params["list-active-projects"] || params["list-hidden-projects"] || params["list-completed-projects"] + project_ids = params["container_project"] @projects = current_user.projects.update_positions( project_ids ) render :nothing => true rescue @@ -186,6 +186,7 @@ class ProjectsController < ApplicationController @projects = current_user.projects.alphabetize(:state => @state) if @state @contexts = current_user.contexts init_not_done_counts(['project']) + init_project_hidden_todo_counts(['project']) if @state == 'hidden' end def actionize @@ -193,6 +194,7 @@ class ProjectsController < ApplicationController @projects = current_user.projects.actionize(current_user.id, :state => @state) if @state @contexts = current_user.contexts init_not_done_counts(['project']) + init_project_hidden_todo_counts(['project']) if @state == 'hidden' end protected diff --git a/app/controllers/recurring_todos_controller.rb b/app/controllers/recurring_todos_controller.rb index 2bf54576..be659b3a 100644 --- a/app/controllers/recurring_todos_controller.rb +++ b/app/controllers/recurring_todos_controller.rb @@ -251,8 +251,6 @@ class RecurringTodosController < ApplicationController @xth_day = [['first',1],['second',2],['third',3],['fourth',4],['last',5]] @projects = current_user.projects.find(:all, :include => [:default_context]) @contexts = current_user.contexts.find(:all) - @default_project_context_name_map = build_default_project_context_name_map(@projects).to_json - @default_project_tags_map = build_default_project_tags_map(@projects).to_json end def get_recurring_todo_from_param @@ -265,4 +263,4 @@ class RecurringTodosController < ApplicationController recurring_todos.each { |rt| rt.toggle_completion! if rt.todos.not_completed.count == 0} end -end \ No newline at end of file +end diff --git a/app/controllers/todos_controller.rb b/app/controllers/todos_controller.rb index 73fd0e00..949d94bf 100644 --- a/app/controllers/todos_controller.rb +++ b/app/controllers/todos_controller.rb @@ -95,6 +95,7 @@ class TodosController < ApplicationController @projects = current_user.projects.find(:all) if @new_project_created @initial_context_name = params['default_context_name'] @initial_project_name = params['default_project_name'] + @default_tags = @todo.project.default_tags unless @todo.project.nil? render :action => 'create' end format.xml do @@ -358,8 +359,6 @@ class TodosController < ApplicationController @not_done_todos = current_user.deferred_todos @count = @not_done_todos.size @down_count = @count - @default_project_context_name_map = build_default_project_context_name_map(@projects).to_json - @default_project_tags_map = build_default_project_tags_map(@projects).to_json respond_to do |format| format.html @@ -434,10 +433,7 @@ class TodosController < ApplicationController @down_count = @count respond_to do |format| - format.html { - @default_project_context_name_map = build_default_project_context_name_map(@projects).to_json - @default_project_tags_map = build_default_project_tags_map(@projects).to_json - } + format.html format.m { cookies[:mobile_url]= {:value => request.request_uri, :secure => SITE_CONFIG['secure_cookies']} render :action => "mobile_tag" @@ -471,8 +467,6 @@ class TodosController < ApplicationController @page_title = "TRACKS::Calendar" @projects = current_user.projects.find(:all) - @default_project_context_name_map = build_default_project_context_name_map(@projects).to_json - @default_project_tags_map = build_default_project_tags_map(@projects).to_json due_today_date = Time.zone.now due_this_week_date = Time.zone.now.end_of_week @@ -757,9 +751,6 @@ class TodosController < ApplicationController end end - @default_project_context_name_map = build_default_project_context_name_map(@projects).to_json - @default_project_tags_map = build_default_project_tags_map(@projects).to_json - render end end diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 61ad8209..26bff1b3 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -166,4 +166,17 @@ module ApplicationHelper return rt+rp+rts end + def date_format_for_date_picker() + standard_format = current_user.prefs.date_format + translations = [ + ['%m', 'mm'], + ['%d', 'dd'], + ['%Y', 'yy'], + ['%y', 'y'] + ] + translations.inject(standard_format) do |str, translation| + str.gsub(*translation) + end + end + end diff --git a/app/helpers/recurring_todos_helper.rb b/app/helpers/recurring_todos_helper.rb index b7f7e25d..5376a9cb 100644 --- a/app/helpers/recurring_todos_helper.rb +++ b/app/helpers/recurring_todos_helper.rb @@ -11,19 +11,15 @@ module RecurringTodosHelper end def recurring_todo_remote_delete_icon - str = link_to( image_tag_for_delete, + link_to( image_tag_for_delete, recurring_todo_path(@recurring_todo), :id => "delete_icon_"+@recurring_todo.id.to_s, :class => "icon delete_icon", :title => "delete the recurring action '#{@recurring_todo.description}'") - set_behavior_for_delete_icon - str end def recurring_todo_remote_star_icon - str = link_to( image_tag_for_star(@recurring_todo), + link_to( image_tag_for_star(@recurring_todo), toggle_star_recurring_todo_path(@recurring_todo), :class => "icon star_item", :title => "star the action '#{@recurring_todo.description}'") - set_behavior_for_star_icon - str end def recurring_todo_remote_edit_icon @@ -31,7 +27,6 @@ module RecurringTodosHelper str = link_to( image_tag_for_edit(@recurring_todo), edit_recurring_todo_path(@recurring_todo), :class => "icon edit_icon") - set_behavior_for_edit_icon else str = '' + image_tag("blank.png") + " " end @@ -40,7 +35,6 @@ module RecurringTodosHelper def recurring_todo_remote_toggle_checkbox str = check_box_tag('item_id', toggle_check_recurring_todo_path(@recurring_todo), @recurring_todo.completed?, :class => 'item-checkbox') - set_behavior_for_toggle_checkbox str end @@ -53,26 +47,4 @@ module RecurringTodosHelper def image_tag_for_edit(todo) image_tag("blank.png", :title =>"Edit action", :class=>"edit_item", :id=> dom_id(todo, 'edit_icon')) end - - def set_behavior_for_delete_icon - parameters = "_source_view=#{@source_view}" - parameters += "&_tag_name=#{@tag_name}" if @source_view == 'tag' - apply_behavior '.item-container a.delete_icon:click', :prevent_default => true do |page| - page.confirming "'Are you sure that you want to ' + this.title + '?'" do - page << "itemContainer = this.up('.item-container'); itemContainer.startWaiting();" - page << remote_to_href(:method => 'delete', :with => "'#{parameters}'", :complete => "itemContainer.stopWaiting();") - end - end - end - - def set_behavior_for_edit_icon - parameters = "_source_view=#{@source_view}" - parameters += "&_tag_name=#{@tag_name}" if @source_view == 'tag' - apply_behavior '.item-container a.edit_icon:click', :prevent_default => true do |page| - page << "Effect.Pulsate(this);" - page << remote_to_href(:method => 'get', :with => "'#{parameters}'") - end - end - - -end \ No newline at end of file +end diff --git a/app/helpers/todos_helper.rb b/app/helpers/todos_helper.rb index f11b5fbe..b39d5674 100644 --- a/app/helpers/todos_helper.rb +++ b/app/helpers/todos_helper.rb @@ -8,52 +8,41 @@ module TodosHelper end def form_remote_tag_edit_todo( &block ) - form_tag( - todo_path(@todo), { + form_remote_tag( + :url => todo_path(@todo), + :loading => "$('#submit_todo_#{@todo.id}').block({message: null})", + :html => { :method => :put, :id => dom_id(@todo, 'form'), :class => dom_id(@todo, 'form') + " inline-form edit_todo_form" }, &block ) - apply_behavior 'form.edit_todo_form', make_remote_form( - :method => :put, - :before => "todoSpinner = this.down('button.positive'); todoSpinner.startWaiting()", - :loaded => "todoSpinner.stopWaiting()", - :condition => "!(this.down('button.positive').isWaiting())"), - :prevent_default => true end - - def set_behavior_for_star_icon - apply_behavior '.item-container a.star_item:click', - remote_to_href(:method => 'put', :with => "{ _source_view : '#{@source_view}' }"), - :prevent_default => true - end def remote_star_icon - str = link_to( image_tag_for_star(@todo), + link_to( image_tag_for_star(@todo), toggle_star_todo_path(@todo), :class => "icon star_item", :title => "star the action '#{@todo.description}'") - set_behavior_for_star_icon - str end def remote_edit_menu_item(parameters, todo) return link_to_remote( - image_tag("edit_off.png", :mouseover => "edit_on.png", :alt => "", :align => "absmiddle")+" Edit", + image_tag("edit_off.png", :mouseover => "edit_on.png", :alt => "Edit", :align => "absmiddle", :id => 'edit_icon_todo_'+todo.id.to_s)+" Edit", :url => {:controller => 'todos', :action => 'edit', :id => todo.id}, :method => 'get', :with => "'#{parameters}'", :before => todo_start_waiting_js(todo), - :complete => todo_stop_waiting_js) + :complete => todo_stop_waiting_js(todo)) end def remote_delete_menu_item(parameters, todo) return link_to_remote( - image_tag("delete_off.png", :mouseover => "delete_on.png", :alt => "", :align => "absmiddle")+" Delete", + image_tag("delete_off.png", :mouseover => "delete_on.png", :alt => "Delete", :align => "absmiddle")+" Delete", :url => {:controller => 'todos', :action => 'destroy', :id => todo.id}, :method => 'delete', :with => "'#{parameters}'", :before => todo_start_waiting_js(todo), - :complete => todo_stop_waiting_js) + :complete => todo_stop_waiting_js(todo), + :confirm => "Are you sure that you want to delete the action '#{todo.description}'?") end def remote_defer_menu_item(days, todo) @@ -64,24 +53,24 @@ module TodosHelper futuredate = (@todo.show_from || @todo.user.date) + days.days 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")}", + image_tag("defer_#{days}_off.png", :mouseover => "defer_#{days}.png", :alt => "Defer #{pluralize(days, "day")}", :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")}", + image_tag("defer_#{days}_off.png", :mouseover => "defer_#{days}.png", :alt => "Defer #{pluralize(days, "day")}", :align => "absmiddle")+" Defer #{pluralize(days, "day")}", :url => url, :before => todo_start_waiting_js(todo), - :complete => todo_stop_waiting_js) + :complete => todo_stop_waiting_js(todo)) end end def todo_start_waiting_js(todo) - return "$('ul#{dom_id(todo)}').hide(); itemContainer = $('#{dom_id(todo)}'); itemContainer.startWaiting()" + return "$('#ul#{dom_id(todo)}').css('visibility', 'hidden'); $('##{dom_id(todo)}').block({message: null})" end - def todo_stop_waiting_js - return "itemContainer.stopWaiting();" + def todo_stop_waiting_js(todo) + return "$('##{dom_id(todo)}').unblock();enable_rich_interaction();" end def image_tag_for_recurring_todo(todo) @@ -91,18 +80,9 @@ module TodosHelper :class => "recurring_icon", :title => recurrence_pattern_as_text(todo.recurring_todo)) end - def set_behavior_for_toggle_checkbox - parameters = "_source_view=#{@source_view}" - parameters += "&_tag_name=#{@tag_name}" if @source_view == 'tag' - apply_behavior '.item-container input.item-checkbox:click', - remote_function(:url => javascript_variable('this.value'), :method => 'put', - :with => "'#{parameters}'") - end def remote_toggle_checkbox - str = check_box_tag('item_id', toggle_check_todo_path(@todo), @todo.completed?, :class => 'item-checkbox') - set_behavior_for_toggle_checkbox - str + check_box_tag('item_id', toggle_check_todo_path(@todo), @todo.completed?, :class => 'item-checkbox') end def date_span @@ -213,10 +193,11 @@ module TodosHelper end def calendar_setup( input_field ) - str = "Calendar.setup({ ifFormat:\"#{prefs.date_format}\"" - str << ",firstDay:#{prefs.week_starts},showOthers:true,range:[2004, 2010]" - str << ",step:1,inputField:\"" + input_field + "\",cache:true,align:\"TR\" })\n" - javascript_tag str + # TODO:jQuery + #str = "Calendar.setup({ ifFormat:\"#{prefs.date_format}\"" + #str << ",firstDay:#{prefs.week_starts},showOthers:true,range:[2004, 2010]" + #str << ",step:1,inputField:\"" + input_field + "\",cache:true,align:\"TR\" })\n" + #javascript_tag str end def item_container_id (todo) @@ -224,7 +205,7 @@ module TodosHelper return "p#{todo.project_id}items" if todo.active? return "tickler" if todo.deferred? end - return "c#{todo.context_id}" + return "c#{todo.context_id}items" end def should_show_new_item @@ -266,6 +247,20 @@ module TodosHelper array_or_string_for_javascript( current_user.contexts.collect{|c| escape_javascript(c.name) } ) end + def tag_names_for_autocomplete + array_or_string_for_javascript( Tag.all.collect{|c| escape_javascript(c.name) } ) + end + + def default_contexts_for_autocomplete + projects = current_user.projects.find(:all, :conditions => ['default_context_id is not null']) + Hash[*projects.map{ |p| [p.name, p.default_context.name] }.flatten].to_json + end + + def default_tags_for_autocomplete + projects = current_user.projects.find(:all, :conditions => ['default_tags != ""']) + Hash[*projects.map{ |p| [p.name, p.default_tags] }.flatten].to_json + end + def format_ical_notes(notes) split_notes = notes.split(/\n/) joined_notes = split_notes.join("\\n") diff --git a/app/models/user.rb b/app/models/user.rb index ce96c267..6ce58aa8 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -10,6 +10,13 @@ class User < ActiveRecord::Base def find_by_params(params) find(params['id'] || params['context_id']) || nil end + def update_positions(context_ids) + context_ids.each_with_index do |id, position| + context = self.detect { |c| c.id == id.to_i } + raise "Context id #{id} not associated with user id #{@user.id}." if context.nil? + context.update_attribute(:position, position + 1) + end + end end has_many :projects, :order => 'projects.position ASC', diff --git a/app/views/contexts/_context.rhtml b/app/views/contexts/_context.rhtml index fafe99fe..c95c93b9 100644 --- a/app/views/contexts/_context.rhtml +++ b/app/views/contexts/_context.rhtml @@ -3,31 +3,9 @@