mirror of
https://github.com/TracksApp/tracks.git
synced 2026-01-17 14:45:28 +01:00
Merge branch 'master' into clinton/master
* master: (40 commits)
Updated the manual in HTML, PDF and .tex format.
Minor updates to the example db.
set version to 1.7RC
update version in template
update changelog
OpenSearch support.
update the sample sqlite databases and update sample content sql. Solves #802
forgot ot change one version to 1.7
update documentation for 1.7rc release
No point in changing the name of the OpenID identity column in users table. Use the existing one.
show recurrence pattern in :title of a recurring todo. Needed slight refactoring to make it happen
Re-write OpenID code to use new authentication plugin. Tested to work!
Upgraded to open_id_authentication plugin at 00d8bc7f97 and unpacked ruby-openid gem version 2.1.2.
remove old compressed js and css from the asset_packager plugin that we don't use anymore
applied the patches from Jakub to improve the mobile html
adds test for changing context on a todo in tag view. Resolves #762
Add testcase where changing the name of a project should be reflected in the default project name. resolves #756
add testcase for deleting a user. Resolves #734
implement suggestions for search in #787
fix failing tests
...
This commit is contained in:
commit
4fb4a98bc8
1905 changed files with 119478 additions and 58883 deletions
|
|
@ -32,13 +32,13 @@ class ApplicationController < ActionController::Base
|
|||
before_filter :set_time_zone
|
||||
prepend_before_filter :login_required
|
||||
prepend_before_filter :enable_mobile_content_negotiation
|
||||
after_filter :restore_content_type_for_mobile
|
||||
after_filter :set_charset
|
||||
|
||||
|
||||
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
||||
helper_method :format_date, :markdown
|
||||
|
||||
# By default, sets the charset to UTF-8 if it isn't already set
|
||||
|
|
@ -148,21 +148,15 @@ class ApplicationController < ActionController::Base
|
|||
# during the processing and then setting it to 'text/html' in an
|
||||
# 'after_filter' -LKM 2007-04-01
|
||||
def mobile?
|
||||
return params[:format] == 'm' || response.content_type == MOBILE_CONTENT_TYPE
|
||||
return params[:format] == 'm'
|
||||
end
|
||||
|
||||
def enable_mobile_content_negotiation
|
||||
if mobile?
|
||||
request.accepts.unshift(Mime::Type::lookup(MOBILE_CONTENT_TYPE))
|
||||
request.format = :m
|
||||
end
|
||||
end
|
||||
|
||||
def restore_content_type_for_mobile
|
||||
if mobile?
|
||||
response.content_type = 'text/html'
|
||||
end
|
||||
end
|
||||
|
||||
def create_todo_from_recurring_todo(rt, date=nil)
|
||||
# create todo and initialize with data from recurring_todo rt
|
||||
todo = current_user.todos.build( { :description => rt.description, :notes => rt.notes, :project_id => rt.project_id, :context_id => rt.context_id})
|
||||
|
|
@ -234,8 +228,13 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def init_data_for_sidebar
|
||||
@projects = @projects || current_user.projects.find(:all, :include => [:default_context ])
|
||||
@contexts = @contexts || current_user.contexts
|
||||
@completed_projects = current_user.projects.completed
|
||||
@hidden_projects = current_user.projects.hidden
|
||||
@active_projects = current_user.projects.active
|
||||
|
||||
@active_contexts = current_user.contexts.active
|
||||
@hidden_contexts = current_user.contexts.hidden
|
||||
|
||||
init_not_done_counts
|
||||
if prefs.show_hidden_projects_in_sidebar
|
||||
init_project_hidden_todo_counts(['project'])
|
||||
|
|
@ -244,13 +243,13 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def init_not_done_counts(parents = ['project','context'])
|
||||
parents.each do |parent|
|
||||
eval("@#{parent}_not_done_counts = @#{parent}_not_done_counts || Todo.count(:conditions => ['user_id = ? and state = ?', current_user.id, 'active'], :group => :#{parent}_id)")
|
||||
eval("@#{parent}_not_done_counts = @#{parent}_not_done_counts || current_user.todos.active.count(:group => :#{parent}_id)")
|
||||
end
|
||||
end
|
||||
|
||||
def init_project_hidden_todo_counts(parents = ['project','context'])
|
||||
parents.each do |parent|
|
||||
eval("@#{parent}_project_hidden_todo_counts = @#{parent}_project_hidden_todo_counts || Todo.count(:conditions => ['user_id = ? and (state = ? or state = ?)', current_user.id, 'project_hidden', 'active'], :group => :#{parent}_id)")
|
||||
eval("@#{parent}_project_hidden_todo_counts = @#{parent}_project_hidden_todo_counts || current_user.todos.count(:conditions => ['state = ? or state = ?', 'project_hidden', 'active'], :group => :#{parent}_id)")
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -134,8 +134,8 @@ class ContextsController < ApplicationController
|
|||
def render_contexts_mobile
|
||||
lambda do
|
||||
@page_title = "TRACKS::List Contexts"
|
||||
@active_contexts = @contexts.find(:all, { :conditions => ["hide = ?", false]})
|
||||
@hidden_contexts = @contexts.find(:all, { :conditions => ["hide = ?", true]})
|
||||
@active_contexts = @contexts.active
|
||||
@hidden_contexts = @contexts.hidden
|
||||
@down_count = @active_contexts.size + @hidden_contexts.size
|
||||
cookies[:mobile_url]= {:value => request.request_uri, :secure => TRACKS_COOKIES_SECURE}
|
||||
render :action => 'index_mobile'
|
||||
|
|
@ -201,6 +201,9 @@ class ContextsController < ApplicationController
|
|||
:conditions => ['todos.state = ? AND (todos.project_id IS ? OR projects.state = ?)', 'active', nil, 'active'],
|
||||
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
||||
:include => [:project, :tags])
|
||||
|
||||
@projects = current_user.projects
|
||||
|
||||
@count = @not_done_todos.size
|
||||
@default_project_context_name_map = build_default_project_context_name_map(@projects).to_json
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,12 +12,12 @@ class FeedlistController < ApplicationController
|
|||
@contexts = current_user.contexts
|
||||
end
|
||||
|
||||
@active_projects = @projects.select{ |p| p.active? }
|
||||
@hidden_projects = @projects.select{ |p| p.hidden? }
|
||||
@completed_projects = @projects.select{ |p| p.completed? }
|
||||
@active_projects = current_user.projects.active
|
||||
@hidden_projects = current_user.projects.hidden
|
||||
@completed_projects = current_user.projects.completed
|
||||
|
||||
@active_contexts = @contexts.select{ |c| !c.hidden? }
|
||||
@hidden_contexts = @contexts.select{ |c| c.hidden? }
|
||||
@active_contexts = current_user.contexts.active
|
||||
@hidden_contexts = current_user.contexts.hidden
|
||||
|
||||
respond_to do |format|
|
||||
format.html { render :layout => 'standard' }
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
class IntegrationsController < ApplicationController
|
||||
|
||||
skip_before_filter :login_required, :only => :search_plugin
|
||||
|
||||
def index
|
||||
@page_title = 'TRACKS::Integrations'
|
||||
end
|
||||
|
|
@ -22,4 +24,12 @@ class IntegrationsController < ApplicationController
|
|||
context = current_user.contexts.find params[:context_id]
|
||||
render :partial => 'applescript2', :locals => { :context => context }
|
||||
end
|
||||
|
||||
def search_plugin
|
||||
@icon_data = [File.open(RAILS_ROOT + '/public/images/done.png').read].
|
||||
pack('m').gsub(/\n/, '')
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,114 +6,45 @@ class LoginController < ApplicationController
|
|||
skip_before_filter :login_required
|
||||
before_filter :login_optional
|
||||
before_filter :get_current_user
|
||||
open_id_consumer if openid_enabled?
|
||||
|
||||
def login
|
||||
@page_title = "TRACKS::Login"
|
||||
@openid_url = cookies[:openid_url] if openid_enabled?
|
||||
case request.method
|
||||
when :post
|
||||
if @user = User.authenticate(params['user_login'], params['user_password'])
|
||||
session['user_id'] = @user.id
|
||||
# If checkbox on login page checked, we don't expire the session after 1 hour
|
||||
# of inactivity and we remember this user for future browser sessions
|
||||
session['noexpiry'] = params['user_noexpiry']
|
||||
msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire."
|
||||
notify :notice, "Login successful: session #{msg}"
|
||||
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE }
|
||||
if openid_enabled? && using_open_id?
|
||||
login_openid
|
||||
else
|
||||
@page_title = "TRACKS::Login"
|
||||
case request.method
|
||||
when :post
|
||||
if @user = User.authenticate(params['user_login'], params['user_password'])
|
||||
session['user_id'] = @user.id
|
||||
# If checkbox on login page checked, we don't expire the session after 1 hour
|
||||
# of inactivity and we remember this user for future browser sessions
|
||||
session['noexpiry'] = params['user_noexpiry']
|
||||
msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire."
|
||||
notify :notice, "Login successful: session #{msg}"
|
||||
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE }
|
||||
end
|
||||
redirect_back_or_home
|
||||
return
|
||||
else
|
||||
@login = params['user_login']
|
||||
notify :warning, "Login unsuccessful"
|
||||
end
|
||||
redirect_back_or_home
|
||||
return
|
||||
else
|
||||
@login = params['user_login']
|
||||
notify :warning, "Login unsuccessful"
|
||||
end
|
||||
when :get
|
||||
if User.no_users_yet?
|
||||
redirect_to :controller => 'users', :action => 'new'
|
||||
return
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.m { render :action => 'login_mobile.html.erb', :layout => 'mobile' }
|
||||
when :get
|
||||
if User.no_users_yet?
|
||||
redirect_to :controller => 'users', :action => 'new'
|
||||
return
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.m { render :action => 'login_mobile.html.erb', :layout => 'mobile' }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def begin
|
||||
# If the URL was unusable (either because of network conditions,
|
||||
# a server error, or that the response returned was not an OpenID
|
||||
# identity page), the library will return HTTP_FAILURE or PARSE_ERROR.
|
||||
# Let the user know that the URL is unusable.
|
||||
case open_id_response.status
|
||||
when OpenID::SUCCESS
|
||||
session['openid_url'] = params[:openid_url]
|
||||
session['user_noexpiry'] = params[:user_noexpiry]
|
||||
# The URL was a valid identity URL. Now we just need to send a redirect
|
||||
# to the server using the redirect_url the library created for us.
|
||||
|
||||
# redirect to the server
|
||||
respond_to do |format|
|
||||
format.html { redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), open_id_complete_url) }
|
||||
format.m { redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), formatted_open_id_complete_url(:format => 'm')) }
|
||||
end
|
||||
else
|
||||
notify :warning, "Unable to find openid server for <q>#{openid_url}</q>"
|
||||
redirect_to_login
|
||||
end
|
||||
end
|
||||
|
||||
def complete
|
||||
openid_url = session['openid_url']
|
||||
if openid_url.blank?
|
||||
notify :error, "expected an openid_url"
|
||||
end
|
||||
|
||||
case open_id_response.status
|
||||
when OpenID::FAILURE
|
||||
# In the case of failure, if info is non-nil, it is the
|
||||
# URL that we were verifying. We include it in the error
|
||||
# message to help the user figure out what happened.
|
||||
if open_id_response.identity_url
|
||||
msg = "Verification of #{openid_url}(#{open_id_response.identity_url}) failed. "
|
||||
else
|
||||
msg = "Verification failed. "
|
||||
end
|
||||
notify :error, open_id_response.msg.to_s + msg
|
||||
|
||||
when OpenID::SUCCESS
|
||||
# Success means that the transaction completed without
|
||||
# error. If info is nil, it means that the user cancelled
|
||||
# the verification.
|
||||
@user = User.find_by_open_id_url(openid_url)
|
||||
unless (@user.nil?)
|
||||
session['user_id'] = @user.id
|
||||
session['noexpiry'] = session['user_noexpiry']
|
||||
msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire."
|
||||
notify :notice, "You have successfully verified #{openid_url} as your identity. Login successful: session #{msg}"
|
||||
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE }
|
||||
end
|
||||
cookies[:openid_url] = { :value => openid_url, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE }
|
||||
redirect_back_or_home
|
||||
else
|
||||
notify :warning, "You have successfully verified #{openid_url} as your identity, but you do not have a Tracks account. Please ask your administrator to sign you up."
|
||||
end
|
||||
|
||||
when OpenID::CANCEL
|
||||
notify :warning, "Verification cancelled."
|
||||
|
||||
else
|
||||
notify :warning, "Unknown response status: #{open_id_response.status}"
|
||||
end
|
||||
redirect_to_login unless performed?
|
||||
end
|
||||
|
||||
def logout
|
||||
@user.forget_me if logged_in?
|
||||
cookies.delete :auth_token
|
||||
|
|
@ -156,5 +87,31 @@ class LoginController < ApplicationController
|
|||
def should_expire_sessions?
|
||||
session['noexpiry'] != "on"
|
||||
end
|
||||
|
||||
|
||||
protected
|
||||
|
||||
def login_openid
|
||||
# If checkbox on login page checked, we don't expire the session after 1 hour
|
||||
# of inactivity and we remember this user for future browser sessions
|
||||
session['noexpiry'] ||= params['user_noexpiry']
|
||||
authenticate_with_open_id do |result, identity_url|
|
||||
if result.successful?
|
||||
if @user = User.find_by_open_id_url(identity_url)
|
||||
session['user_id'] = @user.id
|
||||
msg = (should_expire_sessions?) ? "will expire after 1 hour of inactivity." : "will not expire."
|
||||
notify :notice, "Login successful: session #{msg}"
|
||||
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => TRACKS_COOKIES_SECURE }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => TRACKS_COOKIES_SECURE }
|
||||
end
|
||||
redirect_back_or_home
|
||||
else
|
||||
notify :warning, "Sorry, no user by that identity URL exists (#{identity_url})"
|
||||
end
|
||||
else
|
||||
notify :warning, result.message
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -31,7 +31,7 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
def projects_and_actions
|
||||
@projects = @projects.select { |p| p.active? }
|
||||
@projects = @projects.active
|
||||
respond_to do |format|
|
||||
format.text {
|
||||
render :action => 'index_text_projects_and_actions', :layout => false, :content_type => Mime::TEXT
|
||||
|
|
@ -83,7 +83,7 @@ class ProjectsController < ApplicationController
|
|||
@go_to_project = params['go_to_project']
|
||||
@saved = @project.save
|
||||
@project_not_done_counts = { @project.id => 0 }
|
||||
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
|
||||
@active_projects_count = current_user.projects.active.count
|
||||
@contexts = current_user.contexts
|
||||
respond_to do |format|
|
||||
format.js { @down_count = current_user.projects.size }
|
||||
|
|
@ -124,9 +124,9 @@ class ProjectsController < ApplicationController
|
|||
@project_not_done_counts[@project.id] = @project.reload().not_done_todo_count(:include_project_hidden_todos => true)
|
||||
end
|
||||
@contexts = current_user.contexts
|
||||
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
|
||||
@hidden_projects_count = current_user.projects.count(:conditions => "state = 'hidden'")
|
||||
@completed_projects_count = current_user.projects.count(:conditions => "state = 'completed'")
|
||||
@active_projects_count = current_user.projects.active.count
|
||||
@hidden_projects_count = current_user.projects.hidden.count
|
||||
@completed_projects_count = current_user.projects.completed.count
|
||||
render :template => 'projects/update.js.rjs'
|
||||
return
|
||||
elsif boolean_param('update_status')
|
||||
|
|
@ -161,9 +161,9 @@ class ProjectsController < ApplicationController
|
|||
|
||||
def destroy
|
||||
@project.destroy
|
||||
@active_projects_count = current_user.projects.count(:conditions => "state = 'active'")
|
||||
@hidden_projects_count = current_user.projects.count(:conditions => "state = 'hidden'")
|
||||
@completed_projects_count = current_user.projects.count(:conditions => "state = 'completed'")
|
||||
@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.xml { render :text => "Deleted project #{@project.name}" }
|
||||
|
|
@ -199,9 +199,9 @@ class ProjectsController < ApplicationController
|
|||
lambda do
|
||||
@page_title = "TRACKS::List Projects"
|
||||
@count = current_user.projects.size
|
||||
@active_projects = @projects.select{ |p| p.active? }
|
||||
@hidden_projects = @projects.select{ |p| p.hidden? }
|
||||
@completed_projects = @projects.select{ |p| p.completed? }
|
||||
@active_projects = @projects.active
|
||||
@hidden_projects = @projects.hidden
|
||||
@completed_projects = @projects.completed
|
||||
@no_projects = @projects.empty?
|
||||
@projects.cache_note_counts
|
||||
@new_project = current_user.projects.build
|
||||
|
|
@ -211,9 +211,9 @@ class ProjectsController < ApplicationController
|
|||
|
||||
def render_projects_mobile
|
||||
lambda do
|
||||
@active_projects = @projects.select{ |p| p.active? }
|
||||
@hidden_projects = @projects.select{ |p| p.hidden? }
|
||||
@completed_projects = @projects.select{ |p| p.completed? }
|
||||
@active_projects = @projects.active
|
||||
@hidden_projects = @projects.hidden
|
||||
@completed_projects = @projects.completed
|
||||
@down_count = @active_projects.size + @hidden_projects.size + @completed_projects.size
|
||||
cookies[:mobile_url]= {:value => request.request_uri, :secure => TRACKS_COOKIES_SECURE}
|
||||
render :action => 'index_mobile'
|
||||
|
|
|
|||
|
|
@ -118,7 +118,7 @@ class RecurringTodosController < ApplicationController
|
|||
else
|
||||
@message += " / did not create todo"
|
||||
end
|
||||
@count = current_user.recurring_todos.count(:all, :conditions => ["state = ?", "active"])
|
||||
@count = current_user.recurring_todos.active.count
|
||||
else
|
||||
@message = "Error saving recurring todo"
|
||||
end
|
||||
|
|
@ -140,7 +140,7 @@ class RecurringTodosController < ApplicationController
|
|||
|
||||
# delete the recurring todo
|
||||
@saved = @recurring_todo.destroy
|
||||
@remaining = current_user.recurring_todos.count(:all)
|
||||
@remaining = current_user.recurring_todos.count
|
||||
|
||||
respond_to do |format|
|
||||
|
||||
|
|
|
|||
|
|
@ -1,27 +1,30 @@
|
|||
class SearchController < ApplicationController
|
||||
|
||||
helper :todos, :application, :notes, :projects
|
||||
|
||||
def results
|
||||
@source_view = params['_source_view'] || 'search'
|
||||
@page_title = "TRACKS::Search Results for #{params[:search]}"
|
||||
terms = '%' + params[:search] + '%'
|
||||
@found_todos = current_user.todos.find(:all, :conditions => ["todos.description LIKE ? OR todos.notes LIKE ?", terms, terms], :include => [:tags, :project, :context])
|
||||
@found_projects = current_user.projects.find(:all, :conditions => ["name LIKE ? or description LIKE ?", terms, terms])
|
||||
@found_notes = current_user.notes.find(:all, :conditions => ["body LIKE ?", terms])
|
||||
|
||||
@count = @found_todos.size + @found_projects.size + @found_notes.size
|
||||
|
||||
init_not_done_counts(['project'])
|
||||
init_project_hidden_todo_counts(['project'])
|
||||
end
|
||||
|
||||
def index
|
||||
@page_title = "TRACKS::Search"
|
||||
end
|
||||
|
||||
def init
|
||||
@source_view = params['_source_view'] || 'search'
|
||||
end
|
||||
|
||||
end
|
||||
class SearchController < ApplicationController
|
||||
|
||||
helper :todos, :application, :notes, :projects
|
||||
|
||||
def results
|
||||
@source_view = params['_source_view'] || 'search'
|
||||
@page_title = "TRACKS::Search Results for #{params[:search]}"
|
||||
terms = '%' + params[:search] + '%'
|
||||
@found_todos = current_user.todos.find(:all, :conditions => ["todos.description LIKE ? OR todos.notes LIKE ?", terms, terms], :include => [:tags, :project, :context])
|
||||
@found_projects = current_user.projects.find(:all, :conditions => ["name LIKE ? OR description LIKE ?", terms, terms])
|
||||
@found_notes = current_user.notes.find(:all, :conditions => ["body LIKE ?", terms])
|
||||
@found_contexts = current_user.contexts.find(:all, :conditions => ["name LIKE ?", terms])
|
||||
# TODO: limit search to tags on todos
|
||||
@found_tags = current_user.tags.find(:all, :conditions => ["name LIKE ?", terms])
|
||||
|
||||
@count = @found_todos.size + @found_projects.size + @found_notes.size + @found_contexts.size + @found_tags.size
|
||||
|
||||
init_not_done_counts
|
||||
init_project_hidden_todo_counts
|
||||
end
|
||||
|
||||
def index
|
||||
@page_title = "TRACKS::Search"
|
||||
end
|
||||
|
||||
def init
|
||||
@source_view = params['_source_view'] || 'search'
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ class StatsController < ApplicationController
|
|||
@page_title = 'TRACKS::Statistics'
|
||||
|
||||
@unique_tags = @tags.count(:all, {:group=>"tag_id"})
|
||||
@hidden_contexts = @contexts.find(:all, {:conditions => ["hide = ? ", true]})
|
||||
@hidden_contexts = @contexts.hidden
|
||||
@first_action = @actions.find(:first, :order => "created_at ASC")
|
||||
|
||||
get_stats_actions
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ class TodosController < ApplicationController
|
|||
@projects = current_user.projects.find(:all, :include => [:default_context])
|
||||
@contexts = current_user.contexts.find(:all)
|
||||
|
||||
@contexts_to_show = @contexts.reject {|x| x.hide? }
|
||||
@contexts_to_show = current_user.contexts.active
|
||||
|
||||
respond_to do |format|
|
||||
format.html &render_todos_html
|
||||
|
|
@ -28,7 +28,7 @@ class TodosController < ApplicationController
|
|||
end
|
||||
|
||||
def new
|
||||
@projects = current_user.projects.select { |p| p.active? }
|
||||
@projects = current_user.projects.active
|
||||
@contexts = current_user.contexts.find(:all)
|
||||
respond_to do |format|
|
||||
format.m {
|
||||
|
|
@ -76,7 +76,7 @@ class TodosController < ApplicationController
|
|||
format.m do
|
||||
@return_path=cookies[:mobile_url]
|
||||
# todo: use function for this fixed path
|
||||
@return_path='/mobile' if @return_path.nil?
|
||||
@return_path='/m' if @return_path.nil?
|
||||
if @saved
|
||||
redirect_to @return_path
|
||||
else
|
||||
|
|
@ -116,7 +116,7 @@ class TodosController < ApplicationController
|
|||
def show
|
||||
respond_to do |format|
|
||||
format.m do
|
||||
@projects = current_user.projects.select { |p| p.active? }
|
||||
@projects = current_user.projects.active
|
||||
@contexts = current_user.contexts.find(:all)
|
||||
@edit_mobile = true
|
||||
@return_path=cookies[:mobile_url]
|
||||
|
|
@ -399,8 +399,9 @@ class TodosController < ApplicationController
|
|||
:limit => max_completed,
|
||||
:conditions => ['taggings.user_id = ? and state = ?', current_user.id, 'completed'],
|
||||
:order => 'todos.completed_at DESC')
|
||||
|
||||
@contexts = current_user.contexts.find(:all)
|
||||
|
||||
@projects = current_user.projects
|
||||
@contexts = current_user.contexts
|
||||
@contexts_to_show = @contexts.reject {|x| x.hide? }
|
||||
|
||||
# Set count badge to number of items with this tag
|
||||
|
|
@ -442,33 +443,33 @@ class TodosController < ApplicationController
|
|||
due_next_week_date = due_this_week_date + 7.days
|
||||
due_this_month_date = Time.zone.now.end_of_month
|
||||
|
||||
@due_today = current_user.todos.find(:all,
|
||||
@due_today = current_user.todos.not_completed.find(:all,
|
||||
:include => [:taggings, :tags],
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due <= ?', 'active', 'deferred', due_today_date],
|
||||
:conditions => ['todos.due <= ?', due_today_date],
|
||||
:order => "due")
|
||||
@due_this_week = current_user.todos.find(:all,
|
||||
@due_this_week = current_user.todos.not_completed.find(:all,
|
||||
:include => [:taggings, :tags],
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_today_date, due_this_week_date],
|
||||
:conditions => ['todos.due > ? AND todos.due <= ?', due_today_date, due_this_week_date],
|
||||
:order => "due")
|
||||
@due_next_week = current_user.todos.find(:all,
|
||||
@due_next_week = current_user.todos.not_completed.find(:all,
|
||||
:include => [:taggings, :tags],
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_this_week_date, due_next_week_date],
|
||||
:conditions => ['todos.due > ? AND todos.due <= ?', due_this_week_date, due_next_week_date],
|
||||
:order => "due")
|
||||
@due_this_month = current_user.todos.find(:all,
|
||||
@due_this_month = current_user.todos.not_completed.find(:all,
|
||||
:include => [:taggings, :tags],
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_next_week_date, due_this_month_date],
|
||||
:conditions => ['todos.due > ? AND todos.due <= ?', due_next_week_date, due_this_month_date],
|
||||
:order => "due")
|
||||
@due_after_this_month = current_user.todos.find(:all,
|
||||
@due_after_this_month = current_user.todos.not_completed.find(:all,
|
||||
:include => [:taggings, :tags],
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ?', 'active', 'deferred', due_this_month_date],
|
||||
:conditions => ['todos.due > ?', due_this_month_date],
|
||||
:order => "due")
|
||||
|
||||
|
||||
@count = current_user.todos.not_completed.are_due.count
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.ics {
|
||||
@due_all = current_user.todos.find(:all,
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND NOT todos.due IS NULL', 'active', 'deferred'],
|
||||
:order => "due")
|
||||
@due_all = current_user.todos.not_completed.are_due.find(:all, :order => "due")
|
||||
render :action => 'calendar', :layout => false, :content_type => Mime::ICS
|
||||
}
|
||||
end
|
||||
|
|
@ -536,13 +537,17 @@ class TodosController < ApplicationController
|
|||
end
|
||||
|
||||
def with_parent_resource_scope(&block)
|
||||
@feed_title = "Actions "
|
||||
if (params[:context_id])
|
||||
@context = current_user.contexts.find_by_params(params)
|
||||
@feed_title = @feed_title + "in context '#{@context.name}'"
|
||||
Todo.send :with_scope, :find => {:conditions => ['todos.context_id = ?', @context.id]} do
|
||||
yield
|
||||
end
|
||||
elsif (params[:project_id])
|
||||
@project = current_user.projects.find_by_params(params)
|
||||
@feed_title = @feed_title + "in project '#{@project.name}'"
|
||||
@project_feed = true
|
||||
Todo.send :with_scope, :find => {:conditions => ['todos.project_id = ?', @project.id]} do
|
||||
yield
|
||||
end
|
||||
|
|
@ -718,7 +723,7 @@ class TodosController < ApplicationController
|
|||
render_rss_feed_for @todos, :feed => todo_feed_options,
|
||||
:item => {
|
||||
:title => :description,
|
||||
:link => lambda { |t| context_url(t.context) },
|
||||
:link => lambda { |t| @project_feed.nil? ? context_url(t.context) : project_url(t.project) },
|
||||
:guid => lambda { |t| todo_url(t) },
|
||||
:description => todo_feed_content
|
||||
}
|
||||
|
|
@ -726,7 +731,9 @@ class TodosController < ApplicationController
|
|||
end
|
||||
|
||||
def todo_feed_options
|
||||
Todo.feed_options(current_user)
|
||||
options = Todo.feed_options(current_user)
|
||||
options[:title] = @feed_title
|
||||
return options
|
||||
end
|
||||
|
||||
def todo_feed_content
|
||||
|
|
@ -779,8 +786,8 @@ class TodosController < ApplicationController
|
|||
if todo.from_recurring_todo?
|
||||
recurring_todo = todo.recurring_todo
|
||||
|
||||
# check if there are active todos belonging to this recurring todo.
|
||||
# only add new one if all active todos are completed
|
||||
# check if there are active todos belonging to this recurring todo. only
|
||||
# add new one if all active todos are completed
|
||||
if recurring_todo.todos.active.count == 0
|
||||
|
||||
# check for next todo either from the due date or the show_from date
|
||||
|
|
@ -788,7 +795,7 @@ class TodosController < ApplicationController
|
|||
|
||||
# if both due and show_from are nil, check for a next todo from now
|
||||
date_to_check = Time.zone.now if date_to_check.nil?
|
||||
|
||||
|
||||
if recurring_todo.active? && recurring_todo.has_next_todo(date_to_check)
|
||||
|
||||
# shift the reference date to yesterday if date_to_check is furher in
|
||||
|
|
@ -799,7 +806,7 @@ class TodosController < ApplicationController
|
|||
# that new todos due for today will be created instead of new todos
|
||||
# for tomorrow.
|
||||
date = date_to_check.at_midnight >= Time.zone.now.at_midnight ? date_to_check : Time.zone.now-1.day
|
||||
|
||||
|
||||
new_recurring_todo = create_todo_from_recurring_todo(recurring_todo, date)
|
||||
end
|
||||
end
|
||||
|
|
@ -834,20 +841,20 @@ class TodosController < ApplicationController
|
|||
due_this_month_date = Time.zone.now.end_of_month
|
||||
case id
|
||||
when "due_today"
|
||||
return 0 == current_user.todos.count(:all,
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due <= ?', 'active', 'deferred', due_today_date])
|
||||
return 0 == current_user.todos.not_completed.count(:all,
|
||||
:conditions => ['todos.due <= ?', due_today_date])
|
||||
when "due_this_week"
|
||||
return 0 == current_user.todos.count(:all,
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_today_date, due_this_week_date])
|
||||
return 0 == current_user.todos.not_completed.count(:all,
|
||||
:conditions => ['todos.due > ? AND todos.due <= ?', due_today_date, due_this_week_date])
|
||||
when "due_next_week"
|
||||
return 0 == current_user.todos.count(:all,
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_this_week_date, due_next_week_date])
|
||||
return 0 == current_user.todos.not_completed.count(:all,
|
||||
:conditions => ['todos.due > ? AND todos.due <= ?', due_this_week_date, due_next_week_date])
|
||||
when "due_this_month"
|
||||
return 0 == current_user.todos.count(:all,
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ? AND todos.due <= ?', 'active', 'deferred', due_next_week_date, due_this_month_date])
|
||||
return 0 == current_user.todos.not_completed.count(:all,
|
||||
:conditions => ['todos.due > ? AND todos.due <= ?', due_next_week_date, due_this_month_date])
|
||||
when "due_after_this_month"
|
||||
return 0 == current_user.todos.count(:all,
|
||||
:conditions => ['(todos.state = ? OR todos.state = ?) AND todos.due > ?', 'active', 'deferred', due_this_month_date])
|
||||
return 0 == current_user.todos.not_completed.count(:all,
|
||||
:conditions => ['todos.due > ?', due_this_month_date])
|
||||
else
|
||||
raise Exception.new, "unknown due id for calendar: '#{id}'"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,10 +1,4 @@
|
|||
class UsersController < ApplicationController
|
||||
|
||||
if openid_enabled?
|
||||
open_id_consumer
|
||||
before_filter :begin_open_id_auth, :only => :update_auth_type
|
||||
end
|
||||
|
||||
before_filter :admin_login_required, :only => [ :index, :show, :destroy ]
|
||||
skip_before_filter :login_required, :only => [ :new, :create ]
|
||||
prepend_before_filter :login_optional, :only => [ :new, :create ]
|
||||
|
|
@ -153,18 +147,25 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def update_auth_type
|
||||
if (params[:user][:auth_type] == 'open_id') && openid_enabled?
|
||||
case open_id_response.status
|
||||
when OpenID::SUCCESS
|
||||
# The URL was a valid identity URL. Now we just need to send a redirect
|
||||
# to the server using the redirect_url the library created for us.
|
||||
session['openid_url'] = params[:openid_url]
|
||||
|
||||
# redirect to the server
|
||||
redirect_to open_id_response.redirect_url((request.protocol + request.host_with_port + "/"), url_for(:action => 'complete'))
|
||||
if (params[:open_id_complete] || (params[:user][:auth_type] == 'open_id')) && openid_enabled?
|
||||
authenticate_with_open_id do |result, identity_url|
|
||||
if result.successful?
|
||||
# Success means that the transaction completed without
|
||||
# error. If info is nil, it means that the user cancelled
|
||||
# the verification.
|
||||
@user.auth_type = 'open_id'
|
||||
@user.open_id_url = identity_url
|
||||
if @user.save
|
||||
notify :notice, "You have successfully verified #{identity_url} as your identity and set your authentication type to Open ID."
|
||||
else
|
||||
debugger
|
||||
notify :warning, "You have successfully verified #{identity_url} as your identity but there was a problem saving your authentication preferences."
|
||||
end
|
||||
redirect_to preferences_path
|
||||
else
|
||||
notify :warning, "Unable to find openid server for <q>#{openid_url}</q>"
|
||||
notify :warning, result.message
|
||||
redirect_to :action => 'change_auth_type'
|
||||
end
|
||||
end
|
||||
return
|
||||
end
|
||||
|
|
@ -178,47 +179,6 @@ class UsersController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def complete
|
||||
return unless openid_enabled?
|
||||
openid_url = session['openid_url']
|
||||
if openid_url.blank?
|
||||
notify :error, "expected an openid_url"
|
||||
end
|
||||
case open_id_response.status
|
||||
when OpenID::FAILURE
|
||||
# In the case of failure, if info is non-nil, it is the
|
||||
# URL that we were verifying. We include it in the error
|
||||
# message to help the user figure out what happened.
|
||||
if open_id_response.identity_url
|
||||
msg = "Verification of #{openid_url}(#{open_id_response.identity_url}) failed. "
|
||||
else
|
||||
msg = "Verification failed. "
|
||||
end
|
||||
notify :error, open_id_response.msg.to_s + msg
|
||||
|
||||
when OpenID::SUCCESS
|
||||
# Success means that the transaction completed without
|
||||
# error. If info is nil, it means that the user cancelled
|
||||
# the verification.
|
||||
@user.auth_type = 'open_id'
|
||||
@user.open_id_url = openid_url
|
||||
if @user.save
|
||||
notify :notice, "You have successfully verified #{openid_url} as your identity and set your authentication type to Open ID."
|
||||
else
|
||||
notify :warning, "You have successfully verified #{openid_url} as your identity but there was a problem saving your authentication preferences."
|
||||
end
|
||||
redirect_to preferences_path
|
||||
|
||||
when OpenID::CANCEL
|
||||
notify :warning, "Verification cancelled."
|
||||
|
||||
else
|
||||
notify :warning, "Unknown response status: #{open_id_response.status}"
|
||||
end
|
||||
redirect_to :action => 'change_auth_type' unless performed?
|
||||
end
|
||||
|
||||
|
||||
def refresh_token
|
||||
@user.generate_token
|
||||
@user.save!
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ module ApplicationHelper
|
|||
|
||||
# Replicates the link_to method but also checks request.request_uri to find
|
||||
# current page. If that matches the url, the link is marked id = "current"
|
||||
#
|
||||
#
|
||||
def navigation_link(name, options = {}, html_options = nil, *parameters_for_method_reference)
|
||||
if html_options
|
||||
html_options = html_options.stringify_keys
|
||||
|
|
@ -29,7 +29,7 @@ module ApplicationHelper
|
|||
|
||||
# Check due date in comparison to today's date Flag up date appropriately with
|
||||
# a 'traffic light' colour code
|
||||
#
|
||||
#
|
||||
def due_date(due)
|
||||
if due == nil
|
||||
return ""
|
||||
|
|
@ -62,7 +62,7 @@ module ApplicationHelper
|
|||
|
||||
# Check due date in comparison to today's date Flag up date appropriately with
|
||||
# a 'traffic light' colour code Modified method for mobile screen
|
||||
#
|
||||
#
|
||||
def due_date_mobile(due)
|
||||
if due == nil
|
||||
return ""
|
||||
|
|
@ -92,7 +92,7 @@ module ApplicationHelper
|
|||
# Returns a count of next actions in the given context or project. The result
|
||||
# is count and a string descriptor, correctly pluralised if there are no
|
||||
# actions or multiple actions
|
||||
#
|
||||
#
|
||||
def count_undone_todos_phrase(todos_parent, string="actions")
|
||||
@controller.count_undone_todos_phrase(todos_parent, string)
|
||||
end
|
||||
|
|
@ -143,5 +143,31 @@ module ApplicationHelper
|
|||
page.replace 'flash', "<h4 id='flash' class='alert #{type}'>#{message}</h4>"
|
||||
page.visual_effect :fade, 'flash', :duration => fade_duration
|
||||
end
|
||||
|
||||
|
||||
def recurrence_time_span(rt)
|
||||
case rt.ends_on
|
||||
when "no_end_date"
|
||||
return rt.start_from.nil? ? "" : "from " + format_date(rt.start_from)
|
||||
when "ends_on_number_of_times"
|
||||
return "for "+rt.number_of_occurences.to_s + " times"
|
||||
when "ends_on_end_date"
|
||||
starts = rt.start_from.nil? ? "" : "from " + format_date(rt.start_from)
|
||||
ends = rt.end_date.nil? ? "" : " until " + format_date(rt.end_date)
|
||||
return starts+ends
|
||||
else
|
||||
raise Exception.new, "unknown recurrence time span selection (#{rt.ends_on})"
|
||||
end
|
||||
end
|
||||
|
||||
def recurrence_pattern_as_text(recurring_todo)
|
||||
rt = recurring_todo.recurring_target_as_text
|
||||
rp = recurring_todo.recurrence_pattern
|
||||
# only add space if recurrence_pattern has content
|
||||
rp = " " + rp if !rp.nil?
|
||||
rts = recurrence_time_span(recurring_todo)
|
||||
# only add space if recurrence_time_span has content
|
||||
rts = " " + rts if !(rts == "")
|
||||
return rt+rp+rts
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
module NotesHelper
|
||||
def truncated_note(note, characters = 50)
|
||||
sanitize(textilize_without_paragraph(truncate(note.body, characters, "...")))
|
||||
sanitize(textilize_without_paragraph(truncate(note.body, :length => characters, :omission => "...")))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -20,12 +20,12 @@ module ProjectsHelper
|
|||
def project_next_prev
|
||||
html = ''
|
||||
unless @previous_project.nil?
|
||||
project_name = truncate(@previous_project.name, 40, "...")
|
||||
project_name = truncate(@previous_project.name, :length => 40, :omission => "...")
|
||||
html << link_to_project(@previous_project, "« #{project_name}")
|
||||
end
|
||||
html << ' | ' if @previous_project && @next_project
|
||||
unless @next_project.nil?
|
||||
project_name = truncate(@next_project.name, 40, "...")
|
||||
project_name = truncate(@next_project.name, :length => 40, :omission => "...")
|
||||
html << link_to_project(@next_project, "#{project_name} »")
|
||||
end
|
||||
html
|
||||
|
|
@ -34,12 +34,12 @@ module ProjectsHelper
|
|||
def project_next_prev_mobile
|
||||
html = ''
|
||||
unless @previous_project.nil?
|
||||
project_name = truncate(@previous_project.name, 40, "...")
|
||||
project_name = truncate(@previous_project.name, :length => 40, :omission => "...")
|
||||
html << link_to_project_mobile(@previous_project, "5", "« 5-#{project_name}")
|
||||
end
|
||||
html << ' | ' if @previous_project && @next_project
|
||||
unless @next_project.nil?
|
||||
project_name = truncate(@next_project.name, 40, "...")
|
||||
project_name = truncate(@next_project.name, :length => 40, :omission => "...")
|
||||
html << link_to_project_mobile(@next_project, "6", "6-#{project_name} »")
|
||||
end
|
||||
html
|
||||
|
|
|
|||
|
|
@ -1,37 +1,11 @@
|
|||
module RecurringTodosHelper
|
||||
|
||||
def recurrence_time_span(rt)
|
||||
case rt.ends_on
|
||||
when "no_end_date"
|
||||
return ""
|
||||
when "ends_on_number_of_times"
|
||||
return "for "+rt.number_of_occurences.to_s + " times"
|
||||
when "ends_on_end_date"
|
||||
starts = rt.start_from.nil? ? "" : "from " + format_date(rt.start_from)
|
||||
ends = rt.end_date.nil? ? "" : " until " + format_date(rt.end_date)
|
||||
return starts+ends
|
||||
else
|
||||
raise Exception.new, "unknown recurrence time span selection (#{self.ends_on})"
|
||||
end
|
||||
end
|
||||
|
||||
def recurrence_target(rt)
|
||||
case rt.target
|
||||
when 'due_date'
|
||||
return "due"
|
||||
when 'show_from_date'
|
||||
return "show"
|
||||
else
|
||||
return "ERROR"
|
||||
end
|
||||
end
|
||||
|
||||
def recurring_todo_tag_list
|
||||
tags_except_starred = @recurring_todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME}
|
||||
tag_list = tags_except_starred.collect{|t| "<span class=\"tag #{t.name.gsub(' ','-')}\">" +
|
||||
tag_list = tags_except_starred.collect{|t| "<span class=\"tag #{t.name.gsub(' ','-')}\">" +
|
||||
# link_to(t.name, :controller => "todos", :action => "tag", :id =>
|
||||
# t.name) + TODO: tag view for recurring_todos (yet?)
|
||||
t.name +
|
||||
t.name +
|
||||
"</span>"}.join('')
|
||||
"<span class='tags'>#{tag_list}</span>"
|
||||
end
|
||||
|
|
@ -44,7 +18,7 @@ module RecurringTodosHelper
|
|||
str
|
||||
end
|
||||
|
||||
def recurring_todo_remote_star_icon
|
||||
def recurring_todo_remote_star_icon
|
||||
str = 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}'")
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ module TodosHelper
|
|||
"<span class=\"tag\">" +
|
||||
link_to(t.name, {:action => "tag", :controller => "todos", :id => t.name+".m"}) +
|
||||
"</span>"}.join('')
|
||||
"<span class=\"tags\">#{tag_list}</span>"
|
||||
if tag_list.empty? then "" else "<span class=\"tags\">#{tag_list}</span>" end
|
||||
end
|
||||
|
||||
def deferred_due_date
|
||||
|
|
@ -242,13 +242,13 @@ module TodosHelper
|
|||
end
|
||||
|
||||
def project_names_for_autocomplete
|
||||
array_or_string_for_javascript( ['None'] + @projects.select{ |p| p.active? }.collect{|p| escape_javascript(p.name) } )
|
||||
array_or_string_for_javascript( ['None'] + current_user.projects.active.collect{|p| escape_javascript(p.name) } )
|
||||
end
|
||||
|
||||
def context_names_for_autocomplete
|
||||
# #return array_or_string_for_javascript(['Create a new context']) if
|
||||
# @contexts.empty?
|
||||
array_or_string_for_javascript( @contexts.collect{|c| escape_javascript(c.name) } )
|
||||
array_or_string_for_javascript( current_user.contexts.collect{|c| escape_javascript(c.name) } )
|
||||
end
|
||||
|
||||
def format_ical_notes(notes)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,10 @@ class Context < ActiveRecord::Base
|
|||
|
||||
has_many :todos, :dependent => :delete_all, :include => :project, :order => "todos.completed_at DESC"
|
||||
belongs_to :user
|
||||
|
||||
|
||||
named_scope :active, :conditions => { :hide => false }
|
||||
named_scope :hidden, :conditions => { :hide => true }
|
||||
|
||||
acts_as_list :scope => :user
|
||||
extend NamePartFinder
|
||||
include Tracks::TodoList
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
class MessageGateway < ActionMailer::Base
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
||||
|
||||
def receive(email)
|
||||
user = User.find(:first, :include => [:preference], :conditions => ["preferences.sms_email = ?", email.from[0].strip])
|
||||
if user.nil?
|
||||
|
|
|
|||
|
|
@ -3,6 +3,10 @@ class Project < ActiveRecord::Base
|
|||
has_many :notes, :dependent => :delete_all, :order => "created_at DESC"
|
||||
belongs_to :default_context, :class_name => "Context", :foreign_key => "default_context_id"
|
||||
belongs_to :user
|
||||
|
||||
named_scope :active, :conditions => { :state => 'active' }
|
||||
named_scope :hidden, :conditions => { :state => 'hidden' }
|
||||
named_scope :completed, :conditions => { :state => 'completed'}
|
||||
|
||||
validates_presence_of :name, :message => "project must have a name"
|
||||
validates_length_of :name, :maximum => 255, :message => "project name must be less than 256 characters"
|
||||
|
|
|
|||
|
|
@ -295,6 +295,17 @@ class RecurringTodo < ActiveRecord::Base
|
|||
def recurring_target=(t)
|
||||
self.target = t
|
||||
end
|
||||
|
||||
def recurring_target_as_text
|
||||
case self.target
|
||||
when 'due_date'
|
||||
return "due"
|
||||
when 'show_from_date'
|
||||
return "show"
|
||||
else
|
||||
raise Exception.new, "unexpected value of recurrence target '#{self.target}'"
|
||||
end
|
||||
end
|
||||
|
||||
def recurring_show_days_before=(days)
|
||||
self.show_from_delta=days
|
||||
|
|
@ -361,6 +372,8 @@ class RecurringTodo < ActiveRecord::Base
|
|||
when 'show_from'
|
||||
# so leave due date empty
|
||||
return nil
|
||||
else
|
||||
raise Exception.new, "unexpected value of recurrence target '#{self.target}'"
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -471,12 +484,23 @@ class RecurringTodo < ActiveRecord::Base
|
|||
start = determine_start(previous)
|
||||
day = self.every_other1
|
||||
n = self.every_other2
|
||||
|
||||
|
||||
case self.recurrence_selector
|
||||
when 0 # specific day of the month
|
||||
if start.mday >= day
|
||||
if start.mday >= day
|
||||
# there is no next day n in this month, search in next month
|
||||
start += n.months
|
||||
#
|
||||
# start += n.months
|
||||
#
|
||||
# The above seems to not work. Fiddle with timezone. Looks like we hit a
|
||||
# bug in rails here where 2008-12-01 +0100 plus 1.month becomes
|
||||
# 2008-12-31 +0100. For now, just calculate in UTC and convert back to
|
||||
# local timezone.
|
||||
#
|
||||
# TODO: recheck if future rails versions have this problem too
|
||||
start = Time.utc(start.year, start.month, start.day)+n.months
|
||||
start = Time.zone.local(start.year, start.month, start.day)
|
||||
|
||||
# go back to day
|
||||
end
|
||||
return Time.zone.local(start.year, start.month, day)
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ class Todo < ActiveRecord::Base
|
|||
|
||||
named_scope :active, :conditions => { :state => 'active' }
|
||||
named_scope :not_completed, :conditions => ['NOT state = ? ', 'completed']
|
||||
named_scope :are_due, :conditions => ['NOT todos.due IS NULL']
|
||||
|
||||
STARRED_TAG_NAME = "starred"
|
||||
|
||||
|
|
|
|||
|
|
@ -124,7 +124,7 @@ class User < ActiveRecord::Base
|
|||
|
||||
#for will_paginate plugin
|
||||
cattr_accessor :per_page
|
||||
@@per_page = 1
|
||||
@@per_page = 5
|
||||
|
||||
def validate
|
||||
unless Tracks::Config.auth_schemes.include?(auth_type)
|
||||
|
|
@ -145,8 +145,8 @@ class User < ActiveRecord::Base
|
|||
return nil
|
||||
end
|
||||
|
||||
def self.find_by_open_id_url(raw_open_id_url)
|
||||
normalized_open_id_url = normalize_open_id_url(raw_open_id_url)
|
||||
def self.find_by_open_id_url(raw_identity_url)
|
||||
normalized_open_id_url = OpenIdAuthentication.normalize_url(raw_identity_url)
|
||||
find(:first, :conditions => ['open_id_url = ?', normalized_open_id_url])
|
||||
end
|
||||
|
||||
|
|
@ -188,7 +188,7 @@ class User < ActiveRecord::Base
|
|||
end
|
||||
|
||||
def at_midnight(date)
|
||||
return TimeZone[prefs.time_zone].local(date.year, date.month, date.day, 0, 0, 0)
|
||||
return ActiveSupport::TimeZone[prefs.time_zone].local(date.year, date.month, date.day, 0, 0, 0)
|
||||
end
|
||||
|
||||
def generate_token
|
||||
|
|
@ -237,13 +237,6 @@ protected
|
|||
|
||||
def normalize_open_id_url
|
||||
return if open_id_url.nil?
|
||||
self.open_id_url = self.class.normalize_open_id_url(open_id_url)
|
||||
self.open_id_url = OpenIdAuthentication.normalize_url(open_id_url)
|
||||
end
|
||||
|
||||
def self.normalize_open_id_url(raw_open_id_url)
|
||||
normalized = raw_open_id_url
|
||||
normalized = "http://#{raw_open_id_url}" unless raw_open_id_url =~ /\:\/\//
|
||||
normalized.downcase.chomp('/')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,14 @@
|
|||
<% context = context_listing %>
|
||||
<% context = context_listing
|
||||
suppress_drag_handle ||= false
|
||||
suppress_edit_button ||= false
|
||||
%>
|
||||
<div id="<%= dom_id(context, "container") %>" class="list">
|
||||
<div id="<%= dom_id(context) %>" class="context sortable_row" style="display:'';">
|
||||
<div class="position">
|
||||
<span class="handle">DRAG</span>
|
||||
</div>
|
||||
<% unless suppress_drag_handle -%>
|
||||
<div class="position">
|
||||
<span class="handle">DRAG</span>
|
||||
</div>
|
||||
<% end -%>
|
||||
<div class="data">
|
||||
<%= link_to_context( context ) %> <%= " (" + count_undone_todos_phrase(context,"actions") + ")" %>
|
||||
</div>
|
||||
|
|
@ -32,5 +37,5 @@
|
|||
-%>
|
||||
</div>
|
||||
</div>
|
||||
<%= render :partial => 'context_form', :object => context %>
|
||||
<%= render :partial => 'contexts/context_form', :object => context %>
|
||||
</div>
|
||||
|
|
@ -6,9 +6,9 @@ if not @not_done.empty?
|
|||
# only show a context when there are actions in it
|
||||
-%>
|
||||
<h2><%=mobile_context.name%></h2>
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<ul class="c">
|
||||
<%= render :partial => "todos/mobile_todo",
|
||||
:collection => @not_done,
|
||||
:locals => { :parent_container_type => "context" }-%>
|
||||
</table>
|
||||
<% end -%>
|
||||
</ul>
|
||||
<% end -%>
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@
|
|||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form" %>
|
||||
<%= render "sidebar/sidebar" %>
|
||||
<%= render :template => "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
|
|
@ -123,7 +123,7 @@
|
|||
</div><!-- End of display_box -->
|
||||
|
||||
<div id="input_box">
|
||||
<%= render "sidebar/sidebar" %>
|
||||
<%= render :template => "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
|
||||
<script type="text/javascript">
|
||||
|
|
|
|||
14
app/views/integrations/search_plugin.rxml
Normal file
14
app/views/integrations/search_plugin.rxml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
xml.instruct!
|
||||
|
||||
xml.OpenSearchDescription 'xmlns' => "http://a9.com/-/spec/opensearch/1.1/" do
|
||||
|
||||
xml.ShortName Tracks
|
||||
xml.Description 'Search in Tracks'
|
||||
xml.InputEncoding 'UTF-8'
|
||||
xml.Image("data:image/x-icon;base64," + @icon_data,
|
||||
'width' => '16', 'height' => '16')
|
||||
xml.Url 'type' => 'text/html', 'method' => 'GET',
|
||||
'template' => url_for(:controller => 'search', :action => 'results',
|
||||
:only_path => false) + '?search={searchTerms}'
|
||||
end
|
||||
|
||||
|
|
@ -2,35 +2,40 @@
|
|||
new_todo_params = {}
|
||||
new_todo_params[:from_project] = @mobile_from_project if @mobile_from_project
|
||||
new_todo_params[:from_context] = @mobile_from_context if @mobile_from_context
|
||||
-%><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||
-%><?xml version="1.0"?>
|
||||
<!DOCTYPE html PUBLIC "-//WAPFORUM//DTD XHTML Mobile 1.0//EN" "http://www.wapforum.org/DTD/xhtml-mobile10.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta name="viewport" content="initial-scale = 1.0" />
|
||||
<%= stylesheet_link_tag "mobile"%>
|
||||
<%= stylesheet_link_tag "mobile", :media => 'handheld,all' %>
|
||||
<title><%= @page_title %></title>
|
||||
</head><body>
|
||||
<% if !(@new_mobile || @edit_mobile)
|
||||
if !@prefs.nil? -%>
|
||||
<h1><span class="count"><%= @down_count %></span> <%=
|
||||
user_time.strftime(@prefs.title_date_format) -%></h1>
|
||||
<%= (link_to("0-Add new action", formatted_new_todo_path(:m, new_todo_params))+" | ") unless @new_mobile -%>
|
||||
<div class="nav">
|
||||
<%= (link_to("0-New action", formatted_new_todo_path(:m, new_todo_params))+" | ") unless @new_mobile -%>
|
||||
<%= (link_to("1-Home", formatted_todos_path(:m))+" | ") unless @home -%>
|
||||
<%= (link_to("2-Contexts", formatted_contexts_path(:m))+" | ") -%>
|
||||
<%= (link_to("3-Projects", formatted_projects_path(:m))+" | ") -%>
|
||||
<%= (link_to("4-Starred", {:action => "tag", :controller => "todos", :id => "starred.m"})) -%>
|
||||
<% end
|
||||
end -%><%= render_flash -%>
|
||||
<hr/><%= yield -%>
|
||||
</div>
|
||||
<%= yield -%>
|
||||
<hr/><% if !@prefs.nil? -%>
|
||||
<div class="nav">
|
||||
<%= (link_to("Logout", formatted_logout_path(:format => 'm')) +" | ") -%>
|
||||
<%= (link_to("0-Add new action", formatted_new_todo_path(:m), {:accesskey => "0"})+" | ") unless @new_mobile -%>
|
||||
<%= (link_to("0-New action", formatted_new_todo_path(:m), {:accesskey => "0"})+" | ") unless @new_mobile -%>
|
||||
<%= (link_to("1-Home", formatted_todos_path(:m), {:accesskey => "1"})+" | ") unless @home -%>
|
||||
<%= (link_to("2-Contexts", formatted_contexts_path(:m), {:accesskey => "2"})+" | ") -%>
|
||||
<%= (link_to("3-Projects", formatted_projects_path(:m), {:accesskey => "3"})+" | ") -%>
|
||||
<%= (link_to("4-Starred", {:action => "tag", :controller => "todos", :id => "starred.m"}, {:accesskey => "4"})+" | ") -%>
|
||||
<%= (link_to("Tickler", {:action => "index", :controller => "tickler.m"})+" | ") -%>
|
||||
<%= (link_to("Feeds", {:action => "index", :controller => "feeds.m"})) -%>
|
||||
</div>
|
||||
<% end -%>
|
||||
<%= render :partial => "shared/mobile_footer" -%>
|
||||
</body></html>
|
||||
|
|
@ -5,13 +5,23 @@
|
|||
<% if @prefs.refresh != 0 -%>
|
||||
<meta http-equiv="Refresh" content="<%= @prefs["refresh"].to_i*60 %>;url=<%= request.request_uri %>">
|
||||
<% end -%>
|
||||
<%= javascript_include_merged :tracks %>
|
||||
<% bundle do %>
|
||||
<%= javascript_include_tag *%w[
|
||||
prototype effects dragdrop controls application
|
||||
calendar calendar-en calendar-setup
|
||||
accesskey-hints todo-items niftycube
|
||||
protoload flashobject lowpro
|
||||
] %>
|
||||
<%= stylesheet_link_tag *%w[ standard calendar-system niftyCorners] %>
|
||||
<% end %>
|
||||
<%= javascript_include_tag :unobtrusive %>
|
||||
<%= stylesheet_link_merged :tracks %>
|
||||
<%= stylesheet_link_tag "print", :media => "print" %>
|
||||
|
||||
<link rel="shortcut icon" href="<%= url_for(:controller => 'favicon.ico') %>" />
|
||||
<%= auto_discovery_link_tag(:rss, {:controller => "todos", :action => "index", :format => 'rss', :token => "#{current_user.token}"}, {:title => "RSS feed of next actions"}) %>
|
||||
<link rel="search" type="application/opensearchdescription+xml"
|
||||
title="Tracks"
|
||||
href="<%= search_plugin_path %>" />
|
||||
|
||||
<script type="text/javascript">
|
||||
window.onload=function(){
|
||||
|
|
|
|||
|
|
@ -14,19 +14,19 @@
|
|||
<% form_tag :action=> 'login' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_login">Login:</label></td>
|
||||
<td width="100px"><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
<td><label for="user_login">Login:</label></td>
|
||||
<td><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_password">Password:</label></td>
|
||||
<td width="100px"><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
<td><label for="user_password">Password:</label></td>
|
||||
<td><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
<td><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
@ -36,18 +36,18 @@
|
|||
|
||||
<% if show_openid_form %>
|
||||
<div id="openid_auth_form" style="display:none">
|
||||
<% form_tag :action=> 'login', :action => 'begin' do %>
|
||||
<% form_tag :action=> 'login' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="openid_url">Identity URL:</label></td>
|
||||
<td width="100px"><input type="text" name="openid_url" id="openid_url" value="<%= @openid_url %>" class="login_text open_id" /></td>
|
||||
<td><label for="openid_url">Identity URL:</label></td>
|
||||
<td><input type="text" name="openid_url" id="openid_url" value="<%= @openid_url %>" class="login_text open_id" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
<td><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -14,19 +14,19 @@
|
|||
<% form_tag formatted_login_path(:format => 'm') do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_login">Login:</label></td>
|
||||
<td width="100px"><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
<td><label for="user_login">Login:</label></td>
|
||||
<td><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_password">Password:</label></td>
|
||||
<td width="100px"><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
<td><label for="user_password">Password:</label></td>
|
||||
<td><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
<td><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked="checked" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td> </td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<div class="page_name_auto_complete" id="default_context_list" style="display:none;z-index:9999"></div>
|
||||
<script type="text/javascript">
|
||||
defaultContextAutoCompleter = new Autocompleter.Local('project[default_context_name]', 'default_context_list', <%= context_names_for_autocomplete %>, {choices:100,autoSelect:false});
|
||||
Event.observe($('project[default_context_name]'), "focus", defaultContextAutoCompleter.activate.bind(defaultContextAutoCompleter));
|
||||
Event.observe($('project[default_context_name]'), "click", defaultContextAutoCompleter.activate.bind(defaultContextAutoCompleter));
|
||||
defaultContextAutoCompleter = new Autocompleter.Local('project_default_context_name', 'default_context_list', <%= context_names_for_autocomplete %>, {choices:100,autoSelect:false});
|
||||
Event.observe($('project_default_context_name'), "focus", defaultContextAutoCompleter.activate.bind(defaultContextAutoCompleter));
|
||||
Event.observe($('project_default_context_name'), "click", defaultContextAutoCompleter.activate.bind(defaultContextAutoCompleter));
|
||||
</script>
|
||||
|
|
@ -74,5 +74,5 @@
|
|||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form" %>
|
||||
<%= render "sidebar/sidebar" %>
|
||||
<%= render :template => "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@
|
|||
<div class="description">
|
||||
<span class="todo.descr"><%= sanitize(recurring_todo.description) %></span> <%= recurring_todo_tag_list %>
|
||||
<span class='recurrence_pattern'>
|
||||
[<%=recurrence_target(recurring_todo)%> <%= recurring_todo.recurrence_pattern %> <%= recurrence_time_span(recurring_todo) %>]
|
||||
[<%= recurrence_pattern_as_text(@recurring_todo) %>]
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ if @recurring_saved
|
|||
page.hide 'recurring-todos-empty-nd'
|
||||
page.insert_html :bottom,
|
||||
'recurring_todos_container',
|
||||
:partial => 'recurring_todos/recurring_todo'
|
||||
:partial => 'recurring_todos/recurring_todo', :locals => { :recurring_todo => @recurring_todo}
|
||||
page.visual_effect :highlight, dom_id(@recurring_todo), :duration => 3
|
||||
# update badge count
|
||||
page['badge_count'].replace_html @count
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ if @saved
|
|||
|
||||
if @recurring_todo.completed?
|
||||
# show completed recurring todo
|
||||
page.insert_html :top, "completed_recurring_todos_container", :partial => 'recurring_todos/recurring_todo'
|
||||
page.insert_html :top, "completed_recurring_todos_container", :partial => 'recurring_todos/recurring_todo', :locals => { :recurring_todo => @recurring_todo }
|
||||
page.visual_effect :highlight, dom_id(@recurring_todo), :duration => 3
|
||||
|
||||
# set empty messages
|
||||
|
|
@ -14,7 +14,7 @@ if @saved
|
|||
# recurring_todo is activated
|
||||
|
||||
# show completed recurring todo
|
||||
page.insert_html :top, "recurring_todos_container", :partial => 'recurring_todos/recurring_todo'
|
||||
page.insert_html :top, "recurring_todos_container", :partial => 'recurring_todos/recurring_todo', :locals => { :recurring_todo => @recurring_todo }
|
||||
page.visual_effect :highlight, dom_id(@recurring_todo), :duration => 3
|
||||
|
||||
# inform user if a new todo has been created because of the activation
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ if @saved
|
|||
page << "projectAutoCompleter.options.array = #{project_names_for_autocomplete}; projectAutoCompleter.changed = true" if @new_project_created
|
||||
|
||||
# replace old recurring todo with updated todo
|
||||
page.replace dom_id(@recurring_todo), :partial => 'recurring_todos/recurring_todo'
|
||||
page.replace dom_id(@recurring_todo), :partial => 'recurring_todos/recurring_todo', :locals => { :recurring_todo => @recurring_todo }
|
||||
page.visual_effect :highlight, dom_id(@recurring_todo), :duration => 3
|
||||
|
||||
else
|
||||
|
|
|
|||
|
|
@ -1,6 +1,9 @@
|
|||
<div id="display_box_search">
|
||||
<% form_tag(:action => :results) do %>
|
||||
<%= text_field_tag(:search, params[:search]) %>
|
||||
<%= submit_tag "Search" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<div id="display_box_search">
|
||||
<% form_tag({:action => :results}, :id => 'search-form') do %>
|
||||
<%= text_field_tag(:search, params[:search]) %>
|
||||
<%= submit_tag "Search" %>
|
||||
<% end %>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
Form.focusFirstElement('search-form')
|
||||
</script>
|
||||
|
|
@ -1,32 +1,48 @@
|
|||
<div id="display_box_results">
|
||||
<% if @count == 0 -%>
|
||||
<div class="message"><p>Your search yielded no results.</p></div>
|
||||
<% else -%>
|
||||
<% source_view_is = :search %>
|
||||
<% parent_container_type = 'search' %>
|
||||
<% if not @found_todos.empty? -%>
|
||||
<div id="found-todos-container" class="container">
|
||||
<h2><span id="found-todos-count" class="badge"><%= @found_todos.size %></span>Todos matching query</h2>
|
||||
<%= render :partial => "todos/todo", :collection => @found_todos, :locals => { :parent_container_type => 'search', :suppress_context => false, :suppress_project => false, :suppress_edit_button => true } %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% if not @found_projects.empty? -%>
|
||||
<div id="found-projects-container" class="container">
|
||||
<h2><span id="found-projects-count" class="badge"><%= @found_projects.size %></span>Projects matching query</h2>
|
||||
<%= render :partial => "projects/project_listing", :collection => @found_projects, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% if not @found_notes.empty? -%>
|
||||
<div id="found-notes-container" class="container">
|
||||
<h2><span id="found-notes-count" class="badge"><%= @found_notes.size %></span>Notes matching query</h2>
|
||||
<% for notes in @found_notes -%>
|
||||
<div class="container" id="note-<%= notes.id %>-wrapper">
|
||||
<%= render :partial => "notes/notes_summary", :object => notes %>
|
||||
</div>
|
||||
<% end -%>
|
||||
</div>
|
||||
<% end -%>
|
||||
<% end -%>
|
||||
</div>
|
||||
<div id="display_box_results">
|
||||
<% if @count == 0 -%>
|
||||
<div class="message"><p>Your search yielded no results.</p></div>
|
||||
<% else -%>
|
||||
<% unless @found_todos.empty? -%>
|
||||
<div id="found-todos-container" class="container">
|
||||
<h2><span id="found-todos-count" class="badge"><%= @found_todos.size %></span>Todos matching query</h2>
|
||||
<%= render :partial => "todos/todo", :collection => @found_todos, :locals => { :parent_container_type => 'search', :suppress_context => false, :suppress_project => false, :suppress_edit_button => true } %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% unless @found_projects.empty? -%>
|
||||
<div id="found-projects-container" class="container">
|
||||
<h2><span id="found-projects-count" class="badge"><%= @found_projects.size %></span>Projects matching query</h2>
|
||||
<%= render :partial => "projects/project_listing", :collection => @found_projects, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% unless @found_notes.empty? -%>
|
||||
<div id="found-notes-container" class="container">
|
||||
<h2><span id="found-notes-count" class="badge"><%= @found_notes.size %></span>Notes matching query</h2>
|
||||
<% for notes in @found_notes -%>
|
||||
<div class="container" id="note-<%= notes.id %>-wrapper">
|
||||
<%= render :partial => "notes/notes_summary", :object => notes %>
|
||||
</div>
|
||||
<% end -%>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% unless @found_contexts.empty? -%>
|
||||
<div id="found-contexts-container" class="container">
|
||||
<h2><span id="found-contexts-count" class="badge"><%= @found_contexts.size %></span>Contexts matching query</h2>
|
||||
<%= render :partial => "contexts/context_listing", :collection => @found_contexts, :locals => { :suppress_drag_handle => true, :suppress_edit_button => true } %>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<% unless @found_tags.empty? -%>
|
||||
<div id="found-tags-container" class="container">
|
||||
<h2><span id="found-tags-count" class="badge"><%= @found_tags.size %></span>Tags matching query</h2>
|
||||
<span class="tags"><% @found_tags.each do |tag| -%>
|
||||
<span class="tag"><%= link_to tag.name, {:controller => "todos", :action => "tag", :id => tag.name} -%></span>
|
||||
<% end %>
|
||||
</span>
|
||||
<br/>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end -%>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
@todo = nil
|
||||
@initial_context_name = @context.name unless @context.nil?
|
||||
@initial_context_name ||= @project.default_context.name unless @project.nil? || @project.default_context.nil?
|
||||
@initial_context_name ||= @contexts[0].name unless @contexts[0].nil?
|
||||
@initial_context_name ||= current_user.contexts.first.name unless current_user.contexts.first.nil?
|
||||
@initial_project_name = @project.name unless @project.nil?
|
||||
%>
|
||||
<div id="todo_new_action_container">
|
||||
|
|
|
|||
|
|
@ -1,30 +1,30 @@
|
|||
<div id="sidebar">
|
||||
<% # show active items before hidden / completed items -%>
|
||||
<% # show active items before hidden / completed items -%>
|
||||
|
||||
<%= render :partial => "sidebar/project_list",
|
||||
:locals => { :list_name => 'Active Projects',
|
||||
:projects => @projects.select{|p| p.active? } } -%>
|
||||
:projects => @active_projects } -%>
|
||||
|
||||
<%= render :partial => "sidebar/context_list",
|
||||
:locals => { :list_name => 'Active Contexts',
|
||||
:contexts => @contexts.reject{|c| c.hide? } } -%>
|
||||
:contexts => @active_contexts } -%>
|
||||
|
||||
<% if prefs.show_hidden_projects_in_sidebar -%>
|
||||
<%= render :partial => "sidebar/project_list",
|
||||
:locals => { :list_name => 'Hidden Projects',
|
||||
:projects => @projects.select{|p| p.hidden? } } -%>
|
||||
:projects => @hidden_projects } -%>
|
||||
<% end -%>
|
||||
|
||||
<% if prefs.show_completed_projects_in_sidebar -%>
|
||||
<%= render :partial => "sidebar/project_list",
|
||||
:locals => { :list_name => 'Completed Projects',
|
||||
:projects => @projects.select{|p| p.completed? } } -%>
|
||||
:projects => @completed_projects } -%>
|
||||
<% end -%>
|
||||
|
||||
<% if prefs.show_hidden_contexts_in_sidebar -%>
|
||||
<%= render :partial => "sidebar/context_list",
|
||||
:locals => { :list_name => 'Hidden Contexts',
|
||||
:contexts => @contexts.select{|c| c.hide? } } -%>
|
||||
:contexts => @hidden_contexts } -%>
|
||||
<% end -%>
|
||||
|
||||
<div class="integrations-link"><ul>
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ end
|
|||
-%><%=@actions_per_context[@actions_per_context.size()-1]['total'].to_i*100/@sum%>&
|
||||
&pie_labels=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=truncate(@actions_per_context[i]['name'],@truncate_chars, '...')%>,<%
|
||||
%><%=truncate(@actions_per_context[i]['name'], :length => @truncate_chars, :omission => '...')%>,<%
|
||||
end
|
||||
-%><%=truncate(@actions_per_context[@actions_per_context.size()-1]['name'],@truncate_chars,'...') %>&
|
||||
-%><%=truncate(@actions_per_context[@actions_per_context.size()-1]['name'], :legnth => @truncate_chars, :omission => '...') %>&
|
||||
&links=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=url_for :controller => "contexts", :action => "show", :id=>@actions_per_context[i]['id']%>,<%
|
||||
|
|
|
|||
|
|
@ -8,9 +8,9 @@ end
|
|||
-%><%=@actions_per_context[@actions_per_context.size()-1]['total'].to_i*100/@sum%>&
|
||||
&pie_labels=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=truncate(@actions_per_context[i]['name'], @truncate_chars, '...') %>,<%
|
||||
%><%=truncate(@actions_per_context[i]['name'], :length => @truncate_chars, :omission => '...') %>,<%
|
||||
end
|
||||
-%><%=truncate(@actions_per_context[@actions_per_context.size()-1]['name'], @truncate_chars, '...') %>&
|
||||
-%><%=truncate(@actions_per_context[@actions_per_context.size()-1]['name'], :length => @truncate_chars, :omission => '...') %>&
|
||||
&links=<%
|
||||
0.upto @actions_per_context.size()-2 do | i |
|
||||
%><%=url_for :controller => "contexts", :action => "show", :id=>@actions_per_context[i]['id']%>,<%
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ if parent_container_type == 'show_mobile' -%>
|
|||
<h2><label for="todo_description">Description</label></h2>
|
||||
<%= text_field( "todo", "description", "tabindex" => 2) %>
|
||||
<h2><label for="todo_notes">Notes</label></h2>
|
||||
<%= text_area( "todo", "notes", "cols" => 30, "rows" => 5, "tabindex" => 3) %>
|
||||
<%= text_area( "todo", "notes", "cols" => 30, "rows" => 2, "tabindex" => 3) %>
|
||||
<h2><label for="todo_context_id">Context</label></h2>
|
||||
<%= unless @mobile_from_context
|
||||
collection_select( "todo", "context_id", @contexts, "id", "name", {}, {"tabindex" => 4} )
|
||||
|
|
@ -22,7 +22,7 @@ end %>
|
|||
<h2><label for="todo_project_id">Project</label></h2>
|
||||
<%= unless @mobile_from_project
|
||||
collection_select( "todo", "project_id", @projects, "id", "name",
|
||||
{:include_blank => true}, {"tabindex" => 5} )
|
||||
{:include_blank => '--No project--'}, {"tabindex" => 5} )
|
||||
else
|
||||
# manually add blank option since :include_blank does not work
|
||||
# with options_from_collection_for_select
|
||||
|
|
@ -34,7 +34,7 @@ end %>
|
|||
<%= text_field_tag "tag_list", @tag_list_text, :size => 30, :tabindex => 6 %>
|
||||
<h2><label for="todo_due">Due</label></h2>
|
||||
<%= date_select("todo", "due", {:order => [:day, :month, :year],
|
||||
:start_year => this_year, :include_blank => true}, :tabindex => 7) %>
|
||||
:start_year => this_year, :include_blank => '--'}, :tabindex => 7) %>
|
||||
<h2><label for="todo_show_from">Show from</label></h2>
|
||||
<%= date_select("todo", "show_from", {:order => [:day, :month, :year],
|
||||
:start_year => this_year, :include_blank => true}, :tabindex => 8) %>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
<% @todo = mobile_todo
|
||||
if mobile_todo.starred?
|
||||
bullet = "<span class=star>"+image_tag("menustar_small.gif")+"</span>"
|
||||
li_class = " class=\"star\""
|
||||
else
|
||||
bullet = "<span class=r>» </span>"
|
||||
li_class = ""
|
||||
end -%>
|
||||
<div class="t" id="<%= dom_id(mobile_todo) %>">
|
||||
<tr valign="top"><td><%= bullet %></td><td><%
|
||||
<li id="<%= dom_id(mobile_todo) %>" <%= li_class %>><%
|
||||
if mobile_todo.completed?
|
||||
-%><span class="m_t_d">
|
||||
<% else
|
||||
|
|
@ -23,4 +22,4 @@ end -%>
|
|||
")</span>" -%>
|
||||
<% end -%>
|
||||
<%= tag_list_mobile -%>
|
||||
</span></td></tr></div>
|
||||
</span></li>
|
||||
|
|
|
|||
|
|
@ -14,7 +14,10 @@
|
|||
<% unless @todo.completed? %><span class="defer-container"><%= defer_link(1) %> <%= defer_link(7) %></span><% end %>
|
||||
<%= date_span -%>
|
||||
<span class="todo.descr"><%= h sanitize(todo.description) %></span>
|
||||
<%= link_to(image_tag("recurring16x16.png"), {:controller => "recurring_todos", :action => "index"}, :class => "recurring_icon") if @todo.from_recurring_todo? %>
|
||||
<%= link_to(
|
||||
image_tag("recurring16x16.png"),
|
||||
{:controller => "recurring_todos", :action => "index"},
|
||||
:class => "recurring_icon", :title => recurrence_pattern_as_text(@todo.recurring_todo)) if @todo.from_recurring_todo? %>
|
||||
<%= tag_list %>
|
||||
<%= deferred_due_date %>
|
||||
<%= project_and_context_links( parent_container_type, :suppress_context => suppress_context, :suppress_project => suppress_project ) %>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ CLASS:PUBLIC
|
|||
CATEGORIES:Tracks
|
||||
CREATED:<%= todo.created_at.strftime("%Y%m%dT%H%M%SZ") %>
|
||||
DESCRIPTION:<%= format_ical_notes(todo.notes) %>
|
||||
LAST-MODIFIED:<%= due_date.strftime("%Y%m%dT%H%M%SZ") %>
|
||||
LAST-MODIFIED:<%= todo.updated_at.strftime("%Y%m%dT%H%M%SZ") %>
|
||||
LOCATION:
|
||||
SEQUENCE:0
|
||||
STATUS:CONFIRMED
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ if @saved
|
|||
page.insert_html :top, 'display_box', :partial => 'contexts/context', :locals => { :context => @todo.context, :collapsible => true }
|
||||
else
|
||||
page.call "todoItems.ensureVisibleWithEffectAppear", "c#{@todo.context_id}" if source_view_is_one_of(:todo, :deferred)
|
||||
page.insert_html :bottom, item_container_id(@todo) + 'items', :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type, :source_view => @source_view }
|
||||
page.insert_html :bottom, item_container_id(@todo) + 'items', :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type, :source_view => @source_view }
|
||||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,5 +10,7 @@
|
|||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form" %>
|
||||
<%= render "sidebar/sidebar" %>
|
||||
<%- # TODO: this used to be render :template, but somehow it was not
|
||||
#rendered after the rails2.2.2 upgrade -%>
|
||||
<%= render :file => "sidebar/sidebar.html.erb" %>
|
||||
</div><!-- End of input box -->
|
||||
|
|
@ -11,5 +11,5 @@
|
|||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form" %>
|
||||
<%= render "sidebar/sidebar" %>
|
||||
<%= render :template => "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
|
|
@ -23,5 +23,5 @@
|
|||
|
||||
<div id="input_box">
|
||||
<%= render :partial => "shared/add_new_item_form" %>
|
||||
<%= render "sidebar/sidebar" %>
|
||||
<%= render :template => "sidebar/sidebar" %>
|
||||
</div><!-- End of input box -->
|
||||
|
|
@ -5,7 +5,7 @@ if @saved
|
|||
|
||||
# completed todos move from their context to the completed container
|
||||
unless @prefs.hide_completed_actions?
|
||||
page.insert_html :top, "completed_containeritems", :partial => 'todos/todo', :locals => { :parent_container_type => "completed" }
|
||||
page.insert_html :top, "completed_containeritems", :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => "completed" }
|
||||
page.visual_effect :highlight, dom_id(@todo, 'line'), {'startcolor' => "'#99ff99'"}
|
||||
page[empty_container_msg_div_id].show if @down_count == 0 && !empty_container_msg_div_id.nil?
|
||||
page.show 'tickler-empty-nd' if source_view_is(:project) && @deferred_count == 0
|
||||
|
|
@ -33,7 +33,7 @@ if @saved
|
|||
else
|
||||
# todo is activated from completed container
|
||||
page.call "todoItems.ensureVisibleWithEffectAppear", item_container_id(@todo)
|
||||
page.insert_html :bottom, item_container_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.insert_html :bottom, item_container_id(@todo), :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page.visual_effect :highlight, dom_id(@todo, 'line'), {'startcolor' => "'#99ff99'"}
|
||||
page.show "empty-d" if @completed_count == 0
|
||||
page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil? # If we've checked something as undone, incomplete items can't be empty
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ if @saved
|
|||
page.call "todoItems.expandNextActionListingByContext", "c#{@todo.context_id}items", true
|
||||
page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil?
|
||||
# show all todos in context
|
||||
page.insert_html :bottom, "c#{@todo.context_id}items", :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.insert_html :bottom, "c#{@todo.context_id}items", :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
end
|
||||
|
||||
# update badge count
|
||||
|
|
@ -52,7 +52,7 @@ if @saved
|
|||
end
|
||||
end
|
||||
else
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
end
|
||||
elsif source_view_is :project
|
||||
|
|
@ -63,17 +63,17 @@ if @saved
|
|||
elsif @todo.deferred?
|
||||
page[@todo].remove
|
||||
page.show("p#{@original_item_project_id}empty-nd") if (@remaining_undone_in_project == 0)
|
||||
page.insert_html :bottom, "tickler", :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.insert_html :bottom, "tickler", :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page['tickler-empty-nd'].hide
|
||||
page.replace_html "badge_count", @down_count
|
||||
elsif @todo_was_activated_from_deferred_state
|
||||
page[@todo].remove
|
||||
page['tickler-empty-nd'].show if (@deferred_count == 0)
|
||||
page.insert_html :bottom, "p#{@todo.project_id}", :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.insert_html :bottom, "p#{@todo.project_id}", :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page["p#{@todo.project_id}empty-nd"].hide
|
||||
page.replace_html "badge_count", @down_count
|
||||
else
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
end
|
||||
elsif source_view_is :deferred
|
||||
|
|
@ -87,7 +87,7 @@ if @saved
|
|||
page.call "todoItems.ensureVisibleWithEffectAppear", "c#{@todo.context_id}"
|
||||
page.call "todoItems.expandNextActionListingByContext", "c#{@todo.context_id}items", true
|
||||
page[empty_container_msg_div_id].hide unless empty_container_msg_div_id.nil?
|
||||
page.insert_html :bottom, "c#{@todo.context_id}items", :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.insert_html :bottom, "c#{@todo.context_id}items", :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page.replace_html("badge_count", @down_count)
|
||||
page.delay(0.5) do
|
||||
page.call "todoItems.ensureContainerHeight", "c#{@original_item_context_id}items"
|
||||
|
|
@ -95,18 +95,18 @@ if @saved
|
|||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
end
|
||||
else
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
end
|
||||
elsif source_view_is :stats
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
elsif source_view_is :calendar
|
||||
if @due_date_changed
|
||||
page[@todo].remove
|
||||
page.show "empty_"+@original_item_due_id if @old_due_empty
|
||||
page.hide "empty_"+@new_due_id
|
||||
page.insert_html :bottom, @new_due_id, :partial => 'todos/todo'
|
||||
page.insert_html :bottom, @new_due_id, :partial => 'todos/todo', :locals => {:todo => @todo}
|
||||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
else
|
||||
if @todo.due.nil?
|
||||
|
|
@ -114,7 +114,7 @@ if @saved
|
|||
page[@todo].remove
|
||||
page.show "empty_"+@original_item_due_id if @old_due_empty
|
||||
else
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :parent_container_type => parent_container_type }
|
||||
page.replace dom_id(@todo), :partial => 'todos/todo', :locals => { :todo => @todo, :parent_container_type => parent_container_type }
|
||||
page.visual_effect :highlight, dom_id(@todo), :duration => 3
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue