mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-28 12:58:48 +01:00
Merge branch 'master' of git://github.com/bsag/tracks into bsag
This commit is contained in:
commit
eea421f6d3
1281 changed files with 33862 additions and 58360 deletions
8
.gitignore
vendored
8
.gitignore
vendored
|
|
@ -15,6 +15,8 @@ public/stylesheets/cache
|
|||
tmp
|
||||
vendor/plugins/query_trace/
|
||||
rerun.txt
|
||||
public/javascripts/jquery-all.js
|
||||
public/javascripts/tracks.js
|
||||
public/stylesheets/all.css
|
||||
public/javascripts/jquery-cached.js
|
||||
public/javascripts/tracks-cached.js
|
||||
public/stylesheets/tracks-cached.css
|
||||
.idea
|
||||
.rvmrc
|
||||
|
|
|
|||
|
|
@ -33,10 +33,12 @@ class ApplicationController < ActionController::Base
|
|||
before_filter :set_session_expiration
|
||||
before_filter :set_time_zone
|
||||
before_filter :set_zindex_counter
|
||||
before_filter :set_locale
|
||||
prepend_before_filter :login_required
|
||||
prepend_before_filter :enable_mobile_content_negotiation
|
||||
# after_filter :set_locale
|
||||
after_filter :set_charset
|
||||
|
||||
|
||||
include ActionView::Helpers::TextHelper
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
||||
|
|
@ -47,6 +49,14 @@ class ApplicationController < ActionController::Base
|
|||
headers["Content-Type"] ||= "text/html; charset=UTF-8"
|
||||
end
|
||||
|
||||
def set_locale
|
||||
locale = params[:locale] # specifying a locale in the request takes precedence
|
||||
locale = locale || prefs.locale unless current_user.nil? # otherwise, the locale of the currently logged in user takes over
|
||||
locale = locale || request.env['HTTP_ACCEPT_LANGUAGE'].scan(/^[a-z]{2}/).first if request.env['HTTP_ACCEPT_LANGUAGE']
|
||||
I18n.locale = locale.nil? ? I18n.default_locale : (I18n::available_locales.include?(locale.to_sym) ? locale : I18n.default_locale)
|
||||
logger.debug("Selected '#{I18n.locale}' as locale")
|
||||
end
|
||||
|
||||
def set_session_expiration
|
||||
# http://wiki.rubyonrails.com/rails/show/HowtoChangeSessionOptions
|
||||
unless session == nil
|
||||
|
|
@ -114,21 +124,25 @@ class ApplicationController < ActionController::Base
|
|||
# config/settings.yml
|
||||
#
|
||||
def format_date(date)
|
||||
if date
|
||||
date_format = prefs.date_format
|
||||
formatted_date = date.in_time_zone(prefs.time_zone).strftime("#{date_format}")
|
||||
else
|
||||
formatted_date = ''
|
||||
end
|
||||
formatted_date
|
||||
return date ? date.in_time_zone(prefs.time_zone).strftime("#{prefs.date_format}") : ''
|
||||
end
|
||||
|
||||
|
||||
def for_autocomplete(coll, substr)
|
||||
filtered = coll.find_all{|item| item.name.downcase.include? substr.downcase}
|
||||
return filtered.map {|item| "#{item.name}|#{item.id}"}.join("\n")
|
||||
if substr # protect agains empty request
|
||||
filtered = coll.find_all{|item| item.name.downcase.include? substr.downcase}
|
||||
json_elems = "[{" + filtered.map {|item| "\"value\" : \"#{item.name}\", \"id\" : \"#{item.id}\""}.join("},{") + "}]"
|
||||
return json_elems == "[{}]" ? "" : json_elems
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
def auto_complete_result2(entries, phrase = nil)
|
||||
json_elems = "[{" + entries.map {|item| "\"id\" : \"#{item.id}\", \"value\" : \"#{item.specification()}\""}.join("},{") + "}]"
|
||||
return json_elems == "[{}]" ? "" : json_elems
|
||||
end
|
||||
|
||||
|
||||
# Uses RedCloth to transform text using either Textile or Markdown Need to
|
||||
# require redcloth above RedCloth 3.0 or greater is needed to use Markdown,
|
||||
# otherwise it only handles Textile
|
||||
|
|
@ -196,7 +210,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def admin_login_required
|
||||
unless User.find_by_id_and_is_admin(session['user_id'], true)
|
||||
render :text => "401 Unauthorized: Only admin users are allowed access to this function.", :status => 401
|
||||
render :text => t('errors.user_unauthorized'), :status => 401
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,16 +13,25 @@ class ContextsController < ApplicationController
|
|||
# checks later don't result in separate SQL queries
|
||||
@active_contexts = current_user.contexts.active(true)
|
||||
@hidden_contexts = current_user.contexts.hidden(true)
|
||||
@count = @active_contexts.size + @hidden_contexts.size
|
||||
@new_context = current_user.contexts.build
|
||||
|
||||
# save all contexts here as @new_context will add an empty one to current_user.contexts
|
||||
@all_contexts = @active_contexts + @hidden_contexts
|
||||
@count = @all_contexts.size
|
||||
|
||||
|
||||
init_not_done_counts(['context'])
|
||||
respond_to do |format|
|
||||
format.html &render_contexts_html
|
||||
format.m &render_contexts_mobile
|
||||
format.xml { render :xml => current_user.contexts.to_xml( :except => :user_id ) }
|
||||
format.xml { render :xml => @all_contexts.to_xml( :except => :user_id ) }
|
||||
format.rss &render_contexts_rss_feed
|
||||
format.atom &render_contexts_atom_feed
|
||||
format.text { render :action => 'index', :layout => false, :content_type => Mime::TEXT }
|
||||
format.autocomplete { render :text => for_autocomplete(@active_contexts + @hidden_contexts, params[:q])}
|
||||
format.text do
|
||||
@all_contexts = current_user.contexts.all
|
||||
render :action => 'index', :layout => false, :content_type => Mime::TEXT
|
||||
end
|
||||
format.autocomplete { render :text => for_autocomplete(@active_contexts + @hidden_contexts, params[:term])}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -90,13 +99,18 @@ class ContextsController < ApplicationController
|
|||
@original_context_hidden = @context.hidden?
|
||||
@context.attributes = params["context"]
|
||||
|
||||
if @context.save
|
||||
@saved = @context.save
|
||||
|
||||
if @saved
|
||||
if boolean_param('wants_render')
|
||||
@context_state_changed = (@original_context_hidden != @context.hidden?)
|
||||
@new_state = (@context.hidden? ? "hidden" : "active") if @context_state_changed
|
||||
@state_changed = (@original_context_hidden != @context.hidden?)
|
||||
@new_state = (@context.hidden? ? "hidden" : "active") if @state_changed
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
|
||||
# TODO is this param ever used? is this dead code?
|
||||
|
||||
elsif boolean_param('update_context_name')
|
||||
@contexts = current_user.projects
|
||||
render :template => 'contexts/update_context_name.js.rjs'
|
||||
|
|
@ -105,8 +119,9 @@ class ContextsController < ApplicationController
|
|||
render :text => success_text || 'Success'
|
||||
end
|
||||
else
|
||||
notify :warning, "Couldn't update new context"
|
||||
render :text => ""
|
||||
respond_to do |format|
|
||||
format.js
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -126,7 +141,10 @@ class ContextsController < ApplicationController
|
|||
|
||||
@context.destroy
|
||||
respond_to do |format|
|
||||
format.js { @down_count = current_user.contexts.size }
|
||||
format.js do
|
||||
@down_count = current_user.contexts.size
|
||||
update_state_counts
|
||||
end
|
||||
format.xml { render :text => "Deleted context #{@context.name}" }
|
||||
end
|
||||
end
|
||||
|
|
@ -144,6 +162,13 @@ class ContextsController < ApplicationController
|
|||
|
||||
protected
|
||||
|
||||
def update_state_counts
|
||||
@active_contexts_count = current_user.contexts.active.count
|
||||
@hidden_contexts_count = current_user.contexts.hidden.count
|
||||
@show_active_contexts = @active_contexts_count > 0
|
||||
@show_hidden_contexts = @hidden_contexts_count > 0
|
||||
end
|
||||
|
||||
def render_contexts_html
|
||||
lambda do
|
||||
@page_title = "TRACKS::List Contexts"
|
||||
|
|
@ -179,14 +204,14 @@ class ContextsController < ApplicationController
|
|||
|
||||
def render_contexts_rss_feed
|
||||
lambda do
|
||||
render_rss_feed_for current_user.contexts, :feed => feed_options,
|
||||
render_rss_feed_for current_user.contexts.all, :feed => feed_options,
|
||||
:item => { :description => lambda { |c| c.summary(count_undone_todos_phrase(c)) } }
|
||||
end
|
||||
end
|
||||
|
||||
def render_contexts_atom_feed
|
||||
lambda do
|
||||
render_atom_feed_for current_user.contexts, :feed => feed_options,
|
||||
render_atom_feed_for current_user.contexts.all, :feed => feed_options,
|
||||
:item => { :description => lambda { |c| c.summary(count_undone_todos_phrase(c)) },
|
||||
:author => lambda { |c| nil } }
|
||||
end
|
||||
|
|
@ -230,6 +255,7 @@ class ContextsController < ApplicationController
|
|||
|
||||
@count = @not_done_todos.size
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,13 +26,19 @@ class FeedlistController < ApplicationController
|
|||
end
|
||||
|
||||
def get_feeds_for_context
|
||||
context = current_user.contexts.find params[:context_id]
|
||||
render :partial => 'feed_for_context', :locals => { :context => context }
|
||||
@context = current_user.contexts.find params[:context_id]
|
||||
respond_to do |format|
|
||||
format.html { render :file => 'feedlist/get_feeds_for_context'}
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
def get_feeds_for_project
|
||||
project = current_user.projects.find params[:project_id]
|
||||
render :partial => 'feed_for_project', :locals => { :project => project }
|
||||
@project = current_user.projects.find params[:project_id]
|
||||
respond_to do |format|
|
||||
format.html { render :file => "feedlist/get_feeds_for_project"}
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -33,30 +33,30 @@ class LoginController < ApplicationController
|
|||
@page_title = "TRACKS::Login"
|
||||
cookies[:preferred_auth] = prefered_auth? unless cookies[:preferred_auth]
|
||||
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 => SITE_CONFIG['secure_cookies'] }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
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 signup_path
|
||||
return
|
||||
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 => SITE_CONFIG['secure_cookies'] }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
cookies[:auth_token] = { :value => @user.remember_token , :expires => @user.remember_token_expires_at, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
end
|
||||
redirect_back_or_home
|
||||
return
|
||||
else
|
||||
@login = params['user_login']
|
||||
notify :warning, t('login.unsuccessful')
|
||||
end
|
||||
when :get
|
||||
if User.no_users_yet?
|
||||
redirect_to signup_path
|
||||
return
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
|
|
@ -73,25 +73,38 @@ class LoginController < ApplicationController
|
|||
CASClient::Frameworks::Rails::Filter.logout(self)
|
||||
else
|
||||
reset_session
|
||||
notify :notice, "You have been logged out of Tracks."
|
||||
notify :notice, t('login.logged_out')
|
||||
redirect_to_login
|
||||
end
|
||||
end
|
||||
|
||||
def expire_session
|
||||
# this is a hack to enable cucumber to expire a session by calling this
|
||||
# method. The method will be unavailable for production environment
|
||||
unless Rails.env.production?
|
||||
session['expiry_time'] = Time.now
|
||||
respond_to do |format|
|
||||
format.html { render :text => "Session expired for test purposes"}
|
||||
format.js { render :text => "" }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.html { render :text => "Not available for production use"}
|
||||
format.js { render :text => "" }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def check_expiry
|
||||
# Gets called by periodically_call_remote to check whether
|
||||
# Gets called by periodically_call_remote to check whether
|
||||
# the session has timed out yet
|
||||
unless session == nil
|
||||
if session
|
||||
return unless should_expire_sessions?
|
||||
# Get expiry time (allow ten seconds window for the case where we have none)
|
||||
expiry_time = session['expiry_time'] || Time.now + 10
|
||||
@time_left = expiry_time - Time.now
|
||||
if @time_left < (10*60) # Session will time out before the next check
|
||||
@msg = "Session has timed out. Please "
|
||||
else
|
||||
@msg = ""
|
||||
end
|
||||
time_left = expiry_time - Time.now
|
||||
@session_expired = ( time_left < (10*60) ) # Session will time out before the next check
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
|
|
@ -99,7 +112,7 @@ class LoginController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def login_cas
|
||||
def login_cas
|
||||
# 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
|
||||
|
||||
|
|
@ -107,22 +120,21 @@ class LoginController < ApplicationController
|
|||
if session[:cas_user]
|
||||
if @user = User.find_by_login(session[:cas_user])
|
||||
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}"
|
||||
msg = (should_expire_sessions?) ? t('login.session_will_expire', :hours => 1) : t('login.session_will_not_expire')
|
||||
notify :notice, (t('login.successful_with_session_info') + msg)
|
||||
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
cookies[:auth_token] = { :value => @user.remember_token, :expires => @user.remember_token_expires_at, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
end
|
||||
#redirect_back_or_home
|
||||
else
|
||||
notify :warning, "Sorry, no user by that CAS username exists (#{session[:cas_user]})"
|
||||
notify :warning, t('login.cas_username_not_found', :username => session[:cas_user])
|
||||
redirect_to signup_url ; return
|
||||
end
|
||||
else
|
||||
notify :warning, result.message
|
||||
end
|
||||
redirect_back_or_home
|
||||
redirect_back_or_home
|
||||
|
||||
end
|
||||
|
||||
|
|
@ -149,8 +161,8 @@ class LoginController < ApplicationController
|
|||
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}"
|
||||
msg = (should_expire_sessions?) ? t('login.session_will_expire', :hours => 1) : t('login.session_will_not_expire')
|
||||
notify :notice, (t('login.successful_with_session_info') + msg)
|
||||
cookies[:tracks_login] = { :value => @user.login, :expires => Time.now + 1.year, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
unless should_expire_sessions?
|
||||
@user.remember_me
|
||||
|
|
@ -158,7 +170,7 @@ class LoginController < ApplicationController
|
|||
end
|
||||
redirect_back_or_home
|
||||
else
|
||||
notify :warning, "Sorry, no user by that identity URL exists (#{identity_url})"
|
||||
notify :warning, t('login.openid_identity_url_not_found', :identity_url => identity_url)
|
||||
end
|
||||
else
|
||||
notify :warning, result.message
|
||||
|
|
|
|||
|
|
@ -1,87 +1,72 @@
|
|||
class NotesController < ApplicationController
|
||||
|
||||
def index
|
||||
@all_notes = current_user.notes
|
||||
@count = @all_notes.size
|
||||
@page_title = "TRACKS::All notes"
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.xml { render :xml => @all_notes.to_xml( :except => :user_id ) }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@note = current_user.notes.find(params['id'])
|
||||
@page_title = "TRACKS::Note " + @note.id.to_s
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.m &render_note_mobile
|
||||
end
|
||||
end
|
||||
|
||||
def render_note_mobile
|
||||
lambda do
|
||||
render :action => 'note_mobile'
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
note = current_user.notes.build
|
||||
note.attributes = params["note"]
|
||||
class NotesController < ApplicationController
|
||||
|
||||
saved = note.save
|
||||
before_filter :set_source_view
|
||||
|
||||
def index
|
||||
@all_notes = current_user.notes.all
|
||||
@count = @all_notes.size
|
||||
@page_title = "TRACKS::All notes"
|
||||
@source_view = 'note_list'
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.xml { render :xml => @all_notes.to_xml( :except => :user_id ) }
|
||||
end
|
||||
end
|
||||
|
||||
def show
|
||||
@note = current_user.notes.find(params['id'])
|
||||
@page_title = "TRACKS::Note " + @note.id.to_s
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.m { render :action => 'note_mobile' }
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
@note = current_user.notes.build
|
||||
@note.attributes = params["note"]
|
||||
|
||||
@saved = @note.save
|
||||
|
||||
respond_to do |format|
|
||||
format.js do
|
||||
if note.save
|
||||
render :partial => 'notes_summary', :object => note
|
||||
else
|
||||
render :text => ''
|
||||
end
|
||||
end
|
||||
format.js
|
||||
format.xml do
|
||||
if saved
|
||||
head :created, :location => note_url(note), :text => "new note with id #{note.id}"
|
||||
if @saved
|
||||
head :created, :location => note_url(@note), :text => "new note with id #{@note.id}"
|
||||
else
|
||||
render_failure note.errors.full_messages.join(', ')
|
||||
render_failure @note.errors.full_messages.join(', ')
|
||||
end
|
||||
end
|
||||
format.html do
|
||||
render :text => 'unexpected request for html rendering'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@note = current_user.notes.find(params['id'])
|
||||
|
||||
@note.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js do
|
||||
@count = current_user.notes.size
|
||||
render
|
||||
end
|
||||
end
|
||||
|
||||
# if note.destroy
|
||||
# render :text => ''
|
||||
# else
|
||||
# notify :warning, "Couldn't delete note \"#{note.id}\""
|
||||
# render :text => ''
|
||||
# end
|
||||
end
|
||||
|
||||
def update
|
||||
note = current_user.notes.find(params['id'])
|
||||
note.attributes = params["note"]
|
||||
if note.save
|
||||
render :partial => 'notes', :object => note
|
||||
else
|
||||
notify :warning, "Couldn't update note \"#{note.id}\""
|
||||
render :text => ''
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@note = current_user.notes.find(params['id'])
|
||||
@note.attributes = params["note"]
|
||||
@saved = @note.save
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js { render }
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
@note = current_user.notes.find(params['id'])
|
||||
@note.destroy
|
||||
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.js { @down_count = current_user.notes.size }
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def set_source_view
|
||||
@source_view = params['_source_view'] || 'note'
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
class PreferencesController < ApplicationController
|
||||
|
||||
def index
|
||||
@page_title = "TRACKS::Preferences"
|
||||
@prefs = prefs
|
||||
@page_title = t('preferences.page_title')
|
||||
@prefs = current_user.prefs
|
||||
end
|
||||
|
||||
def edit
|
||||
@page_title = "TRACKS::Edit Preferences"
|
||||
@page_title = t('preferences.page_title_edit')
|
||||
@prefs = current_user.prefs
|
||||
end
|
||||
|
||||
def update
|
||||
|
|
|
|||
|
|
@ -9,14 +9,16 @@ class ProjectsController < ApplicationController
|
|||
|
||||
def index
|
||||
@source_view = params['_source_view'] || 'project_list'
|
||||
@projects = current_user.projects
|
||||
@new_project = current_user.projects.build
|
||||
if params[:projects_and_actions]
|
||||
projects_and_actions
|
||||
else
|
||||
@contexts = current_user.contexts
|
||||
@contexts = current_user.contexts.all
|
||||
init_not_done_counts(['project'])
|
||||
if params[:only_active_with_no_next_actions]
|
||||
@projects = current_user.projects.active.select { |p| count_undone_todos(p) == 0 }
|
||||
else
|
||||
@projects = current_user.projects.all
|
||||
end
|
||||
init_project_hidden_todo_counts(['project'])
|
||||
respond_to do |format|
|
||||
|
|
@ -26,7 +28,7 @@ class ProjectsController < ApplicationController
|
|||
format.rss &render_rss_feed
|
||||
format.atom &render_atom_feed
|
||||
format.text &render_text_feed
|
||||
format.autocomplete { render :text => for_autocomplete(@projects.reject(&:completed?), params[:q]) }
|
||||
format.autocomplete { render :text => for_autocomplete(current_user.projects.uncompleted, params[:term]) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -43,9 +45,9 @@ class ProjectsController < ApplicationController
|
|||
def show
|
||||
@max_completed = current_user.prefs.show_number_completed
|
||||
init_data_for_sidebar unless mobile?
|
||||
@page_title = "TRACKS::Project: #{@project.name}"
|
||||
@page_title = t('projects.page_title', :project => @project.name)
|
||||
|
||||
@not_done = @project.not_done_todos_including_hidden
|
||||
@not_done = @project.todos.active_or_hidden
|
||||
@deferred = @project.deferred_todos
|
||||
@pending = @project.pending_todos
|
||||
@done = @project.todos.find_in_state(:all, :completed, :order => "todos.completed_at DESC", :limit => current_user.prefs.show_number_completed, :include => [:context])
|
||||
|
|
@ -55,6 +57,8 @@ class ProjectsController < ApplicationController
|
|||
@next_project = current_user.projects.next_from(@project)
|
||||
@previous_project = current_user.projects.previous_from(@project)
|
||||
@default_tags = @project.default_tags
|
||||
@new_note = current_user.notes.new
|
||||
@new_note.project_id = @project.id
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.m &render_project_mobile
|
||||
|
|
@ -73,6 +77,7 @@ class ProjectsController < ApplicationController
|
|||
render_failure "Expected post format is valid xml like so: <request><project><name>project name</name></project></request>."
|
||||
return
|
||||
end
|
||||
|
||||
@project = current_user.projects.build
|
||||
params_are_invalid = true
|
||||
if (params['project'] || (params['request'] && params['request']['project']))
|
||||
|
|
@ -81,9 +86,11 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
@go_to_project = params['go_to_project']
|
||||
@saved = @project.save
|
||||
|
||||
@project_not_done_counts = { @project.id => 0 }
|
||||
@active_projects_count = current_user.projects.active.count
|
||||
@contexts = current_user.contexts
|
||||
|
||||
respond_to do |format|
|
||||
format.js { @down_count = current_user.projects.size }
|
||||
format.xml do
|
||||
|
|
@ -95,6 +102,7 @@ class ProjectsController < ApplicationController
|
|||
head :created, :location => project_url(@project), :text => @project.id
|
||||
end
|
||||
end
|
||||
format.html {redirect_to :action => 'index'}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -119,18 +127,19 @@ class ProjectsController < ApplicationController
|
|||
if boolean_param('wants_render')
|
||||
if (@project.hidden?)
|
||||
@project_project_hidden_todo_counts = Hash.new
|
||||
@project_project_hidden_todo_counts[@project.id] = @project.reload().not_done_todos_including_hidden.count
|
||||
@project_project_hidden_todo_counts[@project.id] = @project.reload().todos.active_or_hidden.count
|
||||
else
|
||||
@project_not_done_counts = Hash.new
|
||||
@project_not_done_counts[@project.id] = @project.reload().not_done_todos_including_hidden.count
|
||||
@project_not_done_counts[@project.id] = @project.reload().todos.active_or_hidden.count
|
||||
end
|
||||
@contexts = current_user.contexts
|
||||
@active_projects_count = current_user.projects.active.count
|
||||
@hidden_projects_count = current_user.projects.hidden.count
|
||||
@completed_projects_count = current_user.projects.completed.count
|
||||
update_state_counts
|
||||
init_data_for_sidebar
|
||||
render :template => 'projects/update.js.rjs'
|
||||
render :template => 'projects/update.js.erb'
|
||||
return
|
||||
|
||||
# TODO: are these params ever set? or is this dead code?
|
||||
|
||||
elsif boolean_param('update_status')
|
||||
render :template => 'projects/update_status.js.rjs'
|
||||
return
|
||||
|
|
@ -151,10 +160,10 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
else
|
||||
init_data_for_sidebar
|
||||
render :template => 'projects/update.js.rjs'
|
||||
render :template => 'projects/update.js.erb'
|
||||
return
|
||||
end
|
||||
render :template => 'projects/update.js.rjs'
|
||||
render :template => 'projects/update.js.erb'
|
||||
end
|
||||
|
||||
def edit
|
||||
|
|
@ -166,11 +175,12 @@ class ProjectsController < ApplicationController
|
|||
def destroy
|
||||
@project.recurring_todos.each {|rt| rt.remove_from_project!}
|
||||
@project.destroy
|
||||
@active_projects_count = current_user.projects.active.count
|
||||
@hidden_projects_count = current_user.projects.hidden.count
|
||||
@completed_projects_count = current_user.projects.completed.count
|
||||
|
||||
respond_to do |format|
|
||||
format.js { @down_count = current_user.projects.size }
|
||||
format.js {
|
||||
@down_count = current_user.projects.size
|
||||
update_state_counts
|
||||
}
|
||||
format.xml { render :text => "Deleted project #{@project.name}" }
|
||||
end
|
||||
end
|
||||
|
|
@ -201,11 +211,20 @@ class ProjectsController < ApplicationController
|
|||
end
|
||||
|
||||
protected
|
||||
|
||||
|
||||
def update_state_counts
|
||||
@active_projects_count = current_user.projects.active.count
|
||||
@hidden_projects_count = current_user.projects.hidden.count
|
||||
@completed_projects_count = current_user.projects.completed.count
|
||||
@show_active_projects = @active_projects_count > 0
|
||||
@show_hidden_projects = @hidden_projects_count > 0
|
||||
@show_completed_projects = @completed_projects_count > 0
|
||||
end
|
||||
|
||||
def render_projects_html
|
||||
lambda do
|
||||
@page_title = "TRACKS::List Projects"
|
||||
@count = current_user.projects.size
|
||||
@page_title = t('projects.list_projects')
|
||||
@count = current_user.projects.count
|
||||
@active_projects = current_user.projects.active
|
||||
@hidden_projects = current_user.projects.hidden
|
||||
@completed_projects = current_user.projects.completed
|
||||
|
|
@ -230,10 +249,9 @@ class ProjectsController < ApplicationController
|
|||
def render_project_mobile
|
||||
lambda do
|
||||
if @project.default_context.nil?
|
||||
@project_default_context = "This project does not have a default context"
|
||||
@project_default_context = t('projects.no_default_context')
|
||||
else
|
||||
@project_default_context = "The default context for this project is "+
|
||||
@project.default_context.name
|
||||
@project_default_context = t('projects.default_context', :context => @project.default_context.name)
|
||||
end
|
||||
cookies[:mobile_url]= {:value => request.request_uri, :secure => SITE_CONFIG['secure_cookies']}
|
||||
@mobile_from_project = @project.id
|
||||
|
|
@ -244,7 +262,8 @@ class ProjectsController < ApplicationController
|
|||
def render_rss_feed
|
||||
lambda do
|
||||
render_rss_feed_for @projects, :feed => feed_options,
|
||||
:item => { :title => :name, :description => lambda { |p| summary(p) } }
|
||||
:title => :name,
|
||||
:item => { :description => lambda { |p| summary(p) } }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -293,7 +312,7 @@ class ProjectsController < ApplicationController
|
|||
project_description = ''
|
||||
project_description += sanitize(markdown( project.description )) unless project.description.blank?
|
||||
project_description += "<p>#{count_undone_todos_phrase(p)}. "
|
||||
project_description += "Project is #{project.state}."
|
||||
project_description += t('projects.project_state', :state => project.state)
|
||||
project_description += "</p>"
|
||||
project_description
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,15 +6,17 @@ class RecurringTodosController < ApplicationController
|
|||
append_before_filter :get_recurring_todo_from_param, :only => [:destroy, :toggle_check, :toggle_star, :edit, :update]
|
||||
|
||||
def index
|
||||
find_and_inactivate
|
||||
@page_title = t('todos.recurring_actions_title')
|
||||
|
||||
find_and_inactivate
|
||||
@recurring_todos = current_user.recurring_todos.active
|
||||
@completed_recurring_todos = current_user.recurring_todos.completed
|
||||
|
||||
@no_recurring_todos = @recurring_todos.size == 0
|
||||
@no_completed_recurring_todos = @completed_recurring_todos.size == 0
|
||||
@count = @recurring_todos.size
|
||||
|
||||
@page_title = "TRACKS::Recurring Actions"
|
||||
@count = @recurring_todos.size
|
||||
|
||||
@new_recurring_todo = RecurringTodo.new
|
||||
end
|
||||
|
||||
def new
|
||||
|
|
@ -103,23 +105,24 @@ class RecurringTodosController < ApplicationController
|
|||
@recurring_todo.context_id = context.id
|
||||
end
|
||||
|
||||
@recurring_saved = @recurring_todo.save
|
||||
unless (@recurring_saved == false) || p.tag_list.blank?
|
||||
@saved = @recurring_todo.save
|
||||
unless (@saved == false) || p.tag_list.blank?
|
||||
@recurring_todo.tag_with(p.tag_list)
|
||||
@recurring_todo.tags.reload
|
||||
end
|
||||
|
||||
if @recurring_saved
|
||||
@message = "The recurring todo was saved"
|
||||
if @saved
|
||||
@status_message = "The recurring todo was saved"
|
||||
@todo_saved = create_todo_from_recurring_todo(@recurring_todo).nil? == false
|
||||
if @todo_saved
|
||||
@message += " / created a new todo"
|
||||
@status_message += " / created a new todo"
|
||||
else
|
||||
@message += " / did not create todo"
|
||||
@status_message += " / did not create todo"
|
||||
end
|
||||
@count = current_user.recurring_todos.active.count
|
||||
@down_count = current_user.recurring_todos.active.count
|
||||
@new_recurring_todo = RecurringTodo.new
|
||||
else
|
||||
@message = "Error saving recurring todo"
|
||||
@status_message = "Error saving recurring todo"
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
|
|
@ -139,7 +142,10 @@ class RecurringTodosController < ApplicationController
|
|||
|
||||
# delete the recurring todo
|
||||
@saved = @recurring_todo.destroy
|
||||
@remaining = current_user.recurring_todos.count
|
||||
|
||||
# count remaining recurring todos
|
||||
@active_remaining = current_user.recurring_todos.active.count
|
||||
@completed_remaining = current_user.recurring_todos.completed.count
|
||||
|
||||
respond_to do |format|
|
||||
|
||||
|
|
@ -162,11 +168,12 @@ class RecurringTodosController < ApplicationController
|
|||
def toggle_check
|
||||
@saved = @recurring_todo.toggle_completion!
|
||||
|
||||
@count = current_user.recurring_todos.active.count
|
||||
@remaining = @count
|
||||
@down_count = current_user.recurring_todos.active.count
|
||||
@active_remaining = @down_count
|
||||
@completed_remaining = 0
|
||||
|
||||
if @recurring_todo.active?
|
||||
@remaining = current_user.recurring_todos.completed.count
|
||||
@completed_remaining = current_user.recurring_todos.completed.count
|
||||
|
||||
# from completed back to active -> check if there is an active todo
|
||||
# current_user.todos.count(:all, {:conditions => ["state = ? AND recurring_todo_id = ?", 'active',params[:id]]})
|
||||
|
|
|
|||
10
app/controllers/stats_controller.rb
Executable file → Normal file
10
app/controllers/stats_controller.rb
Executable file → Normal file
|
|
@ -376,7 +376,7 @@ class StatsController < ApplicationController
|
|||
end
|
||||
|
||||
if size==pie_cutoff
|
||||
@actions_per_context[size-1]['name']='(others)'
|
||||
@actions_per_context[size-1]['name']=t('stats.other_actions_label')
|
||||
@actions_per_context[size-1]['total']=0
|
||||
@actions_per_context[size-1]['id']=-1
|
||||
(size-1).upto @all_actions_per_context.size()-1 do |i|
|
||||
|
|
@ -417,7 +417,7 @@ class StatsController < ApplicationController
|
|||
end
|
||||
|
||||
if size==pie_cutoff
|
||||
@actions_per_context[size-1]['name']='(others)'
|
||||
@actions_per_context[size-1]['name']=t('stats.other_actions_label')
|
||||
@actions_per_context[size-1]['total']=0
|
||||
@actions_per_context[size-1]['id']=-1
|
||||
(size-1).upto @all_actions_per_context.size()-1 do |i|
|
||||
|
|
@ -565,7 +565,7 @@ class StatsController < ApplicationController
|
|||
end
|
||||
|
||||
def show_selected_actions_from_chart
|
||||
@page_title = "TRACKS::Action selection"
|
||||
@page_title = t('stats.action_selection_title')
|
||||
@count = 99
|
||||
|
||||
@source_view = 'stats'
|
||||
|
|
@ -582,10 +582,10 @@ class StatsController < ApplicationController
|
|||
week_to = week_from+1
|
||||
|
||||
@chart_name = "actions_visible_running_time_data"
|
||||
@page_title = "Actions selected from week "
|
||||
@page_title = t('stats.actions_selected_from_week')
|
||||
@further = false
|
||||
if params['id'] == 'avrt_end'
|
||||
@page_title += week_from.to_s + " and further"
|
||||
@page_title += week_from.to_s + t('stats.actions_further')
|
||||
@further = true
|
||||
else
|
||||
@page_title += week_from.to_s + " - " + week_to.to_s + ""
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -35,15 +35,15 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
if User.no_users_yet?
|
||||
@page_title = "TRACKS::Sign up as the admin user"
|
||||
@heading = "Welcome to TRACKS. To get started, please create an admin account:"
|
||||
@page_title = t('users.new_user_title')
|
||||
@heading = t('users.first_user_heading')
|
||||
@user = get_new_user
|
||||
elsif (@user && @user.is_admin?) || SITE_CONFIG['open_signups']
|
||||
@page_title = "TRACKS::Sign up a new user"
|
||||
@heading = "Sign up a new user:"
|
||||
@page_title = t('users.new_user_title')
|
||||
@heading = t('users.new_user_heading')
|
||||
@user = get_new_user
|
||||
else # all other situations (i.e. a non-admin is logged in, or no one is logged in, but we have some users)
|
||||
@page_title = "TRACKS::No signups"
|
||||
@page_title = t('users.no_signups_title')
|
||||
@admin_email = User.find_admin.preference.admin_email
|
||||
render :action => "nosignup", :layout => "login"
|
||||
return
|
||||
|
|
@ -66,7 +66,7 @@ class UsersController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html do
|
||||
unless User.no_users_yet? || (@user && @user.is_admin?) || SITE_CONFIG['open_signups']
|
||||
@page_title = "No signups"
|
||||
@page_title = t('users.no_signups_title')
|
||||
@admin_email = User.find_admin.preference.admin_email
|
||||
render :action => "nosignup", :layout => "login"
|
||||
return
|
||||
|
|
@ -98,10 +98,10 @@ class UsersController < ApplicationController
|
|||
user.is_admin = true if first_user_signing_up
|
||||
if user.save
|
||||
@user = User.authenticate(user.login, params['user']['password'])
|
||||
@user.create_preference
|
||||
@user.create_preference({:locale => I18n.locale})
|
||||
@user.save
|
||||
session['user_id'] = @user.id if first_user_signing_up
|
||||
notify :notice, "Signup successful for user #{@user.login}."
|
||||
notify :notice, t('users.signup_successful', :username => @user.login)
|
||||
redirect_back_or_home
|
||||
end
|
||||
return
|
||||
|
|
@ -121,7 +121,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
user.password_confirmation = params[:request][:password]
|
||||
if user.save
|
||||
render :text => "User created.", :status => 200
|
||||
render :text => t('users.user_created'), :status => 200
|
||||
else
|
||||
render_failure user.errors.to_xml
|
||||
end
|
||||
|
|
@ -139,9 +139,9 @@ class UsersController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html do
|
||||
if @saved
|
||||
notify :notice, "Successfully deleted user #{@deleted_user.login}", 2.0
|
||||
notify :notice, t('users.successfully_deleted_user', :username => @deleted_user.login), 2.0
|
||||
else
|
||||
notify :error, "Failed to delete user #{@deleted_user.login}", 2.0
|
||||
notify :error, t('users.failed_to_delete_user', :username => @deleted_user.login), 2.0
|
||||
end
|
||||
redirect_to users_url
|
||||
end
|
||||
|
|
@ -152,12 +152,12 @@ class UsersController < ApplicationController
|
|||
|
||||
|
||||
def change_password
|
||||
@page_title = "TRACKS::Change password"
|
||||
@page_title = t('users.change_password_title')
|
||||
end
|
||||
|
||||
def update_password
|
||||
@user.change_password(params[:updateuser][:password], params[:updateuser][:password_confirmation])
|
||||
notify :notice, "Password updated."
|
||||
notify :notice, t('users.password_updated')
|
||||
redirect_to preferences_path
|
||||
rescue Exception => error
|
||||
notify :error, error.message
|
||||
|
|
@ -165,7 +165,7 @@ class UsersController < ApplicationController
|
|||
end
|
||||
|
||||
def change_auth_type
|
||||
@page_title = "TRACKS::Change authentication type"
|
||||
@page_title = t('users.change_auth_type_title')
|
||||
end
|
||||
|
||||
def update_auth_type
|
||||
|
|
@ -177,10 +177,10 @@ class UsersController < ApplicationController
|
|||
@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."
|
||||
notify :notice, t('users.openid_url_verified', :url => identity_url)
|
||||
else
|
||||
debugger
|
||||
notify :warning, "You have successfully verified #{identity_url} as your identity but there was a problem saving your authentication preferences."
|
||||
notify :warning, t('users.openid_ok_pref_failed', :url => identity_url)
|
||||
end
|
||||
redirect_to preferences_path
|
||||
else
|
||||
|
|
@ -192,10 +192,10 @@ class UsersController < ApplicationController
|
|||
end
|
||||
@user.auth_type = params[:user][:auth_type]
|
||||
if @user.save
|
||||
notify :notice, "Authentication type updated."
|
||||
notify :notice, t('users.auth_type_updated')
|
||||
redirect_to preferences_path
|
||||
else
|
||||
notify :warning, "There was a problem updating your authentication type: #{ @user.errors.full_messages.join(', ')}"
|
||||
notify :warning, t('users.auth_type_update_error', :error_messages => @user.errors.full_messages.join(', '))
|
||||
redirect_to :action => 'change_auth_type'
|
||||
end
|
||||
end
|
||||
|
|
@ -203,7 +203,7 @@ class UsersController < ApplicationController
|
|||
def refresh_token
|
||||
@user.generate_token
|
||||
@user.save!
|
||||
notify :notice, "New token successfully generated"
|
||||
notify :notice, t('users.new_token_generated')
|
||||
redirect_to preferences_path
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -104,11 +104,29 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def link_to_context(context, descriptor = sanitize(context.name))
|
||||
link_to( descriptor, context_path(context), :title => "View context: #{context.name}" )
|
||||
link_to( descriptor, context, :title => "View context: #{context.name}" )
|
||||
end
|
||||
|
||||
def link_to_project(project, descriptor = sanitize(project.name))
|
||||
link_to( descriptor, project_path(project), :title => "View project: #{project.name}" )
|
||||
link_to( descriptor, project, :title => "View project: #{project.name}" )
|
||||
end
|
||||
|
||||
def link_to_edit_project (project, descriptor = sanitize(project.name))
|
||||
link_to(descriptor,
|
||||
url_for({:controller => 'projects', :action => 'edit', :id => project.id}),
|
||||
{:id => "link_edit_#{dom_id(project)}", :class => "project_edit_settings"})
|
||||
end
|
||||
|
||||
def link_to_edit_context (context, descriptor = sanitize(context.name))
|
||||
link_to(descriptor,
|
||||
url_for({:controller => 'contexts', :action => 'edit', :id => context.id}),
|
||||
{:id => "link_edit_#{dom_id(context)}", :class => "context_edit_settings"})
|
||||
end
|
||||
|
||||
def link_to_edit_note (note, descriptor = sanitize(note.id.to_s))
|
||||
link_to(descriptor,
|
||||
url_for({:controller => 'notes', :action => 'edit', :id => note.id}),
|
||||
{:id => "link_edit_#{dom_id(note)}", :class => "note_edit_settings"})
|
||||
end
|
||||
|
||||
def link_to_project_mobile(project, accesskey, descriptor = sanitize(project.name))
|
||||
|
|
@ -128,16 +146,7 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def render_flash
|
||||
render :partial => 'shared/flash', :locals => { :flash => flash }
|
||||
end
|
||||
|
||||
# Display a flash message in RJS templates Usage: page.notify :warning, "This
|
||||
# is the message", 5.0 Puts the message into a flash of type 'warning', fades
|
||||
# over 5 secs
|
||||
def notify(type, message, fade_duration)
|
||||
type = type.to_s # symbol to string
|
||||
page.replace 'flash', "<h4 id='flash' class='alert #{type}'>#{message}</h4>"
|
||||
page.visual_effect :fade, 'flash', :duration => fade_duration
|
||||
render :partial => 'shared/flash', :object => flash
|
||||
end
|
||||
|
||||
def recurrence_time_span(rt)
|
||||
|
|
@ -213,4 +222,41 @@ module ApplicationHelper
|
|||
note = Sanitize.clean(note, Sanitize::Config::RELAXED)
|
||||
return note
|
||||
end
|
||||
|
||||
def sidebar_html_for_titled_list (list, title)
|
||||
return content_tag(:h3, title+" (#{list.length})") +
|
||||
content_tag(:ul, sidebar_html_for_list(list))
|
||||
end
|
||||
|
||||
def sidebar_html_for_list(list)
|
||||
if list.empty?
|
||||
return content_tag(:li, t('sidebar.list_empty'))
|
||||
else
|
||||
return list.inject("") do |html, item|
|
||||
link = (item.class == "Project") ? link_to_project( item ) : link_to_context(item)
|
||||
html << content_tag(:li, link + " (" + count_undone_todos_phrase(item,"actions")+")")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def generate_i18n_strings
|
||||
js = ""
|
||||
js << "i18n = new Array();\n"
|
||||
%w{
|
||||
shared.toggle_multi shared.toggle_multi_title
|
||||
shared.hide_form shared.hide_action_form_title
|
||||
shared.toggle_single shared.toggle_single_title
|
||||
projects.hide_form projects.hide_form_title
|
||||
projects.show_form projects.show_form_title
|
||||
contexts.hide_form contexts.hide_form_title
|
||||
contexts.show_form contexts.show_form_title
|
||||
contexts.new_context_pre contexts.new_context_post
|
||||
common.cancel common.ok
|
||||
common.ajaxError
|
||||
}.each do |s|
|
||||
js << "i18n['#{s}'] = '#{ t(s).gsub(/'/, "\\\\'") }';\n"
|
||||
end
|
||||
return js
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,4 +9,17 @@ module ContextsHelper
|
|||
}
|
||||
end
|
||||
|
||||
def link_to_delete_context(context, descriptor = sanitize(context.name))
|
||||
link_to(
|
||||
descriptor,
|
||||
context_path(context, :format => 'js'),
|
||||
{
|
||||
:id => "delete_context_#{context.id}",
|
||||
:class => "delete_context_button",
|
||||
:x_confirm_message => t('contexts.delete_context_confirmation', :name => context.name),
|
||||
:title => t('contexts.delete_context_title')
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,7 +15,25 @@ module FeedlistHelper
|
|||
linkoptions = merge_hashes( {:format => 'ics'}, user_token_hash, options)
|
||||
link_to('<span class="feed">iCal</span>', linkoptions, :title => "iCal feed" )
|
||||
end
|
||||
|
||||
|
||||
def feed_links(feeds, link_options, title)
|
||||
space = " "
|
||||
html = ""
|
||||
html << rss_formatted_link(link_options)+space if feeds.include?(:rss)
|
||||
html << text_formatted_link(link_options)+space if feeds.include?(:txt)
|
||||
html << ical_formatted_link(link_options)+space if feeds.include?(:ical)
|
||||
html << title
|
||||
return html
|
||||
end
|
||||
|
||||
def all_feed_links_for_project(project)
|
||||
feed_links([:rss, :txt, :ical], { :controller=> 'todos', :action => 'index', :project_id => project.to_param }, content_tag(:strong, project.name))
|
||||
end
|
||||
|
||||
def all_feed_links_for_context(context)
|
||||
feed_links([:rss, :txt, :ical], { :controller=> 'todos', :action => 'index', :context_id => context.to_param }, content_tag(:strong, context.name))
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def merge_hashes(*hashes)
|
||||
|
|
|
|||
|
|
@ -6,4 +6,14 @@ module NotesHelper
|
|||
def rendered_note(note)
|
||||
sanitize(textilize_without_paragraph(note.body))
|
||||
end
|
||||
|
||||
def link_to_delete_note(note, descriptor = sanitize(note.id.to_s))
|
||||
link_to(
|
||||
descriptor,
|
||||
note_path(note, :format => 'js'),
|
||||
{:id => "delete_note_#{note.id}", :class => "delete_note_button",
|
||||
:title => t('notes.delete_note_title', :id => note.id), :x_confirm_message => t('notes.delete_note_confirm', :id => note.id)}
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,5 +44,18 @@ module ProjectsHelper
|
|||
end
|
||||
html
|
||||
end
|
||||
|
||||
def link_to_delete_project(project, descriptor = sanitize(project.name))
|
||||
link_to(
|
||||
descriptor,
|
||||
project_path(project, :format => 'js'),
|
||||
{
|
||||
:id => "delete_project_#{project.id}",
|
||||
:class => "delete_project_button",
|
||||
:x_confirm_message => t('projects.delete_project_confirmation', :name => project.name),
|
||||
:title => t('projects.delete_project_title')
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,20 +13,20 @@ module RecurringTodosHelper
|
|||
def recurring_todo_remote_delete_icon
|
||||
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}'")
|
||||
:class => "icon delete_icon", :title => t('todos.delete_recurring_action_title'), :x_confirm_message => t('todos.delete_recurring_action_confirm', :description => @recurring_todo.description))
|
||||
end
|
||||
|
||||
def recurring_todo_remote_star_icon
|
||||
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}'")
|
||||
toggle_star_recurring_todo_path(@recurring_todo), :id => "star_icon_"+@recurring_todo.id.to_s,
|
||||
:class => "icon star_item", :title => t('todos.star_action'))
|
||||
end
|
||||
|
||||
def recurring_todo_remote_edit_icon
|
||||
if !@recurring_todo.completed?
|
||||
str = link_to( image_tag_for_edit(@recurring_todo),
|
||||
edit_recurring_todo_path(@recurring_todo),
|
||||
:class => "icon edit_icon")
|
||||
:class => "icon edit_icon", :id => "link_edit_recurring_todo_#{@recurring_todo.id}")
|
||||
else
|
||||
str = '<a class="icon">' + image_tag("blank.png") + "</a> "
|
||||
end
|
||||
|
|
@ -34,17 +34,16 @@ module RecurringTodosHelper
|
|||
end
|
||||
|
||||
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')
|
||||
str
|
||||
return check_box_tag("check_#{@recurring_todo.id}", toggle_check_recurring_todo_path(@recurring_todo), @recurring_todo.completed?, :class => 'item-checkbox')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def image_tag_for_delete
|
||||
image_tag("blank.png", :title =>"Delete action", :class=>"delete_item")
|
||||
image_tag("blank.png", :title =>t('todos.delete_action'), :class=>"delete_item")
|
||||
end
|
||||
|
||||
def image_tag_for_edit(todo)
|
||||
image_tag("blank.png", :title =>"Edit action", :class=>"edit_item", :id=> dom_id(todo, 'edit_icon'))
|
||||
image_tag("blank.png", :title =>t('todos.edit_action'), :class=>"edit_item", :id=> dom_id(todo, 'edit_icon'))
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
module SearchHelper
|
||||
|
||||
end
|
||||
module SearchHelper
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,66 +1,50 @@
|
|||
module TodosHelper
|
||||
|
||||
# #require 'users_controller' Counts the number of incomplete items in the
|
||||
# specified context
|
||||
#
|
||||
def count_items(context)
|
||||
count = Todo.find_all("done=0 AND context_id=#{context.id}").length
|
||||
def remote_star_icon(todo=@todo)
|
||||
link_to( image_tag_for_star(todo),
|
||||
toggle_star_todo_path(todo),
|
||||
:class => "icon star_item", :title => t('todos.star_action_with_description', :description => todo.description))
|
||||
end
|
||||
|
||||
def form_remote_tag_edit_todo( &block )
|
||||
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 )
|
||||
end
|
||||
|
||||
def remote_star_icon
|
||||
link_to( image_tag_for_star(@todo),
|
||||
toggle_star_todo_path(@todo),
|
||||
:class => "icon star_item", :title => "star the action '#{@todo.description}'")
|
||||
end
|
||||
|
||||
def remote_edit_button
|
||||
def remote_edit_button(todo=@todo)
|
||||
link_to(
|
||||
image_tag("blank.png", :alt => "Edit", :align => "absmiddle", :id => 'edit_icon_todo_'+@todo.id.to_s, :class => 'edit_item'),
|
||||
{:controller => 'todos', :action => 'edit', :id => @todo.id},
|
||||
image_tag("blank.png", :alt => t('todos.edit'), :align => "absmiddle", :id => 'edit_icon_todo_'+todo.id.to_s, :class => 'edit_item'),
|
||||
{:controller => 'todos', :action => 'edit', :id => todo.id},
|
||||
:class => "icon edit_item",
|
||||
:title => "Edit the action '#{@todo.description}'")
|
||||
:title => t('todos.edit_action_with_description', :description => todo.description))
|
||||
end
|
||||
|
||||
def remote_delete_menu_item(parameters, todo)
|
||||
return link_to_remote(
|
||||
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(todo),
|
||||
:confirm => "Are you sure that you want to delete the action '#{todo.description}'?")
|
||||
def remote_delete_menu_item(todo)
|
||||
return link_to(
|
||||
image_tag("delete_off.png", :mouseover => "delete_on.png", :alt => t('todos.delete'), :align => "absmiddle")+" "+t('todos.delete'),
|
||||
{:controller => 'todos', :action => 'destroy', :id => todo.id},
|
||||
:class => "icon_delete_item",
|
||||
:id => "delete_#{dom_id(todo)}",
|
||||
:x_confirm_message => t('todos.confirm_delete', :description => todo.description),
|
||||
:title => t('todos.delete_action'));
|
||||
end
|
||||
|
||||
def remote_defer_menu_item(days, todo)
|
||||
url = {:controller => 'todos', :action => 'defer', :id => todo.id, :days => days,
|
||||
:_source_view => (@source_view.underscore.gsub(/\s+/,'_') rescue "")}
|
||||
url[:_tag_name] = @tag_name if @source_view == 'tag'
|
||||
|
||||
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 => "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 => "Defer #{pluralize(days, "day")}", :align => "absmiddle")+" Defer #{pluralize(days, "day")}",
|
||||
:url => url,
|
||||
:before => todo_start_waiting_js(todo),
|
||||
:complete => todo_stop_waiting_js(todo))
|
||||
|
||||
futuredate = (todo.show_from || todo.user.date) + days.days
|
||||
options = {:x_defer_alert => false, :class => "icon_defer_item" }
|
||||
if todo.due && futuredate > todo.due
|
||||
options[:x_defer_alert] = true
|
||||
options[:x_defer_date_after_due_date] = t('todos.defer_date_after_due_date')
|
||||
end
|
||||
|
||||
return link_to(image_tag_for_defer(days), url, options)
|
||||
end
|
||||
|
||||
def remote_delete_dependency(todo, predecessor)
|
||||
link_to(
|
||||
image_tag("blank.png", :title => t('todos.remove_dependency'), :align => "absmiddle", :class => "delete_item"),
|
||||
url_for({:controller => 'todos', :action => 'remove_predecessor', :id => todo.id}),
|
||||
{:class => "delete_dependency_button", :x_predecessors_id => predecessor.id}
|
||||
)
|
||||
end
|
||||
|
||||
def remote_promote_to_project_menu_item(todo)
|
||||
|
|
@ -68,19 +52,31 @@ module TodosHelper
|
|||
:_source_view => (@source_view.underscore.gsub(/\s+/,'_') rescue "")}
|
||||
url[:_tag_name] = @tag_name if @source_view == 'tag'
|
||||
|
||||
return link_to(image_tag("to_project_off.png", :align => "absmiddle")+" Make project", url)
|
||||
end
|
||||
|
||||
def todo_start_waiting_js(todo)
|
||||
return "$('#ul#{dom_id(todo)}').css('visibility', 'hidden'); $('##{dom_id(todo)}').block({message: null})"
|
||||
return link_to(image_tag("to_project_off.png", :align => "absmiddle")+" " + t('todos.convert_to_project'), url)
|
||||
end
|
||||
|
||||
def image_tag_for_defer(days)
|
||||
image_tag("defer_#{days}_off.png", :mouseover => "defer_#{days}.png", :alt => t('todos.defer_x_days', :count => days), :align => "absmiddle")+" "+t('todos.defer_x_days', :count => days)
|
||||
end
|
||||
|
||||
# waiting stuff can be deleted after migration of defer and dependencies
|
||||
def successor_start_waiting_js(successor)
|
||||
return "$('##{dom_id(successor, "successor")}').block({message: null})"
|
||||
end
|
||||
|
||||
def todo_stop_waiting_js(todo)
|
||||
return "$('##{dom_id(todo)}').unblock();enable_rich_interaction();"
|
||||
def collapsed_notes_image(todo)
|
||||
link = link_to(image_tag( 'blank.png', :width=>'16', :height=>'16', :border=>'0' ), "#", {:class => 'show_notes', :title => 'Show notes'})
|
||||
notes = content_tag(:div, {:class => "todo_notes", :id => dom_id(todo, 'notes'), :style => "display:none"}) { format_note(todo.notes) }
|
||||
return link+notes
|
||||
end
|
||||
|
||||
def collapsed_successors_image(todo)
|
||||
link = link_to(image_tag( 'blank.png', :width=>'16', :height=>'16', :border=>'0' ), "#", {:class => 'show_successors', :title => 'Show successors'})
|
||||
successors = content_tag(:div, {:class => "todo_successors", :id => dom_id(todo, 'successors'), :style => "display:none"}) do
|
||||
render :partial => "todos/successor", :collection => todo.pending_successors,
|
||||
:locals => { :parent_container_type => parent_container_type, :suppress_dependencies => true, :predecessor => todo }
|
||||
end
|
||||
return link+successors
|
||||
end
|
||||
|
||||
def image_tag_for_recurring_todo(todo)
|
||||
|
|
@ -89,53 +85,52 @@ module TodosHelper
|
|||
{:controller => "recurring_todos", :action => "index"},
|
||||
:class => "recurring_icon", :title => recurrence_pattern_as_text(todo.recurring_todo))
|
||||
end
|
||||
|
||||
|
||||
def remote_toggle_checkbox
|
||||
check_box_tag('item_id', toggle_check_todo_path(@todo), @todo.completed?, :class => 'item-checkbox',
|
||||
:title => @todo.pending? ? 'Blocked by ' + @todo.uncompleted_predecessors.map(&:description).join(', ') : "", :readonly => @todo.pending?)
|
||||
def remote_toggle_checkbox(todo=@todo)
|
||||
check_box_tag('item_id', toggle_check_todo_path(todo), todo.completed?, :class => 'item-checkbox',
|
||||
:title => todo.pending? ? t('todos.blocked_by', :predecessors => todo.uncompleted_predecessors.map(&:description).join(', ')) : "", :readonly => todo.pending?)
|
||||
end
|
||||
|
||||
def date_span
|
||||
if @todo.completed?
|
||||
"<span class=\"grey\">#{format_date( @todo.completed_at )}</span>"
|
||||
elsif @todo.pending?
|
||||
"<a title='Depends on: #{@todo.uncompleted_predecessors.map(&:description).join(', ')}'><span class=\"orange\">Pending</span></a> "
|
||||
elsif @todo.deferred?
|
||||
show_date( @todo.show_from )
|
||||
def date_span(todo=@todo)
|
||||
if todo.completed?
|
||||
"<span class=\"grey\">#{format_date( todo.completed_at )}</span>"
|
||||
elsif todo.pending?
|
||||
"<a title='#{t('todos.depends_on')}: #{todo.uncompleted_predecessors.map(&:description).join(', ')}'><span class=\"orange\">#{t('todos.pending')}</span></a> "
|
||||
elsif todo.deferred?
|
||||
show_date( todo.show_from )
|
||||
else
|
||||
due_date( @todo.due )
|
||||
due_date( todo.due )
|
||||
end
|
||||
end
|
||||
|
||||
def successors_span
|
||||
unless @todo.pending_successors.empty?
|
||||
pending_count = @todo.pending_successors.length
|
||||
title = "Has #{pluralize(pending_count, 'pending action')}: #{@todo.pending_successors.map(&:description).join(', ')}"
|
||||
def successors_span(todo=@todo)
|
||||
unless todo.pending_successors.empty?
|
||||
pending_count = todo.pending_successors.length
|
||||
title = "#{t('todos.has_x_pending', :count => pending_count)}: #{todo.pending_successors.map(&:description).join(', ')}"
|
||||
image_tag( 'successor_off.png', :width=>'10', :height=>'16', :border=>'0', :title => title )
|
||||
end
|
||||
end
|
||||
|
||||
def grip_span
|
||||
unless @todo.completed?
|
||||
def grip_span(todo=@todo)
|
||||
unless todo.completed?
|
||||
image_tag('grip.png', :width => '7', :height => '16', :border => '0',
|
||||
:title => 'Drag onto another action to make it depend on that action',
|
||||
:title => t('todos.drag_action_title'),
|
||||
:class => 'grip')
|
||||
end
|
||||
end
|
||||
|
||||
def tag_list_text
|
||||
@todo.tags.collect{|t| t.name}.join(', ')
|
||||
def tag_list_text(todo=@todo)
|
||||
todo.tags.collect{|t| t.name}.join(', ')
|
||||
end
|
||||
|
||||
def tag_list
|
||||
tags_except_starred = @todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME}
|
||||
def tag_list(todo=@todo)
|
||||
tags_except_starred = todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME}
|
||||
tag_list = tags_except_starred.collect{|t| "<span class=\"tag #{t.name.gsub(' ','-')}\">" + link_to(t.name, :controller => "todos", :action => "tag", :id => t.name) + "</span>"}.join('')
|
||||
"<span class='tags'>#{tag_list}</span>"
|
||||
end
|
||||
|
||||
def tag_list_mobile
|
||||
tags_except_starred = @todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME}
|
||||
def tag_list_mobile(todo=@todo)
|
||||
tags_except_starred = todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME}
|
||||
# removed the link. TODO: add link to mobile view of tagged actions
|
||||
tag_list = tags_except_starred.collect{|t|
|
||||
"<span class=\"tag\">" +
|
||||
|
|
@ -144,30 +139,30 @@ module TodosHelper
|
|||
if tag_list.empty? then "" else "<span class=\"tags\">#{tag_list}</span>" end
|
||||
end
|
||||
|
||||
def predecessor_list_text
|
||||
@todo.predecessors.map{|t| t.specification}.join(', ')
|
||||
def predecessor_list_text(todo=@todo)
|
||||
todo.predecessors.map{|t| t.specification}.join(', ')
|
||||
end
|
||||
|
||||
def deferred_due_date
|
||||
if @todo.deferred? && @todo.due
|
||||
"(action due on #{format_date(@todo.due)})"
|
||||
def deferred_due_date(todo=@todo)
|
||||
if todo.deferred? && todo.due
|
||||
t('todos.action_due_on', :date => format_date(todo.due))
|
||||
end
|
||||
end
|
||||
|
||||
def project_and_context_links(parent_container_type, opts = {})
|
||||
def project_and_context_links(todo, parent_container_type, opts = {})
|
||||
str = ''
|
||||
if @todo.completed?
|
||||
str += @todo.context.name unless opts[:suppress_context]
|
||||
should_suppress_project = opts[:suppress_project] || @todo.project.nil?
|
||||
if todo.completed?
|
||||
str += todo.context.name unless opts[:suppress_context]
|
||||
should_suppress_project = opts[:suppress_project] || todo.project.nil?
|
||||
str += ", " unless str.blank? || should_suppress_project
|
||||
str += @todo.project.name unless should_suppress_project
|
||||
str += todo.project.name unless should_suppress_project
|
||||
str = "(#{str})" unless str.blank?
|
||||
else
|
||||
if (['project', 'tag', 'stats', 'search'].include?(parent_container_type))
|
||||
str << item_link_to_context( @todo )
|
||||
str << item_link_to_context( todo )
|
||||
end
|
||||
if (['context', 'tickler', 'tag', 'stats', 'search'].include?(parent_container_type)) && @todo.project_id
|
||||
str << item_link_to_project( @todo )
|
||||
if (['context', 'tickler', 'tag', 'stats', 'search'].include?(parent_container_type)) && todo.project_id
|
||||
str << item_link_to_project( todo )
|
||||
end
|
||||
end
|
||||
return str
|
||||
|
|
@ -207,66 +202,67 @@ module TodosHelper
|
|||
case days
|
||||
# overdue or due very soon! sound the alarm!
|
||||
when -1000..-1
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"red\">Scheduled to show " + (days * -1).to_s + " days ago</span></a> "
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"red\">#{t('todos.scheduled_overdue', :days => (days * -1).to_s)}</span></a> "
|
||||
when 0
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"amber\">Show Today</span></a> "
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"amber\">#{t('todos.show_today')}</span></a> "
|
||||
when 1
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"amber\">Show Tomorrow</span></a> "
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"amber\">#{t('todos.show_tomorrow')}</span></a> "
|
||||
# due 2-7 days away
|
||||
when 2..7
|
||||
if prefs.due_style == Preference.due_styles[:due_on]
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"orange\">Show on " + d.strftime("%A") + "</span></a> "
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"orange\">#{t('todos.show_on_date', :date => d.strftime("%A"))}</span></a> "
|
||||
else
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"orange\">Show in " + days.to_s + " days</span></a> "
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"orange\">#{t('todos.show_in_days', :days => days.to_s)}</span></a> "
|
||||
end
|
||||
# more than a week away - relax
|
||||
else
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"green\">Show in " + days.to_s + " days</span></a> "
|
||||
"<a title=\"" + format_date(d) + "\"><span class=\"green\">#{t('todos.show_in_days', :days => days.to_s)}</span></a> "
|
||||
end
|
||||
end
|
||||
|
||||
def item_container_id (todo)
|
||||
if todo.deferred? or todo.pending?
|
||||
return "tickleritems"
|
||||
elsif source_view_is :project
|
||||
return "p#{todo.project_id}items"
|
||||
def should_show_new_item
|
||||
source_view do |page|
|
||||
page.todo { return !@todo.hidden? }
|
||||
page.deferred { return @todo.deferred? || @todo.pending? }
|
||||
page.context {
|
||||
logger.debug "ci=#{@todo.context_id} dci=#{@default_context.id} th=#{@todo.hidden?} tch=#{@todo.context.hidden?}"
|
||||
return @todo.context_id==@default_context.id && ( (@todo.hidden? && @todo.context.hidden?) || (!@todo.hidden?) )
|
||||
}
|
||||
page.tag {
|
||||
return ( (@todo.pending? && @todo.has_tag?(@tag_name)) ||
|
||||
(@todo.has_tag?(@tag_name)) ||
|
||||
(@todo.starred? && @tag_name == Todo::STARRED_TAG_NAME)
|
||||
)
|
||||
}
|
||||
page.project {
|
||||
return (@todo.active? && @todo.project && @todo.project.id == @default_project.id) ||
|
||||
(@todo.project.hidden? && @todo.project_hidden?) || @todo.deferred? || @todo.pending?
|
||||
}
|
||||
end
|
||||
return "c#{todo.context_id}items"
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
def should_show_new_item
|
||||
def should_make_context_visible
|
||||
return @todo.active? && (!@todo.hidden? && !source_view_is(:project) )
|
||||
end
|
||||
|
||||
unless @todo.project.nil?
|
||||
# do not show new actions that were added to hidden or completed projects
|
||||
# on home page and context page
|
||||
return false if source_view_is(:todo) && (@todo.project.hidden? || @todo.project.completed?)
|
||||
return false if source_view_is(:context) && (@todo.project.hidden? || @todo.project.completed?)
|
||||
end
|
||||
|
||||
return false if (source_view_is(:tag) && !@todo.tags.include?(@tag_name))
|
||||
|
||||
return true if source_view_is(:deferred) && @todo.deferred?
|
||||
return true if source_view_is(:project) && @todo.project.hidden? && @todo.project_hidden?
|
||||
return true if source_view_is(:project) && @todo.deferred?
|
||||
return true if !source_view_is(:deferred) && @todo.active?
|
||||
return true if source_view_is(:project) && @todo.pending?
|
||||
|
||||
return true if source_view_is(:tag) && @todo.pending?
|
||||
return false
|
||||
def should_add_new_context
|
||||
return @new_context_created && !source_view_is(:project)
|
||||
end
|
||||
|
||||
def parent_container_type
|
||||
return 'tickler' if source_view_is :deferred
|
||||
return 'project' if source_view_is :project
|
||||
return 'stats' if source_view_is :stats
|
||||
return 'tag' if source_view_is :tag
|
||||
return 'context'
|
||||
end
|
||||
|
||||
def empty_container_msg_div_id
|
||||
todo = @todo || @successor
|
||||
return "tickler-empty-nd" if source_view_is_one_of(:project, :tag) && todo.deferred?
|
||||
return "p#{todo.project_id}empty-nd" if source_view_is :project
|
||||
return "c#{todo.context_id}empty-nd"
|
||||
def todo_container_is_empty
|
||||
default_container_empty = ( @down_count == 0 )
|
||||
deferred_container_empty = ( @todo.deferred? && @remaining_deferred_count == 0)
|
||||
return default_container_empty || deferred_container_empty
|
||||
end
|
||||
|
||||
def default_contexts_for_autocomplete
|
||||
|
|
@ -280,7 +276,7 @@ module TodosHelper
|
|||
end
|
||||
|
||||
def format_ical_notes(notes)
|
||||
unless notes.blank?
|
||||
unless notes.nil? || notes.blank?
|
||||
split_notes = notes.split(/\n/)
|
||||
joined_notes = split_notes.join("\\n")
|
||||
end
|
||||
|
|
@ -295,16 +291,128 @@ module TodosHelper
|
|||
def date_field_tag(name, id, value = nil, options = {})
|
||||
text_field_tag name, value, {"size" => 12, "id" => id, "class" => "Date", "onfocus" => "Calendar.setup", "autocomplete" => "off"}.update(options.stringify_keys)
|
||||
end
|
||||
|
||||
|
||||
def update_needs_to_hide_context
|
||||
return (@remaining_in_context == 0 && (@todo_hidden_state_changed && @todo.hidden?)) ||
|
||||
(@remaining_in_context == 0 && @todo_was_deferred_from_active_state) ||
|
||||
(@remaining_in_context == 0 && @todo.completed? && !(@original_item_was_deferred || @original_item_was_hidden)) if source_view_is(:tag)
|
||||
|
||||
return false if source_view_is(:project)
|
||||
|
||||
return (@remaining_in_context == 0) && !source_view_is(:context)
|
||||
end
|
||||
|
||||
def update_needs_to_remove_todo_from_container
|
||||
source_view do |page|
|
||||
page.context { return @context_changed || @todo.deferred? || @todo.pending? }
|
||||
page.project { return @todo_deferred_state_changed || @todo_pending_state_changed }
|
||||
page.deferred { return @context_changed || !(@todo.deferred? || @todo.pending?) }
|
||||
page.calendar { return @due_date_changed || !@todo.due }
|
||||
page.stats { return @todo.completed? }
|
||||
page.tag { return (@context_changed && !@todo.hidden?) || @tag_was_removed || @todo_hidden_state_changed || @todo_deferred_state_changed }
|
||||
page.todo { return @context_changed || @todo.hidden? || @todo.deferred? || @todo.pending?}
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def replace_with_updated_todo
|
||||
source_view do |page|
|
||||
page.context { return !update_needs_to_remove_todo_from_container }
|
||||
page.project { return !update_needs_to_remove_todo_from_container }
|
||||
page.deferred { return !@context_changed && (@todo.deferred? || @todo.pending?) }
|
||||
page.calendar { return !@due_date_changed && @todo.due }
|
||||
page.stats { return !@todo.completed? }
|
||||
page.tag { return !update_needs_to_remove_todo_from_container && !@tag_was_removed }
|
||||
page.todo { return !update_needs_to_remove_todo_from_container }
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def append_updated_todo
|
||||
source_view do |page|
|
||||
page.context { return false }
|
||||
page.project { return @todo_deferred_state_changed || @todo_pending_state_changed }
|
||||
page.deferred { return @context_changed && (@todo.deferred? || @todo.pending?) }
|
||||
page.calendar { return @due_date_changed && @todo.due }
|
||||
page.stats { return false }
|
||||
page.tag { return update_needs_to_remove_todo_from_container && !@tag_was_removed}
|
||||
page.todo { return @context_changed && !(@todo.deferred? || @todo.pending? || @todo.hidden?) }
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
def item_container_id (todo)
|
||||
return "hiddenitems" if source_view_is(:tag) && todo.hidden?
|
||||
return "c#{todo.context_id}items" if source_view_is :deferred
|
||||
return @new_due_id if source_view_is :calendar
|
||||
return "tickleritems" if !source_view_is(:todo) && (todo.deferred? || todo.pending?)
|
||||
return "completed_containeritems" if todo.completed?
|
||||
return "p#{todo.project_id}items" if source_view_is :project
|
||||
return "c#{todo.context_id}items"
|
||||
end
|
||||
|
||||
def empty_container_msg_div_id(todo = @todo || @successor)
|
||||
raise Exception.new, "no @todo or @successor set" if !todo
|
||||
|
||||
source_view do |page|
|
||||
page.project {
|
||||
return "tickler-empty-nd" if @todo_was_deferred_from_active_state || @todo_was_blocked_from_active_state
|
||||
return "p#{todo.project_id}empty-nd"
|
||||
}
|
||||
page.tag {
|
||||
return "tickler-empty-nd" if @todo_was_deferred_from_active_state
|
||||
return "hidden-empty-nd" if @todo.hidden?
|
||||
return "c#{todo.context_id}empty-nd"
|
||||
}
|
||||
page.calendar {
|
||||
return "empty_#{@new_due_id}"
|
||||
}
|
||||
end
|
||||
|
||||
return "c#{todo.context_id}empty-nd"
|
||||
end
|
||||
|
||||
def show_empty_message_in_source_container
|
||||
container_id = ""
|
||||
source_view do |page|
|
||||
page.project {
|
||||
container_id = "p#{@original_item_project_id}empty-nd" if @remaining_in_context == 0
|
||||
container_id = "tickler-empty-nd" if (
|
||||
( (@todo_was_activated_from_deferred_state || @todo_was_activated_from_pending_state) && @remaining_deferred_or_pending_count == 0) ||
|
||||
(@original_item_was_deferred && @remaining_deferred_or_pending_count == 0 && @todo.completed?) )
|
||||
container_id = "empty-d" if @completed_count && @completed_count == 0 && !@todo.completed?
|
||||
}
|
||||
page.deferred { container_id = "c#{@original_item_context_id}empty-nd" if @remaining_in_context == 0 }
|
||||
page.calendar { container_id = "empty_#{@original_item_due_id}" if @old_due_empty }
|
||||
page.tag {
|
||||
container_id = "hidden-empty-nd" if (@remaining_hidden_count == 0 && !@todo.hidden? && @todo_hidden_state_changed) ||
|
||||
(@remaining_hidden_count == 0 && @todo.completed? && @original_item_was_hidden)
|
||||
container_id = "tickler-empty-nd" if (@todo_was_activated_from_deferred_state && @remaining_deferred_or_pending_count == 0) ||
|
||||
(@original_item_was_deferred && @remaining_deferred_or_pending_count == 0 && @todo.completed?)
|
||||
container_id = "empty-d" if @completed_count && @completed_count == 0 && !@todo.completed?
|
||||
}
|
||||
page.context { container_id = "c#{@original_item_context_id}empty-nd" if @remaining_in_context == 0 }
|
||||
page.todo { container_id = "c#{@original_item_context_id}empty-nd" if @remaining_in_context == 0 }
|
||||
end
|
||||
return container_id.blank? ? "" : "$(\"##{container_id}\").slideDown(100);"
|
||||
end
|
||||
|
||||
def render_animation(animation)
|
||||
html = ""
|
||||
animation.each do |step|
|
||||
unless step.blank?
|
||||
html += step + "({ go: function() {\r\n"
|
||||
end
|
||||
end
|
||||
html += "}}) " * animation.count
|
||||
return html
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def image_tag_for_star(todo)
|
||||
class_str = todo.starred? ? "starred_todo" : "unstarred_todo"
|
||||
image_tag("blank.png", :title =>"Star action", :class => class_str)
|
||||
image_tag("blank.png", :title =>t('todos.star_action'), :class => class_str, :id => "star_img_"+todo.id.to_s)
|
||||
end
|
||||
|
||||
def auto_complete_result2(entries, phrase = nil)
|
||||
return entries.map{|e| e.specification()}.join("\n") rescue ''
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,2 +1,12 @@
|
|||
module UsersHelper
|
||||
def remote_delete_user(user)
|
||||
return link_to(
|
||||
image_tag("blank.png", :title =>t('users.destroy_user'), :class=>"delete_item"),
|
||||
url_for({:controller => 'users', :action => 'destroy', :id => user.id}),
|
||||
{:id => "delete_user_#{user.id}",
|
||||
:class => "delete_user_button",
|
||||
:title => t('users.destroy_user'),
|
||||
:x_confirm_message => t('users.destroy_confirmation', :login => user.login)
|
||||
})
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -6,16 +6,6 @@ class Preference < ActiveRecord::Base
|
|||
{ :due_in_n_days => 0, :due_on => 1}
|
||||
end
|
||||
|
||||
def self.day_number_to_name_map
|
||||
{ 0 => "Sunday",
|
||||
1 => "Monday",
|
||||
2 => "Tuesday",
|
||||
3 => "Wednesday",
|
||||
4 => "Thursday",
|
||||
5 => "Friday",
|
||||
6 => "Saturday"}
|
||||
end
|
||||
|
||||
def hide_completed_actions?
|
||||
return show_number_completed == 0
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,15 +1,12 @@
|
|||
class Project < ActiveRecord::Base
|
||||
has_many :todos, :dependent => :delete_all, :include => [:context,:tags]
|
||||
has_many :todos, :dependent => :delete_all
|
||||
|
||||
# TODO: remove these scopes. Can be replaced by the named scopes on the todo relation
|
||||
has_many :not_done_todos,
|
||||
:include => [:context,:tags,:project],
|
||||
:class_name => 'Todo',
|
||||
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
||||
:conditions => ["todos.state = ?", 'active']
|
||||
has_many :not_done_todos_including_hidden,
|
||||
:include => [:context,:tags,:project],
|
||||
:class_name => 'Todo',
|
||||
:order => "todos.due IS NULL, todos.due ASC, todos.created_at ASC",
|
||||
:conditions => ["(todos.state = ? OR todos.state = ?)", 'active', 'project_hidden']
|
||||
has_many :done_todos,
|
||||
:include => [:context,:tags,:project],
|
||||
:class_name => 'Todo',
|
||||
|
|
@ -35,11 +32,12 @@ class Project < ActiveRecord::Base
|
|||
named_scope :active, :conditions => { :state => 'active' }
|
||||
named_scope :hidden, :conditions => { :state => 'hidden' }
|
||||
named_scope :completed, :conditions => { :state => 'completed'}
|
||||
named_scope :uncompleted, :conditions => ["NOT 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"
|
||||
validates_uniqueness_of :name, :message => "already exists", :scope =>"user_id"
|
||||
validates_does_not_contain :name, :string => ',', :message => "cannot contain the comma (',') character"
|
||||
validates_presence_of :name
|
||||
validates_length_of :name, :maximum => 255
|
||||
validates_uniqueness_of :name, :scope => "user_id"
|
||||
validates_does_not_contain :name, :string => ','
|
||||
|
||||
acts_as_list :scope => 'user_id = #{user_id} AND state = \'#{state}\''
|
||||
acts_as_state_machine :initial => :active, :column => 'state'
|
||||
|
|
@ -71,8 +69,8 @@ class Project < ActiveRecord::Base
|
|||
|
||||
def self.feed_options(user)
|
||||
{
|
||||
:title => 'Tracks Projects',
|
||||
:description => "Lists all the projects for #{user.display_name}"
|
||||
:title => I18n.t('models.project.feed_title'),
|
||||
:description => I18n.t('models.project.feed_description', :username => user.display_name)
|
||||
}
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -10,27 +10,40 @@ class Todo < ActiveRecord::Base
|
|||
has_many :predecessors, :through => :successor_dependencies
|
||||
has_many :successors, :through => :predecessor_dependencies
|
||||
has_many :uncompleted_predecessors, :through => :successor_dependencies,
|
||||
:source => :predecessor, :conditions => ['NOT (state = ?)', 'completed']
|
||||
:source => :predecessor, :conditions => ['NOT (todos.state = ?)', 'completed']
|
||||
has_many :pending_successors, :through => :predecessor_dependencies,
|
||||
:source => :successor, :conditions => ['state = ?', 'pending']
|
||||
:source => :successor, :conditions => ['todos.state = ?', 'pending']
|
||||
|
||||
after_save :save_predecessors
|
||||
|
||||
named_scope :active, :conditions => { :state => 'active' }
|
||||
named_scope :active_or_hidden, :conditions => ["todos.state = ? OR todos.state = ?", 'active', 'project_hidden']
|
||||
named_scope :not_completed, :conditions => ['NOT (todos.state = ? )', 'completed']
|
||||
named_scope :completed, :conditions => ["NOT completed_at IS NULL"]
|
||||
named_scope :completed, :conditions => ["NOT todos.completed_at IS NULL"]
|
||||
named_scope :are_due, :conditions => ['NOT (todos.due IS NULL)']
|
||||
named_scope :deferred, :conditions => ["completed_at IS NULL AND NOT show_from IS NULL"]
|
||||
named_scope :deferred, :conditions => ["todos.completed_at IS NULL AND NOT todos.show_from IS NULL"]
|
||||
named_scope :blocked, :conditions => ['todos.state = ?', 'pending']
|
||||
named_scope :deferred_or_blocked, :conditions => ["(todos.completed_at IS NULL AND NOT todos.show_from IS NULL) OR (todos.state = ?)", "pending"]
|
||||
named_scope :not_deferred_or_blocked, :conditions => ["todos.completed_at IS NULL AND todos.show_from IS NULL AND NOT todos.state = ?", "pending"]
|
||||
named_scope :with_tag, lambda { |tag| {:joins => :taggings, :conditions => ["taggings.tag_id = ? ", tag.id] } }
|
||||
named_scope :of_user, lambda { |user_id| {:conditions => ["todos.user_id = ? ", user_id] } }
|
||||
named_scope :hidden,
|
||||
:joins => :context,
|
||||
:conditions => ["todos.state = ? OR (contexts.hide = ? AND (todos.state = ? OR todos.state = ? OR todos.state = ?))",
|
||||
'project_hidden', true, 'active', 'deferred', 'pending']
|
||||
named_scope :not_hidden,
|
||||
:joins => [:context],
|
||||
:conditions => ['NOT(todos.state = ? OR (contexts.hide = ? AND (todos.state = ? OR todos.state = ? OR todos.state = ?)))',
|
||||
'project_hidden', true, 'active', 'deferred', 'pending']
|
||||
|
||||
STARRED_TAG_NAME = "starred"
|
||||
|
||||
# regular expressions for dependencies
|
||||
RE_TODO = /[^"]+/
|
||||
RE_CONTEXT = /[^"]+/
|
||||
RE_PROJECT = /[^"]+/
|
||||
RE_PARTS = /"(#{RE_TODO})"\s<"(#{RE_CONTEXT})";\s"(#{RE_PROJECT})">/ # results in array
|
||||
RE_SPEC = /"#{RE_TODO}"\s<"#{RE_CONTEXT}";\s"#{RE_PROJECT}">/ # results in string
|
||||
RE_TODO = /[^']+/
|
||||
RE_CONTEXT = /[^']+/
|
||||
RE_PROJECT = /[^']+/
|
||||
RE_PARTS = /'(#{RE_TODO})'\s<'(#{RE_CONTEXT})';\s'(#{RE_PROJECT})'>/ # results in array
|
||||
RE_SPEC = /'#{RE_TODO}'\s<'#{RE_CONTEXT}';\s'#{RE_PROJECT}'>/ # results in string
|
||||
|
||||
acts_as_state_machine :initial => :active, :column => 'state'
|
||||
|
||||
|
|
@ -82,6 +95,7 @@ class Todo < ActiveRecord::Base
|
|||
def initialize(*args)
|
||||
super(*args)
|
||||
@predecessor_array = nil # Used for deferred save of predecessors
|
||||
@removed_predecessors = nil
|
||||
end
|
||||
|
||||
def no_uncompleted_predecessors_or_deferral?
|
||||
|
|
@ -91,12 +105,11 @@ class Todo < ActiveRecord::Base
|
|||
def no_uncompleted_predecessors?
|
||||
return uncompleted_predecessors.empty?
|
||||
end
|
||||
|
||||
|
||||
# Returns a string with description <context, project>
|
||||
def specification
|
||||
project_name = project.is_a?(NullProject) ? "(none)" : project.name
|
||||
return "\"#{description}\" <\"#{context.title}\"; \"#{project_name}\">"
|
||||
return "\'#{description}\' <\'#{context.title}\'; \'#{project_name}\'>"
|
||||
end
|
||||
|
||||
def todo_from_specification(specification)
|
||||
|
|
@ -112,9 +125,9 @@ class Todo < ActiveRecord::Base
|
|||
project_id = nil;
|
||||
unless project_name == "(none)"
|
||||
project = Project.first(:conditions => {
|
||||
:user_id => self.user.id,
|
||||
:name => project_name
|
||||
})
|
||||
:user_id => self.user.id,
|
||||
:name => project_name
|
||||
})
|
||||
project_id = project.id unless project.nil?
|
||||
end
|
||||
|
||||
|
|
@ -127,6 +140,7 @@ class Todo < ActiveRecord::Base
|
|||
:project_id => project_id
|
||||
}
|
||||
)
|
||||
|
||||
return nil if todos.empty?
|
||||
|
||||
# TODO: what todo if there are more than one todo that fit the specification
|
||||
|
|
@ -135,7 +149,7 @@ class Todo < ActiveRecord::Base
|
|||
|
||||
def validate
|
||||
if !show_from.blank? && show_from < user.date
|
||||
errors.add("show_from", "must be a date in the future")
|
||||
errors.add("show_from", I18n.t('models.todo.error_date_must_be_future'))
|
||||
end
|
||||
errors.add(:description, "may not contain \" characters") if /\"/.match(description)
|
||||
unless @predecessor_array.nil? # Only validate predecessors if they changed
|
||||
|
|
@ -155,11 +169,15 @@ class Todo < ActiveRecord::Base
|
|||
current_array = predecessors.map{|p| p.specification}
|
||||
remove_array = current_array - @predecessor_array
|
||||
add_array = @predecessor_array - current_array
|
||||
|
||||
|
||||
@removed_predecessors = []
|
||||
# This is probably a bit naive code...
|
||||
remove_array.each do |specification|
|
||||
t = todo_from_specification(specification)
|
||||
self.predecessors.delete(t) unless t.nil?
|
||||
unless t.nil?
|
||||
@removed_predecessors << t
|
||||
self.predecessors.delete(t)
|
||||
end
|
||||
end
|
||||
# ... as is this?
|
||||
add_array.each do |specification|
|
||||
|
|
@ -170,7 +188,11 @@ class Todo < ActiveRecord::Base
|
|||
logger.error "Could not find #{specification}" # Unexpected since validation passed
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def removed_predecessors
|
||||
return @removed_predecessors
|
||||
end
|
||||
|
||||
def remove_predecessor(predecessor)
|
||||
|
|
@ -195,16 +217,25 @@ class Todo < ActiveRecord::Base
|
|||
return false
|
||||
end
|
||||
|
||||
def has_tag?(tag)
|
||||
return self.tags.select{|t| t.name==tag }.size > 0
|
||||
end
|
||||
|
||||
def hidden?
|
||||
return self.state == 'project_hidden' || ( self.context.hidden? && (self.state == 'active' || self.state == 'deferred'))
|
||||
end
|
||||
|
||||
def update_state_from_project
|
||||
if state == 'project_hidden' and !project.hidden?
|
||||
if self.state == 'project_hidden' and !self.project.hidden?
|
||||
if self.uncompleted_predecessors.empty?
|
||||
self.state = 'active'
|
||||
else
|
||||
self.state = 'pending'
|
||||
end
|
||||
elsif state == 'active' and project.hidden?
|
||||
elsif self.state == 'active' and self.project.hidden?
|
||||
self.state = 'project_hidden'
|
||||
end
|
||||
self.save!
|
||||
end
|
||||
|
||||
def toggle_completion!
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ require 'digest/sha1'
|
|||
class User < ActiveRecord::Base
|
||||
# Virtual attribute for the unencrypted password
|
||||
attr_accessor :password
|
||||
attr_protected :is_admin # don't allow mass-assignment for this
|
||||
|
||||
has_many :contexts,
|
||||
:order => 'position ASC',
|
||||
|
|
@ -11,11 +12,11 @@ class User < ActiveRecord::Base
|
|||
find(params['id'] || params['context_id']) || nil
|
||||
end
|
||||
def update_positions(context_ids)
|
||||
context_ids.each_with_index do |id, position|
|
||||
context_ids.each_with_index {|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?
|
||||
raise I18n.t('models.user.error_context_not_associated', :context => id, :user => @user.id) if context.nil?
|
||||
context.update_attribute(:position, position + 1)
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
has_many :projects,
|
||||
|
|
@ -25,11 +26,11 @@ class User < ActiveRecord::Base
|
|||
find(params['id'] || params['project_id'])
|
||||
end
|
||||
def update_positions(project_ids)
|
||||
project_ids.each_with_index do |id, position|
|
||||
project_ids.each_with_index {|id, position|
|
||||
project = self.detect { |p| p.id == id.to_i }
|
||||
raise "Project id #{id} not associated with user id #{@user.id}." if project.nil?
|
||||
raise I18n.t('models.user.error_project_not_associated', :project => id, :user => @user.id) if project.nil?
|
||||
project.update_attribute(:position, position + 1)
|
||||
end
|
||||
}
|
||||
end
|
||||
def projects_in_state_by_position(state)
|
||||
self.sort{ |a,b| a.position <=> b.position }.select{ |p| p.state == state }
|
||||
|
|
@ -149,13 +150,25 @@ class User < ActiveRecord::Base
|
|||
return nil if login.blank?
|
||||
candidate = find(:first, :conditions => ["login = ?", login])
|
||||
return nil if candidate.nil?
|
||||
return candidate if candidate.auth_type == 'database' && candidate.crypted_password == sha1(pass)
|
||||
|
||||
if Tracks::Config.auth_schemes.include?('database')
|
||||
return candidate if candidate.auth_type == 'database' && candidate.crypted_password == sha1(pass)
|
||||
end
|
||||
|
||||
if Tracks::Config.auth_schemes.include?('ldap')
|
||||
return candidate if candidate.auth_type == 'ldap' && SimpleLdapAuthenticator.valid?(login, pass)
|
||||
end
|
||||
if Tracks::Config.auth_schemes.include?('cas') && candidate.auth_type.eql?("cas")
|
||||
return candidate #because we can not auth them with out thier real password we have to settle for this
|
||||
|
||||
if Tracks::Config.auth_schemes.include?('cas')
|
||||
# because we can not auth them with out thier real password we have to settle for this
|
||||
return candidate if candidate.auth_type.eql?("cas")
|
||||
end
|
||||
|
||||
if Tracks::Config.auth_schemes.include?('open_id')
|
||||
# hope the user enters the correct data
|
||||
return candidate if candidate.auth_type.eql?("open_id")
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
|
|
@ -251,6 +264,13 @@ protected
|
|||
|
||||
def normalize_open_id_url
|
||||
return if open_id_url.nil?
|
||||
|
||||
# fixup empty url value
|
||||
if open_id_url.empty?
|
||||
self.open_id_url = nil
|
||||
return
|
||||
end
|
||||
|
||||
self.open_id_url = OpenIdAuthentication.normalize_identifier(open_id_url)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@
|
|||
<div id="c_<%=context.id%>_target" class="context_target drop_target"></div>
|
||||
<div id="c<%= context.id %>items" class="items toggle_target">
|
||||
<div id="c<%= context.id %>empty-nd" style="display:<%= @not_done.empty? ? 'block' : 'none'%>;">
|
||||
<div class="message"><p>Currently there are no incomplete actions in this context</p></div>
|
||||
<div class="message"><p><%= t 'contexts.no_actions' %></p></div>
|
||||
</div>
|
||||
<%= render :partial => "todos/todo", :collection => @not_done, :locals => { :parent_container_type => "context" } %>
|
||||
</div><!-- [end:items] -->
|
||||
|
|
|
|||
|
|
@ -1,28 +1,36 @@
|
|||
<% context = context_form
|
||||
@context = context-%>
|
||||
<% form_remote_tag(:url => context_path(context), :html => {:id => dom_id(context, 'edit_form'), :class => "inline-form "+dom_id(context, 'edit_form')+"-edit-context-form edit-context-form", :method => :put}) do -%>
|
||||
<%= error_messages_for 'context' %>
|
||||
@context = context
|
||||
-%>
|
||||
|
||||
<% form_for(context, :html => {
|
||||
:id => dom_id(context, 'edit_form'),
|
||||
:class => "inline-form edit-project-form",
|
||||
:method => :put }) do
|
||||
-%>
|
||||
|
||||
<div id="edit_error_status"><%= error_messages_for("project") %></div>
|
||||
|
||||
|
||||
<label for="context_name">Context name</label><br/>
|
||||
<%= text_field('context', 'name', :class => 'context-name') %><br/>
|
||||
|
||||
<label for="context_hide">Hide from front page?</label>
|
||||
<label for="context_hide">Hide from front page?</label>
|
||||
<%= check_box('context', 'hide', :class => 'context-hide') %>
|
||||
<input type="hidden" name="wants_render" value="true" />
|
||||
<input type="hidden" name="wants_render" value="true" />
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="<%= dom_id(context, 'submit') %>" tabindex="15">
|
||||
<%=image_tag("accept.png", :alt => "") %>
|
||||
Update
|
||||
<%= t 'common.update' %>
|
||||
</button>
|
||||
<a href="" onclick="" class="negative">
|
||||
<%=image_tag("cancel.png", :alt => "") %>
|
||||
Cancel
|
||||
<%= t 'common.cancel' %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<br/><br/>
|
||||
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,43 +1,28 @@
|
|||
<% context = context_listing
|
||||
suppress_drag_handle ||= false
|
||||
suppress_edit_button ||= false
|
||||
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:'';">
|
||||
<% unless suppress_drag_handle -%>
|
||||
<div class="position">
|
||||
<span class="handle">DRAG</span>
|
||||
<span class="handle"><%= t('common.drag_handle') %></span>
|
||||
</div>
|
||||
<% end -%>
|
||||
<div class="data">
|
||||
<%= link_to_context( context ) %> <%= " (" + count_undone_todos_phrase(context,"actions") + ")" %>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="buttons">
|
||||
<% if context.hide? %>
|
||||
<span class="grey">HIDDEN</span>
|
||||
<span class="grey"><%= t('states.hidden') %></span>
|
||||
<% else %>
|
||||
<span class="grey">VISIBLE</span>
|
||||
<span class="grey"><%= t('states.visible') %></span>
|
||||
<% end %>
|
||||
<%= link_to_remote(
|
||||
image_tag( "blank.png", :title => "Delete context", :class=>"delete_item"),
|
||||
:url => {:controller => 'contexts', :action => 'destroy', :id => context.id},
|
||||
:method => 'delete',
|
||||
:with => "'_source_view=#{@source_view}'",
|
||||
:before => "$('#{dom_id(context)}').block({message:null});",
|
||||
:complete => "$('#{dom_id(context)}').unblock();",
|
||||
:confirm => "Are you sure that you want to delete the context '#{context.name}'? Be aware that this will also delete all (repeating) actions in this context!",
|
||||
:html => { :id => dom_id(context, 'delete') }
|
||||
) %>
|
||||
<%= link_to_remote(
|
||||
image_tag( "blank.png", :title => "Edit context", :class=>"edit_item"),
|
||||
:url => {:controller => 'contexts', :action => 'edit', :id => context.id},
|
||||
:method => 'get',
|
||||
:with => "'_source_view=#{@source_view}'",
|
||||
:before => "$('#{dom_id(context)}').block({message:null});",
|
||||
:complete => "$('#{dom_id(context)}').unblock();",
|
||||
:html => {:id => "edit_context_#{context.id}_link"}
|
||||
) %>
|
||||
|
||||
<%= link_to_delete_context(context, image_tag( "blank.png", :title => t('contexts.delete_context'), :class=>"delete_item")) %>
|
||||
<%= suppress_edit_button ? "" : link_to_edit_context(context, image_tag( "blank.png", :title => t('contexts.edit_context'), :class=>"edit_item")) %>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div id="<%= dom_id(context, 'edit') %>" class="edit-form" style="display:none;">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
<div class="list-stategroup-contexts-container">
|
||||
<h2><span id="<%= state %>-contexts-count" class="badge"><%= context_state_group.length %></span><%= state.titlecase %> Contexts</h2>
|
||||
<div class="list-stategroup-contexts-container" id="list-<%= state %>-contexts-container">
|
||||
<h2><span id="<%= state %>-contexts-count" class="badge"><%= context_state_group.length %></span><%= t("states."+ state +"_plural")%> <%= t('common.contexts') %></h2>
|
||||
<div id="<%= state%>-contexts-empty-nd" style="<%= no_contexts ? 'display:block' : 'display:none'%>">
|
||||
<div class="message"><p>Currently there are no <%= state %> contexts</p></div>
|
||||
<div class="message"><p><%= t('contexts.no_contexts_' + state) %></p></div>
|
||||
</div>
|
||||
<div id="list-contexts-<%= state %>">
|
||||
<%= render :partial => 'context_listing', :collection => context_state_group %>
|
||||
|
|
|
|||
28
app/views/contexts/_new_context_form.rhtml
Normal file
28
app/views/contexts/_new_context_form.rhtml
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
<div id="context_new_container">
|
||||
|
||||
<div id="toggle_context_link" class="hide_form">
|
||||
<a id="toggle_context_new" href="#" title="<%= t('contexts.hide_form_title') %>" accesskey="n"><%= t('contexts.hide_form') %></a>
|
||||
</div>
|
||||
|
||||
<div id="context_new" class="context_new" style="display:block">
|
||||
<% form_for(@new_context, :html => {:id => 'context-form',:name=>'context',:class => "inline-form", :method => :post }) do -%>
|
||||
|
||||
<div id="error_status"><%= error_messages_for('context') %></div>
|
||||
|
||||
<label for="context_name"><%= t 'contexts.context_name' %></label><br />
|
||||
<%= text_field( "context", "name" ) %><br />
|
||||
|
||||
<label for="context_hide"><%= t 'contexts.context_hide' %></label>
|
||||
<%= check_box( "context", "hide" ) %><br />
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="context_new_submit">
|
||||
<%= image_tag("accept.png", :alt => "") + 'Add Context' %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<br/><br/>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
30
app/views/contexts/create.js.erb
Normal file
30
app/views/contexts/create.js.erb
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
<% if @saved -%>
|
||||
hide_empty_message();
|
||||
TracksPages.hide_errors();
|
||||
TracksPages.set_page_badge(<%= @down_count %>);
|
||||
add_context("<%=@context.hidden? ? 'hidden' : 'active'%>");
|
||||
clear_form();
|
||||
<% else -%>
|
||||
TracksPages.show_errors(html_for_error_messages());
|
||||
<% end -%>
|
||||
|
||||
function hide_empty_message() {
|
||||
$('contexts-empty-nd').hide();
|
||||
}
|
||||
|
||||
function add_context(state) {
|
||||
$('#list-contexts-'+state).append(html_for_context_listing());
|
||||
}
|
||||
|
||||
function clear_form() {
|
||||
$('#context-form').clearForm();
|
||||
$('#context-form input:text:first').focus();
|
||||
}
|
||||
|
||||
function html_for_context_listing() {
|
||||
return "<%= @saved ? escape_javascript(render(:partial => 'context_listing', :object => @context )) : "" %>";
|
||||
}
|
||||
|
||||
function html_for_error_messages() {
|
||||
return "<%= escape_javascript(error_messages_for('context')) %>";
|
||||
}
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
if @saved
|
||||
container_name = 'list-contexts-' + (@context.hidden? ? 'hidden' : 'active')
|
||||
page.hide 'contexts-empty-nd'
|
||||
page.insert_html :bottom, container_name, :partial => 'context_listing', :locals => { :context_listing => @context }
|
||||
page.hide 'status'
|
||||
page['badge_count'].replace_html @down_count
|
||||
page << '$("#context-form").clearForm();'
|
||||
page << '$("#context-form input:text:first").focus();'
|
||||
else
|
||||
page.show 'status'
|
||||
page.replace_html 'status', "#{error_messages_for('context')}"
|
||||
end
|
||||
14
app/views/contexts/destroy.js.erb
Normal file
14
app/views/contexts/destroy.js.erb
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
remove_deleted_context();
|
||||
|
||||
ContextListPage.update_all_states_count(<%=@active_contexts_count%>, <%=@hidden_contexts_count%>)
|
||||
ContextListPage.show_or_hide_all_state_containers(<%= @show_active_contexts %>, <%= @show_hidden_contexts %>);
|
||||
|
||||
TracksPages.set_page_badge(<%=@down_count%>);
|
||||
TracksPages.page_notify('notice', "<%= t('contexts.context_deleted', :name=>@context.name)%>", 5);
|
||||
|
||||
/* TODO: refactor and move function to application.js */
|
||||
function remove_deleted_context() {
|
||||
$('div#<%=dom_id(@context, "container")%>').slideUp(1000, function() {
|
||||
$('div#<%=dom_id(@context, "container")%>').remove();
|
||||
});
|
||||
}
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
page.visual_effect :fade, dom_id(@context, "container"), :duration => 0.5
|
||||
page.delay(0.5) do
|
||||
page[dom_id(@context, "container")].remove
|
||||
end
|
||||
page['badge_count'].replace_html @down_count
|
||||
page.notify :notice, "Deleted context '#{@context.name}'", 5.0
|
||||
21
app/views/contexts/edit.js.erb
Normal file
21
app/views/contexts/edit.js.erb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
replace_context_with_edit_form();
|
||||
|
||||
function replace_context_with_edit_form() {
|
||||
$('div#<%=dom_id(@context)%>').fadeOut(250, function() {
|
||||
show_edit_form();
|
||||
set_focus();
|
||||
});
|
||||
}
|
||||
|
||||
function show_edit_form() {
|
||||
$('div#<%=dom_id(@context, 'edit')%>').html(html_for_edit_form());
|
||||
$('div#<%=dom_id(@context, 'edit')%>').fadeIn(500);
|
||||
}
|
||||
|
||||
function set_focus() {
|
||||
$('input.context-name').focus();
|
||||
}
|
||||
|
||||
function html_for_edit_form() {
|
||||
return "<%= escape_javascript(render(:partial => 'context_form', :object => @context)) %>"
|
||||
}
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
page[dom_id(@context, 'edit')].replace_html :partial => 'context_form', :locals => { :context_form => @context }
|
||||
page[@context].hide
|
||||
page[dom_id(@context, 'edit')].show
|
||||
page[dom_id(@context, 'edit_form')].find('input.context-name').focus
|
||||
|
|
@ -1 +1 @@
|
|||
page.notify :error, @error_message || "An error occurred on the server.", 8.0
|
||||
page.notify :error, @error_message || t('common.server_error'), 8.0
|
||||
|
|
@ -4,41 +4,5 @@
|
|||
</div>
|
||||
|
||||
<div id="input_box">
|
||||
<div id="context_new_container">
|
||||
|
||||
<div id="toggle_context_new" class="hide_form">
|
||||
<a title="Hide new context form" accesskey="n">« Hide form</a>
|
||||
</div>
|
||||
|
||||
<div id="context_new" class="context_new" style="display:block">
|
||||
<% form_remote_tag(
|
||||
:url => contexts_path,
|
||||
:method => :post,
|
||||
:html=> { :id => 'context-form', :name => 'context', :class => 'inline-form'},
|
||||
:before => "$('#context_new_submit').block({message: null})",
|
||||
:complete => "$('#context_new_submit').unblock()") do -%>
|
||||
|
||||
<div id="status"><%= error_messages_for('context') %></div>
|
||||
|
||||
<label for="context_name">Context name</label><br />
|
||||
<%= text_field( "context", "name" ) %><br />
|
||||
|
||||
<label for="context_hide">Hide from front page?</label>
|
||||
<%= check_box( "context", "hide" ) %><br />
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="context_new_submit">
|
||||
<%= image_tag("accept.png", :alt => "") + 'Add Context' %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<br/><br/>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<%
|
||||
sortable_element 'list-contexts-active', get_listing_sortable_options
|
||||
sortable_element 'list-contexts-hidden', get_listing_sortable_options
|
||||
-%>
|
||||
<%= render :partial => 'new_context_form' %>
|
||||
</div>
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<% current_user.contexts.each do |c| -%>
|
||||
<% @all_contexts.each do |c| -%>
|
||||
|
||||
<%= c.name.upcase %>
|
||||
<%= count_undone_todos_phrase_text(c)%>. Context is <%= c.hidden? ? "Hidden" : "Active" %>.
|
||||
<%= count_undone_todos_phrase_text(c)%>. <%= c.hidden? ? t('contexts.status_hidden') : t('contexts.status_active') %>.
|
||||
<% end -%>
|
||||
|
|
|
|||
|
|
@ -1,2 +1,2 @@
|
|||
<h2>Visible Contexts</h2><%= render :partial => 'mobile_context_listing', :collection => @active_contexts %>
|
||||
<h2>Hidden Contexts</h2><%= render :partial => 'mobile_context_listing', :collection => @hidden_contexts %>
|
||||
<h2><%= t('contexts.visible_contexts') %></h2><%= render :partial => 'mobile_context_listing', :collection => @active_contexts %>
|
||||
<h2><%= t('contexts.hidden_contexts') %></h2><%= render :partial => 'mobile_context_listing', :collection => @hidden_contexts %>
|
||||
|
|
@ -11,5 +11,6 @@ if not @not_done.empty?
|
|||
<%= render :partial => "todos/mobile_todo",
|
||||
:collection => @not_done,
|
||||
:locals => { :parent_container_type => "context" }-%>
|
||||
</table>
|
||||
</ul>
|
||||
<% end -%>
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
<div id="display_box">
|
||||
<%= render :partial => "contexts/context", :locals => { :context => @context, :collapsible => false } %>
|
||||
<%= render :partial => "contexts/context", :object => @context, :locals => { :collapsible => false } %>
|
||||
<% unless @max_completed==0 -%>
|
||||
<%= render :partial => "todos/completed", :locals => { :done => @done, :suppress_context => true, :collapsible => false, :append_descriptor => "in this context (last #{prefs.show_number_completed})" } %>
|
||||
<%= render :partial => "todos/completed", :object => @done, :locals => { :suppress_context => true, :collapsible => false, :append_descriptor => t('contexts.last_completed_in_context', :number=>prefs.show_number_completed) } %>
|
||||
<% end -%>
|
||||
|
||||
</div><!-- [end:display_box] -->
|
||||
|
||||
<div id="input_box">
|
||||
|
|
|
|||
42
app/views/contexts/update.js.erb
Normal file
42
app/views/contexts/update.js.erb
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
<% if @saved -%>
|
||||
|
||||
TracksPages.page_notify('notice', '<%= t('contexts.save_status_message') %>', 5);
|
||||
|
||||
<% if @state_changed -%>
|
||||
remove_and_re_add_context();
|
||||
<% else -%>
|
||||
replace_context_form_with_updated_context();
|
||||
<% end -%>
|
||||
|
||||
<% else -%>
|
||||
TracksPages.show_edit_errors(html_for_error_messages());
|
||||
<% end -%>
|
||||
|
||||
function remove_and_re_add_context() {
|
||||
$('#<%=dom_id(@context, 'container')%>').slideUp(500, function() {
|
||||
$('#<%=dom_id(@context, 'container')%>').remove();
|
||||
$('#list-contexts-<%=@new_state%>').append(html_for_context_listing());
|
||||
});
|
||||
}
|
||||
|
||||
function replace_context_form_with_updated_context() {
|
||||
$('#<%=dom_id(@context, 'container')%>').fadeOut(250, function() {
|
||||
<%
|
||||
# first add the updated context after the old one, then remove old one
|
||||
# using html() does not work, because it will replace the _content_ of
|
||||
# the container instead of the container itself, i.e. you will get
|
||||
# a container within a container which will break drag-and-drop sorting
|
||||
-%>
|
||||
$('#<%=dom_id(@context, 'container')%>').after(html_for_context_listing());
|
||||
$('#<%=dom_id(@context, 'container')%>').remove();
|
||||
$('#<%=dom_id(@context, 'container')%>').fadeIn(500);
|
||||
});
|
||||
}
|
||||
|
||||
function html_for_error_messages() {
|
||||
return "<%= escape_javascript(error_messages_for('context')) %>";
|
||||
}
|
||||
|
||||
function html_for_context_listing() {
|
||||
return "<%= escape_javascript(render(:partial => 'context_listing', :object => @context))%>";
|
||||
}
|
||||
|
|
@ -1,9 +0,0 @@
|
|||
status_message = 'Context saved'
|
||||
page.notify :notice, status_message, 5.0
|
||||
if @context_state_changed
|
||||
page.remove dom_id(@context, 'container')
|
||||
page.insert_html :bottom, "list-contexts-#{@new_state}", :partial => 'context_listing', :object => @context
|
||||
else
|
||||
page.replace_html dom_id(@context, 'container'), :partial => 'context_listing', :object => @context
|
||||
end
|
||||
page.visual_effect :highlight, dom_id(@context), :duration => 3
|
||||
|
|
@ -4,5 +4,5 @@ page['todo_context_name'].value = @context.name
|
|||
# renew context auto complete array
|
||||
page << "contextAutoCompleter.options.array = #{context_names_for_autocomplete}; contextAutoCompleter.changed = true"
|
||||
|
||||
status_message = "Name of context was changed"
|
||||
status_message = t('contexts.update_status_message')
|
||||
page.notify :notice, status_message, 5.0
|
||||
|
|
|
|||
36
app/views/data/index.de.html.erb
Normal file
36
app/views/data/index.de.html.erb
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
<div id="display_box">
|
||||
<div id="feeds">
|
||||
<div id="feedlegend">
|
||||
<h3>Daten exportieren</h3>
|
||||
<p>Sie können zwischen den folgenden Formaten wählen:</p>
|
||||
<ul>
|
||||
<li><strong>YAML: </strong>Für den Daten-Import bevorzugt.<br/><i>Bitte beachten Sie, dass der YAML-Import zur Zeit noch experimentelle Funktionalität darstellt. Nutzen Sie diese Option also nicht. um kritische Daten zu sichern.</i></li>
|
||||
<li><strong>CSV: </strong>Am besten für den Export in eine Tabellen-Kalkulation oder ähnliche Auswertungs-Software geeignet</li>
|
||||
<li><strong>XML: </strong>Am besten für den Daten-Import oder automatische Weiterverarbeitung</li>
|
||||
</ul>
|
||||
</div>
|
||||
<br/><br/>
|
||||
<table class="export_table">
|
||||
<tr>
|
||||
<th>Beschreibung</th>
|
||||
<th>Download link</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>YAML-Datei mit all Ihren Aktionen, Umgebungen, Projekten, Tags und Notizen</td>
|
||||
<td><%= link_to "YAML Datei", :controller => 'data', :action => 'yaml_export' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSV-Datei mit all Ihren Aktionen, benannten Umgebungen und Projekten</td>
|
||||
<td><%= link_to "CSV Dile (Aktionen, Umgebungen und Projekte)", :controller => 'data', :action => 'csv_actions' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>CSV-Datei mit all Ihren Notizen</td>
|
||||
<td><%= link_to "CSV Datei (nur Notizen)", :controller => 'data', :action => 'csv_notes' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>XML-Datei mit all Ihren Aktionen, Umgebungen, Projekten, Tags und Notizen</td>
|
||||
<td><%= link_to "XML file (actions only)", :controller => 'data', :action => 'xml_export' %></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div><!-- End of feeds -->
|
||||
</div>
|
||||
17
app/views/data/yaml_form.de.html.erb
Normal file
17
app/views/data/yaml_form.de.html.erb
Normal file
|
|
@ -0,0 +1,17 @@
|
|||
<div id="display_box">
|
||||
<div id="feeds">
|
||||
<div id="feedlegend">
|
||||
<p><b>Vorsicht</b>: vor dem Import der YAML Datei werden alle Daten in Ihrer Datenbank gelöscht.
|
||||
Falls Sie entsprechenden Zugriff auf Ihre Datenbank haben, empfiehlt es sich, ein Backup anzulegen,
|
||||
bevor Sie fortfahren.
|
||||
</p>
|
||||
<p>Fügen Sie den Inhalt der kopierten YAML Datei in das untenstehende Formular ein:</p>
|
||||
</div>
|
||||
<p>
|
||||
<% form_for :import, @import, :url => {:controller => 'data', :action => 'yaml_import'} do |f| %>
|
||||
<%= f.text_area :yaml %><br />
|
||||
<input type="submit" value="Daten importieren">
|
||||
<% end %>
|
||||
</p>
|
||||
</div><!-- End of feeds -->
|
||||
</div><!-- End of display_box -->
|
||||
|
|
@ -1,7 +1,5 @@
|
|||
<% if !(@errmessage == '') %>
|
||||
<p>There were these errors:
|
||||
<pre><%= @errmessage %></pre>
|
||||
</p>
|
||||
<p><%= t('data.import_errors') %>:<pre><%= @errmessage %></pre></p>
|
||||
<% else %>
|
||||
<p>Import was successful.</p>
|
||||
<p><%= t('data.import_successful') %></p>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,25 @@
|
|||
<li>
|
||||
<%= rss_formatted_link({ :controller=> 'todos', :action => 'index', :context_id => context.to_param }) %>
|
||||
<%= text_formatted_link({ :controller=> 'todos', :action => 'index', :context_id => context.to_param }) %>
|
||||
<%= ical_formatted_link({ :controller=> 'todos', :action => 'index', :context_id => context.to_param }) %>
|
||||
<strong><%=h context.name %></strong>
|
||||
</li>
|
||||
<% context = @active_contexts.empty? ? @hidden_contexts.first : @active_contexts.first
|
||||
-%>
|
||||
|
||||
<h4><%= t('feedlist.context_centric_actions') %>:</h4>
|
||||
<% if @active_contexts.empty? && @hidden_contexts.empty? -%>
|
||||
<ul><li><%= t('feedlist.context_needed') %></li></ul>
|
||||
<% else -%>
|
||||
<ul>
|
||||
<li><%= t('common.numbered_step', :number => 1) %> - <%= t('feedlist.choose_context') %>:
|
||||
<select name="feed-contexts" id="feed-contexts">
|
||||
<%= options_from_collection_for_select(@active_contexts, "id", "name", @active_contexts.first.id) unless @active_contexts.empty?-%>
|
||||
<%= options_from_collection_for_select(@hidden_contexts, "id", "name") -%>
|
||||
</select>
|
||||
</li>
|
||||
<li><%= t('common.numbered_step', :number => 2) %> - <%= t('feedlist.select_feed_for_context') %>
|
||||
<div id="feedicons-context">
|
||||
<div id="feeds-for-context">
|
||||
<li><%= all_feed_links_for_context(context) %></li>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<% end -%>
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,22 @@
|
|||
<li>
|
||||
<%= rss_formatted_link({ :controller=> 'todos', :action => 'index', :project_id => project.to_param }) %>
|
||||
<%= text_formatted_link({ :controller=> 'todos', :action => 'index', :project_id => project.to_param }) %>
|
||||
<%= ical_formatted_link({ :controller=> 'todos', :action => 'index', :project_id => project.to_param }) %>
|
||||
<strong><%=h project.name %></strong>
|
||||
</li>
|
||||
<% project = @active_projects.empty? ? @hidden_projects.first : @active_projects.first -%>
|
||||
<h4><%= t('feedlist.project_centric') %>:</h4>
|
||||
<ul>
|
||||
<% if @active_projects.empty? && @hidden_projects.empty? -%>
|
||||
<li><%= t('feedlist.project_needed') %></li>
|
||||
<% else -%>
|
||||
<li><%= t('common.numbered_step', :number => 1) %> - <%= t('feedlist.choose_project') %>:
|
||||
<select name="feed-projects" id="feed-projects">
|
||||
<%= options_from_collection_for_select(@active_projects, "id", "name", @active_projects.first.id) unless @active_projects.empty?-%>
|
||||
<%= options_from_collection_for_select(@hidden_projects, "id", "name") -%>
|
||||
<%= options_from_collection_for_select(@completed_projects, "id", "name") -%>
|
||||
</select>
|
||||
</li>
|
||||
<li><%= t('common.numbered_step', :number => 2) %> - <%= t('feedlist.select_feed_for_project') %>
|
||||
<div id="feedicons-project">
|
||||
<div id="feeds-for-project">
|
||||
<li><%= all_feed_links_for_project(project) %></li>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
14
app/views/feedlist/_legend.rhtml
Normal file
14
app/views/feedlist/_legend.rhtml
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
<div id="feedlegend">
|
||||
<h3><%= t('feedlist.legend') %></h3>
|
||||
<dl>
|
||||
<dt><%= image_tag("feed-icon.png", :size => "16X16", :border => 0)%></dt>
|
||||
<dd><%= t('feedlist.rss_feed') %></dd>
|
||||
|
||||
<dt><span class="feed">TXT</span></dt>
|
||||
<dd><%= t('feedlist.plain_text_feed') %></dd>
|
||||
|
||||
<dt><span class="feed">iCal</span></dt>
|
||||
<dd><%= t('feedlist.ical_feed') %></dd>
|
||||
</dl>
|
||||
<p><%= t('feedlist.notice_incomplete_only') %></p>
|
||||
</div>
|
||||
1
app/views/feedlist/get_feeds_for_context.erb
Normal file
1
app/views/feedlist/get_feeds_for_context.erb
Normal file
|
|
@ -0,0 +1 @@
|
|||
<li><%= all_feed_links_for_context(@context) %></li>
|
||||
1
app/views/feedlist/get_feeds_for_project.erb
Normal file
1
app/views/feedlist/get_feeds_for_project.erb
Normal file
|
|
@ -0,0 +1 @@
|
|||
<li><%= all_feed_links_for_project(@project) %></li>
|
||||
|
|
@ -1,115 +1,23 @@
|
|||
<div id="display_box">
|
||||
<div id="feeds">
|
||||
<div id="feedlegend">
|
||||
<h3>Legend:</h3>
|
||||
<dl>
|
||||
<dt><%= image_tag("feed-icon.png", :size => "16X16", :border => 0)%></dt><dd>RSS Feed</dd>
|
||||
<dt><span class="feed">TXT</span></dt><dd>Plain Text Feed</dd>
|
||||
<dt><span class="feed">iCal</span></dt><dd>iCal feed</dd>
|
||||
</dl>
|
||||
<p>Note: All feeds show only actions that have not been marked as done.</p>
|
||||
</div>
|
||||
<%= render :partial => 'legend' %>
|
||||
<ul>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) %>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :limit => 15 }) %>
|
||||
Last 15 actions
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link( { :controller => 'todos', :action => 'index' } ) %>
|
||||
<%= text_formatted_link( { :controller => 'todos', :action => 'index' } ) %>
|
||||
<%= ical_formatted_link( { :controller => 'todos', :action => 'index' } ) %>
|
||||
All actions
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) %>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :due => 0 }) %>
|
||||
Actions due today or earlier
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) %>
|
||||
<%= ical_formatted_link({ :controller => 'todos', :action => 'index', :due => 6 }) %>
|
||||
Actions due in 7 days or earlier
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({ :controller => 'todos', :action => 'index', :done => 7 }) %>
|
||||
<%= text_formatted_link({ :controller => 'todos', :action => 'index', :done => 7 }) %>
|
||||
Actions completed in the last 7 days
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({:controller => 'contexts', :action => 'index'}) %>
|
||||
<%= text_formatted_link({:controller => 'contexts', :action => 'index'}) %>
|
||||
All Contexts
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({:controller => 'projects', :action => 'index'}) %>
|
||||
<%= text_formatted_link({:controller => 'projects', :action => 'index'}) %>
|
||||
All Projects
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({:controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true}) %>
|
||||
<%= text_formatted_link({:controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true}) %>
|
||||
Active projects with no next actions
|
||||
</li>
|
||||
<li>
|
||||
<%= rss_formatted_link({:controller => 'todos', :action => 'index', :tag => 'starred'}) %>
|
||||
<%= text_formatted_link({:controller => 'todos', :action => 'index', :tag => 'starred'}) %>
|
||||
All starred, active actions
|
||||
</li>
|
||||
<li>
|
||||
<%= text_formatted_link({:controller => 'projects', :action => 'index', :projects_and_actions => true}) %>
|
||||
Active projects with their actions
|
||||
</li>
|
||||
<li><h4>Feeds for incomplete actions in a specific context:</h4>
|
||||
<% if @active_contexts.empty? && @hidden_contexts.empty? -%>
|
||||
<ul><li>There need to be at least one context before you can request a feed</li></ul>
|
||||
<% else -%>
|
||||
<ul>
|
||||
<li>Step 1 - Choose the context you want a feed of:
|
||||
<select name="feed-contexts" id="feed-contexts">
|
||||
<%= options_from_collection_for_select(@active_contexts, "id", "name", @active_contexts.first.id) unless @active_projects.empty?-%>
|
||||
<%= options_from_collection_for_select(@hidden_contexts, "id", "name") -%>
|
||||
</select>
|
||||
</li>
|
||||
<li>Step 2 - Select the feed for this context
|
||||
<div id="feedicons-context">
|
||||
<div id="feeds-for-context">
|
||||
<%= render :partial => 'feed_for_context', :locals => { :context => @active_contexts.empty? ? @hidden_contexts.first : @active_contexts.first } %>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<% end -%>
|
||||
</li>
|
||||
<li><h4>Feeds for incomplete actions in a specific project:</h4>
|
||||
<% if @active_projects.empty? && @hidden_projects.empty? -%>
|
||||
<ul><li>There need to be at least one project before you can request a feed</li></ul>
|
||||
<% else -%>
|
||||
<ul>
|
||||
<li>Step 1 - Choose the project you want a feed of:
|
||||
<select name="feed-projects" id="feed-projects">
|
||||
<%= options_from_collection_for_select(@active_projects, "id", "name", @active_projects.first.id) unless @active_projects.empty?-%>
|
||||
<%= options_from_collection_for_select(@hidden_projects, "id", "name") -%>
|
||||
<%= options_from_collection_for_select(@completed_projects, "id", "name") -%>
|
||||
</select>
|
||||
</li>
|
||||
<li>Step 2 - Select the feed for this project
|
||||
<div id="feedicons-project">
|
||||
<div id="feeds-for-project">
|
||||
<%= render :partial => 'feed_for_project', :locals => { :project => @active_projects.empty? ? @hidden_projects.first : @active_projects.first } %>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<% end -%>
|
||||
</li>
|
||||
<li><%= feed_links([:rss, :txt, :ical], { :controller => 'todos', :action => 'index', :limit => 15 }, t('feedlist.last_fixed_number', :number=>15)) %></li>
|
||||
<li><%= feed_links([:rss, :txt, :ical], { :controller => 'todos', :action => 'index' }, t('feedlist.all_actions')) %></li>
|
||||
<li><%= feed_links([:rss, :txt, :ical], { :controller => 'todos', :action => 'index', :due => 0 }, t('feedlist.actions_due_today')) %></li>
|
||||
<li><%= feed_links([:rss, :txt, :ical], { :controller => 'todos', :action => 'index', :due => 6 }, t('feedlist.actions_due_next_week')) %></li>
|
||||
<li><%= feed_links([:rss, :txt], { :controller => 'todos', :action => 'index', :done => 7 }, t('feedlist.actions_completed_last_week')) %></li>
|
||||
<li><%= feed_links([:rss, :txt], { :controller => 'contexts', :action => 'index' }, t('feedlist.all_contexts')) %></li>
|
||||
<li><%= feed_links([:rss, :txt], { :controller => 'projects', :action => 'index' }, t('feedlist.all_projects')) %></li>
|
||||
<li><%= feed_links([:rss, :txt], { :controller => 'projects', :action => 'index', :only_active_with_no_next_actions => true }, t('feedlist.active_projects_wo_next')) %></li>
|
||||
<li><%= feed_links([:rss, :txt], { :controller => 'todos', :action => 'index', :tag => 'starred' }, t('feedlist.active_starred_actions')) %></li>
|
||||
<li><%= feed_links([:txt], {:controller => 'projects', :action => 'index', :projects_and_actions => true}, t('feedlist.projects_and_actions')) %></li>
|
||||
<li><%= render :partial => 'feed_for_context' %></li>
|
||||
<li><%= render :partial => 'feed_for_project' %></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div><!-- End of display_box -->
|
||||
</div>
|
||||
|
||||
<div id="input_box">
|
||||
<%= render :file => "sidebar/sidebar.html.erb" %>
|
||||
</div><!-- End of input box -->
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ set myToken to "<%= current_user.token %>"
|
|||
set myContextID to <%= context.id %> (* <%= context.name %> *)
|
||||
|
||||
-- Display dialog to enter your description
|
||||
display dialog "Description of next action:" default answer ""
|
||||
display dialog "<%= t('integrations.applescript_next_action_prompt') %>" default answer ""
|
||||
set myDesc to text returned of the result
|
||||
|
||||
-- Now send all that info to Tracks
|
||||
|
|
@ -17,4 +17,4 @@ tell application "<%= home_url %>backend/api"
|
|||
end tell
|
||||
|
||||
-- Show the ID of the newly created next action
|
||||
display dialog "New next action with id " & returnValue & " created"
|
||||
display dialog "<%= t('integrations.applescript_success_before_id') %> " & returnValue & " <%= t('integrations.applescript_success_after_id') %>"
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
<Module>
|
||||
<ModulePrefs title="Tracks" directory_title="Tracks" description="Gadget to add Tracks to Gmail as a gadget" author="Tracks" author_email="butshesagirl@rousette.org.uk" author_affiliation="Tracks" author_location="UK" title_url="http://www.getontracks.org/" screenshot="http://www.getontracks.org/images/uploads/tracks_home_thumb.png" thumbnail="http://www.getontracks.org/images/uploads/tracks_tickler.png" category="communication" category2="tools" height="300">
|
||||
<ModulePrefs title="Tracks" directory_title="Tracks" description="<%= t('integrations.gmail_description') %>" author="Tracks" author_email="butshesagirl@rousette.org.uk" author_affiliation="Tracks" author_location="UK" title_url="http://www.getontracks.org/" screenshot="http://www.getontracks.org/images/uploads/tracks_home_thumb.png" thumbnail="http://www.getontracks.org/images/uploads/tracks_tickler.png" category="communication" category2="tools" height="300">
|
||||
</ModulePrefs>
|
||||
<Content type="url" href="<%= home_url %>mobile"/>
|
||||
</Module>
|
||||
125
app/views/integrations/index.de.html.erb
Normal file
125
app/views/integrations/index.de.html.erb
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
<% has_contexts = !current_user.contexts.empty? -%>
|
||||
<h1>Integration</h1>
|
||||
<p>Tracks kann mit verschiedenen Werkzeugen zusammenarbeiten...
|
||||
was immer Sie brauchen, um Ihre Aufgaben zu erledigen!
|
||||
Auf dieser Seite finden Sie Informationen, um einige dieser Werkzeuge einzurichten.
|
||||
Diese Beispiele sind nicht unbedingt auf Ihre Umgebung anwendbar oder bedürfen mehr
|
||||
technisches Wissen als andere.
|
||||
Weitere Informationen finden Sie in der <%= link_to "Entwickler Documentation der Tracks' REST API", url_for(:action => 'rest_api') %> (englisch).</p>
|
||||
<br/><p>Inhalt:</p>
|
||||
<ul>
|
||||
<li><a href="#applescript1-section">Eine Aktion mit Applescript hinzufügen</a></li>
|
||||
<li><a href="#applescript2-section">Eine Aktion anhand der aktuell in Mail.app selektierten Nachricht erstellen</a></li>
|
||||
<li><a href="#quicksilver-applescript-section">Aktionen mit Quicksilver und Applescript erstellen</a></li>
|
||||
<li><a href="#email-cron-section">Anstehende Aufgaben automatisch sich via E-Mail zusenden lassen</a></li>
|
||||
<li><a href="#message_gateway">Tracks mit einem Mail-Server integrieren, um Aufgaben via E-Mail zu erstellen</a></li>
|
||||
<li><a href="#google_gadget">Tracks zu Ihrer Google Gmail Seite hinzufügen</a></li>
|
||||
</ul><br/>
|
||||
<p>Sie haben weitere Beispiele?
|
||||
<a href="http://www.getontracks.org/forums/viewforum/10/" title="Tracks | Tips and Tricks">Berichten Sie uns
|
||||
in unserem Tipps&Tricks Forum</a>, damit wir es für die nächsten Versionen berücksichtigen können.
|
||||
</p>
|
||||
|
||||
<a name="applescript1-section"> </a>
|
||||
<h2>Eine Aktion mit Applescript hinzufügen</h2>
|
||||
<p>Dieses Beispiel-Script zeigt einen Dialog, welcher nach einer Beschreibung fragt und die Aufgabe in einem festen Kontext anlegt.</p>
|
||||
|
||||
<% if has_contexts -%>
|
||||
<ol>
|
||||
<li>Wählen Sie den Kontext, für welchen die Aktion erstellt werden soll: <select name="applescript1-contexts" id="applescript1-contexts"><%= options_from_collection_for_select(current_user.contexts, "id", "name", current_user.contexts.first.id) %></select>
|
||||
</li>
|
||||
<li>Kopieren Sie das AppleScript in die Zwischenablage.<br />
|
||||
|
||||
<textarea id="applescript1" name="applescript1" rows="15"><%= render :partial => 'applescript1', :locals => { :context => current_user.contexts.first } %></textarea>
|
||||
</li>
|
||||
<li>Öffnen Sie den Script Editor und fügen die Daten in ein neues Script ein.</li>
|
||||
<li>Kompilieren und speichern Sie das Script, um es bei Bedarf einzusetzen.</li>
|
||||
</ol>
|
||||
<% else %>
|
||||
<br/><p id="no_context_msg"><i>Sie haben noch keinen Kontext angelegt. Dieses Script ist automatisch verfügbar, sobald Sie Ihren ersten Kontext angelegt haben.</i></p>
|
||||
<% end %>
|
||||
|
||||
<a name="applescript2-section"> </a>
|
||||
<h2>Add an Action with Applescript based on the currently selected Email in Mail.app</h2>
|
||||
<p>This script takes the sender and subject of the selected email(s) in Mail and creates a new action for each one, with the description, "Email [sender] about [subject]". The description gets truncated to 100 characters (the validation limit for the field) if it is longer than that. It also has Growl notifications if you have Growl installed.</p>
|
||||
|
||||
<% if has_contexts -%>
|
||||
<ol>
|
||||
<li>Choose the context you want to add actions to: <select name="applescript2-contexts" id="applescript2-contexts"><%= options_from_collection_for_select(current_user.contexts, "id", "name", current_user.contexts.first.id) %></select>
|
||||
</li>
|
||||
<li>Copy the Applescript below to the clipboard.<br />
|
||||
|
||||
<textarea id="applescript2" name="applescript2" rows="15"><%= render :partial => 'applescript2', :locals => { :context => current_user.contexts.first } %></textarea>
|
||||
</li>
|
||||
<li>Open Script Editor and paste the script into a new document.</li>
|
||||
<li>Compile and save the script to the ~/Library/Scriipts/Mail Scripts directory.</li>
|
||||
<li>For more information on using AppleScript with Mail.app, see <a href="http://www.apple.com/applescript/mail/" title="Scriptable Applications: Mail">this overview</a>.</li>
|
||||
</ol>
|
||||
<% else %>
|
||||
<br/><p><i>You do not have any context yet. The script will be available after you add your first context</i></p>
|
||||
<% end %>
|
||||
|
||||
<a name="quicksilver-applescript-section"></a>
|
||||
<h2>Add Actions with Quicksilver and Applescript</h2>
|
||||
|
||||
<p>This integration will allow you to add actions to Tracks via <a href="http://quicksilver.blacktree.com/">Quicksilver</a>.</p>
|
||||
|
||||
<% if has_contexts -%>
|
||||
<ol>
|
||||
<li>Choose the context you want to add actions to: <select name="quicksilver-contexts" id="quicksilver-contexts"><%= options_from_collection_for_select(current_user.contexts, "id", "name", current_user.contexts.first.id) %></select>
|
||||
</li>
|
||||
<li>Copy the Applescript below to the clipboard.<br />
|
||||
|
||||
<textarea id="quicksilver" name="quicksilver" rows="15"><%= render :partial => 'quicksilver_applescript', :locals => { :context => current_user.contexts.first } %></textarea>
|
||||
</li>
|
||||
<li>Open Script Editor and paste the script into a new document.</li>
|
||||
<li>Compile and save the script as "Add to Tracks.scpt" in ~/Library/Application Support/Quicksilver/Actions/ (you may need to create the Actions directory)</li>
|
||||
<li>Restart Quicksilver</li>
|
||||
<li>Activate Quicksilver (Ctrl+Space by default)</li>
|
||||
<li>Press "." to put quicksilver into text mode</li>
|
||||
<li>Type the description of the next action you want to add</li>
|
||||
<li>Press tab to switch to the action pane.</li>
|
||||
<li>By typing or scrolling, choose the "Add to Tracks" action.</li>
|
||||
</ol>
|
||||
<% else %>
|
||||
<br/><p><i>You do not have any context yet. The script will be available after you add your first context</i></p>
|
||||
<% end %>
|
||||
|
||||
<a name="email-cron-section"> </a>
|
||||
<h2>Automatically Email Yourself Upcoming Actions</h2>
|
||||
|
||||
<p>If you enter the following entry to your crontab, you will receive email every day around 5 AM with a list of the upcoming actions which are due within the next 7 days.</p>
|
||||
|
||||
<textarea id="cron" name="cron">0 5 * * * /usr/bin/curl -0 "<%= home_url %>todos.txt?due=6&token=<%= current_user.token %>" | /usr/bin/mail -e -s 'Tracks actions due in the next 7 days' youremail@yourdomain.com</textarea>
|
||||
|
||||
<p>You can of course use other text <%= link_to 'feeds provided by Tracks', feeds_path %> -- why not email a list of next actions in a particular project to a group of colleagues who are working on the project?</p>
|
||||
|
||||
<a name="message_gateway"> </a>
|
||||
<h2>Integrated email/SMS receiver</h2>
|
||||
<p>
|
||||
If Tracks is running on the same server as your mail server, you can use the integrated mail handler built into tracks. Steps to set it up:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Go to <%= link_to "Preferences", preferences_url %> and set your "From email" and "default email context" for todos sent in via email (which could come from an SMS message)</li>
|
||||
<li>In sendmail/qmail/postfix/whatever, set up an email address alias to pipe messages to <pre >/PATH/TO/RUBY/ruby /PATH/TO/TRACKS/script/runner -e production 'MessageGateway.receive(STDIN.read)'</pre></li>
|
||||
<li>Send an email to your newly configured address!</li>
|
||||
</ul>
|
||||
<p>You can also use the Rich Todo API to send in tasks like "do laundry @ Home"
|
||||
or "Call Bill > project X". The subject of the message will fill description,
|
||||
context, and project, while the body will populate the tasks's note.
|
||||
</p>
|
||||
|
||||
<a name="google_gadget"> </a>
|
||||
<h2>Add Tracks as a Google Gmail gadget</h2>
|
||||
<p>
|
||||
You can now manage your projects/actions inside Gmail using Tracks Gmail Gadget.
|
||||
Add Tracks Gmail gadget to the sidebar of Gmail and track your next actions
|
||||
or add new action without explicitly open new browser tab for Tracks. Steps to set it up:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Sign in to Gmail and click Settings in the top right of your Gmail page. In Gmail setting page, click Labs tab</li>
|
||||
<li>Enable the "Add any gadget by URL" feature. You will find it at bottom of the list. Select Enable radio button and click Save Changes button.</li>
|
||||
<li>Now you can see Gadgets tab added to Gmail Settings. Go to the Gadgets tab</li>
|
||||
<li>Paste following link to the Add a gadget by its URL: and then click Add button:<br/>
|
||||
<pre><%= integrations_url + "/google_gadget" %></pre></li>
|
||||
</ul>
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
</li>
|
||||
<li>Open Script Editor and paste the script into a new document.</li>
|
||||
<li>Compile and save the script to the ~/Library/Scriipts/Mail Scripts directory.</li>
|
||||
<li>For more information on using AppleScript with Mail.app, see <a href="http://www.apple.com/applescript/mail/" title="Scriptable Applications: Mail">this overview</a>.
|
||||
<li>For more information on using AppleScript with Mail.app, see <a href="http://www.apple.com/applescript/mail/" title="Scriptable Applications: Mail">this overview</a>.</li>
|
||||
</ol>
|
||||
<% else %>
|
||||
<br/><p><i>You do not have any context yet. The script will be available after you add your first context</i></p>
|
||||
|
|
@ -98,6 +98,7 @@
|
|||
<h2>Integrated email/SMS receiver</h2>
|
||||
<p>
|
||||
If Tracks is running on the same server as your mail server, you can use the integrated mail handler built into tracks. Steps to set it up:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Go to <%= link_to "Preferences", preferences_url %> and set your "From email" and "default email context" for todos sent in via email (which could come from an SMS message)</li>
|
||||
<li>In sendmail/qmail/postfix/whatever, set up an email address alias to pipe messages to <pre >/PATH/TO/RUBY/ruby /PATH/TO/TRACKS/script/runner -e production 'MessageGateway.receive(STDIN.read)'</pre></li>
|
||||
|
|
@ -121,10 +122,4 @@
|
|||
<li>Now you can see Gadgets tab added to Gmail Settings. Go to the Gadgets tab</li>
|
||||
<li>Paste following link to the Add a gadget by its URL: and then click Add button:<br/>
|
||||
<pre><%= integrations_url + "/google_gadget" %></pre></li>
|
||||
</ul>
|
||||
|
||||
<Module>
|
||||
<ModulePrefs title="GTDify" directory_title="GTDify" description="Official gadget for GTDify service." author="GTDify" author_email="support@gtdify.com" author_affiliation="GTDify" author_location="NJ, USA" title_url="http://www.gtdify.com/" screenshot="http://www.gtdify.com/modules/gmail/ss.png" thumbnail="http://www.gtdify.com/modules/gmail/tn.png" category="communication" category2="tools" height="300">
|
||||
</ModulePrefs>
|
||||
<Content type="url" href="http://my.gtdify.com/mobile/"/>
|
||||
</Module>
|
||||
</ul>
|
||||
|
|
@ -3,7 +3,7 @@ xml.instruct!
|
|||
xml.OpenSearchDescription 'xmlns' => "http://a9.com/-/spec/opensearch/1.1/" do
|
||||
|
||||
xml.ShortName Tracks
|
||||
xml.Description 'Search in Tracks'
|
||||
xml.Description t('integrations.opensearch_description')
|
||||
xml.InputEncoding 'UTF-8'
|
||||
xml.Image("data:image/x-icon;base64," + @icon_data,
|
||||
'width' => '16', 'height' => '16')
|
||||
|
|
|
|||
|
|
@ -3,8 +3,7 @@
|
|||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<%= stylesheet_link_tag "scaffold" %>
|
||||
<%= javascript_include_tag 'jquery' %>
|
||||
<%= javascript_include_tag 'jquery.cookie' %>
|
||||
<%= javascript_include_tag 'jquery-1.5.min', 'jquery.cookie' %>
|
||||
|
||||
<title><%= @page_title -%></title>
|
||||
|
||||
|
|
|
|||
|
|
@ -12,29 +12,29 @@
|
|||
<title><%= @page_title %></title>
|
||||
</head><body>
|
||||
<% if !(@new_mobile || @edit_mobile)
|
||||
if !@prefs.nil? -%>
|
||||
if !current_user.prefs.nil? -%>
|
||||
<h1><span class="count"><%= @down_count %></span> <%=
|
||||
current_user.time.strftime(@prefs.title_date_format) -%></h1>
|
||||
l(Date.today, :format => current_user.prefs.title_date_format) -%></h1>
|
||||
<div class="nav">
|
||||
<%= (link_to("0-New action", new_todo_path(new_todo_params))+" | ") unless @new_mobile -%>
|
||||
<%= (link_to("1-Home", todos_path(:format => 'm'))+" | ") unless @home -%>
|
||||
<%= (link_to("2-Contexts", contexts_path(:format => 'm'))+" | ") -%>
|
||||
<%= (link_to("3-Projects", projects_path(:format => 'm'))+" | ") -%>
|
||||
<%= (link_to("4-Starred", {:action => "tag", :controller => "todos", :id => "starred.m"})) -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.new_action'), new_todo_path(new_todo_params))+" | ") unless @new_mobile -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.home'), todos_path(:format => 'm'))+" | ") unless @home -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.contexts'), contexts_path(:format => 'm'))+" | ") -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.projects'), projects_path(:format => 'm'))+" | ") -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.starred'), {:action => "tag", :controller => "todos", :id => "starred.m"})) -%>
|
||||
<% end
|
||||
end -%><%= render_flash -%>
|
||||
</div>
|
||||
<%= yield -%>
|
||||
<hr/><% if !@prefs.nil? -%>
|
||||
<hr/><% if !current_user.prefs.nil? -%>
|
||||
<div class="nav">
|
||||
<%= (link_to("Logout", logout_path(:format => 'm')) +" | ") -%>
|
||||
<%= (link_to("0-New action", new_todo_path(new_todo_params), {:accesskey => "0"})+" | ") unless @new_mobile -%>
|
||||
<%= (link_to("1-Home", todos_path(:format => 'm'), {:accesskey => "1"})+" | ") unless @home -%>
|
||||
<%= (link_to("2-Contexts", contexts_path(:format => 'm'), {:accesskey => "2"})+" | ") -%>
|
||||
<%= (link_to("3-Projects", projects_path(:format => '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"})) -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.logout'), logout_path(:format => 'm')) +" | ") -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.new_action'), new_todo_path(new_todo_params), {:accesskey => "0"})+" | ") unless @new_mobile -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.home'), todos_path(:format => 'm'), {:accesskey => "1"})+" | ") unless @home -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.contexts'), contexts_path(:format => 'm'), {:accesskey => "2"})+" | ") -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.projects'), projects_path(:format => 'm'), {:accesskey => "3"})+" | ") -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.starred'), {:action => "tag", :controller => "todos", :id => "starred.m"}, {:accesskey => "4"})+" | ") -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.tickler'), {:action => "index", :controller => "tickler.m"})+" | ") -%>
|
||||
<%= (link_to(t('layouts.mobile_navigation.feeds'), {:action => "index", :controller => "feeds.m"})) -%>
|
||||
</div>
|
||||
<% end -%>
|
||||
<%= render :partial => "shared/mobile_footer" -%>
|
||||
|
|
|
|||
|
|
@ -2,29 +2,36 @@
|
|||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<%= stylesheet_link_tag 'standard','superfish','niftyCorners','jquery-ui',
|
||||
'jquery.autocomplete', :cache => true %>
|
||||
<%= stylesheet_link_tag 'standard','superfish','niftyCorners', 'jquery-ui-1.8.9.custom', :cache => 'tracks-cached' %>
|
||||
<%= stylesheet_link_tag "print", :media => "print" %>
|
||||
<%= javascript_include_tag 'jquery','jquery-ui','jquery.cookie',
|
||||
'jquery.blockUI','jquery.jeditable','jquery.autocomplete',
|
||||
'jquery.truncator', :cache => 'jquery-all' %>
|
||||
<%= javascript_include_tag 'jquery-1.5.min', 'jquery-ui-1.8.9.custom.min',
|
||||
'jquery.truncator','jquery.jeditable.mini', 'jquery.cookie', 'jquery.blockUI',
|
||||
'jquery.form','jquery.ui.autocomplete.selectFirst',
|
||||
:cache => 'jquery-cached' %>
|
||||
<%= javascript_include_tag 'hoverIntent','superfish','application',
|
||||
'accesskey-hints','niftycube','swfobject', :cache => 'tracks' %>
|
||||
'accesskey-hints','niftycube','swfobject',
|
||||
:cache => 'tracks-cached' %>
|
||||
<%= javascript_tag "var AUTH_TOKEN = #{form_authenticity_token.inspect};" if protect_against_forgery? %>
|
||||
<%= javascript_tag "var SOURCE_VIEW = '#{@source_view}';" %>
|
||||
<%= javascript_tag "var TAG_NAME = '#{@tag_name}';" if @tag_name %>
|
||||
<%= csrf_meta_tag %>
|
||||
<script type="text/javascript">
|
||||
var defaultContexts = <%= default_contexts_for_autocomplete rescue '{}' %>;
|
||||
var defaultTags = <%= default_tags_for_autocomplete rescue '{}' %>;
|
||||
var dateFormat = '<%= date_format_for_date_picker %>';
|
||||
var weekStart = '<%= current_user.prefs.week_starts %>';
|
||||
function relative_to_root(path) { return '<%= root_url %>'+path; };
|
||||
<% if @prefs.refresh != 0 -%>
|
||||
setup_auto_refresh(<%= @prefs["refresh"].to_i*60000 %>);
|
||||
<% if current_user.prefs.refresh != 0 -%>
|
||||
setup_auto_refresh(<%= current_user.prefs["refresh"].to_i*60000 %>);
|
||||
<% end -%>
|
||||
<% unless @controller_name == 'feed' or session['noexpiry'] == "on" -%>
|
||||
setup_periodic_check("<%=url_for(:controller => "login", :action => "check_expiry")%>", 5*60);
|
||||
<% end -%>
|
||||
setup_periodic_check("<%=check_deferred_todos_path(:format => 'js')%>", 10*60, 'POST');
|
||||
<%= generate_i18n_strings %>
|
||||
</script>
|
||||
<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"}) %>
|
||||
<%= auto_discovery_link_tag(:rss, {:controller => "todos", :action => "index", :format => 'rss', :token => "#{current_user.token}"}, {:title => t('layouts.next_actions_rss_feed')}) %>
|
||||
<link rel="search" type="application/opensearchdescription+xml" title="Tracks" href="<%= search_plugin_path %>" />
|
||||
<title><%= @page_title %></title>
|
||||
</head>
|
||||
|
|
@ -36,64 +43,57 @@
|
|||
<% if @count -%>
|
||||
<span id="badge_count" class="badge"><%= @count %></span>
|
||||
<% end -%>
|
||||
<%= current_user.time.strftime(@prefs.title_date_format) %>
|
||||
<%= l(Date.today, :format => current_user.prefs.title_date_format) %>
|
||||
</h1>
|
||||
</div>
|
||||
<div id="minilinks">
|
||||
<%= link_to("Toggle notes", "#", {:accesskey => "S", :title => "Toggle all notes", :id => "toggle-notes-nav"}) %>
|
||||
<%= link_to(t('layouts.toggle_notes'), "#", {:accesskey => "S", :title => t('layouts.toggle_notes_title'), :id => "toggle-notes-nav"}) %>
|
||||
|
|
||||
<%= link_to "Logout (#{current_user.display_name}) »", logout_path %>
|
||||
<%= link_to( t('common.logout') + " (#{current_user.display_name}) »", logout_path) %>
|
||||
</div>
|
||||
<div id="navcontainer">
|
||||
<ul class="sf-menu">
|
||||
<li><%= navigation_link("Home", home_path, {:accesskey => "t", :title => "Home"} ) %></li>
|
||||
<li><%= navigation_link("Starred", tag_path("starred"), :title => "See your starred actions" ) %></li>
|
||||
<li><%= navigation_link("Projects", projects_path, {:accesskey=>"p", :title=>"Projects"} ) %></li>
|
||||
<li><%= navigation_link("Tickler", tickler_path, {:accesskey =>"k", :title => "Tickler"} ) %></li>
|
||||
<li><a href="#">Organize</a>
|
||||
<li><%= navigation_link(t('layouts.navigation.home'), home_path, {:accesskey => "t", :title => t('layouts.navigation.home_title')} ) %></li>
|
||||
<li><%= navigation_link(t('layouts.navigation.starred'), tag_path("starred"), :title => t('layouts.navigation.starred_title')) %></li>
|
||||
<li><%= navigation_link(t('common.projects'), projects_path, {:accesskey=>"p", :title=>t('layouts.navigation.projects_title')} ) %></li>
|
||||
<li><%= navigation_link(t('layouts.navigation.tickler'), tickler_path, {:accesskey =>"k", :title => t('layouts.navigation.tickler_title')} ) %></li>
|
||||
<li><a href="#"><%= t('layouts.navigation.organize') %></a>
|
||||
<ul>
|
||||
<li><%= navigation_link( "Contexts", contexts_path, {:accesskey=>"c", :title=>"Contexts"} ) %></li>
|
||||
<li><%= navigation_link( "Notes", notes_path, {:accesskey => "o", :title => "Show all notes"} ) %></li>
|
||||
<li><%= navigation_link( "Repeating todos", {:controller => "recurring_todos", :action => "index"}, :title => "Manage recurring actions" ) %></li>
|
||||
<li><%= navigation_link( t('common.contexts'), contexts_path, {:accesskey=>"c", :title=>t('layouts.navigation.contexts_title')} ) %></li>
|
||||
<li><%= navigation_link( t('common.notes'), notes_path, {:accesskey => "o", :title => t('layouts.navigation.notes_title')} ) %></li>
|
||||
<li><%= navigation_link( t('layouts.navigation.recurring_todos'), {:controller => "recurring_todos", :action => "index"}, :title => t('layouts.navigation.recurring_todos_title')) %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">View</a>
|
||||
<li><a href="#"><%= t('layouts.navigation.view') %></a>
|
||||
<ul>
|
||||
<li><%= navigation_link( "Calendar", calendar_path, :title => "Calendar of due actions" ) %></li>
|
||||
<li><%= navigation_link( "Done", done_path, {:accesskey=>"d", :title=>"Completed"} ) %></li>
|
||||
<li><%= navigation_link( "Feeds", {:controller => "feedlist", :action => "index"}, :title => "See a list of available feeds" ) %></li>
|
||||
<li><%= navigation_link( "Statistics", {:controller => "stats", :action => "index"}, :title => "See your statistics" ) %></li>
|
||||
<li><%= navigation_link( t('layouts.navigation.calendar'), calendar_path, :title => t('layouts.navigation.calendar_title')) %></li>
|
||||
<li><%= navigation_link( t('layouts.navigation.completed_tasks'), done_path, {:accesskey=>"d", :title=>t('layouts.navigation.completed_tasks_title')} ) %></li>
|
||||
<li><%= navigation_link( t('layouts.navigation.feeds'), {:controller => "feedlist", :action => "index"}, :title => t('layouts.navigation.feeds_title')) %></li>
|
||||
<li><%= navigation_link( t('layouts.navigation.stats'), {:controller => "stats", :action => "index"}, :title => t('layouts.navigation.stats_title')) %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">Admin</a>
|
||||
<ul>
|
||||
<li><%= navigation_link( "Preferences", preferences_path, {:accesskey => "u", :title => "Show my preferences"} ) %></li>
|
||||
<li><%= navigation_link( "Export", {:controller => "data", :action => "index"}, {:accesskey => "i", :title => "Import and export data"} ) %></li>
|
||||
<li><%= navigation_link( t('layouts.navigation.preferences'), preferences_path, {:accesskey => "u", :title => t('layouts.navigation.preferences_title')} ) %></li>
|
||||
<li><%= navigation_link( t('layouts.navigation.export'), {:controller => "data", :action => "index"}, {:accesskey => "i", :title => t('layouts.navigation.export_title')} ) %></li>
|
||||
<% if current_user.is_admin? -%>
|
||||
<li><%= navigation_link("Manage users", users_path, {:accesskey => "a", :title => "Add or delete users"} ) %></li>
|
||||
<li><%= navigation_link(t('layouts.navigation.manage_users'), users_path, {:accesskey => "a", :title => t('layouts.navigation.manage_users_title')} ) %></li>
|
||||
<% end -%>
|
||||
</ul>
|
||||
</li>
|
||||
<li><a href="#">?</a>
|
||||
<ul>
|
||||
<li><%= link_to 'Integrate Tracks', integrations_path %></li>
|
||||
<li><%= link_to 'REST API Docs', rest_api_docs_path %></li>
|
||||
<li><%= link_to t('layouts.navigation.integrations_'), integrations_path %></li>
|
||||
<li><%= link_to t('layouts.navigation.api_docs'), rest_api_docs_path %></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li><%= navigation_link(image_tag("system-search.png", :size => "16X16", :border => 0), {:controller => "search", :action => "index"}, :title => "Search All Items" ) %></li>
|
||||
<li><%= navigation_link(image_tag("system-search.png", :size => "16X16", :border => 0), {:controller => "search", :action => "index"}, :title => t('layouts.navigation.search')) %></li>
|
||||
</ul>
|
||||
</div>
|
||||
<%= render_flash %>
|
||||
</div>
|
||||
|
||||
<div id="content" class="<%= @controller.controller_name %>">
|
||||
<% unless @controller_name == 'feed' or session['noexpiry'] == "on" -%>
|
||||
<%= periodically_call_remote( :url => {:controller => "login", :action => "check_expiry"},
|
||||
:frequency => (5*60)) %>
|
||||
<% end -%>
|
||||
<%= periodically_call_remote( :url => check_deferred_todos_path(:format => 'js'),
|
||||
:method => :post,
|
||||
:frequency => (10*60)) %>
|
||||
<%= yield %>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
1
app/views/login/_redirect_to_login.js.erb
Normal file
1
app/views/login/_redirect_to_login.js.erb
Normal file
|
|
@ -0,0 +1 @@
|
|||
window.location.href = '<%= login_path %>';
|
||||
|
|
@ -1 +0,0 @@
|
|||
page.redirect_to :controller => 'login', :action => 'login'
|
||||
8
app/views/login/check_expiry.js.erb
Normal file
8
app/views/login/check_expiry.js.erb
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
<% if @session_expired
|
||||
theLink = link_to(t('login.log_in_again'), :controller => "login", :action => "login")
|
||||
message = I18n.t('login.session_time_out', :link => theLink)
|
||||
theHtml = escape_javascript(content_tag(:div, message, :"class" => "warning"))
|
||||
-%>
|
||||
$('div#navcontainer').hide();
|
||||
$('div#content').html('<%=theHtml%>');
|
||||
<% end -%>
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
unless @msg == ""
|
||||
page.replace_html "info", content_tag("div", @msg + link_to("log in again.", :controller => "login", :action => "login"), "class" => "warning")
|
||||
end
|
||||
|
|
@ -4,30 +4,30 @@
|
|||
show_cas_form = auth_schemes.include?('cas')
|
||||
-%>
|
||||
|
||||
<div title="Account login" id="loginform" class="form">
|
||||
<div title="<%= t('login.account_login') %>" id="loginform" class="form">
|
||||
|
||||
<%= render_flash %>
|
||||
|
||||
<h3>Please log in to use Tracks:</h3>
|
||||
<h3><%= t('login.please_login') %>:</h3>
|
||||
<% if show_database_form %>
|
||||
<div id="database_auth_form" style="display:<%=(@prefered_auth.eql?('database')) ? "block" : "none"%>">
|
||||
<% form_tag :action=> 'login' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="user_login">Login:</label></td>
|
||||
<td><label for="user_login"><%= User.human_attribute_name('login') %>:</label></td>
|
||||
<td><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="user_password">Password:</label></td>
|
||||
<td><label for="user_password"><%= User.human_attribute_name('password') %>:</label></td>
|
||||
<td><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td><label for="user_noexpiry"><%= t('login.user_no_expiry') %>:</label></td>
|
||||
<td><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
<td><input type="submit" name="login" value="<%= t('login.sign_in') %> »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
|
|
@ -39,16 +39,16 @@
|
|||
<% form_tag :action=> 'login' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="openid_url">Identity URL:</label></td>
|
||||
<td><label for="openid_url"><%= User.human_attribute_name('open_id_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><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td><label for="user_noexpiry"><%= t('login.user_no_expiry') %>:</label></td>
|
||||
<td><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
<td><input type="submit" name="login" value="<%= t('login.sign_in') %> »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
|
|
@ -61,15 +61,15 @@
|
|||
<tr>
|
||||
<td>
|
||||
<% if @username && @user%>
|
||||
<p>Hello, <%= @username %>! You are authenticated.</p>
|
||||
<p><%= t('login.cas_logged_in_greeting', :username => @username) %></p>
|
||||
<% elsif @username %>
|
||||
<p>Hello, <%= @username %>! You do not have an account on Tracks.
|
||||
<p><%= t('login.cas_no_user_found', :username => @username) %>
|
||||
<%if SITE_CONFIG['open_signups']%>
|
||||
If you like to request on please go here to <%= link_to "Request Account" , signup_url %>
|
||||
<%= t('login.cas_create_account', :signup_link => link_to(t('login.cas_signup_link'), signup_url)) %>
|
||||
<%end%>
|
||||
</p>
|
||||
<% else %>
|
||||
<p><%= link_to("CAS Login", login_cas_url) %> </p>
|
||||
<p><%= link_to(t('login.cas_login'), login_cas_url) %> </p>
|
||||
<% end %>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
@ -78,9 +78,9 @@
|
|||
<% end %>
|
||||
|
||||
</div>
|
||||
<% if show_openid_form %><p id="alternate_auth_openid" class="alternate_auth">or, <a href="#" onclick="Login.showOpenid();return false;">login with an OpenId</a></p><% end %>
|
||||
<% if show_database_form %><p id="alternate_auth_database" class="alternate_auth">or, <a href="#" onclick="Login.showDatabase();return false;">go back to the standard login</a></p><% end %>
|
||||
<% if show_cas_form %><p id="alternate_auth_cas" class="alternate_auth">or, <a href="#" onclick="Login.showCAS();return false;">go to the CAS</a></p><% end %>
|
||||
<% if show_openid_form %><p id="alternate_auth_openid" class="alternate_auth"><%= t('login.option_separator') %> <a href="#" onclick="Login.showOpenid();return false;"><%= t('login.login_with_openid') %></a></p><% end %>
|
||||
<% if show_database_form %><p id="alternate_auth_database" class="alternate_auth"><%= t('login.option_separator') %> <a href="#" onclick="Login.showDatabase();return false;"><%= t('login.login_standard') %></a></p><% end %>
|
||||
<% if show_cas_form %><p id="alternate_auth_cas" class="alternate_auth"><%= t('login.option_separator') %> <a href="#" onclick="Login.showCAS();return false;"><%= t('login.login_cas')%></a></p><% end %>
|
||||
|
||||
<script type="text/javascript">
|
||||
function showPreferredAuth() {
|
||||
|
|
|
|||
|
|
@ -3,31 +3,31 @@
|
|||
show_openid_form = auth_schemes.include?('open_id')
|
||||
-%>
|
||||
|
||||
<div title="Account login" id="loginform" class="form">
|
||||
<div title="<%= t('login.account_login') %>" id="loginform" class="form">
|
||||
|
||||
<%= render_flash %>
|
||||
|
||||
<h3>Please log in to use Tracks:</h3>
|
||||
<h3><%= t('login.please_login') %>:</h3>
|
||||
|
||||
<% if show_database_form %>
|
||||
<div id="database_auth_form">
|
||||
<% form_tag login_path(:format => 'm') do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td><label for="user_login">Login:</label></td>
|
||||
<td><label for="user_login"><%= User.human_attribute_name('login') %>:</label></td>
|
||||
<td><input type="text" name="user_login" id="user_login" value="" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="user_password">Password:</label></td>
|
||||
<td><label for="user_password"><%= User.human_attribute_name('password') %>:</label></td>
|
||||
<td><input type="password" name="user_password" id="user_password" class="login_text" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label for="user_noexpiry">Stay logged in:</label></td>
|
||||
<td><label for="user_noexpiry"><%= t('login.user_no_expiry') %>:</label></td>
|
||||
<td><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked="checked" /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
<td><input type="submit" name="login" value="<%= t('login.sign_in') %> »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
|
|
@ -36,22 +36,22 @@
|
|||
|
||||
<% if show_openid_form %>
|
||||
|
||||
<h4>...or login with an Open ID:</h4>
|
||||
<h4><%= t('login.mobile_use_openid') %>:</h4>
|
||||
|
||||
<div id="openid_auth_form">
|
||||
<% form_tag login_path(:format => 'm') do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td width="100px"><label for="openid_url">Identity URL:</label></td>
|
||||
<td width="100px"><label for="openid_url"><%= User.human_attribute_name('open_id_url') %>:</label></td>
|
||||
<td width="100px"><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"><label for="user_noexpiry"><%= t('login.user_no_expiry') %>:</label></td>
|
||||
<td width="100px"><input type="checkbox" name="user_noexpiry" id="user_noexpiry" checked /></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td width="100px"></td>
|
||||
<td><input type="submit" name="login" value="Sign In »" class="primary" /></td>
|
||||
<td><input type="submit" name="login" value="<%= t('login.sign_in') %> »" class="primary" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -4,10 +4,10 @@
|
|||
</div>
|
||||
<div class="mobile_note_info">
|
||||
<br/>
|
||||
<%= link_to("In: " + note.project.name, project_path(note.project, :format => 'm')) %>
|
||||
Created: <%= format_date(note.created_at) %>
|
||||
<%= link_to(t('notes.note_location_link') + note.project.name, project_path(note.project, :format => 'm')) %>
|
||||
<%= Note.human_attribute_name('created_at') %>: <%= format_date(note.created_at) %>
|
||||
<% if note.updated_at? -%>
|
||||
| Modified: <%= format_date(note.updated_at) %>
|
||||
| <%= Note.human_attribute_name('updated_at') %>: <%= format_date(note.updated_at) %>
|
||||
<% end -%>
|
||||
</div>
|
||||
<% note = nil -%>
|
||||
|
|
|
|||
15
app/views/notes/_note.rhtml
Normal file
15
app/views/notes/_note.rhtml
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
<div class="container" id="note-<%= note.id %>-wrapper">
|
||||
<div id="<%= dom_id(note, 'container') %>">
|
||||
|
||||
<h2><%= link_to(t('notes.note_header', :id => note.id.to_s), note, :title => t('notes.note_link_title', :id => note.id.to_s)) %></h2>
|
||||
|
||||
<div class="project_notes" id="<%= dom_id(note) %>">
|
||||
<%= render :partial => "notes/note_details", :object => note %>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(note, 'edit') %>" class="note-edit-form" style="display:none;">
|
||||
<%= render :partial => "notes/note_edit_form", :object => note %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
16
app/views/notes/_note_details.rhtml
Normal file
16
app/views/notes/_note_details.rhtml
Normal file
|
|
@ -0,0 +1,16 @@
|
|||
<% note = note_details -%>
|
||||
<div class="note_boby"><%= format_note(note.body) %></div>
|
||||
|
||||
<div class="note_footer">
|
||||
|
||||
<%= link_to_delete_note(note, image_tag( "blank.png",:title => t('notes.delete_item_title'), :class=>"delete_item")) %>
|
||||
<%= link_to_edit_note(note, image_tag( "blank.png", :title => t('notes.edit_item_title'), :class=>"edit_item") ) %>
|
||||
|
||||
| <%= link_to("In: " + note.project.name, note.project, :class=>"footer_link" ) %> |
|
||||
|
||||
<%= Note.human_attribute_name('created_at') %>: <%= format_date(note.created_at) %>
|
||||
|
||||
<% if note.updated_at? -%>
|
||||
| <%= Note.human_attribute_name('updated_at') %>: <%= format_date(note.updated_at) %>
|
||||
<% end -%>
|
||||
</div>
|
||||
|
|
@ -1,6 +1,29 @@
|
|||
<% @note = note_edit_form %>
|
||||
<%= hidden_field( "note", "project_id" ) %>
|
||||
<%= text_area( "note", "body", "cols" => 70, "rows" => 15, "tabindex" => 1 ) %>
|
||||
<br /><br />
|
||||
<input type="submit" value="Update" tabindex="2" />
|
||||
<% @note = nil %>
|
||||
<%
|
||||
submit_text ||= t('common.update')
|
||||
|
||||
form_for(note_edit_form, :html => {
|
||||
:id => dom_id(note_edit_form, 'edit_form'),
|
||||
:class => "inline-form edit-note-form"}) do |f|
|
||||
-%>
|
||||
|
||||
<div id="error_status"><%= error_messages_for("note") %></div>
|
||||
|
||||
<%= f.hidden_field( "project_id" ) %>
|
||||
<%= f.text_area( "body", "cols" => 70, "rows" => 15, "tabindex" => 1 ) %>
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="<%= dom_id(note_edit_form, 'submit') %>" tabindex="15">
|
||||
<%=image_tag("accept.png", :alt => "") %>
|
||||
<%= submit_text %>
|
||||
</button>
|
||||
<a href="" class="negative" id="neg_<%=dom_id(note_edit_form, 'edit_form')%>">
|
||||
<%=image_tag("cancel.png", :alt => "") %>
|
||||
<%= t 'common.cancel' %>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br/><br/>
|
||||
|
||||
<% end -%>
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
<% note = notes -%>
|
||||
<div id="<%= dom_id(note, 'container') %>">
|
||||
<h2><%= link_to("Note #{note.id}", note_path(note), :title => "Show note #{note.id}" ) %></h2>
|
||||
<div class="project_notes" id="<%= dom_id(note) %>">
|
||||
<%= format_note(note.body) %>
|
||||
|
||||
<div class="note_footer">
|
||||
<%= link_to_remote(
|
||||
image_tag("blank.png", :title =>"Delete this note", :class=>"delete_item", :id => "delete_note_"+note.id.to_s),
|
||||
:url => note_path(note),
|
||||
:html => {:class => 'delete_note', :title => "delete note"},
|
||||
:method => :delete,
|
||||
:confirm => "Are you sure that you want to delete the note \'#{note.id.to_s}\'?",
|
||||
:before => visual_effect(:fade, dom_id(note, 'container'))) -%>
|
||||
<%= link_to_function(image_tag( "blank.png", :title => "Edit item", :class=>"edit_item"),
|
||||
"$('##{dom_id(note)}').toggle(); $('##{dom_id(note, 'edit')}').show(); $('##{dom_id(note, 'edit_form')} textarea').focus();" ) + " | " %>
|
||||
<%= link_to("In: " + note.project.name, project_path(note.project), :class=>"footer_link" ) %> |
|
||||
Created: <%= format_date(note.created_at) %>
|
||||
<% if note.updated_at? -%>
|
||||
| Modified: <%= format_date(note.updated_at) %>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(note, 'edit') %>" class="edit-form" style="display:none;">
|
||||
<% form_remote_tag :url => note_path(note),
|
||||
:method => :put,
|
||||
:html => { :id => dom_id(note, 'edit_form'), :class => "inline-form" },
|
||||
:update => dom_id(note, 'container'),
|
||||
:complete => visual_effect(:appear, dom_id(note, 'container')) do -%>
|
||||
<%= render :partial => "notes/note_edit_form", :object => note %>
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
<% note = nil -%>
|
||||
|
||||
|
|
@ -1,6 +1,11 @@
|
|||
<% note = notes_summary -%>
|
||||
<div class="note_wrapper" id="<%= dom_id(note) %>">
|
||||
<%= link_to( image_tag("blank.png", :border => 0), note_path(note), :title => "Show note", :class => "link_to_notes icon") %>
|
||||
<%= link_to(
|
||||
image_tag("blank.png", :border => 0),
|
||||
note,
|
||||
:title => t('notes.show_note_title'),
|
||||
:class => "link_to_notes icon",
|
||||
:id => dom_id(note, "link")) %>
|
||||
<%= rendered_note(note) %>
|
||||
</div>
|
||||
<% note = nil -%>
|
||||
|
|
|
|||
25
app/views/notes/create.js.erb
Normal file
25
app/views/notes/create.js.erb
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
<% if @saved -%>
|
||||
TracksPages.hide_errors();
|
||||
add_note();
|
||||
clear_form();
|
||||
<% else -%>
|
||||
TracksPages.show_errors(html_for_error_messages());
|
||||
<% end -%>
|
||||
|
||||
function add_note() {
|
||||
$('div#notes').append(html_for_note_summary());
|
||||
$('#empty-n').hide();
|
||||
}
|
||||
|
||||
function clear_form() {
|
||||
$('#new-note').hide();
|
||||
$('#edit-note-form').clearForm();
|
||||
}
|
||||
|
||||
function html_for_error_messages() {
|
||||
return "<%= escape_javascript(error_messages_for('project')) %>";
|
||||
}
|
||||
|
||||
function html_for_note_summary() {
|
||||
return "<%= @saved ? escape_javascript(render(:partial => 'notes_summary', :object => @note)) : "" %>";
|
||||
}
|
||||
10
app/views/notes/destroy.js.erb
Normal file
10
app/views/notes/destroy.js.erb
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
remove_deleted_note();
|
||||
TracksPages.set_page_badge(<%=@down_count%>);
|
||||
TracksPages.page_notify('notice', "<%= t('notes.deleted_note', :id => @note.id)%>", 5);
|
||||
|
||||
function remove_deleted_note() {
|
||||
$('div#note-<%=@note.id%>-wrapper').slideUp(1000,
|
||||
function() {
|
||||
$('div#note-<%=@note.id%>-wrapper').remove();
|
||||
});
|
||||
}
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
page.notify :notice, "Deleted note '#{@note.id}'", 5.0
|
||||
page['badge_count'].replace_html @count
|
||||
page.hide "busy"
|
||||
|
|
@ -1,11 +1,7 @@
|
|||
<div id="display_box_projects">
|
||||
<% if @all_notes.empty? -%>
|
||||
<div class="message"><p>Currently there are no notes: add notes to projects from individual project pages.</p></div>
|
||||
<div class="message"><p><%= t('notes.no_notes_available') %></p></div>
|
||||
<% else -%>
|
||||
<% for notes in @all_notes -%>
|
||||
<div class="container" id="note-<%= notes.id %>-wrapper">
|
||||
<%= render :partial => 'notes', :object => notes %>
|
||||
</div>
|
||||
<% end -%>
|
||||
<%= render :partial => @all_notes %>
|
||||
<% end -%>
|
||||
</div>
|
||||
|
|
@ -1,5 +1,3 @@
|
|||
<div id="display_box_projects">
|
||||
<div class="container" id="note-<%= @note.id %>-wrapper">
|
||||
<%= render :partial => 'notes', :object => @note %>
|
||||
</div>
|
||||
<%= render :partial => @note %>
|
||||
</div>
|
||||
29
app/views/notes/update.js.erb
Normal file
29
app/views/notes/update.js.erb
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
<% if @saved -%>
|
||||
|
||||
TracksPages.hide_errors();
|
||||
TracksPages.page_notify('notice', 'Note <%=@note.id %> saved', 5);
|
||||
replace_note_form_with_updated_note();
|
||||
|
||||
<% else -%>
|
||||
TracksPages.show_errors(html_for_error_messages());
|
||||
<% end %>
|
||||
|
||||
function replace_note_form_with_updated_note() {
|
||||
$('#<%= dom_id(@note, 'edit')%>').fadeOut(250, function() {
|
||||
$('#<%= dom_id(@note, 'edit')%>').html(html_for_updated_note_form());
|
||||
$('div.project_notes#<%= dom_id(@note)%>').html(html_for_updated_note_details());
|
||||
$('#<%= dom_id(@note)%>').fadeIn(500);
|
||||
});
|
||||
}
|
||||
|
||||
function html_for_error_messages() {
|
||||
return "<%= escape_javascript(error_messages_for('note')) %>";
|
||||
}
|
||||
|
||||
function html_for_updated_note_form(){
|
||||
return "<%= escape_javascript(render(:partial => 'note_edit_form', :object => @note)) %>";
|
||||
}
|
||||
|
||||
function html_for_updated_note_details(){
|
||||
return "<%= escape_javascript(render(:partial => 'note_details', :object => @note)) %>";
|
||||
}
|
||||
22
app/views/preferences/_help.html.erb
Normal file
22
app/views/preferences/_help.html.erb
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
<h2>Help on preferences</h2>
|
||||
<ul>
|
||||
<li><strong>first name and last name:</strong> Used for display purposes if set</li>
|
||||
<li><strong>date format:</strong> the format in which you'd like dates to be shown. For example, for the date 31st January 2006, %d/%m/%Y will show 31/01/2006, %b-%e-%y will show Jan-31-06. See the <a href="http://uk2.php.net/strftime" title="PHP strftime manual">strftime manual</a> for more formatting options for the date.</li>
|
||||
<li><strong>title date format:</strong> same as above, but for the big date at the top of each page.</li>
|
||||
<li><strong>time zone:</strong> your local time zone</li>
|
||||
<li><strong>week starts:</strong> day of the week shown as the start of the week on the popup calendar.</li>
|
||||
<li><strong>due style:</strong> style in which due dates are shown, e.g. "Due in 3 days", "Due on Wednesday"</li>
|
||||
<li><strong>show completed projects in sidebar:</strong> whether or not projects marked as complete are shown in the sidebar on the home page and elsewhere</li>
|
||||
<li><strong>show hidden contexts in sidebar:</strong> whether or not contexts marked as hidden are shown in the sidebar on the home page and elsewhere</li>
|
||||
<li><strong>show project on todo done:</strong> whether or not to redirect to the project page when an action associated with a project is marked complete</li>
|
||||
<% if current_user.is_admin? %>
|
||||
<li><strong>admin email:</strong> email address for the admin user of Tracks (displayed on the signup page for users to contact to obtain an account)</li>
|
||||
<% end %>
|
||||
<li><strong>staleness starts:</strong> the number of days before items with no due date get marked as stale (with a yellow highlight)</li>
|
||||
<li><strong>show number completed:</strong> number of completed actions to show on the page. If you set this to zero, the completed actions box will not be shown on the home page or on the individual context or project pages. You can still see all your completed items by clicking the 'Done' link in the navigation bar at the top of each page.</li>
|
||||
<li><strong>refresh:</strong> automatic refresh interval for each of the pages (in minutes)</li>
|
||||
<li><strong>verbose action descriptor:</strong> when true, show project/context name in action listing; when false show [P]/[C] with tool tips</li>
|
||||
<li><strong>mobile todos per page:</strong> the maximum number of actions to show on a single page in the mobile view</li>
|
||||
<li><strong>From email:</strong> the email address you use for sending todos as email or SMS messages to your Tracks account</li>
|
||||
<li><strong>Default email context:</strong> the context to which tasks sent in via email or SMS should be added</li>
|
||||
</ul>
|
||||
|
|
@ -1,43 +1,22 @@
|
|||
<div id="display_box" class="container context">
|
||||
<h2>Help on preferences</h2>
|
||||
<ul>
|
||||
<li><strong>first name and last name:</strong> Used for display purposes if set</li>
|
||||
<li><strong>date format:</strong> the format in which you'd like dates to be shown. For example, for the date 31st January 2006, %d/%m/%Y will show 31/01/2006, %b-%e-%y will show Jan-31-06. See the <a href="http://uk2.php.net/strftime" title="PHP strftime manual">strftime manual</a> for more formatting options for the date.</li>
|
||||
<li><strong>title date format:</strong> same as above, but for the big date at the top of each page.</li>
|
||||
<li><strong>time zone:</strong> your local time zone</li>
|
||||
<li><strong>week starts:</strong> day of the week shown as the start of the week on the popup calendar.</li>
|
||||
<li><strong>due style:</strong> style in which due dates are shown, e.g. "Due in 3 days", "Due on Wednesday"</li>
|
||||
<li><strong>show completed projects in sidebar:</strong> whether or not projects marked as complete are shown in the sidebar on the home page and elsewhere</li>
|
||||
<li><strong>show hidden contexts in sidebar:</strong> whether or not contexts marked as hidden are shown in the sidebar on the home page and elsewhere</li>
|
||||
<li><strong>show project on todo done:</strong> whether or not to redirect to the project page when an action associated with a project is marked complete</li>
|
||||
<% if current_user.is_admin? %>
|
||||
<li><strong>admin email:</strong> email address for the admin user of Tracks (displayed on the signup page for users to contact to obtain an account)</li>
|
||||
<% end %>
|
||||
<li><strong>staleness starts:</strong> the number of days before items with no due date get marked as stale (with a yellow highlight)</li>
|
||||
<li><strong>show number completed:</strong> number of completed actions to show on the page. If you set this to zero, the completed actions box will not be shown on the home page or on the individual context or project pages. You can still see all your completed items by clicking the 'Done' link in the navigation bar at the top of each page.</li>
|
||||
<li><strong>refresh:</strong> automatic refresh interval for each of the pages (in minutes)</li>
|
||||
<li><strong>verbose action descriptor:</strong> when true, show project/context name in action listing; when false show [P]/[C] with tool tips</li>
|
||||
<li><strong>mobile todos per page:</strong> the maximum number of actions to show on a single page in the mobile view</li>
|
||||
<li><strong>From email:</string> the email address you use for sending todos as email or SMS messages to your Tracks account</li>
|
||||
<li><string>Default email context:</string> the context to which tasks sent in via email or SMS should be added</li>
|
||||
</ul>
|
||||
<%= render :partial => 'help' %>
|
||||
</div>
|
||||
|
||||
<div id="input_box" class="container context">
|
||||
<% form_tag :action => 'update' do %>
|
||||
<table>
|
||||
<tr>
|
||||
<td><label>first name:</label></td>
|
||||
<td><label><%= User.human_attribute_name('first_name') %></label></td>
|
||||
<td><%= text_field 'user', 'first_name' %></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><label>last name:</label></td>
|
||||
<td><label><%= User.human_attribute_name('last_name') %></label></td>
|
||||
<td><%= text_field 'user', 'last_name' %></td>
|
||||
</tr>
|
||||
<%
|
||||
def table_row(pref_name, nowrap_label = false, &block)
|
||||
nowrap_attribute = nowrap_label ? ' nowrap="nowrap"' : ''
|
||||
s = %Q|<tr>\n<td#{nowrap_attribute}><label>#{pref_name.gsub(/_/,' ')}:</label></td>\n<td>\n|
|
||||
s = %Q|<tr>\n<td#{nowrap_attribute}><label>#{Preference.human_attribute_name(pref_name)}:</label></td>\n<td>\n|
|
||||
s << yield
|
||||
s << "\n</td></tr>"
|
||||
s
|
||||
|
|
@ -51,12 +30,13 @@
|
|||
table_row(pref_name, nowrap_label) { text_field('prefs', pref_name) }
|
||||
end
|
||||
%>
|
||||
<%= row_with_select_field('locale', I18n.available_locales) %>
|
||||
<%= row_with_text_field('date_format') %>
|
||||
<%= row_with_text_field('title_date_format') %>
|
||||
<%= table_row('time_zone', false) { time_zone_select('prefs','time_zone') } %>
|
||||
|
||||
<%= row_with_select_field("week_starts", Preference.day_number_to_name_map.invert.sort{|a,b| a[1]<=>b[1]})%>
|
||||
<%= row_with_select_field("due_style", [['Due in ___ days',Preference.due_styles[:due_in_n_days]],['Due on _______',Preference.due_styles[:due_on]]]) %>
|
||||
<%= row_with_select_field("week_starts", (0..6).to_a.map {|num| [t('date.day_names')[num], num] }) %>
|
||||
<%= row_with_select_field("due_style", [[t('models.preference.due_styles')[0],Preference.due_styles[:due_in_n_days]],[t('models.preference.due_styles')[1],Preference.due_styles[:due_on]]]) %>
|
||||
<%= row_with_select_field("show_completed_projects_in_sidebar") %>
|
||||
<%= row_with_select_field("show_hidden_projects_in_sidebar") %>
|
||||
<%= row_with_select_field("show_hidden_contexts_in_sidebar") %>
|
||||
|
|
@ -71,8 +51,8 @@
|
|||
<%= row_with_text_field("sms_email") %>
|
||||
<%= table_row("sms_context", false) { select('prefs', 'sms_context_id', current_user.contexts.map{|c| [c.name, c.id]}) } %>
|
||||
|
||||
<tr><td><%= submit_tag "Update" %></td>
|
||||
<td><%= link_to "Cancel", :action => 'index' %></td>
|
||||
<tr><td><%= submit_tag t('common.update') %></td>
|
||||
<td><%= link_to t('common.cancel'), :action => 'index' %></td>
|
||||
</tr>
|
||||
</table>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -1,66 +1,67 @@
|
|||
<div id="single_box" class="container context prefscontainer">
|
||||
|
||||
<h2>Your preferences</h2>
|
||||
<h2><%= t('preferences.title') %></h2>
|
||||
|
||||
<ul id="prefs">
|
||||
<li>First name: <span class="highlight"><%= current_user.first_name %></span></li>
|
||||
<li>Last name: <span class="highlight"><%= current_user.last_name %></span></li>
|
||||
<li>Date format: <span class="highlight"><%= prefs.date_format %></span> Your current date: <%= format_date(current_user.time) %></li>
|
||||
<li>Title date format: <span class="highlight"><%= prefs.title_date_format %></span> Your current title date: <%= current_user.time.strftime(prefs.title_date_format) %></li>
|
||||
<li>Time zone: <span class="highlight"><%= prefs.time_zone %></span> Your current time: <%= current_user.time.strftime('%I:%M %p') %></li>
|
||||
<li>Week starts on: <span class="highlight"><%= Preference.day_number_to_name_map[prefs.week_starts] %></span></li>
|
||||
<li>Show the last <span class="highlight"><%= prefs.show_number_completed %></span> completed items</li>
|
||||
<li>Show completed projects in sidebar: <span class="highlight"><%= prefs.show_completed_projects_in_sidebar %></span></li>
|
||||
<li>Show hidden projects in sidebar: <span class="highlight"><%= prefs.show_hidden_projects_in_sidebar %></span></li>
|
||||
<li>Show hidden contexts in sidebar: <span class="highlight"><%= prefs.show_hidden_contexts_in_sidebar %></span></li>
|
||||
<li>Go to project page on todo complete: <span class="highlight"><%= prefs.show_project_on_todo_done %></span></li>
|
||||
<li>Staleness starts after <span class="highlight"><%= prefs.staleness_starts %></span> days</li>
|
||||
<li>Due style: <span class="highlight">
|
||||
<li><%= User.human_attribute_name('first_name') %>: <span class="highlight"><%= current_user.first_name %></span></li>
|
||||
<li><%= User.human_attribute_name('last_name') %>: <span class="highlight"><%= current_user.last_name %></span></li>
|
||||
<li><%= Preference.human_attribute_name('date_format') %>: <span class="highlight"><%= current_user.prefs.date_format %></span> Your current date: <%= format_date(current_user.time) %></li>
|
||||
<li><%= Preference.human_attribute_name('locale') %>: <span class="highlight"><%= current_user.prefs.locale %></span></li>
|
||||
<li><%= Preference.human_attribute_name('title_date_format') %>: <span class="highlight"><%= current_user.prefs.title_date_format %></span> Your current title date: <%= current_user.time.strftime(current_user.prefs.title_date_format) %></li>
|
||||
<li><%= Preference.human_attribute_name('time_zone') %>: <span class="highlight"><%= current_user.prefs.time_zone %></span> Your current time: <%= current_user.time.strftime('%I:%M %p') %></li>
|
||||
<li><%= Preference.human_attribute_name('week_starts') %>: <span class="highlight"><%= t('date.day_names')[current_user.prefs.week_starts] %></span></li>
|
||||
<li><%= t('preferences.show_number_completed', :number=> "<span class=\"highlight\">#{current_user.prefs.show_number_completed}</span>")%></li>
|
||||
<li><%= Preference.human_attribute_name('show_completed_projects_in_sidebar') %>: <span class="highlight"><%= current_user.prefs.show_completed_projects_in_sidebar %></span></li>
|
||||
<li><%= Preference.human_attribute_name('show_hidden_projects_in_sidebar') %>: <span class="highlight"><%= current_user.prefs.show_hidden_projects_in_sidebar %></span></li>
|
||||
<li><%= Preference.human_attribute_name('show_hidden_contexts_in_sidebar') %>: <span class="highlight"><%= current_user.prefs.show_hidden_contexts_in_sidebar %></span></li>
|
||||
<li><%= Preference.human_attribute_name('show_project_on_todo_done') %>: <span class="highlight"><%= current_user.prefs.show_project_on_todo_done %></span></li>
|
||||
<li><%= t('preferences.staleness_starts_after', :days => "<span class=\"highlight\">#{current_user.prefs.staleness_starts}</span>") %></li>
|
||||
<li><%= Preference.human_attribute_name('due_style') %>: <span class="highlight">
|
||||
<% if prefs.due_style == Preference.due_styles[:due_in_n_days] %>
|
||||
Due in ___ days
|
||||
<%= t('models.preference.due_styles')[0] %>
|
||||
<% else %>
|
||||
Due on ________
|
||||
<%= t('models.preference.due_styles')[1] %>
|
||||
<% end %>
|
||||
</span></li>
|
||||
<% if current_user.is_admin? %>
|
||||
<li>Admin email: <span class="highlight"><%= prefs.admin_email %></span></li>
|
||||
<li><%= Preference.human_attribute_name('admin_email') %>: <span class="highlight"><%= current_user.prefs.admin_email %></span></li>
|
||||
<% end %>
|
||||
<li>Refresh interval (in minutes): <span class="highlight"><%= prefs.refresh %></span></li>
|
||||
<li>Verbose action descriptors: <span class="highlight"><%= prefs.verbose_action_descriptors %></span></li>
|
||||
<li>Actions per page (Mobile View): <span class="highlight"><%= prefs.mobile_todos_per_page %></span></li>
|
||||
<li>From email: <span class="highlight"><%= prefs.sms_email %></span></li>
|
||||
<li>Default email context: <span class="highlight"><%= prefs.sms_context.nil? ? "None" : prefs.sms_context.name %></span></li>
|
||||
<li><%= Preference.human_attribute_name('refresh') %>: <span class="highlight"><%= current_user.prefs.refresh %></span></li>
|
||||
<li><%= Preference.human_attribute_name('verbose_action_descriptors') %>: <span class="highlight"><%= current_user.prefs.verbose_action_descriptors %></span></li>
|
||||
<li><%= Preference.human_attribute_name('mobile_todos_per_page') %>: <span class="highlight"><%= current_user.prefs.mobile_todos_per_page %></span></li>
|
||||
<li><%= Preference.human_attribute_name('sms_email') %>: <span class="highlight"><%= current_user.prefs.sms_email %></span></li>
|
||||
<li><%= Preference.human_attribute_name('sms_context') %>: <span class="highlight"><%= current_user.prefs.sms_context.nil? ? t('preferences.sms_context_none') : current_user.prefs.sms_context.name %></span></li>
|
||||
</ul>
|
||||
<div class="actions">
|
||||
<%= link_to "Edit preferences »", { :controller => 'preferences', :action => 'edit'}, :class => 'edit_link' %>
|
||||
<%= link_to t('preferences.edit_preferences') + " »", { :controller => 'preferences', :action => 'edit'}, :class => 'edit_link' %>
|
||||
</div>
|
||||
|
||||
<h2>Your token</h2>
|
||||
<h2><%= t('preferences.token_header') %></h2>
|
||||
<div id="token_area">
|
||||
<div class="description">Token (for feeds and API use):</div>
|
||||
<div id="token><span class="highlight"><%= current_user.token %></span></div>
|
||||
<div class="description"><%= t('preferences.token_description') %>:</div>
|
||||
<div id="token"><span class="highlight"><%= current_user.token %></span></div>
|
||||
<div class="token_regenerate">
|
||||
<%= button_to "Generate a new token", refresh_token_user_path(current_user),
|
||||
:confirm => "Are you sure? Generating a new token will replace the existing one and break any external usages of this token." %>
|
||||
<%= button_to t('preferences.generate_new_token'), refresh_token_user_path(current_user),
|
||||
:confirm => t('preferences.generate_new_token_confirm') %>
|
||||
</div>
|
||||
</div>
|
||||
<h2>Your authentication</h2>
|
||||
<h2><%= t('preferences.authentication_header') %></h2>
|
||||
<div id="authentication_area">
|
||||
<% if Tracks::Config.auth_schemes.length > 1 %>
|
||||
<p>Your authentication type is <span class="highlight"><%= current_user.auth_type %></span>.
|
||||
<p><%= t('preferences.current_authentication_type', :auth_type => "<span class=\"highlight\">#{current_user.auth_type}</span>") %>.</p>
|
||||
<div class="actions">
|
||||
<%= link_to "Change your authentication type »", change_auth_type_user_path(current_user), :class => 'edit_link' %>
|
||||
<%= link_to(t('preferences.change_authentication_type') + " »", change_auth_type_user_path(current_user), :class => 'edit_link') %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if current_user.auth_type == 'database' %>
|
||||
<div class="actions">
|
||||
<%= link_to 'Change your password »', change_password_user_path(current_user) %>
|
||||
<%= link_to(t('preferences.change_password') + ' »', change_password_user_path(current_user)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
<% if current_user.auth_type == 'open_id' %>
|
||||
<p>Your Open ID URL is <span class="highlight"><%= current_user.open_id_url %></span>.
|
||||
<p><%= t('preferences.open_id_url') %> <span class="highlight"><%= current_user.open_id_url %></span>.</p>
|
||||
<div class="actions">
|
||||
<%= link_to 'Change Your Identity URL »', change_auth_type_user_path(current_user) %></p>
|
||||
<%= link_to(t('preferences.change_identity_url') + ' »', change_auth_type_user_path(current_user)) %>
|
||||
</div>
|
||||
<% end %>
|
||||
</div>
|
||||
|
|
|
|||
40
app/views/projects/_new_project_form.rhtml
Normal file
40
app/views/projects/_new_project_form.rhtml
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
<div id="project_new_project_container">
|
||||
|
||||
<div id="toggle_project_link" class="hide_form">
|
||||
<a id="toggle_project_new" href="#" title="<%= t('projects.hide_form_title') %>" accesskey="n">« <%= t('projects.hide_form') %></a>
|
||||
</div>
|
||||
|
||||
<div id="project_new" class="project_new" style="display:block">
|
||||
<% form_for(@new_project, :html => {:id => 'project_form',:name=>'project',:class => "inline-form", :method => :post }) do -%>
|
||||
<div id="error_status"><%= error_messages_for("project") %></div>
|
||||
|
||||
<label for="project_name"><%= Project.human_attribute_name(:name) %>:</label><br />
|
||||
<%= text_field 'project', 'name', "tabindex" => 1 %><br />
|
||||
|
||||
<label for="project_description"><%= Project.human_attribute_name(:description) %> (<%= t('common.optional') %>):</label><br />
|
||||
<%= text_area 'project', 'description', "cols" => 30, "rows" => 4, "tabindex" => 2 %><br />
|
||||
|
||||
<% unless @contexts.empty? -%>
|
||||
<label for="default_context_name"><%= Project.human_attribute_name(:default_context_name) %> (<%= t('common.optional') %>):</label><br />
|
||||
<%= text_field_tag("project[default_context_name]", @new_project.default_context.name, :tabindex => 3) %>
|
||||
<br />
|
||||
<% end -%>
|
||||
|
||||
<label for="default_tags"><%= Project.human_attribute_name(:default_tags) %> (<%= t('common.optional') %>):</label><br />
|
||||
<%= text_field_tag("project[default_tags]", @new_project.default_tags, :tabindex => 4) %>
|
||||
|
||||
<br/>
|
||||
|
||||
<div class="submit_box">
|
||||
<div class="widgets">
|
||||
<button type="submit" class="positive" id="project_new_project_submit">
|
||||
<%= image_tag("accept.png", :alt => "") + t('projects.add_project') %>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input id="go_to_project" type="checkbox" tabindex="5" name="go_to_project"/><label for="go_to_project"><%= t('projects.to_new_project_page') %></label><br />
|
||||
|
||||
<% end -%>
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
<% end -%>
|
||||
<%= project.name -%></h2>
|
||||
<div id="<%= dom_id(project, "container")%>">
|
||||
<%= render :partial => "projects/project_settings", :locals => { :project => project, :collapsible => collapsible } %>
|
||||
<%= render :partial => "projects/project_settings", :object => project, :locals => { :collapsible => collapsible } %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -2,8 +2,12 @@
|
|||
project = project_form
|
||||
%>
|
||||
|
||||
<% form_remote_tag(:url => project_path(project), :html => { :id => dom_id(project, 'edit_form'), :class => "inline-form "+dom_id(project, 'edit_form')+"-edit-project-form", :method => :put }) do -%>
|
||||
<div id="error_status"><%= error_messages_for("project") %></div>
|
||||
<% form_for(project, :html => {
|
||||
:id => dom_id(project, 'edit_form'),
|
||||
:class => "inline-form edit-project-form",
|
||||
:method => :put }) do
|
||||
-%>
|
||||
<div id="edit_error_status"><%= error_messages_for("project") %></div>
|
||||
<%= source_view_tag( @source_view ) -%>
|
||||
|
||||
<label for="project_name">Name:</label><br/>
|
||||
|
|
@ -39,6 +43,6 @@ project = project_form
|
|||
</div>
|
||||
</div>
|
||||
<br/><br/>
|
||||
|
||||
<% end -%>
|
||||
|
||||
<%
|
||||
end
|
||||
-%>
|
||||
|
|
@ -1,40 +1,27 @@
|
|||
<% project = project_listing
|
||||
<%
|
||||
project = project_listing
|
||||
suppress_drag_handle ||= false
|
||||
suppress_edit_button ||= false
|
||||
-%>
|
||||
<div id="<%= dom_id(project, "container") %>" class="list">
|
||||
<div id="<%= dom_id(project) %>" class="project sortable_row" style="display:''">
|
||||
<div id="<%= dom_id(project) %>" class="project sortable_row" style="display:block">
|
||||
|
||||
<% unless suppress_drag_handle -%>
|
||||
<div class="position">
|
||||
<span class="handle">DRAG</span>
|
||||
<span class="handle"><%= t('common.drag_handle') %></span>
|
||||
</div>
|
||||
<% end -%>
|
||||
|
||||
<div class="data">
|
||||
<%= link_to_project( project ) %><%= " (" + count_undone_todos_and_notes_phrase(project,"actions") + ")" %>
|
||||
</div>
|
||||
|
||||
<div class="buttons">
|
||||
<span class="grey"><%= project.current_state.to_s.upcase %></span>
|
||||
<a class="delete_project_button"
|
||||
href="<%= project_path(project, :format => 'js') %>"
|
||||
title="delete the project '<%= project.name %>'"><%= image_tag( "blank.png",
|
||||
:title => "Delete project",
|
||||
:class=>"delete_item") %></a>
|
||||
|
||||
<% unless suppress_edit_button -%>
|
||||
<%= link_to_remote(
|
||||
image_tag( "blank.png", :title => "Edit project", :class=>"edit_item"),
|
||||
:url => {:controller => 'projects', :action => 'edit', :id => project.id},
|
||||
:method => 'get',
|
||||
:with => "'_source_view=#{@source_view}'",
|
||||
:before => "$('#{dom_id(project)}').block({message:null});",
|
||||
:complete => "$('#{dom_id(project)}').unblock();enable_rich_interaction();",
|
||||
:html => {:id => "link_edit_#{dom_id(project)}"}
|
||||
) %>
|
||||
|
||||
<% end -%>
|
||||
<%= link_to_delete_project(project, image_tag( "blank.png", :title => t('projects.delete_project_title'), :class=>"delete_item")) %>
|
||||
<%= suppress_edit_button ? "" : link_to_edit_project(project, image_tag( "blank.png", :title => t('projects.edit_project_title'), :class=>"edit_item")) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(project, 'edit') %>" class="edit-form" style="display:none;">
|
||||
</div>
|
||||
<div id="<%= dom_id(project, 'edit') %>" class="edit-form" style="display:none;"></div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
<% project = project_settings -%>
|
||||
<div id="<%= dom_id(project) %>" class="project">
|
||||
<div class="project_settings">This project
|
||||
<% if project.completed? -%>has been marked as completed
|
||||
|
|
@ -14,15 +15,7 @@
|
|||
<% else -%>
|
||||
'<%= project.default_tags -%>' as the default tags.
|
||||
<% end -%>
|
||||
<%= link_to_remote(
|
||||
"Edit Project Settings",
|
||||
:url => {:controller => 'projects', :action => 'edit', :id => project.id},
|
||||
:method => 'get',
|
||||
:with => "'_source_view=#{@source_view}'",
|
||||
:before => "$('#{dom_id(project)}').block({message: null});",
|
||||
:complete => "$('#{dom_id(project)}').unblock();enable_rich_interaction();",
|
||||
:html => {:id => "link_edit_#{dom_id(project)}"}
|
||||
) %>
|
||||
<%= link_to_edit_project(project, "Edit Project Settings") %>
|
||||
</div>
|
||||
<% unless project.description.blank? -%>
|
||||
<div class="project_description"><%= format_note(project.description) %></div>
|
||||
|
|
|
|||
|
|
@ -1,12 +1,12 @@
|
|||
<div class="project-state-group" id="list-<%= state %>-projects-container" <%= " style=\"display:none\"" if project_state_group.empty? %>>
|
||||
<h2><span id="<%= state %>-projects-count" class="badge"><%= project_state_group.length %></span><%= state.titlecase %> Projects</h2>
|
||||
<div class="menu_sort"><span class="sort_separator">Sort </span>
|
||||
<h2><span id="<%= state %>-projects-count" class="badge"><%= project_state_group.length %></span><%= t('states.'+state+'_plural' )%> <%= t('common.projects') %></h2>
|
||||
<div class="menu_sort"><span class="sort_separator"><%= t('common.sort.sort') %> </span>
|
||||
<div class="alpha_sort">
|
||||
<%= link_to("Alphabetically", alphabetize_projects_path(:state => state),
|
||||
:class => "alphabetize_link", :title => "Sort these projects alphabetically") %>
|
||||
:id => "#{state}_alphabetize_link", :class => "alphabetize_link", :title => t('common.sort.alphabetically_title'), :x_confirm_message => t('common.sort.alphabetically_confirm')) %>
|
||||
</div><span class="sort_separator"> | </span><div class="tasks_sort">
|
||||
<%= link_to("By number of tasks", actionize_projects_path(:state => state),
|
||||
:class => "actionize_link", :title => "Sort these projects by number of tasks") %>
|
||||
:id => "#{state}_actionize_link", :class => "actionize_link", :title => t('common.sort.by_task_count_title'), :x_confirm_message => t('common.sort.by_task_count_title_confirm')) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
2
app/views/projects/actionize.js.erb
Normal file
2
app/views/projects/actionize.js.erb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
new_html = "<%= escape_javascript(render(:partial => 'project_listing', :collection => @projects)) %>";
|
||||
$("#list-<%=@state%>-projects").html(new_html);
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
list_id = "list-#{@state}-projects"
|
||||
page.replace_html list_id,
|
||||
:partial => 'project_listing',
|
||||
:collection => @projects
|
||||
page.sortable list_id, get_listing_sortable_options(list_id)
|
||||
|
||||
2
app/views/projects/alphabetize.js.erb
Normal file
2
app/views/projects/alphabetize.js.erb
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
new_html = "<%= escape_javascript(render(:partial => 'project_listing', :collection => @projects)) %>";
|
||||
$("#list-<%=@state%>-projects").html(new_html);
|
||||
|
|
@ -1,6 +0,0 @@
|
|||
list_id = "list-#{@state}-projects"
|
||||
page.replace_html list_id,
|
||||
:partial => 'project_listing',
|
||||
:collection => @projects
|
||||
page.sortable list_id, get_listing_sortable_options(list_id)
|
||||
|
||||
45
app/views/projects/create.js.erb
Normal file
45
app/views/projects/create.js.erb
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
<% if @saved -%>
|
||||
<% if @go_to_project -%>
|
||||
redirect_to("<%= project_path(@project) -%>")
|
||||
<% else -%>
|
||||
TracksPages.hide_errors();
|
||||
hide_empty_message();
|
||||
TracksPages.set_page_badge(<%= @down_count %>);
|
||||
update_active_projects_container();
|
||||
add_project();
|
||||
clear_form();
|
||||
TracksPages.page_notify('notice', "Created new project '<%= @project.name%>'", 5);
|
||||
<% end -%>
|
||||
<% else -%>
|
||||
TracksPages.show_errors(html_for_error_messages());
|
||||
<% end -%>
|
||||
|
||||
/* TODO: make this generic for all pages with lists */
|
||||
function hide_empty_message() {
|
||||
$('projects-empty-nd').hide();
|
||||
}
|
||||
|
||||
/* TODO: refactor and move this to application.js */
|
||||
function add_project() {
|
||||
$('#list-active-projects').append(html_for_project_listing());
|
||||
}
|
||||
|
||||
/* TODO: refactor and move this to application.js */
|
||||
function clear_form() {
|
||||
$('#project_form').clearForm();
|
||||
$('#project_form input:text:first').focus();
|
||||
}
|
||||
|
||||
/* TODO: refactor and move this to application.js */
|
||||
function update_active_projects_container() {
|
||||
ProjectListPage.set_state_container_visibility('active', true);
|
||||
ProjectListPage.update_state_count('active', <%=@active_projects_count%>);
|
||||
}
|
||||
|
||||
function html_for_error_messages() {
|
||||
return "<%= escape_javascript(error_messages_for('project')) %>";
|
||||
}
|
||||
|
||||
function html_for_project_listing() {
|
||||
return "<%= @saved ? escape_javascript(render(:partial => 'project_listing', :object => @project)) : "" %>";
|
||||
}
|
||||
|
|
@ -1,17 +0,0 @@
|
|||
if @saved and @go_to_project
|
||||
page.redirect_to project_path(@project)
|
||||
elsif @saved
|
||||
page.hide 'status'
|
||||
page['badge_count'].replace_html @down_count
|
||||
page.hide 'projects-empty-nd'
|
||||
page.show 'list-active-projects-container'
|
||||
page.replace_html "active-projects-count", @active_projects_count
|
||||
page.insert_html :bottom, "list-active-projects", :partial => 'project_listing', :locals => { :project_listing => @project }
|
||||
page.sortable "list-active-projects", get_listing_sortable_options('list-active-projects')
|
||||
page << "$('#project-form').clearForm();"
|
||||
page << "$('#project-form input:text:first').focus();"
|
||||
else
|
||||
page.show 'status'
|
||||
page.replace_html 'status', "#{error_messages_for('project')}"
|
||||
end
|
||||
page.hide "busy"
|
||||
13
app/views/projects/destroy.js.erb
Normal file
13
app/views/projects/destroy.js.erb
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
remove_deleted_project();
|
||||
ProjectListPage.update_all_states_count(<%=@active_projects_count%>, <%=@hidden_projects_count%>, <%=@completed_projects_count%>)
|
||||
ProjectListPage.show_or_hide_all_state_containers(<%= @show_active_projects %>, <%= @show_hidden_projects %>, <%= @show_completed_projects %>);
|
||||
TracksPages.page_notify('notice', "Deleted project '<%= @project.name%>'", 5);
|
||||
TracksPages.set_page_badge(<%=@down_count%>);
|
||||
|
||||
/* TODO: refactor and move function to application.js */
|
||||
function remove_deleted_project() {
|
||||
$('div#<%=dom_id(@project, "container")%>').slideUp(1000,
|
||||
function() {
|
||||
$('div#<%=dom_id(@project, "container")%>').remove();
|
||||
});
|
||||
}
|
||||
|
|
@ -1,13 +0,0 @@
|
|||
page.visual_effect :fade, dom_id(@project, "container"), :duration => 0.5
|
||||
page.delay(0.5) do
|
||||
page[dom_id(@project, "container")].remove
|
||||
page.replace_html "active-projects-count", @active_projects_count
|
||||
page.replace_html "hidden-projects-count", @hidden_projects_count
|
||||
page.replace_html "completed-projects-count", @completed_projects_count
|
||||
page.set_element_visible("list-hidden-projects-container", @hidden_projects_count > 0)
|
||||
page.set_element_visible("list-active-projects-container", @active_projects_count > 0)
|
||||
page.set_element_visible("list-completed-projects-container", @completed_projects_count > 0)
|
||||
end
|
||||
page.notify :notice, "Deleted project '#{@project.name}'", 5.0
|
||||
page['badge_count'].replace_html @down_count
|
||||
page.hide "busy"
|
||||
21
app/views/projects/edit.js.erb
Normal file
21
app/views/projects/edit.js.erb
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
replace_project_with_edit_form();
|
||||
|
||||
function replace_project_with_edit_form() {
|
||||
$('div#<%=dom_id(@project)%>').fadeOut(250, function() {
|
||||
show_edit_form();
|
||||
set_focus();
|
||||
});
|
||||
}
|
||||
|
||||
function show_edit_form() {
|
||||
$('div#<%=dom_id(@project, 'edit')%>').html(html_for_edit_form());
|
||||
$('div#<%=dom_id(@project, 'edit')%>').fadeIn(500);
|
||||
}
|
||||
|
||||
function set_focus() {
|
||||
$('input.project-name').focus();
|
||||
}
|
||||
|
||||
function html_for_edit_form() {
|
||||
return "<%= escape_javascript(render(:partial => 'project_form', :object => @project)) %>"
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue