mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-16 07:10:12 +01:00
Code style fixes
This commit is contained in:
parent
c6bbc67dab
commit
d8acf60049
72 changed files with 458 additions and 594 deletions
|
|
@ -1,6 +1,18 @@
|
|||
engines:
|
||||
brakeman:
|
||||
enabled: true
|
||||
fixme:
|
||||
enabled: true
|
||||
flog:
|
||||
enabled: true
|
||||
reek:
|
||||
enabled: true
|
||||
rubocop:
|
||||
enabled: true
|
||||
checks:
|
||||
Rubocop/Style/StringLiterals:
|
||||
enabled: false
|
||||
Rubocop/Style/TrailingCommaInLiteral:
|
||||
enabled: false
|
||||
Rubocop/Style/HashSyntax:
|
||||
enabled: false
|
||||
|
|
|
|||
|
|
@ -60,7 +60,6 @@ class ApplicationController < ActionController::Base
|
|||
# Returns a count of next actions in the given context or project The result
|
||||
# is count and a string descriptor, correctly pluralised if there are no
|
||||
# actions or multiple actions
|
||||
#
|
||||
def count_undone_todos_phrase(todos_parent)
|
||||
count = count_undone_todos(todos_parent)
|
||||
deferred_count = count_deferred_todos(todos_parent)
|
||||
|
|
@ -83,13 +82,13 @@ class ApplicationController < ActionController::Base
|
|||
init_hidden_todo_counts(['context']) if !@context_hidden_todo_counts
|
||||
count = @context_hidden_todo_counts[todos_parent.id]
|
||||
else
|
||||
count = eval "@#{todos_parent.class.to_s.downcase}_not_done_counts[#{todos_parent.id}]"
|
||||
count = eval("@#{todos_parent.class.to_s.downcase}_not_done_counts[#{todos_parent.id}]", binding, __FILE__, __LINE__)
|
||||
end
|
||||
count || 0
|
||||
end
|
||||
|
||||
def count_deferred_todos(todos_parent)
|
||||
return todos_parent.nil? ? 0 : eval("@#{todos_parent.class.to_s.downcase}_deferred_counts[#{todos_parent.id}]") || 0
|
||||
return todos_parent.nil? ? 0 : eval("@#{todos_parent.class.to_s.downcase}_deferred_counts[#{todos_parent.id}]", binding, __FILE__, __LINE__) || 0
|
||||
end
|
||||
|
||||
# Convert a date object to the format specified in the user's preferences in
|
||||
|
|
@ -101,8 +100,8 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def for_autocomplete(coll, substr)
|
||||
if substr # protect agains empty request
|
||||
filtered = coll.find_all{|item| item.name.downcase.include? substr.downcase}
|
||||
json_elems = Array[*filtered.map{ |e| {:id => e.id.to_s, :value => e.name} }].to_json
|
||||
filtered = coll.find_all{ |item| item.name.downcase.include? substr.downcase }
|
||||
json_elems = Array[*filtered.map{ |e| { :id => e.id.to_s, :value => e.name } }].to_json
|
||||
return json_elems
|
||||
else
|
||||
return ""
|
||||
|
|
@ -110,7 +109,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def format_dependencies_as_json_for_auto_complete(entries)
|
||||
json_elems = Array[*entries.map{ |e| {:value => e.id.to_s, :label => e.specification} }].to_json
|
||||
json_elems = Array[*entries.map{ |e| { :value => e.id.to_s, :label => e.specification } }].to_json
|
||||
return json_elems
|
||||
end
|
||||
|
||||
|
|
@ -138,7 +137,7 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
|
||||
def handle_unverified_request
|
||||
unless request.format=="application/xml"
|
||||
unless request.format == "application/xml"
|
||||
super # handle xml http auth via our own login code
|
||||
end
|
||||
end
|
||||
|
|
@ -204,7 +203,7 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
private
|
||||
|
||||
def parse_date_per_user_prefs( s )
|
||||
def parse_date_per_user_prefs(s)
|
||||
prefs.parse_date(s)
|
||||
end
|
||||
|
||||
|
|
@ -220,16 +219,16 @@ class ApplicationController < ActionController::Base
|
|||
end
|
||||
end
|
||||
|
||||
def init_not_done_counts(parents = ['project','context'])
|
||||
def init_not_done_counts(parents=['project', 'context'])
|
||||
parents.each do |parent|
|
||||
eval("@#{parent}_not_done_counts ||= current_user.todos.active.count_by_group('#{parent}_id')")
|
||||
eval("@#{parent}_deferred_counts ||= current_user.todos.deferred.count_by_group('#{parent}_id')")
|
||||
eval("@#{parent}_not_done_counts ||= current_user.todos.active.count_by_group('#{parent}_id')", binding, __FILE__, __LINE__)
|
||||
eval("@#{parent}_deferred_counts ||= current_user.todos.deferred.count_by_group('#{parent}_id')", binding, __FILE__, __LINE__)
|
||||
end
|
||||
end
|
||||
|
||||
def init_hidden_todo_counts(parents = ['project', 'context'])
|
||||
def init_hidden_todo_counts(parents=['project', 'context'])
|
||||
parents.each do |parent|
|
||||
eval("@#{parent}_hidden_todo_counts ||= current_user.todos.active_or_hidden.count_by_group('#{parent}_id')")
|
||||
eval("@#{parent}_hidden_todo_counts ||= current_user.todos.active_or_hidden.count_by_group('#{parent}_id')", binding, __FILE__, __LINE__)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -252,9 +251,9 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
def todo_xml_params
|
||||
if params[:limit_fields] == 'index'
|
||||
return [:only => [:id, :created_at, :updated_at, :completed_at] ]
|
||||
return [:only => [:id, :created_at, :updated_at, :completed_at]]
|
||||
else
|
||||
return [:except => :user_id, :include => [:tags, :predecessors, :successors] ]
|
||||
return [:except => :user_id, :include => [:tags, :predecessors, :successors]]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -263,8 +262,8 @@ class ApplicationController < ActionController::Base
|
|||
@source_view = "all_done"
|
||||
@page_title = t("#{object_name.pluralize}.all_completed_tasks_title", "#{object_name}_name".to_sym => object.name)
|
||||
|
||||
@done = object.todos.completed.reorder('completed_at DESC').includes(Todo::DEFAULT_INCLUDES).
|
||||
paginate(:page => params[:page], :per_page => 20)
|
||||
@done = object.todos.completed.reorder('completed_at DESC').includes(Todo::DEFAULT_INCLUDES)
|
||||
.paginate(:page => params[:page], :per_page => 20)
|
||||
@count = @done.size
|
||||
render :template => 'todos/all_done'
|
||||
end
|
||||
|
|
@ -284,5 +283,4 @@ class ApplicationController < ActionController::Base
|
|||
def set_group_view_by
|
||||
@group_view_by = params['_group_view_by'] || cookies['group_view_by'] || 'context'
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,13 +14,13 @@ class CalendarController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html
|
||||
format.m {
|
||||
cookies[:mobile_url]= {:value => request.fullpath, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url]= { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
}
|
||||
format.ics {
|
||||
render :action => 'show', :layout => false, :content_type => Mime[:ics]
|
||||
}
|
||||
format.xml {
|
||||
render :xml => @due_all.to_xml( *[todo_xml_params[0].merge({:root => :todos})] )
|
||||
render :xml => @due_all.to_xml( *[todo_xml_params[0].merge({ :root => :todos })] )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class ContextsController < ApplicationController
|
||||
|
||||
helper :todos
|
||||
|
||||
before_action :init, :except => [:index, :create, :destroy, :order]
|
||||
|
|
@ -19,15 +18,15 @@ class ContextsController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html &render_contexts_html
|
||||
format.m &render_contexts_mobile
|
||||
format.xml { render :xml => @all_contexts.to_xml(:root => :contexts, :except => :user_id) }
|
||||
format.m &render_contexts_mobile
|
||||
format.xml { render :xml => @all_contexts.to_xml(:root => :contexts, :except => :user_id) }
|
||||
format.any(:rss, :atom) do
|
||||
@feed_title = 'Tracks Contexts'
|
||||
@feed_description = "Lists all the contexts for #{current_user.display_name}"
|
||||
end
|
||||
format.text do
|
||||
# somehow passing Mime[:text] using content_type to render does not work
|
||||
headers['Content-Type']=Mime[:text].to_s
|
||||
headers['Content-Type'] = Mime[:text].to_s
|
||||
render :action => 'index', :layout => false, :content_type => Mime[:text]
|
||||
end
|
||||
format.autocomplete &render_autocomplete
|
||||
|
|
@ -41,7 +40,7 @@ class ContextsController < ApplicationController
|
|||
@max_completed = current_user.prefs.show_number_completed
|
||||
@done = @context.todos.completed.limit(@max_completed).reorder(Arel.sql("todos.completed_at DESC, todos.created_at DESC")).includes(Todo::DEFAULT_INCLUDES)
|
||||
@not_done_todos = @context.todos.active_or_hidden.not_project_hidden.reorder(Arel.sql('todos.due IS NULL, todos.due ASC, todos.created_at ASC')).includes(Todo::DEFAULT_INCLUDES)
|
||||
@todos_without_project = @not_done_todos.select{|t| t.project.nil?}
|
||||
@todos_without_project = @not_done_todos.select{ |t| t.project.nil? }
|
||||
|
||||
@deferred_todos = @context.todos.deferred.includes(Todo::DEFAULT_INCLUDES)
|
||||
@pending_todos = @context.todos.pending.includes(Todo::DEFAULT_INCLUDES)
|
||||
|
|
@ -93,7 +92,6 @@ class ContextsController < ApplicationController
|
|||
end
|
||||
|
||||
# Edit the details of the context
|
||||
#
|
||||
def update
|
||||
process_params_for_update
|
||||
|
||||
|
|
@ -113,12 +111,12 @@ class ContextsController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.js
|
||||
format.xml {
|
||||
if @saved
|
||||
render :xml => @context.to_xml( :except => :user_id )
|
||||
else
|
||||
render :body => "Error on update: #{@context.errors.full_messages.inject("") {|v, e| v + e + " " }}", :status => 409
|
||||
end
|
||||
}
|
||||
if @saved
|
||||
render :xml => @context.to_xml(:except => :user_id)
|
||||
else
|
||||
render :body => "Error on update: #{@context.errors.full_messages.inject("") { |v, e| v + e + " " }}", :status => 409
|
||||
end
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -204,7 +202,7 @@ class ContextsController < ApplicationController
|
|||
@active_contexts = current_user.contexts.active
|
||||
@hidden_contexts = current_user.contexts.hidden
|
||||
@down_count = @active_contexts.size + @hidden_contexts.size
|
||||
cookies[:mobile_url]= {:value => request.fullpath, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url]= { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
render
|
||||
end
|
||||
end
|
||||
|
|
@ -214,7 +212,7 @@ class ContextsController < ApplicationController
|
|||
@page_title = "TRACKS::List actions in "+@context.name
|
||||
@not_done = @not_done_todos.select {|t| t.context_id == @context.id }
|
||||
@down_count = @not_done.size
|
||||
cookies[:mobile_url]= {:value => request.fullpath, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url]= { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
@mobile_from_context = @context.id
|
||||
render
|
||||
end
|
||||
|
|
@ -270,5 +268,4 @@ class ContextsController < ApplicationController
|
|||
return false
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class DataController < ApplicationController
|
||||
|
||||
require 'csv'
|
||||
|
||||
def index
|
||||
|
|
@ -7,7 +6,6 @@ class DataController < ApplicationController
|
|||
end
|
||||
|
||||
def import
|
||||
|
||||
end
|
||||
|
||||
def csv_map
|
||||
|
|
@ -147,8 +145,7 @@ class DataController < ApplicationController
|
|||
def csv_notes
|
||||
content_type = 'text/csv'
|
||||
CSV.generate(result = "") do |csv|
|
||||
csv << ["id", "User ID", "Project", "Note",
|
||||
"Created at", "Updated at"]
|
||||
csv << ["id", "User ID", "Project", "Note", "Created at", "Updated at"]
|
||||
# had to remove project include because it's association order is leaking
|
||||
# through and causing an ambiguous column ref even with_exclusive_scope
|
||||
# didn't seem to help -JamesKebinger
|
||||
|
|
@ -198,7 +195,7 @@ class DataController < ApplicationController
|
|||
|
||||
# adjusts time to utc
|
||||
def adjust_time(timestring)
|
||||
if (timestring=='') or ( timestring == nil)
|
||||
if (timestring == '') or (timestring == nil)
|
||||
return nil
|
||||
else
|
||||
return Time.parse(timestring + 'UTC')
|
||||
|
|
@ -210,8 +207,8 @@ class DataController < ApplicationController
|
|||
end
|
||||
|
||||
private
|
||||
|
||||
def sanitize_filename(filename)
|
||||
filename.gsub(/[^0-9A-z.\-]/, '_')
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class FeedlistController < ApplicationController
|
||||
|
||||
helper :feedlist
|
||||
|
||||
def index
|
||||
|
|
@ -37,9 +36,8 @@ class FeedlistController < ApplicationController
|
|||
|
||||
def get_feeds_for(object)
|
||||
respond_to do |format|
|
||||
format.html { render :file => "feedlist/get_feeds_for_#{object.class.name.downcase}"}
|
||||
format.html { render :file => "feedlist/get_feeds_for_#{object.class.name.downcase}" }
|
||||
format.js
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -59,6 +59,4 @@ class IntegrationsController < ApplicationController
|
|||
|
||||
return result
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class LoginController < ApplicationController
|
|||
end
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.m { render :action => 'login', :layout => 'mobile' }
|
||||
format.m { render :action => 'login', :layout => 'mobile' }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -44,7 +44,7 @@ class LoginController < ApplicationController
|
|||
return unless should_expire_sessions?
|
||||
# Get expiry time (allow ten seconds window for the case where we have none)
|
||||
time_left = expiry_time - Time.now
|
||||
@session_expired = ( time_left < (10*60) ) # Session will time out before the next check
|
||||
@session_expired = ( time_left < (10 * 60) ) # Session will time out before the next check
|
||||
end
|
||||
end
|
||||
respond_to do |format|
|
||||
|
|
@ -54,25 +54,25 @@ class LoginController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def handle_post_success
|
||||
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
|
||||
def handle_post_success
|
||||
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
|
||||
end
|
||||
|
||||
def handle_post_failure
|
||||
@login = params['user_login']
|
||||
notify :warning, t('login.unsuccessful')
|
||||
end
|
||||
def handle_post_failure
|
||||
@login = params['user_login']
|
||||
notify :warning, t('login.unsuccessful')
|
||||
end
|
||||
|
||||
def should_expire_sessions?
|
||||
session['noexpiry'] != "on"
|
||||
|
|
@ -82,5 +82,4 @@ class LoginController < ApplicationController
|
|||
return Time.now + 10 unless session['expiry_time']
|
||||
DateTime.strptime(session['expiry_time'], "%FT%T.%L%Z")
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
require 'openssl'
|
||||
|
||||
class MailgunController < ApplicationController
|
||||
|
||||
skip_before_action :login_required, :only => [:mailgun]
|
||||
before_action :verify, :only => [:mailgun]
|
||||
protect_from_forgery with: :null_session
|
||||
|
|
@ -34,5 +33,4 @@ class MailgunController < ApplicationController
|
|||
return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class NotesController < ApplicationController
|
||||
|
||||
before_action :set_source_view
|
||||
|
||||
def index
|
||||
|
|
@ -9,7 +8,7 @@ class NotesController < ApplicationController
|
|||
@source_view = 'note_list'
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.xml { render :xml => @all_notes.to_xml(:root => :notes, :except => :user_id ) }
|
||||
format.xml { render :xml => @all_notes.to_xml(:root => :notes, :except => :user_id) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -75,5 +74,4 @@ class NotesController < ApplicationController
|
|||
def note_params
|
||||
params.require(:note).permit(:project_id, :body)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class PreferencesController < ApplicationController
|
||||
|
||||
def index
|
||||
@page_title = t('preferences.page_title')
|
||||
@prefs = current_user.prefs
|
||||
|
|
@ -31,7 +30,7 @@ class PreferencesController < ApplicationController
|
|||
render :body => l(Date.current, :format => format)
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def prefs_params
|
||||
params.require(:prefs).permit(
|
||||
|
|
@ -52,5 +51,4 @@ private
|
|||
notify :notice, t('preferences.updated')
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class ProjectsController < ApplicationController
|
||||
|
||||
helper :application, :todos, :notes
|
||||
before_action :set_source_view
|
||||
before_action :set_project_from_params, :only => [:update, :destroy, :show, :edit, :set_reviewed]
|
||||
|
|
@ -16,14 +15,14 @@ class ProjectsController < ApplicationController
|
|||
init_not_done_counts(['project'])
|
||||
init_hidden_todo_counts(['project'])
|
||||
if params[:only_active_with_no_next_actions]
|
||||
@projects = current_user.projects.active.select { |p| count_undone_todos(p) == 0 }
|
||||
@projects = current_user.projects.active.select { |p| count_undone_todos(p) == 0 }
|
||||
else
|
||||
@projects = current_user.projects
|
||||
end
|
||||
@active_projects = current_user.projects.active
|
||||
@hidden_projects = current_user.projects.hidden
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
format.html do
|
||||
@page_title = t('projects.list_projects')
|
||||
@count = current_user.projects.count
|
||||
@completed_projects = current_user.projects.completed.limit(10)
|
||||
|
|
@ -32,7 +31,7 @@ class ProjectsController < ApplicationController
|
|||
current_user.projects.cache_note_counts
|
||||
@new_project = current_user.projects.build
|
||||
end
|
||||
format.m do
|
||||
format.m do
|
||||
@completed_projects = current_user.projects.completed
|
||||
@down_count = @active_projects.size + @hidden_projects.size + @completed_projects.size
|
||||
cookies[:mobile_url]= {:value => request.fullpath, :secure => SITE_CONFIG['secure_cookies']}
|
||||
|
|
@ -58,9 +57,9 @@ class ProjectsController < ApplicationController
|
|||
@source_view = params['_source_view'] || 'review'
|
||||
@page_title = t('projects.list_reviews')
|
||||
projects = current_user.projects
|
||||
@projects_to_review = projects.select {|p| p.needs_review?(current_user)}
|
||||
@stalled_projects = projects.select {|p| p.stalled?}
|
||||
@blocked_projects = projects.select {|p| p.blocked?}
|
||||
@projects_to_review = projects.select { |p| p.needs_review?(current_user) }
|
||||
@stalled_projects = projects.select { |p| p.stalled? }
|
||||
@blocked_projects = projects.select { |p| p.blocked? }
|
||||
@current_projects = projects.uncompleted.select { |p| not (p.needs_review?(current_user)) }.sort_by { |p| p.last_reviewed || Time.zone.at(0) }
|
||||
|
||||
init_not_done_counts(['project'])
|
||||
|
|
@ -85,7 +84,7 @@ class ProjectsController < ApplicationController
|
|||
@total = current_user.projects.completed.count
|
||||
@no_projects = @projects.empty?
|
||||
|
||||
@range_low = (page.to_i-1) * items_per_page + 1
|
||||
@range_low = (page.to_i - 1) * items_per_page + 1
|
||||
@range_high = @range_low + @projects.size - 1
|
||||
|
||||
@range_low = 0 if @total == 0
|
||||
|
|
@ -115,7 +114,7 @@ class ProjectsController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.text {
|
||||
# somehow passing Mime[:text] using content_type to render does not work
|
||||
headers['Content-Type']=Mime[:text].to_s
|
||||
headers['Content-Type'] = Mime[:text].to_s
|
||||
render :action => 'index_text_projects_and_actions', :layout => false, :content_type => Mime[:text]
|
||||
}
|
||||
end
|
||||
|
|
@ -133,13 +132,13 @@ class ProjectsController < ApplicationController
|
|||
@projects_to_show = [@project]
|
||||
|
||||
@done = {}
|
||||
@done = @project.todos.completed.
|
||||
reorder("todos.completed_at DESC").
|
||||
limit(current_user.prefs.show_number_completed).
|
||||
includes(Todo::DEFAULT_INCLUDES) unless @max_completed == 0
|
||||
@done = @project.todos.completed
|
||||
.reorder("todos.completed_at DESC")
|
||||
.limit(current_user.prefs.show_number_completed)
|
||||
.includes(Todo::DEFAULT_INCLUDES) unless @max_completed == 0
|
||||
|
||||
@down_count = @not_done_todos.size + @deferred_todos.size + @pending_todos.size
|
||||
@count=@down_count
|
||||
@count = @down_count
|
||||
@next_project = current_user.projects.next_from(@project)
|
||||
@previous_project = current_user.projects.previous_from(@project)
|
||||
@default_tags = @project.default_tags
|
||||
|
|
@ -148,16 +147,16 @@ class ProjectsController < ApplicationController
|
|||
@contexts = current_user.contexts
|
||||
respond_to do |format|
|
||||
format.html
|
||||
format.m do
|
||||
format.m do
|
||||
if @project.default_context.nil?
|
||||
@project_default_context = t('projects.no_default_context')
|
||||
else
|
||||
@project_default_context = t('projects.default_context', :context => @project.default_context.name)
|
||||
end
|
||||
cookies[:mobile_url]= {:value => request.fullpath, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url]= { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
@mobile_from_project = @project.id
|
||||
end
|
||||
format.xml do
|
||||
format.xml do
|
||||
render :xml => @project.to_xml(:root => :project, :except => :user_id) { |xml|
|
||||
xml.not_done { @not_done_todos.each { |child| child.to_xml(:builder => xml, :skip_instruct => true) } }
|
||||
xml.deferred { @deferred_todos.each { |child| child.to_xml(:builder => xml, :skip_instruct => true) } }
|
||||
|
|
@ -192,12 +191,11 @@ class ProjectsController < ApplicationController
|
|||
head :created, :location => project_url(@project), :text => @project.id
|
||||
end
|
||||
end
|
||||
format.html {redirect_to :action => 'index'}
|
||||
format.html { redirect_to :action => 'index' }
|
||||
end
|
||||
end
|
||||
|
||||
# Edit the details of the project
|
||||
#
|
||||
def update
|
||||
template = ""
|
||||
|
||||
|
|
@ -252,7 +250,7 @@ class ProjectsController < ApplicationController
|
|||
if @saved
|
||||
render :xml => @project.to_xml( :except => :user_id )
|
||||
else
|
||||
render :body => "Error on update: #{@project.errors.full_messages.inject("") {|v, e| v + e + " " }}", :status => 409
|
||||
render :body => "Error on update: #{@project.errors.full_messages.inject("") { |v, e| v + e + " " }}", :status => 409
|
||||
end
|
||||
}
|
||||
end
|
||||
|
|
@ -280,7 +278,7 @@ class ProjectsController < ApplicationController
|
|||
|
||||
def order
|
||||
project_ids = params["container_project"]
|
||||
@projects = current_user.projects.update_positions( project_ids )
|
||||
@projects = current_user.projects.update_positions(project_ids)
|
||||
head :ok
|
||||
rescue
|
||||
notify :error, $!
|
||||
|
|
@ -350,5 +348,4 @@ class ProjectsController < ApplicationController
|
|||
def project_params
|
||||
params.require(:project).permit(:name, :position, :user_id, :description, :state, :default_context_id, :default_tags)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,18 +1,16 @@
|
|||
module RecurringTodos
|
||||
|
||||
class FormHelper
|
||||
|
||||
def initialize(recurring_todo)
|
||||
@recurring_todo = recurring_todo
|
||||
|
||||
@method_map = {
|
||||
# delegate daily_xxx to daily_pattern.xxx
|
||||
"daily" => {prefix: "", method: daily_pattern},
|
||||
"weekly" => {prefix: "", method: weekly_pattern},
|
||||
"monthly" => {prefix: "", method: monthly_pattern},
|
||||
"yearly" => {prefix: "", method: yearly_pattern},
|
||||
"daily" => { prefix: "", method: daily_pattern },
|
||||
"weekly" => { prefix: "", method: weekly_pattern },
|
||||
"monthly" => { prefix: "", method: monthly_pattern },
|
||||
"yearly" => { prefix: "", method: yearly_pattern },
|
||||
# delegate on_xxx to weekly_pattern.on_xxx
|
||||
"on" => {prefix: "on_", method: weekly_pattern}
|
||||
"on" => { prefix: "on_", method: weekly_pattern }
|
||||
}
|
||||
end
|
||||
|
||||
|
|
@ -47,7 +45,5 @@ module RecurringTodos
|
|||
# no match, let @recurring_todo handle it, or fail
|
||||
@recurring_todo.send(method, *args)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class RecurringTodosController < ApplicationController
|
||||
|
||||
helper :todos, :recurring_todos
|
||||
|
||||
append_before_action :init, :only => [:index, :new, :edit, :create]
|
||||
|
|
@ -34,7 +33,7 @@ class RecurringTodosController < ApplicationController
|
|||
@completed_recurring_todos = current_user.recurring_todos.completed.paginate :page => page, :per_page => items_per_page
|
||||
@total = @count = current_user.recurring_todos.completed.count
|
||||
|
||||
@range_low = (page.to_i-1) * items_per_page + 1
|
||||
@range_low = (page.to_i - 1) * items_per_page + 1
|
||||
@range_high = @range_low + @completed_recurring_todos.size - 1
|
||||
|
||||
@range_low = 0 if @total == 0
|
||||
|
|
@ -98,7 +97,6 @@ class RecurringTodosController < ApplicationController
|
|||
@completed_remaining = current_user.recurring_todos.completed.count
|
||||
|
||||
respond_to do |format|
|
||||
|
||||
format.html do
|
||||
if @saved
|
||||
notify :notice, t('todos.recurring_deleted_success')
|
||||
|
|
@ -107,7 +105,6 @@ class RecurringTodosController < ApplicationController
|
|||
end
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
format.js do
|
||||
render
|
||||
end
|
||||
|
|
@ -165,7 +162,7 @@ class RecurringTodosController < ApplicationController
|
|||
# derived attributes
|
||||
:weekly_return_monday, :weekly_return_tuesday, :weekly_return_wednesday,
|
||||
:weekly_return_thursday, :weekly_return_friday, :weekly_return_saturday, :weekly_return_sunday
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def all_recurring_todo_params
|
||||
|
|
@ -230,5 +227,4 @@ class RecurringTodosController < ApplicationController
|
|||
where("fai_todos.id IS NULL").
|
||||
each { |rt| current_user.recurring_todos.find(rt.id).toggle_completion! }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class SearchController < ApplicationController
|
||||
|
||||
helper :todos, :application, :notes, :projects, :contexts
|
||||
|
||||
def results
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
class StatsController < ApplicationController
|
||||
|
||||
SECONDS_PER_DAY = 86400;
|
||||
SECONDS_PER_DAY = 86_400;
|
||||
|
||||
helper :todos, :projects, :recurring_todos
|
||||
append_before_action :init, :except => :index
|
||||
|
|
@ -31,15 +30,15 @@ class StatsController < ApplicationController
|
|||
@max = (@actions_done_last_months_array + @actions_created_last_months_array).max
|
||||
|
||||
# set running avg
|
||||
@actions_done_avg_last_months_array = compute_running_avg_array(@actions_done_last_months_array,month_count+1)
|
||||
@actions_created_avg_last_months_array = compute_running_avg_array(@actions_created_last_months_array,month_count+1)
|
||||
@actions_done_avg_last_months_array = compute_running_avg_array(@actions_done_last_months_array,month_count + 1)
|
||||
@actions_created_avg_last_months_array = compute_running_avg_array(@actions_created_last_months_array,month_count + 1)
|
||||
|
||||
# interpolate avg for this month.
|
||||
@interpolated_actions_created_this_month = interpolate_avg_for_current_month(@actions_created_last_months_array)
|
||||
@interpolated_actions_done_this_month = interpolate_avg_for_current_month(@actions_done_last_months_array)
|
||||
|
||||
@created_count_array = Array.new(month_count+1, actions_last_months.select { |x| x.created_at }.size/month_count)
|
||||
@done_count_array = Array.new(month_count+1, actions_last_months.select { |x| x.completed_at }.size/month_count)
|
||||
@created_count_array = Array.new(month_count + 1, actions_last_months.select { |x| x.created_at }.size / month_count)
|
||||
@done_count_array = Array.new(month_count + 1, actions_last_months.select { |x| x.completed_at }.size / month_count)
|
||||
|
||||
render :layout => false
|
||||
end
|
||||
|
|
@ -52,7 +51,6 @@ class StatsController < ApplicationController
|
|||
|
||||
case params['id']
|
||||
when 'avrt', 'avrt_end' # actions_visible_running_time
|
||||
|
||||
# HACK: because open flash chart uses & to denote the end of a parameter,
|
||||
# we cannot use URLs with multiple parameters (that would use &). So we
|
||||
# revert to using two id's for the same selection. avtr_end means that the
|
||||
|
|
@ -72,11 +70,11 @@ class StatsController < ApplicationController
|
|||
end
|
||||
|
||||
# get all running actions that are visible
|
||||
@actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked.
|
||||
select("todos.id, todos.created_at").
|
||||
reorder("todos.created_at DESC")
|
||||
@actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked
|
||||
.select("todos.id, todos.created_at")
|
||||
.reorder("todos.created_at DESC")
|
||||
|
||||
selected_todo_ids = get_ids_from(@actions_running_time, week_from, week_to, params['id']== 'avrt_end')
|
||||
selected_todo_ids = get_ids_from(@actions_running_time, week_from, week_to, params['id'] == 'avrt_end')
|
||||
@selected_actions = selected_todo_ids.size == 0 ? [] : current_user.todos.where("id in (" + selected_todo_ids.join(",") + ")")
|
||||
@count = @selected_actions.size
|
||||
|
||||
|
|
@ -84,7 +82,7 @@ class StatsController < ApplicationController
|
|||
|
||||
when 'art', 'art_end'
|
||||
week_from = params['index'].to_i
|
||||
week_to = week_from+1
|
||||
week_to = week_from + 1
|
||||
|
||||
@chart = Stats::Chart.new('actions_running_time_data')
|
||||
@page_title = "Actions selected from week "
|
||||
|
|
@ -99,7 +97,7 @@ class StatsController < ApplicationController
|
|||
# get all running actions
|
||||
@actions_running_time = current_user.todos.not_completed.select("id, created_at")
|
||||
|
||||
selected_todo_ids = get_ids_from(@actions_running_time, week_from, week_to, params['id']=='art_end')
|
||||
selected_todo_ids = get_ids_from(@actions_running_time, week_from, week_to, params['id'] == 'art_end')
|
||||
@selected_actions = selected_todo_ids.size == 0 ? [] : current_user.todos.where("id in (#{selected_todo_ids.join(",")})")
|
||||
@count = @selected_actions.size
|
||||
|
||||
|
|
@ -145,7 +143,7 @@ class StatsController < ApplicationController
|
|||
if at_end
|
||||
selected_todo_ids << r.id.to_s if weeks >= week_from
|
||||
else
|
||||
selected_todo_ids << r.id.to_s if weeks.between?(week_from, week_to-1)
|
||||
selected_todo_ids << r.id.to_s if weeks.between?(week_from, week_to - 1)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -161,12 +159,12 @@ class StatsController < ApplicationController
|
|||
end
|
||||
|
||||
def put_events_into_month_buckets(records, array_size, date_method_on_todo)
|
||||
convert_to_array(records.select { |x| x.send(date_method_on_todo) }, array_size) { |r| [difference_in_months(@today, r.send(date_method_on_todo))]}
|
||||
convert_to_array(records.select { |x| x.send(date_method_on_todo) }, array_size) { |r| [difference_in_months(@today, r.send(date_method_on_todo))] }
|
||||
end
|
||||
|
||||
# assumes date1 > date2
|
||||
def difference_in_days(date1, date2)
|
||||
return ((date1.utc.at_midnight-date2.utc.at_midnight)/SECONDS_PER_DAY).to_i
|
||||
return ((date1.utc.at_midnight - date2.utc.at_midnight) / SECONDS_PER_DAY).to_i
|
||||
end
|
||||
|
||||
# assumes date1 > date2
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
module Todos
|
||||
class TodoCreateParamsHelper
|
||||
|
||||
attr_reader :new_project_created, :new_context_created, :attributes
|
||||
|
||||
def initialize(params, user)
|
||||
|
|
@ -85,7 +84,7 @@ module Todos
|
|||
end
|
||||
|
||||
def sequential?
|
||||
return @params[:todos_sequential].present? && @params[:todos_sequential]=='true'
|
||||
return @params[:todos_sequential].present? && @params[:todos_sequential] == 'true'
|
||||
end
|
||||
|
||||
def specified_by_name?(group_type)
|
||||
|
|
@ -110,7 +109,7 @@ module Todos
|
|||
end
|
||||
|
||||
def add_errors(model)
|
||||
@errors.each {|e| model.errors.add(e[:attribute], e[:message]) }
|
||||
@errors.each { |e| model.errors.add(e[:attribute], e[:message]) }
|
||||
end
|
||||
|
||||
private
|
||||
|
|
@ -124,7 +123,7 @@ module Todos
|
|||
|
||||
# accept empty :todo hash
|
||||
if params[:todo].empty?
|
||||
params[:todo] = {:ignore => true}
|
||||
params[:todo] = { :ignore => true }
|
||||
end
|
||||
|
||||
filtered = params.require(:todo).permit(
|
||||
|
|
@ -136,7 +135,7 @@ module Todos
|
|||
:project => [:name])
|
||||
|
||||
# add back :predecessor_dependencies
|
||||
filtered[:predecessor_dependencies] = {:predecessor => deps } unless deps.nil?
|
||||
filtered[:predecessor_dependencies] = { :predecessor => deps } unless deps.nil?
|
||||
filtered
|
||||
end
|
||||
|
||||
|
|
@ -157,9 +156,8 @@ module Todos
|
|||
# be aware, this will replace the project_id/context_id (string) in @attributes with the new found id (int)
|
||||
@attributes["#{group_type}_id"] = set.find(id).id
|
||||
return false
|
||||
rescue
|
||||
@errors << { :attribute => group_type, :message => "unknown"}
|
||||
rescue
|
||||
@errors << { :attribute => group_type, :message => "unknown" }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class TodosController < ApplicationController
|
||||
|
||||
skip_before_action :login_required, :only => [:index, :tag, :list_deferred, :show, :list_hidden, :done]
|
||||
prepend_before_action :login_or_feed_token_required, :only => [:index, :tag, :list_deferred, :show, :list_hidden, :done]
|
||||
append_before_action :find_and_activate_ready, :only => [:index, :list_deferred]
|
||||
|
|
@ -35,29 +34,29 @@ class TodosController < ApplicationController
|
|||
@done = current_user.todos.completed.limit(max_completed).includes(Todo::DEFAULT_INCLUDES) unless max_completed == 0
|
||||
|
||||
respond_to do |format|
|
||||
format.html do
|
||||
format.html do
|
||||
@page_title = t('todos.task_list_title')
|
||||
# Set count badge to number of not-done, not hidden context items
|
||||
@count = current_user.todos.active.not_hidden.count(:all)
|
||||
@todos_without_project = @not_done_todos.select{|t|t.project.nil?}
|
||||
@todos_without_project = @not_done_todos.select{ |t| t.project.nil? }
|
||||
end
|
||||
format.m do
|
||||
@page_title = t('todos.mobile_todos_page_title')
|
||||
@home = true
|
||||
|
||||
cookies[:mobile_url]= { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url] = { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
determine_down_count
|
||||
|
||||
render :action => 'index'.freeze
|
||||
end
|
||||
format.text do
|
||||
# somehow passing Mime[:text] using content_type to render does not work
|
||||
headers['Content-Type'.freeze]=Mime[:text].to_s
|
||||
headers['Content-Type'.freeze] = Mime[:text].to_s
|
||||
render :content_type => Mime[:text]
|
||||
end
|
||||
format.xml do
|
||||
@xml_todos = params[:limit_to_active_todos] ? @not_done_todos : @todos
|
||||
render :xml => @xml_todos.to_xml( *[todo_xml_params[0].merge({:root => :todos})] )
|
||||
render :xml => @xml_todos.to_xml( *[todo_xml_params[0].merge({ :root => :todos })] )
|
||||
end
|
||||
format.any(:rss, :atom) do
|
||||
@feed_title = 'Tracks Actions'.freeze
|
||||
|
|
@ -73,7 +72,7 @@ class TodosController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.m {
|
||||
@new_mobile = true
|
||||
@return_path=cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
@return_path = cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
@mobile_from_context = current_user.contexts.find(params[:from_context]) if params[:from_context]
|
||||
@mobile_from_project = current_user.projects.find(params[:from_project]) if params[:from_project]
|
||||
if params[:from_project] && !params[:from_context]
|
||||
|
|
@ -123,7 +122,7 @@ class TodosController < ApplicationController
|
|||
redirect_to :action => "index"
|
||||
end
|
||||
format.m do
|
||||
@return_path=cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
@return_path = cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
if @saved
|
||||
onsite_redirect_to @return_path
|
||||
else
|
||||
|
|
@ -176,7 +175,7 @@ class TodosController < ApplicationController
|
|||
# first build all todos and check if they would validate on save
|
||||
params[:todo][:multiple_todos].split("\n").map do |line|
|
||||
if line.present? #ignore blank lines
|
||||
@todo = current_user.todos.build({:description => line, :context_id => p.context_id, :project_id => p.project_id})
|
||||
@todo = current_user.todos.build({ :description => line, :context_id => p.context_id, :project_id => p.project_id })
|
||||
validates &&= @todo.valid?
|
||||
|
||||
@build_todos << @todo
|
||||
|
|
@ -250,7 +249,7 @@ class TodosController < ApplicationController
|
|||
@projects = current_user.projects.active
|
||||
@contexts = current_user.contexts
|
||||
@edit_mobile = true
|
||||
@return_path=cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
@return_path = cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
}
|
||||
end
|
||||
end
|
||||
|
|
@ -259,7 +258,7 @@ class TodosController < ApplicationController
|
|||
@todo = current_user.todos.find(params['id'])
|
||||
respond_to do |format|
|
||||
format.m { render :action => 'show' }
|
||||
format.xml { render :xml => @todo.to_xml( *[todo_xml_params[0].merge({:root => :todo})] ) }
|
||||
format.xml { render :xml => @todo.to_xml( *[todo_xml_params[0].merge({ :root => :todo })] ) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -363,7 +362,7 @@ class TodosController < ApplicationController
|
|||
if @saved
|
||||
if cookies[:mobile_url]
|
||||
old_path = cookies[:mobile_url]
|
||||
cookies[:mobile_url] = {:value => nil, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url] = { :value => nil, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
notify(:notice, t("todos.action_marked_complete", :description => @todo.description, :completed => @todo.completed? ? 'complete' : 'incomplete'))
|
||||
onsite_redirect_to old_path
|
||||
else
|
||||
|
|
@ -384,11 +383,11 @@ class TodosController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.js
|
||||
format.xml { render :xml => @todo.to_xml( *todo_xml_params ) }
|
||||
format.html { redirect_to request.referrer}
|
||||
format.html { redirect_to request.referrer }
|
||||
format.m {
|
||||
if cookies[:mobile_url]
|
||||
old_path = cookies[:mobile_url]
|
||||
cookies[:mobile_url] = {:value => nil, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url] = { :value => nil, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
notify(:notice, "Star toggled")
|
||||
onsite_redirect_to old_path
|
||||
else
|
||||
|
|
@ -456,7 +455,7 @@ class TodosController < ApplicationController
|
|||
end
|
||||
|
||||
determine_changes_by_this_update
|
||||
determine_remaining_in_container_count( (@context_changed || @project_changed) ? @original_item : @todo)
|
||||
determine_remaining_in_container_count((@context_changed || @project_changed) ? @original_item : @todo)
|
||||
determine_down_count
|
||||
determine_deferred_tag_count(sanitize(params['_tag_name'])) if source_view_is(:tag)
|
||||
|
||||
|
|
@ -519,7 +518,6 @@ class TodosController < ApplicationController
|
|||
@new_recurring_todo = check_for_next_todo(@todo) if @saved
|
||||
|
||||
respond_to do |format|
|
||||
|
||||
format.html do
|
||||
if @saved
|
||||
message = t('todos.action_deleted_success')
|
||||
|
|
@ -533,7 +531,6 @@ class TodosController < ApplicationController
|
|||
redirect_to :action => 'index'
|
||||
end
|
||||
end
|
||||
|
||||
format.js do
|
||||
if @saved
|
||||
determine_down_count
|
||||
|
|
@ -546,9 +543,7 @@ class TodosController < ApplicationController
|
|||
end
|
||||
render
|
||||
end
|
||||
|
||||
format.xml { render :body => '200 OK. Action deleted.', :status => 200 }
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -563,7 +558,7 @@ class TodosController < ApplicationController
|
|||
format.html
|
||||
format.xml do
|
||||
completed_todos = current_user.todos.completed
|
||||
render :xml => completed_todos.to_xml( *[todo_xml_params[0].merge({:root => :todos})] )
|
||||
render :xml => completed_todos.to_xml( *[todo_xml_params[0].merge({ :root => :todos })] )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -583,7 +578,7 @@ class TodosController < ApplicationController
|
|||
@contexts_to_show = @contexts = current_user.contexts
|
||||
@projects_to_show = @projects = current_user.projects
|
||||
|
||||
includes = params[:format]=='xml' ? [:context, :project] : Todo::DEFAULT_INCLUDES
|
||||
includes = params[:format] == 'xml' ? [:context, :project] : Todo::DEFAULT_INCLUDES
|
||||
|
||||
@not_done_todos = current_user.todos.deferred.includes(includes).reorder('show_from') + current_user.todos.pending.includes(includes)
|
||||
@todos_without_project = @not_done_todos.select{|t|t.project.nil?}
|
||||
|
|
@ -596,7 +591,7 @@ class TodosController < ApplicationController
|
|||
init_data_for_sidebar unless mobile?
|
||||
end
|
||||
format.m
|
||||
format.xml { render :xml => @not_done_todos.to_xml( *[todo_xml_params[0].merge({:root => :todos})] ) }
|
||||
format.xml { render :xml => @not_done_todos.to_xml( *[todo_xml_params[0].merge({ :root => :todos })] ) }
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -646,14 +641,14 @@ class TodosController < ApplicationController
|
|||
blocked.
|
||||
reorder(Arel.sql('todos.show_from ASC, todos.created_at DESC')).
|
||||
includes(Todo::DEFAULT_INCLUDES)
|
||||
@todos_without_project = @not_done_todos.select{|t| t.project.nil?}
|
||||
@todos_without_project = @not_done_todos.select{ |t| t.project.nil? }
|
||||
|
||||
# If you've set no_completed to zero, the completed items box isn't shown on
|
||||
# the tag page
|
||||
@done = todos_with_tag_ids.completed.
|
||||
limit(current_user.prefs.show_number_completed).
|
||||
reorder('todos.completed_at DESC').
|
||||
includes(Todo::DEFAULT_INCLUDES)
|
||||
@done = todos_with_tag_ids.completed
|
||||
.limit(current_user.prefs.show_number_completed)
|
||||
.reorder('todos.completed_at DESC')
|
||||
.includes(Todo::DEFAULT_INCLUDES)
|
||||
|
||||
@projects = current_user.projects
|
||||
@contexts = current_user.contexts
|
||||
|
|
@ -670,7 +665,7 @@ class TodosController < ApplicationController
|
|||
respond_to do |format|
|
||||
format.html
|
||||
format.m {
|
||||
cookies[:mobile_url]= {:value => request.fullpath, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url]= { :value => request.fullpath, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
}
|
||||
format.text {
|
||||
render :action => 'index', :layout => false, :content_type => Mime[:text]
|
||||
|
|
@ -705,7 +700,6 @@ class TodosController < ApplicationController
|
|||
@tag = Tag.where(:name => @tag_name).first_or_create
|
||||
end
|
||||
|
||||
|
||||
def tags
|
||||
tags_beginning = current_user.tags.where(Tag.arel_table[:name].matches("#{params[:term]}%"))
|
||||
tags_all = current_user.tags.where(Tag.arel_table[:name].matches("%#{params[:term]}%"))
|
||||
|
|
@ -747,7 +741,7 @@ class TodosController < ApplicationController
|
|||
|
||||
respond_to do |format|
|
||||
format.html { redirect_to :back }
|
||||
format.js {render :action => 'update'}
|
||||
format.js { render :action => 'update' }
|
||||
format.m {
|
||||
notify(:notice, t("todos.action_deferred", :description => @todo.description))
|
||||
do_mobile_todo_redirection
|
||||
|
|
@ -759,20 +753,20 @@ class TodosController < ApplicationController
|
|||
@hidden = current_user.todos.hidden
|
||||
respond_to do |format|
|
||||
format.xml {
|
||||
render :xml => @hidden.to_xml( *[todo_xml_params[0].merge({:root => :todos})] )
|
||||
render :xml => @hidden.to_xml( *[todo_xml_params[0].merge({ :root => :todos })] )
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
def get_not_completed_for_predecessor(relation, todo_id=nil)
|
||||
items = relation.todos.not_completed.
|
||||
where('(LOWER(todos.description) ' + Common.like_operator + '?)', "%#{params[:term].downcase}%")
|
||||
items = relation.todos.not_completed
|
||||
.where('(LOWER(todos.description) ' + Common.like_operator + '?)', "%#{params[:term].downcase}%")
|
||||
items = items.where("AND NOT(todos.id=?)", todo_id) unless todo_id.nil?
|
||||
|
||||
items.
|
||||
includes(:context, :project).
|
||||
reorder('description ASC').
|
||||
limit(10)
|
||||
items
|
||||
.includes(:context, :project)
|
||||
.reorder('description ASC')
|
||||
.limit(10)
|
||||
end
|
||||
|
||||
def auto_complete_for_predecessor
|
||||
|
|
@ -805,12 +799,12 @@ class TodosController < ApplicationController
|
|||
|
||||
def show_notes
|
||||
@todo = current_user.todos.find(params['id'])
|
||||
@return_path=cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
@return_path = cookies[:mobile_url] ? cookies[:mobile_url] : mobile_path
|
||||
respond_to do |format|
|
||||
format.html {
|
||||
redirect_to home_path, "Viewing note of todo is not implemented"
|
||||
}
|
||||
format.m {
|
||||
format.m {
|
||||
render :action => "show_notes"
|
||||
}
|
||||
end
|
||||
|
|
@ -839,7 +833,7 @@ class TodosController < ApplicationController
|
|||
def do_mobile_todo_redirection
|
||||
if cookies[:mobile_url]
|
||||
old_path = cookies[:mobile_url]
|
||||
cookies[:mobile_url] = {:value => nil, :secure => SITE_CONFIG['secure_cookies']}
|
||||
cookies[:mobile_url] = { :value => nil, :secure => SITE_CONFIG['secure_cookies'] }
|
||||
onsite_redirect_to old_path
|
||||
else
|
||||
onsite_redirect_to todos_path(:format => 'm')
|
||||
|
|
@ -990,7 +984,7 @@ end
|
|||
return todos_in_container, todos_in_target_container
|
||||
end
|
||||
|
||||
def determine_remaining_in_container_count(todo = @todo)
|
||||
def determine_remaining_in_container_count(todo=@todo)
|
||||
source_view do |from|
|
||||
from.deferred {
|
||||
todos_in_container, todos_in_target_container = find_todos_in_container_and_target_container(todo, @todo)
|
||||
|
|
@ -1060,7 +1054,7 @@ end
|
|||
end
|
||||
|
||||
def determine_completed_count
|
||||
todos=nil
|
||||
todos = nil
|
||||
|
||||
source_view do |from|
|
||||
from.todo { todos = current_user.todos.not_hidden.completed }
|
||||
|
|
@ -1096,7 +1090,6 @@ end
|
|||
date_to_check ||= Time.zone.now
|
||||
|
||||
if recurring_todo.active? && recurring_todo.continues_recurring?(date_to_check)
|
||||
|
||||
# shift the reference date to yesterday if date_to_check is furher in
|
||||
# the past. This is to make sure we do not get older todos for overdue
|
||||
# todos. I.e. checking a daily todo that is overdue with 5 days will
|
||||
|
|
@ -1104,7 +1097,7 @@ end
|
|||
# date. Discard the time part in the compare. We pick yesterday so
|
||||
# that new todos due for today will be created instead of new todos
|
||||
# for tomorrow.
|
||||
date = date_to_check.at_midnight >= Time.zone.now.at_midnight ? date_to_check : Time.zone.now-1.day
|
||||
date = date_to_check.at_midnight >= Time.zone.now.at_midnight ? date_to_check : Time.zone.now - 1.day
|
||||
|
||||
new_recurring_todo = TodoFromRecurringTodo.new(current_user, recurring_todo).create(date)
|
||||
end
|
||||
|
|
@ -1179,7 +1172,6 @@ end
|
|||
end
|
||||
end
|
||||
|
||||
|
||||
def update_context
|
||||
@context_changed = false
|
||||
if params['todo']['context_id'].blank? && params['context_name'].present?
|
||||
|
|
@ -1218,7 +1210,7 @@ end
|
|||
end
|
||||
|
||||
def update_due_and_show_from_dates
|
||||
%w{ due show_from }.each {|date| update_date_for_update(date) }
|
||||
%w{ due show_from }.each { |date| update_date_for_update(date) }
|
||||
end
|
||||
|
||||
def update_completed_state
|
||||
|
|
@ -1290,22 +1282,22 @@ end
|
|||
end
|
||||
|
||||
# all completed todos [today@00:00, today@now]
|
||||
def get_done_today(completed_todos, includes = {:include => Todo::DEFAULT_INCLUDES})
|
||||
def get_done_today(completed_todos, includes={ :include => Todo::DEFAULT_INCLUDES })
|
||||
start_of_this_day = Time.zone.now.beginning_of_day
|
||||
completed_todos.completed_after(start_of_this_day).includes(includes[:include])
|
||||
end
|
||||
|
||||
def get_done_in_period(completed_todos, before, after, includes = {:include => Todo::DEFAULT_INCLUDES})
|
||||
def get_done_in_period(completed_todos, before, after, includes={ :include => Todo::DEFAULT_INCLUDES })
|
||||
completed_todos.completed_before(before).completed_after(after).includes(includes[:include])
|
||||
end
|
||||
|
||||
# all completed todos [begin_of_week, start_of_today]
|
||||
def get_done_rest_of_week(completed_todos, includes = {:include => Todo::DEFAULT_INCLUDES})
|
||||
def get_done_rest_of_week(completed_todos, includes={ :include => Todo::DEFAULT_INCLUDES })
|
||||
get_done_in_period(completed_todos, Time.zone.now.beginning_of_day, Time.zone.now.beginning_of_week)
|
||||
end
|
||||
|
||||
# all completed todos [begin_of_month, begin_of_week]
|
||||
def get_done_rest_of_month(completed_todos, includes = {:include => Todo::DEFAULT_INCLUDES})
|
||||
def get_done_rest_of_month(completed_todos, includes={ :include => Todo::DEFAULT_INCLUDES })
|
||||
get_done_in_period(completed_todos, Time.zone.now.beginning_of_week, Time.zone.now.beginning_of_month)
|
||||
end
|
||||
|
||||
|
|
@ -1322,5 +1314,4 @@ end
|
|||
redirect_to(uri.path)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,8 @@
|
|||
class UsersController < ApplicationController
|
||||
|
||||
before_action :admin_login_required, :only => [ :index, :show ]
|
||||
before_action :admin_or_self_login_required, :only => [ :destroy ]
|
||||
skip_before_action :login_required, :only => [ :new, :create ]
|
||||
prepend_before_action :login_optional, :only => [ :new, :create ]
|
||||
before_action :admin_login_required, :only => [:index, :show]
|
||||
before_action :admin_or_self_login_required, :only => [:destroy]
|
||||
skip_before_action :login_required, :only => [:new, :create]
|
||||
prepend_before_action :login_optional, :only => [:new, :create]
|
||||
|
||||
# GET /users GET /users.xml
|
||||
def index
|
||||
|
|
@ -17,8 +16,8 @@ class UsersController < ApplicationController
|
|||
store_location
|
||||
end
|
||||
format.xml do
|
||||
@users = User.order('login')
|
||||
render :xml => @users.to_xml(:root => :users, :except => [ :password ])
|
||||
@users = User.order('login')
|
||||
render :xml => @users.to_xml(:root => :users, :except => [:password])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -26,16 +25,16 @@ class UsersController < ApplicationController
|
|||
# GET /users/id GET /users/id.xml
|
||||
def show
|
||||
@user = User.find(params[:id])
|
||||
render :xml => @user.to_xml(:root => :user, :except => [ :password ])
|
||||
render :xml => @user.to_xml(:root => :user, :except => [:password])
|
||||
end
|
||||
|
||||
# GET /users/new
|
||||
def new
|
||||
@auth_types = []
|
||||
unless session[:cas_user]
|
||||
Tracks::Config.auth_schemes.each {|auth| @auth_types << [auth,auth]}
|
||||
Tracks::Config.auth_schemes.each { |auth| @auth_types << [auth, auth] }
|
||||
else
|
||||
@auth_types << ['cas','cas']
|
||||
@auth_types << ['cas', 'cas']
|
||||
end
|
||||
|
||||
if User.no_users_yet?
|
||||
|
|
@ -223,5 +222,4 @@ class UsersController < ApplicationController
|
|||
return false if params[:user][:password].empty?
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ module ApplicationHelper
|
|||
link_to(
|
||||
t("layouts.navigation.group_view_by_#{menu_name}"),
|
||||
'#',
|
||||
{:id => "group_view_by_link", :accesskey => "g", :title => t('layouts.navigation.group_view_by_title'), :x_current_group_by => @group_view_by} )
|
||||
{ :id => "group_view_by_link", :accesskey => "g", :title => t('layouts.navigation.group_view_by_title'), :x_current_group_by => @group_view_by } )
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -18,7 +18,7 @@ module ApplicationHelper
|
|||
link_to(
|
||||
image_tag("blank.png", :alt => t('common.collapse_expand')),
|
||||
"#",
|
||||
{:class => "container_toggle", :id => id} )
|
||||
{ :class => "container_toggle", :id => id })
|
||||
end
|
||||
|
||||
# Check due date in comparison to today's date Flag up date appropriately with
|
||||
|
|
@ -54,28 +54,28 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def link_to_context(context, descriptor = sanitize(context.name))
|
||||
link_to( descriptor, 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, :title => "View project: #{project.name}" )
|
||||
link_to(descriptor, project, :title => "View project: #{project.name}")
|
||||
end
|
||||
|
||||
def link_to_edit_note (note, descriptor = sanitize(note.id.to_s))
|
||||
link_to(descriptor, edit_note_path(note),
|
||||
{:id => "link_edit_#{dom_id(note)}", :class => "note_edit_settings"})
|
||||
{ :id => "link_edit_#{dom_id(note)}", :class => "note_edit_settings" })
|
||||
end
|
||||
|
||||
def link_to_project_mobile(project, accesskey, descriptor = sanitize(project.name))
|
||||
link_to( descriptor, project_path(project, :format => 'm'), {:title => "View project: #{project.name}", :accesskey => accesskey} )
|
||||
link_to(descriptor, project_path(project, :format => 'm'), { :title => "View project: #{project.name}", :accesskey => accesskey })
|
||||
end
|
||||
|
||||
def item_link_to_context(item)
|
||||
link_to_context( item.context, prefs.verbose_action_descriptors ? "[#{item.context.name}]" : "[C]" )
|
||||
link_to_context(item.context, prefs.verbose_action_descriptors ? "[#{item.context.name}]" : "[C]")
|
||||
end
|
||||
|
||||
def item_link_to_project(item)
|
||||
link_to_project( item.project, prefs.verbose_action_descriptors ? "[#{item.project.name}]" : "[P]" )
|
||||
link_to_project(item.project, prefs.verbose_action_descriptors ? "[#{item.project.name}]" : "[P]")
|
||||
end
|
||||
|
||||
def render_flash
|
||||
|
|
@ -127,15 +127,15 @@ module ApplicationHelper
|
|||
end
|
||||
|
||||
def sidebar_html_for_titled_list (list, title)
|
||||
return content_tag(:h3, title+" (#{list.size})") + content_tag(:ul, sidebar_html_for_list(list))
|
||||
return content_tag(:h3, title+" (#{list.size})") + content_tag(:ul, sidebar_html_for_list(list))
|
||||
end
|
||||
|
||||
def link_to_sidebar_item(item)
|
||||
item.is_a?(Project) ? link_to_project( item ) : link_to_context( item )
|
||||
item.is_a?(Project) ? link_to_project(item) : link_to_context(item)
|
||||
end
|
||||
|
||||
def sidebar_html_for_item(item)
|
||||
content_tag(:li, link_to_sidebar_item(item) + " (" + count_undone_todos_phrase(item)+")")
|
||||
content_tag(:li, link_to_sidebar_item(item) + " (" + count_undone_todos_phrase(item) + ")")
|
||||
end
|
||||
|
||||
def sidebar_html_for_list(list)
|
||||
|
|
@ -175,12 +175,12 @@ module ApplicationHelper
|
|||
def done_path(controller_name, type)
|
||||
case controller_name
|
||||
when "contexts"
|
||||
send("#{type}_todos_context_path",@context)
|
||||
send("#{type}_todos_context_path", @context)
|
||||
when "projects"
|
||||
send("#{type}_todos_project_path", @project)
|
||||
when "todos"
|
||||
if @tag_name
|
||||
send("#{type}_tag_path",@tag_name)
|
||||
send("#{type}_tag_path", @tag_name)
|
||||
else
|
||||
send("#{type}_todos_path")
|
||||
end
|
||||
|
|
@ -199,7 +199,7 @@ module ApplicationHelper
|
|||
|
||||
def get_list_of_error_messages_for(model)
|
||||
if model.errors.any?
|
||||
content_tag(:div, {:id=>"errorExplanation"}) do
|
||||
content_tag(:div, { :id => "errorExplanation" }) do
|
||||
content_tag(:ul) do
|
||||
model.errors.full_messages.collect { |msg| concat(content_tag(:li, msg)) }
|
||||
end
|
||||
|
|
@ -207,10 +207,8 @@ module ApplicationHelper
|
|||
end
|
||||
end
|
||||
|
||||
def link_to_delete(type, object, descriptor = sanitize(object.name))
|
||||
link_to(
|
||||
descriptor,
|
||||
self.send("#{type}_path", object, :format => 'js'),
|
||||
def link_to_delete(type, object, descriptor=sanitize(object.name))
|
||||
link_to(descriptor, self.send("#{type}_path", object, :format => 'js'),
|
||||
{
|
||||
:id => "delete_#{type}_#{object.id}",
|
||||
:class => "delete_#{type}_button icon",
|
||||
|
|
@ -239,7 +237,7 @@ module ApplicationHelper
|
|||
"#{name}_#{SecureRandom.hex(5)}"
|
||||
end
|
||||
|
||||
def js_render(partial, locals = {}, object=nil)
|
||||
def js_render(partial, locals={}, object=nil)
|
||||
if object
|
||||
escape_javascript(render(partial: partial, locals: locals, object: object))
|
||||
else
|
||||
|
|
@ -250,5 +248,4 @@ module ApplicationHelper
|
|||
def js_error_messages_for(object)
|
||||
escape_javascript(get_list_of_error_messages_for(object))
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module ContextsHelper
|
||||
|
||||
def show_context_name(context)
|
||||
if source_view_is :context
|
||||
content_tag(:span, :id => "context_name"){context.name}
|
||||
|
|
@ -19,5 +18,4 @@ module ContextsHelper
|
|||
def context_summary(context, undone_todo_count)
|
||||
content_tag(:p, "#{undone_todo_count}. Context is #{context.hidden? ? 'Hidden' : 'Active'}.".html_safe)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module DateLabelHelper
|
||||
|
||||
class GenericDateView
|
||||
include ActionView::Context
|
||||
include ActionView::Helpers
|
||||
|
|
@ -66,11 +65,9 @@ module DateLabelHelper
|
|||
yield
|
||||
}
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class DueDateView < GenericDateView
|
||||
|
||||
def due_text
|
||||
case @days_sym
|
||||
when :overdue_by_one
|
||||
|
|
@ -100,11 +97,9 @@ module DateLabelHelper
|
|||
def due_date_mobile_html
|
||||
date_mobile_html_wrapper { @prefs.format_date(@due) }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class ShowFromDateView < GenericDateView
|
||||
|
||||
def show_from_text
|
||||
case @days_sym
|
||||
when :overdue_by_more_than_one, :overdue_by_one
|
||||
|
|
@ -127,7 +122,5 @@ module DateLabelHelper
|
|||
def show_from_date_html
|
||||
date_html_wrapper { show_from_text }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
module FeedlistHelper
|
||||
|
||||
def linkoptions(format, options)
|
||||
merge_hashes( {:format => format}, options, user_token_hash)
|
||||
merge_hashes( { :format => format }, options, user_token_hash)
|
||||
end
|
||||
|
||||
def rss_formatted_link(options = {})
|
||||
|
|
@ -10,25 +9,25 @@ module FeedlistHelper
|
|||
end
|
||||
|
||||
def text_formatted_link(options = {})
|
||||
link_to(content_tag(:span, 'TXT', {:class => 'feed', :title => "Plain text feed"}), linkoptions('txt', options))
|
||||
link_to(content_tag(:span, 'TXT', { :class => 'feed', :title => "Plain text feed" }), linkoptions('txt', options))
|
||||
end
|
||||
|
||||
def ical_formatted_link(options = {})
|
||||
link_to(content_tag(:span, 'iCal', {:class=>"feed", :title => "iCal feed"}), linkoptions('ics', options))
|
||||
link_to(content_tag(:span, 'iCal', { :class=>"feed", :title => "iCal feed" }), linkoptions('ics', options))
|
||||
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 << 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.html_safe
|
||||
end
|
||||
|
||||
def all_feed_links(object, symbol)
|
||||
feed_links([:rss, :txt, :ical], { :controller=> 'todos', :action => 'index', symbol => object.to_param }, content_tag(:strong, object.name))
|
||||
feed_links([:rss, :txt, :ical], { :controller => 'todos', :action => 'index', symbol => object.to_param }, content_tag(:strong, object.name))
|
||||
end
|
||||
|
||||
def all_feed_links_for_project(project)
|
||||
|
|
@ -48,6 +47,4 @@ module FeedlistHelper
|
|||
def user_token_hash
|
||||
{ :token => current_user.token }
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module IconHelper
|
||||
include FontAwesome::Sass::Rails::ViewHelpers
|
||||
|
||||
def icon_fw(style, name, text = nil, html_options = {})
|
||||
def icon_fw(style, name, text=nil, html_options={})
|
||||
text, html_options = nil, text if text.is_a?(Hash)
|
||||
|
||||
if html_options.key?(:class)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,2 @@
|
|||
module LoginHelper
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module PreferencesHelper
|
||||
|
||||
def pref(model, pref_name, &block)
|
||||
s = content_tag(:label, Preference.human_attribute_name(pref_name), :for => model + "_" + pref_name)
|
||||
s << yield
|
||||
|
|
@ -10,7 +9,7 @@ module PreferencesHelper
|
|||
pref(model, pref_name) { check_box(model, pref_name, class: "form-control") }
|
||||
end
|
||||
|
||||
def pref_with_select_field(model, pref_name, collection = [ [t('preferences.is_true'),true], [t('preferences.is_false'), false] ])
|
||||
def pref_with_select_field(model, pref_name, collection = [[t('preferences.is_true'), true], [t('preferences.is_false'), false]])
|
||||
pref(model, pref_name) { select(model, pref_name, collection, {}, class: "form-control") }
|
||||
end
|
||||
|
||||
|
|
@ -21,8 +20,8 @@ module PreferencesHelper
|
|||
def profile_delete_user(user)
|
||||
return link_to(
|
||||
t('users.destroy_user'),
|
||||
url_for({:controller => 'users', :action => 'destroy', :id => user.id}),
|
||||
{:id => "delete_user_#{user.id}",
|
||||
url_for({ :controller => 'users', :action => 'destroy', :id => user.id }),
|
||||
{ :id => "delete_user_#{user.id}",
|
||||
:class => "delete_user_button btn btn-danger",
|
||||
:title => t('users.destroy_user'),
|
||||
:x_confirm_message => t('users.destroy_confirmation', :login => user.login)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module ProjectsHelper
|
||||
|
||||
def show_project_name(project)
|
||||
if source_view_is :project
|
||||
content_tag(:span, :id => "project_name"){project.name}
|
||||
|
|
@ -9,7 +8,7 @@ module ProjectsHelper
|
|||
end
|
||||
|
||||
def show_project_settings(project)
|
||||
content_tag(:div, :id => dom_id(project, "container"), :class=>"list") do
|
||||
content_tag(:div, :id => dom_id(project, "container"), :class => "list") do
|
||||
render :partial => "projects/project_settings", :object => project
|
||||
end
|
||||
end
|
||||
|
|
@ -27,9 +26,9 @@ module ProjectsHelper
|
|||
def project_next_prev_mobile
|
||||
prev_project = ""
|
||||
next_project = ""
|
||||
prev_project = content_tag(:li, link_to_project_mobile(@previous_project, "5", @previous_project.shortened_name), :class=>"prev") if @previous_project
|
||||
next_project = content_tag(:li, link_to_project_mobile(@next_project, "6", @next_project.shortened_name), :class=>"next") if @next_project
|
||||
return content_tag(:ul, "#{prev_project}#{next_project}".html_safe, :class=>"next-prev-project")
|
||||
prev_project = content_tag(:li, link_to_project_mobile(@previous_project, "5", @previous_project.shortened_name), :class => "prev") if @previous_project
|
||||
next_project = content_tag(:li, link_to_project_mobile(@next_project, "6", @next_project.shortened_name), :class => "next") if @next_project
|
||||
return content_tag(:ul, "#{prev_project}#{next_project}".html_safe, :class => "next-prev-project")
|
||||
end
|
||||
|
||||
def project_summary(project)
|
||||
|
|
@ -52,5 +51,4 @@ module ProjectsHelper
|
|||
def link_to_edit_project (project, descriptor = sanitize(project.name))
|
||||
link_to_edit(:project, project, descriptor)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,28 +1,27 @@
|
|||
module RecurringTodosHelper
|
||||
|
||||
def recurring_todo_tag_list
|
||||
tags_except_starred = @recurring_todo.tags.reject{|t| t.name == Todo::STARRED_TAG_NAME}
|
||||
tag_list = tags_except_starred.
|
||||
collect{|t| content_tag(:span,link_to(t.name, tag_path(t.name)), :class => "tag #{t.label}")}.
|
||||
join('')
|
||||
tags_except_starred = @recurring_todo.tags.reject{ |t| t.name == Todo::STARRED_TAG_NAME }
|
||||
tag_list = tags_except_starred
|
||||
.collect{ |t| content_tag(:span,link_to(t.name, tag_path(t.name)), :class => "tag #{t.label}") }
|
||||
.join('')
|
||||
return content_tag :span, tag_list.html_safe, :class => "tags"
|
||||
end
|
||||
|
||||
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,
|
||||
link_to(image_tag_for_delete, recurring_todo_path(@recurring_todo),
|
||||
:id => "delete_icon_" + @recurring_todo.id.to_s,
|
||||
: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), :id => "star_icon_"+@recurring_todo.id.to_s,
|
||||
link_to(image_tag_for_star(@recurring_todo),
|
||||
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),
|
||||
str = link_to(image_tag_for_edit(@recurring_todo),
|
||||
edit_recurring_todo_path(@recurring_todo),
|
||||
:class => "icon edit_icon", :id => "link_edit_recurring_todo_#{@recurring_todo.id}")
|
||||
else
|
||||
|
|
@ -38,10 +37,10 @@ module RecurringTodosHelper
|
|||
private
|
||||
|
||||
def image_tag_for_delete
|
||||
image_tag("blank.png", :title =>t('todos.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 =>t('todos.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
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ module RenderingHelper
|
|||
# add onenote and message protocols, allow a target
|
||||
a_href_config = relaxed_config[:protocols]['a']['href'] + %w(onenote message)
|
||||
a_attributes = relaxed_config[:attributes]['a'] + ['target']
|
||||
config = Sanitize::Config.merge(config, protocols: {'a' => {'href' => a_href_config}}, :attributes => {'a' => a_attributes})
|
||||
config = Sanitize::Config.merge(config, protocols: { 'a' => { 'href' => a_href_config } }, :attributes => { 'a' => a_attributes })
|
||||
|
||||
rendered = Sanitize.fragment(rendered, config)
|
||||
return rendered.html_safe
|
||||
|
|
|
|||
|
|
@ -1,11 +1,10 @@
|
|||
module StatsHelper
|
||||
|
||||
def font_size(cloud, tag)
|
||||
9 + 2 * cloud.relative_size(tag)
|
||||
end
|
||||
|
||||
def month_and_year_label(i)
|
||||
t('date.month_names')[ (Time.zone.now.mon - i -1 ) % 12 + 1 ]+ " " + (Time.zone.now - i.months).year.to_s
|
||||
t('date.month_names')[(Time.zone.now.mon - i - 1) % 12 + 1] + " " + (Time.zone.now - i.months).year.to_s
|
||||
end
|
||||
|
||||
def array_of_month_and_year_labels(count)
|
||||
|
|
@ -13,11 +12,10 @@ module StatsHelper
|
|||
end
|
||||
|
||||
def month_label(i)
|
||||
t('date.month_names')[ (Time.zone.now.mon - i -1 ) % 12 + 1 ]
|
||||
t('date.month_names')[(Time.zone.now.mon - i - 1) % 12 + 1]
|
||||
end
|
||||
|
||||
def array_of_month_labels(count)
|
||||
Array.new(count) { |i| month_label(i) }
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,7 @@
|
|||
require 'staleness'
|
||||
|
||||
module TodosHelper
|
||||
|
||||
# === helpers for rendering container
|
||||
|
||||
def empty_message_holder(container_name, show, title_param=nil)
|
||||
content_tag(:div, :id => "no_todos_in_view", :class => "container #{container_name}", :style => "display:" + (show ? "block" : "none") ) do
|
||||
content_tag(:h2) { t("todos.no_actions.title", :param=>title_param) } +
|
||||
|
|
@ -14,7 +12,7 @@ module TodosHelper
|
|||
end
|
||||
|
||||
def todos_container_empty_message(container_name, container_id, show_message)
|
||||
content_tag(:div, :id=>"#{container_id}-empty-d", :style=>"display:#{show_message ? 'block' : 'none'}") do
|
||||
content_tag(:div, :id => "#{container_id}-empty-d", :style => "display:#{show_message ? 'block' : 'none'}") do
|
||||
content_tag(:div, :class=>"message") do
|
||||
content_tag(:p) do
|
||||
t("todos.no_actions.#{container_name}")
|
||||
|
|
@ -49,7 +47,7 @@ module TodosHelper
|
|||
|
||||
render :partial => 'todos/collection',
|
||||
:object => done_todos,
|
||||
:locals => {:settings => settings.reverse_merge!(default_collection_settings)}
|
||||
:locals => { :settings => settings.reverse_merge!(default_collection_settings) }
|
||||
end
|
||||
|
||||
def show_completed_todos_for(period, collection)
|
||||
|
|
@ -62,7 +60,7 @@ module TodosHelper
|
|||
|
||||
render :partial => "todos/collection",
|
||||
:object => collection,
|
||||
:locals => { :settings => settings}
|
||||
:locals => { :settings => settings }
|
||||
end
|
||||
|
||||
def show_hidden_todos(hidden_todos, settings={})
|
||||
|
|
@ -70,7 +68,7 @@ module TodosHelper
|
|||
|
||||
render :partial => 'todos/collection',
|
||||
:object => hidden_todos,
|
||||
:locals => {:settings => settings.reverse_merge!(default_collection_settings)}
|
||||
:locals => { :settings => settings.reverse_merge!(default_collection_settings) }
|
||||
end
|
||||
|
||||
def show_deferred_pending_todos(deferred_todos, pending_todos, settings={})
|
||||
|
|
@ -79,13 +77,13 @@ module TodosHelper
|
|||
|
||||
render :partial => "todos/collection",
|
||||
:object => deferred_todos+pending_todos,
|
||||
:locals => {:settings => settings.reverse_merge!(default_collection_settings)}
|
||||
:locals => { :settings => settings.reverse_merge!(default_collection_settings) }
|
||||
end
|
||||
|
||||
def show_todos_without_project(todos_without_project, settings = {})
|
||||
render :partial => 'todos/collection',
|
||||
:object => todos_without_project,
|
||||
:locals => {:settings => settings.reverse_merge!({
|
||||
:locals => { :settings => settings.reverse_merge!({
|
||||
:collapsible => true,
|
||||
:container_name => "without_project",
|
||||
:parent_container_type => "home"
|
||||
|
|
@ -104,8 +102,8 @@ module TodosHelper
|
|||
end
|
||||
|
||||
content_tag(:div,
|
||||
:class=>settings[:class],
|
||||
:id=>settings[:id],
|
||||
:class => settings[:class],
|
||||
:id => settings[:id],
|
||||
:style => "display:" + (settings[:show_container] ? "block" : "none")) do
|
||||
yield
|
||||
end
|
||||
|
|
@ -129,7 +127,7 @@ module TodosHelper
|
|||
# do not pass :class to partial locals
|
||||
settings.delete(:class)
|
||||
|
||||
content_tag(:div, :id =>settings[:id]+"_items", :class=>"items toggle_target") do
|
||||
content_tag(:div, :id => settings[:id] + "_items", :class => "items toggle_target") do
|
||||
todos_container_empty_message(settings[:container_name], settings[:id], collection.empty?) +
|
||||
render(:partial => "todos/todo", :collection => collection, :locals => settings)
|
||||
end
|
||||
|
|
@ -138,19 +136,18 @@ module TodosHelper
|
|||
def todos_calendar_container(period, collection)
|
||||
render :partial => 'todos/collection',
|
||||
:object => collection,
|
||||
:locals => {:settings => {
|
||||
:locals => { :settings => {
|
||||
:collapsible => false,
|
||||
:show_empty_containers => true,
|
||||
:container_name => "#{period}",
|
||||
:title =>t("todos.calendar.#{period}", :month => l(Time.zone.now, :format => "%B"), :next_month => l(1.month.from_now, :format => "%B"))
|
||||
}
|
||||
}
|
||||
} }
|
||||
end
|
||||
|
||||
# === helpers for rendering a todo
|
||||
|
||||
def remote_star_icon(todo=@todo)
|
||||
link_to( image_tag_for_star(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
|
||||
|
|
@ -167,7 +164,7 @@ module TodosHelper
|
|||
def remote_delete_menu_item(todo)
|
||||
return link_to(
|
||||
t('todos.delete'),
|
||||
{:controller => 'todos', :action => 'destroy', :id => todo.id},
|
||||
{ :controller => 'todos', :action => 'destroy', :id => todo.id },
|
||||
:class => "icon_delete_item",
|
||||
:id => dom_id(todo, "delete"),
|
||||
:x_confirm_message => t('todos.confirm_delete', :description => todo.description),
|
||||
|
|
@ -175,11 +172,11 @@ module TodosHelper
|
|||
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 = { :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'
|
||||
|
||||
options = {:x_defer_alert => false, :class => "icon_defer_item icon_defer_#{days}_item", :id => "defer_#{days}_#{dom_id(todo)}" }
|
||||
options = { :x_defer_alert => false, :class => "icon_defer_item icon_defer_#{days}_item", :id => "defer_#{days}_#{dom_id(todo)}" }
|
||||
if todo.due
|
||||
futuredate = (todo.show_from || todo.user.date) + days.days
|
||||
if futuredate.at_midnight > todo.due.at_midnight
|
||||
|
|
@ -204,32 +201,32 @@ module TodosHelper
|
|||
:_source_view => (@source_view.underscore.gsub(/\s+/,'_') rescue "")}
|
||||
url[:_tag_name] = @tag_name if @source_view == 'tag'
|
||||
|
||||
link_to(t('todos.convert_to_project'), url, {:class => "icon_item_to_project", :id => dom_id(todo, "to_project")})
|
||||
link_to(t('todos.convert_to_project'), url, { :class => "icon_item_to_project", :id => dom_id(todo, "to_project") })
|
||||
end
|
||||
|
||||
def attachment_image(todo)
|
||||
link_to(
|
||||
image_tag('blank.png', width: 16, height: 16, border:0),
|
||||
todo.attachments.first.file.url,
|
||||
{:class => 'todo_attachment', title: 'Get attachments of this todo'}
|
||||
{ :class => 'todo_attachment', title: 'Get attachments of this todo' }
|
||||
)
|
||||
end
|
||||
|
||||
def collapsed_notes_image(todo)
|
||||
link = link_to(
|
||||
image_tag( 'blank.png', :width=>'16', :height=>'16', :border=>'0' ),
|
||||
image_tag( 'blank.png', :width => '16', :height => '16', :border => '0' ),
|
||||
"#",
|
||||
{:class => 'show_notes', :title => 'Show notes'})
|
||||
{ :class => 'show_notes', :title => 'Show notes' })
|
||||
notes = content_tag(:div, {
|
||||
:class => "todo_notes",
|
||||
:id => dom_id(todo, 'notes'),
|
||||
:style => "display:none"}) { raw render_text(todo.notes) }
|
||||
:style => "display:none" }) { raw render_text(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
|
||||
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
|
||||
|
|
@ -244,7 +241,7 @@ module TodosHelper
|
|||
end
|
||||
|
||||
def image_tag_for_star(todo)
|
||||
image_tag("blank.png", :title =>t('todos.star_action'), :class => "todo_star"+(todo.starred? ? " starred":""), :id => "star_img_"+todo.id.to_s)
|
||||
image_tag("blank.png", :title => t('todos.star_action'), :class => "todo_star" + (todo.starred? ? " starred" : ""), :id => "star_img_" + todo.id.to_s)
|
||||
end
|
||||
|
||||
def remote_toggle_checkbox(todo=@todo)
|
||||
|
|
@ -260,14 +257,14 @@ module TodosHelper
|
|||
|
||||
def date_span(todo=@todo)
|
||||
if todo.completed?
|
||||
content_tag(:span, {:class => :grey}) { format_date( todo.completed_at ) }
|
||||
content_tag(:span, { :class => :grey }) { format_date( todo.completed_at ) }
|
||||
elsif todo.pending?
|
||||
title = t('todos.depends_on')+ ": " + todo.uncompleted_predecessors.to_a.map(&:description).join(', ')
|
||||
content_tag(:a, {:title => title}) { content_tag(:span, {:class => :orange}) { t('todos.pending') } }
|
||||
content_tag(:a, { :title => title }) { content_tag(:span, { :class => :orange }) { t('todos.pending') } }
|
||||
elsif todo.deferred?
|
||||
show_date( todo.show_from )
|
||||
show_date(todo.show_from)
|
||||
else
|
||||
due_date( todo.due )
|
||||
due_date(todo.due)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -275,7 +272,7 @@ module TodosHelper
|
|||
unless todo.pending_successors.empty?
|
||||
pending_count = todo.pending_successors.count
|
||||
title = "#{t('todos.has_x_pending', :count => pending_count)}: #{todo.pending_successors.to_a.map(&:description).join(', ')}"
|
||||
image_tag( 'successor_off.png', :width=>'10', :height=>'16', :border=>'0', :title => title )
|
||||
image_tag('successor_off.png', :width => '10', :height => '16', :border => '0', :title => title)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -291,12 +288,12 @@ module TodosHelper
|
|||
todo.tags.to_a.join(', ')
|
||||
end
|
||||
|
||||
def tag_span (tag, mobile=false)
|
||||
def tag_span(tag, mobile=false)
|
||||
content_tag(:span, :class => "tag #{tag.label}") { link_to(tag.name, tag_path(tag.name, :format => mobile ? :m : nil)) }
|
||||
end
|
||||
|
||||
def tag_list(todo=@todo, mobile=false)
|
||||
content_tag(:span, :class => 'tags') { todo.tags.all_except_starred.collect{|tag| tag_span(tag, mobile)}.join('').html_safe }
|
||||
content_tag(:span, :class => 'tags') { todo.tags.all_except_starred.collect{ |tag| tag_span(tag, mobile) }.join('').html_safe }
|
||||
end
|
||||
|
||||
def tag_list_mobile(todo=@todo)
|
||||
|
|
@ -310,11 +307,11 @@ module TodosHelper
|
|||
def project_and_context_links(todo, parent_container_type, opts = {})
|
||||
links = ''
|
||||
if todo.completed?
|
||||
links << item_link_to_context( todo ) unless opts[:suppress_context]
|
||||
links << item_link_to_project( todo ) unless opts[:suppress_project] || todo.project.nil?
|
||||
links << item_link_to_context(todo) unless opts[:suppress_context]
|
||||
links << item_link_to_project(todo) unless opts[:suppress_project] || todo.project.nil?
|
||||
else
|
||||
links << item_link_to_context( todo ) if include_context_link(todo, parent_container_type)
|
||||
links << item_link_to_project( todo ) if include_project_link(todo, parent_container_type)
|
||||
links << item_link_to_context(todo) if include_context_link(todo, parent_container_type)
|
||||
links << item_link_to_project(todo) if include_project_link(todo, parent_container_type)
|
||||
end
|
||||
|
||||
links.html_safe
|
||||
|
|
@ -364,7 +361,7 @@ module TodosHelper
|
|||
end
|
||||
|
||||
def date_field_tag(name, id, value = nil, options = {})
|
||||
text_field_tag name, value, {"size" => 12, "id" => id, "class" => "Date", "autocomplete" => "off"}.update(options.stringify_keys)
|
||||
text_field_tag name, value, { "size" => 12, "id" => id, "class" => "Date", "autocomplete" => "off" }.update(options.stringify_keys)
|
||||
end
|
||||
|
||||
def sort_key(todo)
|
||||
|
|
@ -484,11 +481,11 @@ module TodosHelper
|
|||
|
||||
def todo_moved_out_of_container
|
||||
# moved from one project container to another
|
||||
moved_project = @project_changed && @group_view_by=='project'
|
||||
moved_project = @project_changed && @group_view_by == 'project'
|
||||
# moved from one context container to another
|
||||
moved_context = @context_changed && @group_view_by=='context'
|
||||
moved_context = @context_changed && @group_view_by == 'context'
|
||||
# moved from actions-without-project container to another
|
||||
moved_without_project = @context_changed && @group_view_by=='project' && @todo.project_id.nil?
|
||||
moved_without_project = @context_changed && @group_view_by == 'project' && @todo.project_id.nil?
|
||||
|
||||
return moved_project || moved_context || moved_without_project
|
||||
end
|
||||
|
|
@ -557,7 +554,7 @@ module TodosHelper
|
|||
page.deferred { return todo_moved_out_of_container && (@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.tag { return update_needs_to_remove_todo_from_container && !@tag_was_removed }
|
||||
page.todo { return todo_moved_out_of_container && !(@todo.deferred? || @todo.pending? || @todo.hidden?) }
|
||||
end
|
||||
return false
|
||||
|
|
@ -684,5 +681,4 @@ module TodosHelper
|
|||
end
|
||||
return container_id.blank? ? "" : "$(\"##{container_id}\").slideDown(100);".html_safe
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
module UsersHelper
|
||||
def remote_delete_user(user)
|
||||
return link_to(
|
||||
image_tag("blank.png", :title =>t('users.destroy_user'), :class=>"delete_item"),
|
||||
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}",
|
||||
{ :id => "delete_user_#{user.id}",
|
||||
:class => "delete_user_button",
|
||||
:title => t('users.destroy_user'),
|
||||
:x_confirm_message => t('users.destroy_confirmation', :login => user.login)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class Context < ApplicationRecord
|
||||
|
||||
has_many :todos, -> { order(Arel.sql("todos.due IS NULL, todos.due ASC, todos.created_at ASC")).includes(:project) }, :dependent => :delete_all
|
||||
has_many :recurring_todos, :dependent => :delete_all
|
||||
belongs_to :user
|
||||
|
|
@ -15,7 +14,6 @@ class Context < ApplicationRecord
|
|||
include AASM
|
||||
|
||||
aasm :column => :state do
|
||||
|
||||
state :active, :initial => true
|
||||
state :closed
|
||||
state :hidden
|
||||
|
|
@ -48,11 +46,9 @@ class Context < ApplicationRecord
|
|||
def no_active_todos?
|
||||
return todos.active.count == 0
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class NullContext
|
||||
|
||||
def nil?
|
||||
true
|
||||
end
|
||||
|
|
@ -64,5 +60,4 @@ class NullContext
|
|||
def name
|
||||
''
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,17 +1,13 @@
|
|||
class Dependency < ApplicationRecord
|
||||
|
||||
# touch to make sure todo caches for predecessor and successor are invalidated
|
||||
|
||||
belongs_to :predecessor, :foreign_key => 'predecessor_id', :class_name => 'Todo', :touch => true
|
||||
belongs_to :successor, :foreign_key => 'successor_id', :class_name => 'Todo', :touch => true
|
||||
belongs_to :successor, :foreign_key => 'successor_id', :class_name => 'Todo', :touch => true
|
||||
|
||||
validate :check_circular_dependencies
|
||||
|
||||
def check_circular_dependencies
|
||||
unless predecessor.nil? or successor.nil?
|
||||
unless predecessor.nil? || successor.nil?
|
||||
errors.add("Depends on:", "Adding '#{successor.specification}' would create a circular dependency") if successor.is_successor?(predecessor)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class MessageGateway < ActionMailer::Base
|
||||
|
||||
def receive(email)
|
||||
user = get_receiving_user_from_email_address(email)
|
||||
return false if user.nil?
|
||||
|
|
|
|||
|
|
@ -3,11 +3,11 @@ class Preference < ApplicationRecord
|
|||
belongs_to :sms_context, :class_name => 'Context'
|
||||
|
||||
def self.themes
|
||||
{ :black => 'black', :light_blue => 'light_blue'}
|
||||
{ :black => 'black', :light_blue => 'light_blue' }
|
||||
end
|
||||
|
||||
def self.due_styles
|
||||
{ :due_in_n_days => 0, :due_on => 1}
|
||||
{ :due_in_n_days => 0, :due_on => 1 }
|
||||
end
|
||||
|
||||
def hide_completed_actions?
|
||||
|
|
@ -29,8 +29,7 @@ class Preference < ApplicationRecord
|
|||
date.in_time_zone(time_zone).beginning_of_day
|
||||
end
|
||||
|
||||
def format_date (date)
|
||||
def format_date(date)
|
||||
return date ? date.in_time_zone(time_zone).strftime("#{date_format}") : ''
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
class Project < ApplicationRecord
|
||||
has_many :todos, -> {order(Arel.sql("todos.due IS NULL, todos.due ASC, todos.created_at ASC"))}, dependent: :delete_all
|
||||
has_many :notes, -> {order "created_at DESC"}, dependent: :delete_all
|
||||
has_many :todos, -> { order(Arel.sql("todos.due IS NULL, todos.due ASC, todos.created_at ASC")) }, dependent: :delete_all
|
||||
has_many :notes, -> { order "created_at DESC" }, dependent: :delete_all
|
||||
has_many :recurring_todos
|
||||
|
||||
belongs_to :default_context, :class_name => "Context", :foreign_key => "default_context_id"
|
||||
|
|
@ -25,7 +25,6 @@ class Project < ApplicationRecord
|
|||
include AASM
|
||||
|
||||
aasm :column => :state do
|
||||
|
||||
state :active, :initial => true
|
||||
state :hidden
|
||||
state :completed, :enter => :set_completed_at_date, :exit => :clear_completed_at_date
|
||||
|
|
@ -145,11 +144,9 @@ class Project < ApplicationRecord
|
|||
end
|
||||
count
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class NullProject
|
||||
|
||||
def hidden?
|
||||
false
|
||||
end
|
||||
|
|
@ -169,5 +166,4 @@ class NullProject
|
|||
def persisted?
|
||||
false
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ class RecurringTodo < ApplicationRecord
|
|||
|
||||
has_many :todos
|
||||
|
||||
scope :active, -> { where state: 'active'}
|
||||
scope :completed, -> { where state: 'completed'}
|
||||
scope :active, -> { where state: 'active' }
|
||||
scope :completed, -> { where state: 'completed' }
|
||||
|
||||
include IsTaggable
|
||||
|
||||
|
|
@ -27,7 +27,7 @@ class RecurringTodo < ApplicationRecord
|
|||
validates_presence_of :description, :recurring_period, :target, :ends_on, :context
|
||||
|
||||
validates_length_of :description, :maximum => 100
|
||||
validates_length_of :notes, :maximum => 60000, :allow_nil => true
|
||||
validates_length_of :notes, :maximum => 60_000, :allow_nil => true
|
||||
|
||||
validate :period_validation
|
||||
validate :pattern_specific_validations
|
||||
|
|
@ -72,7 +72,7 @@ class RecurringTodo < ApplicationRecord
|
|||
|
||||
def pattern
|
||||
if valid_period?
|
||||
@pattern = eval("RecurringTodos::#{recurring_period.capitalize}RecurrencePattern.new(user)")
|
||||
@pattern = eval("RecurringTodos::#{recurring_period.capitalize}RecurrencePattern.new(user)", binding, __FILE__, __LINE__)
|
||||
@pattern.build_from_recurring_todo(self)
|
||||
end
|
||||
@pattern
|
||||
|
|
@ -138,5 +138,4 @@ class RecurringTodo < ApplicationRecord
|
|||
def continues_recurring?(previous)
|
||||
pattern.continues_recurring?(previous)
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
module RecurringTodos
|
||||
|
||||
class AbstractRecurrencePattern
|
||||
|
||||
attr_accessor :attributes
|
||||
|
||||
def initialize(user)
|
||||
|
|
@ -147,7 +145,7 @@ module RecurringTodos
|
|||
|
||||
# checks if the next todos should be put in the tickler for recurrence_target == 'due_date'
|
||||
def put_in_tickler?
|
||||
!( show_always? || show_from_delta.nil?)
|
||||
!(show_always? || show_from_delta.nil?)
|
||||
end
|
||||
|
||||
def get_next_date(previous)
|
||||
|
|
@ -207,14 +205,14 @@ module RecurringTodos
|
|||
end
|
||||
|
||||
def find_xth_day_of_month(x, weekday, month, year)
|
||||
start = Time.zone.local(year,month,1)
|
||||
start = Time.zone.local(year, month, 1)
|
||||
n = x
|
||||
while n > 0
|
||||
while start.wday() != weekday
|
||||
start += 1.day
|
||||
end
|
||||
n -= 1
|
||||
start += 1.day unless n==0
|
||||
start += 1.day unless n == 0
|
||||
end
|
||||
start
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,20 +1,18 @@
|
|||
module RecurringTodos
|
||||
|
||||
class AbstractRecurringTodosBuilder
|
||||
|
||||
attr_reader :mapped_attributes, :pattern
|
||||
|
||||
def initialize(user, attributes, pattern_class)
|
||||
@user = user
|
||||
@saved = false
|
||||
|
||||
@attributes = attributes
|
||||
@selector = get_selector(selector_key)
|
||||
@filterred_attributes = filter_attributes(@attributes)
|
||||
@mapped_attributes = map_attributes(@filterred_attributes)
|
||||
@attributes = attributes
|
||||
@selector = get_selector(selector_key)
|
||||
@filtered_attributes = filter_attributes(@attributes)
|
||||
@mapped_attributes = map_attributes(@filtered_attributes)
|
||||
|
||||
@pattern = pattern_class.new(user)
|
||||
@pattern.attributes = @mapped_attributes
|
||||
@pattern = pattern_class.new(user)
|
||||
@pattern.attributes = @mapped_attributes
|
||||
end
|
||||
|
||||
# build does not add tags. For tags, the recurring todos needs to be saved
|
||||
|
|
@ -60,36 +58,36 @@ module RecurringTodos
|
|||
|
||||
def filter_attributes(attributes)
|
||||
# get pattern independend attributes
|
||||
filterred_attributes = filter_generic_attributes(attributes)
|
||||
filtered_attributes = filter_generic_attributes(attributes)
|
||||
# append pattern specific attributes
|
||||
attributes_to_filter.each{|key| filterred_attributes[key]= attributes[key] if attributes.key?(key)}
|
||||
attributes_to_filter.each{ |key| filtered_attributes[key]= attributes[key] if attributes.key?(key) }
|
||||
|
||||
filterred_attributes
|
||||
filtered_attributes
|
||||
end
|
||||
|
||||
def filter_generic_attributes(attributes)
|
||||
return Tracks::AttributeHandler.new(@user, {
|
||||
recurring_period: attributes[:recurring_period],
|
||||
description: attributes[:description],
|
||||
notes: attributes[:notes],
|
||||
tag_list: tag_list_or_empty_string(attributes),
|
||||
start_from: attributes[:start_from],
|
||||
end_date: attributes[:end_date],
|
||||
ends_on: attributes[:ends_on],
|
||||
recurring_period: attributes[:recurring_period],
|
||||
description: attributes[:description],
|
||||
notes: attributes[:notes],
|
||||
tag_list: tag_list_or_empty_string(attributes),
|
||||
start_from: attributes[:start_from],
|
||||
end_date: attributes[:end_date],
|
||||
ends_on: attributes[:ends_on],
|
||||
number_of_occurrences: attributes[:number_of_occurrences],
|
||||
project: attributes[:project],
|
||||
context: attributes[:context],
|
||||
project_id: attributes[:project_id],
|
||||
context_id: attributes[:context_id],
|
||||
target: attributes[:recurring_target],
|
||||
show_from_delta: attributes[:recurring_show_days_before],
|
||||
show_always: attributes[:recurring_show_always]
|
||||
project: attributes[:project],
|
||||
context: attributes[:context],
|
||||
project_id: attributes[:project_id],
|
||||
context_id: attributes[:context_id],
|
||||
target: attributes[:recurring_target],
|
||||
show_from_delta: attributes[:recurring_show_days_before],
|
||||
show_always: attributes[:recurring_show_always]
|
||||
})
|
||||
end
|
||||
|
||||
def map_attributes
|
||||
# should be overwritten by subclasses to map attributes to activerecord model attributes
|
||||
@filterred_attributes
|
||||
@filtered_attributes
|
||||
end
|
||||
|
||||
# helper method to be used in mapped_attributes in subclasses
|
||||
|
|
@ -129,7 +127,7 @@ module RecurringTodos
|
|||
end
|
||||
|
||||
def save_tags
|
||||
@recurring_todo.tag_with(@filterred_attributes[:tag_list]) if @filterred_attributes[:tag_list].present?
|
||||
@recurring_todo.tag_with(@filtered_attributes[:tag_list]) if @filtered_attributes[:tag_list].present?
|
||||
@recurring_todo.reload
|
||||
end
|
||||
|
||||
|
|
@ -145,7 +143,5 @@ module RecurringTodos
|
|||
# avoid nil
|
||||
attributes[:tag_list].blank? ? "" : attributes[:tag_list].strip
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
module RecurringTodos
|
||||
|
||||
class DailyRecurrencePattern < AbstractRecurrencePattern
|
||||
|
||||
def initialize(user)
|
||||
super user
|
||||
end
|
||||
|
|
@ -44,9 +42,8 @@ module RecurringTodos
|
|||
else
|
||||
# if there was no previous todo, do not add n: the first todo starts on
|
||||
# today or on start_from
|
||||
return previous == nil ? start : start+every_x_days.day-1.day
|
||||
return previous == nil ? start : start + every_x_days.day - 1.day
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module RecurringTodos
|
||||
|
||||
class DailyRecurringTodosBuilder < AbstractRecurringTodosBuilder
|
||||
attr_reader :recurring_todo, :pattern
|
||||
|
||||
|
|
@ -19,7 +18,7 @@ module RecurringTodos
|
|||
|
||||
def only_work_days?(daily_selector)
|
||||
{ 'daily_every_x_day' => false,
|
||||
'daily_every_work_day' => true}[daily_selector]
|
||||
'daily_every_work_day' => true }[daily_selector]
|
||||
end
|
||||
|
||||
def selector_key
|
||||
|
|
@ -29,7 +28,5 @@ module RecurringTodos
|
|||
def valid_selector?(selector)
|
||||
%w{daily_every_x_day daily_every_work_day}.include?(selector)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
module RecurringTodos
|
||||
|
||||
class MonthlyRecurrencePattern < AbstractRecurrencePattern
|
||||
|
||||
def initialize(user)
|
||||
super user
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module RecurringTodos
|
||||
|
||||
class MonthlyRecurringTodosBuilder < AbstractRecurringTodosBuilder
|
||||
attr_reader :recurring_todo
|
||||
|
||||
|
|
@ -26,7 +25,7 @@ module RecurringTodos
|
|||
end
|
||||
|
||||
def get_recurrence_selector
|
||||
@selector=='monthly_every_x_day' ? 0 : 1
|
||||
@selector == 'monthly_every_x_day' ? 0 : 1
|
||||
end
|
||||
|
||||
def get_every_other2
|
||||
|
|
@ -40,7 +39,5 @@ module RecurringTodos
|
|||
def valid_selector?(selector)
|
||||
%w{monthly_every_x_day monthly_every_xth_day}.include?(selector)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
module RecurringTodos
|
||||
|
||||
class RecurringTodosBuilder
|
||||
|
||||
attr_reader :builder, :project, :context, :tag_list, :user
|
||||
|
||||
def initialize (user, attributes)
|
||||
|
|
@ -17,7 +15,7 @@ module RecurringTodos
|
|||
|
||||
def create_builder(selector)
|
||||
raise "Unknown recurrence selector in :recurring_period (#{selector})" unless valid_selector? selector
|
||||
eval("RecurringTodos::#{selector.capitalize}RecurringTodosBuilder.new(@user, @attributes)")
|
||||
eval("RecurringTodos::#{selector.capitalize}RecurringTodosBuilder.new(@user, @attributes)", binding, __FILE__, __LINE__)
|
||||
end
|
||||
|
||||
def build
|
||||
|
|
@ -72,7 +70,5 @@ module RecurringTodos
|
|||
def parse_context
|
||||
@context, @new_context_created = @attributes.parse_collection(:context, @user.contexts)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
module RecurringTodos
|
||||
|
||||
class WeeklyRecurrencePattern < AbstractRecurrencePattern
|
||||
|
||||
def initialize(user)
|
||||
super user
|
||||
end
|
||||
|
|
@ -31,7 +29,7 @@ module RecurringTodos
|
|||
def validate
|
||||
super
|
||||
validate_not_blank(every_x_week, "Every other nth week may not be empty for weekly recurrence setting")
|
||||
something_set = %w{sunday monday tuesday wednesday thursday friday saturday}.inject(false) { |set, day| set || self.send("on_#{day}") }
|
||||
something_set = %w{ sunday monday tuesday wednesday thursday friday saturday }.inject(false) { |set, day| set || self.send("on_#{day}") }
|
||||
errors[:base] << "You must specify at least one day on which the todo recurs" unless something_set
|
||||
end
|
||||
|
||||
|
|
@ -61,7 +59,7 @@ module RecurringTodos
|
|||
if start.wday() == 0
|
||||
# we went to a new week, go to the nth next week and find first match
|
||||
# that week. Note that we already went into the next week, so -1
|
||||
start += (every_x_week-1).week
|
||||
start += (every_x_week - 1).week
|
||||
end
|
||||
unless self.start_from.nil?
|
||||
# check if the start_from date is later than previous. If so, use
|
||||
|
|
@ -75,12 +73,9 @@ module RecurringTodos
|
|||
def find_first_day_in_this_week(start)
|
||||
# check if there are any days left this week for the next todo
|
||||
start.wday().upto 6 do |i|
|
||||
return start + (i-start.wday()).days if on_xday(i)
|
||||
return start + (i - start.wday()).days if on_xday(i)
|
||||
end
|
||||
-1
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module RecurringTodos
|
||||
|
||||
class WeeklyRecurringTodosBuilder < AbstractRecurringTodosBuilder
|
||||
attr_reader :recurring_todo
|
||||
|
||||
|
|
@ -8,7 +7,7 @@ module RecurringTodos
|
|||
end
|
||||
|
||||
def attributes_to_filter
|
||||
%w{weekly_selector weekly_every_x_week} + %w{monday tuesday wednesday thursday friday saturday sunday}.map{|day| "weekly_return_#{day}" }
|
||||
%w{ weekly_selector weekly_every_x_week } + %w{ monday tuesday wednesday thursday friday saturday sunday }.map{ |day| "weekly_return_#{day}" }
|
||||
end
|
||||
|
||||
def map_attributes(mapping)
|
||||
|
|
@ -26,7 +25,7 @@ module RecurringTodos
|
|||
mapping.set_if_nil(key, ' ') # avoid nil
|
||||
mapping.set_if_nil(source_key, ' ') # avoid nil
|
||||
|
||||
mapping.set(key, mapping.get(key)[0, index] + mapping.get(source_key) + mapping.get(key)[index+1, mapping.get(key).length])
|
||||
mapping.set(key, mapping.get(key)[0, index] + mapping.get(source_key) + mapping.get(key)[index + 1, mapping.get(key).length])
|
||||
mapping.except(source_key)
|
||||
end
|
||||
|
||||
|
|
@ -37,7 +36,5 @@ module RecurringTodos
|
|||
def valid_selector?(key)
|
||||
true
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
module RecurringTodos
|
||||
|
||||
class YearlyRecurrencePattern < AbstractRecurrencePattern
|
||||
|
||||
def initialize(user)
|
||||
super user
|
||||
end
|
||||
|
|
@ -104,6 +102,5 @@ module RecurringTodos
|
|||
|
||||
the_next
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module RecurringTodos
|
||||
|
||||
class YearlyRecurringTodosBuilder < AbstractRecurringTodosBuilder
|
||||
attr_reader :recurring_todo
|
||||
|
||||
|
|
@ -39,7 +38,5 @@ module RecurringTodos
|
|||
def get_every_other2
|
||||
{ 0 => :yearly_month_of_year, 1 => :yearly_month_of_year2 }[get_recurrence_selector]
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
module Search
|
||||
|
||||
class SearchResults
|
||||
attr_reader :results
|
||||
|
||||
|
|
@ -27,28 +26,26 @@ module Search
|
|||
|
||||
def incomplete_todos(terms)
|
||||
@user.todos.
|
||||
where("(todos.description " + Common.like_operator + " ? OR todos.notes " + Common.like_operator + " ?) AND todos.completed_at IS NULL", terms, terms).
|
||||
includes(Todo::DEFAULT_INCLUDES).
|
||||
reorder(Arel.sql("todos.due IS NULL, todos.due ASC, todos.created_at ASC"))
|
||||
where("(todos.description " + Common.like_operator + " ? OR todos.notes " + Common.like_operator + " ?) AND todos.completed_at IS NULL", terms, terms)
|
||||
.includes(Todo::DEFAULT_INCLUDES)
|
||||
.reorder(Arel.sql("todos.due IS NULL, todos.due ASC, todos.created_at ASC"))
|
||||
end
|
||||
|
||||
def complete_todos(terms)
|
||||
@user.todos.
|
||||
where("(todos.description " + Common.like_operator + " ? OR todos.notes " + Common.like_operator + " ?) AND NOT (todos.completed_at IS NULL)", terms, terms).
|
||||
includes(Todo::DEFAULT_INCLUDES).
|
||||
reorder("todos.completed_at DESC")
|
||||
where("(todos.description " + Common.like_operator + " ? OR todos.notes " + Common.like_operator + " ?) AND NOT (todos.completed_at IS NULL)", terms, terms)
|
||||
.includes(Todo::DEFAULT_INCLUDES)
|
||||
.reorder("todos.completed_at DESC")
|
||||
end
|
||||
|
||||
def todo_tags_by_name(terms)
|
||||
Tagging.find_by_sql([
|
||||
"SELECT DISTINCT tags.name as name "+
|
||||
"FROM tags "+
|
||||
"LEFT JOIN taggings ON tags.id = taggings.tag_id "+
|
||||
"LEFT JOIN todos ON taggings.taggable_id = todos.id "+
|
||||
"WHERE todos.user_id=? "+
|
||||
"AND tags.name " + Common.like_operator + " ? ", @user.id, terms])
|
||||
"SELECT DISTINCT tags.name as name " +
|
||||
"FROM tags " +
|
||||
"LEFT JOIN taggings ON tags.id = taggings.tag_id " +
|
||||
"LEFT JOIN todos ON taggings.taggable_id = todos.id " +
|
||||
"WHERE todos.user_id=? " +
|
||||
"AND tags.name " + Common.like_operator + " ? ", @user.id, terms])
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
module Stats
|
||||
class Actions
|
||||
|
||||
SECONDS_PER_DAY = 86400;
|
||||
SECONDS_PER_DAY = 86_400
|
||||
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
|
||||
|
|
@ -58,17 +58,17 @@ module Stats
|
|||
@interpolated_actions_created_this_month = interpolate_avg_for_current_month(@actions_created_last12months_array)
|
||||
@interpolated_actions_done_this_month = interpolate_avg_for_current_month(@actions_done_last12months_array)
|
||||
|
||||
@created_count_array = Array.new(13, actions_last12months.created_after(@cut_off_year).count(:all)/12.0)
|
||||
@done_count_array = Array.new(13, actions_last12months.completed_after(@cut_off_year).count(:all)/12.0)
|
||||
@created_count_array = Array.new(13, actions_last12months.created_after(@cut_off_year).count(:all) / 12.0)
|
||||
@done_count_array = Array.new(13, actions_last12months.completed_after(@cut_off_year).count(:all) / 12.0)
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.labels.avg_created'), data: @created_count_array, type: "line"},
|
||||
{label: I18n.t('stats.labels.avg_completed'), data: @done_count_array, type: "line"},
|
||||
{label: I18n.t('stats.labels.month_avg_completed', :months => 3), data: @actions_done_avg_last12months_array, type: "line"},
|
||||
{label: I18n.t('stats.labels.month_avg_created', :months => 3), data: @actions_created_avg_last12months_array, type: "line"},
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_created_last12months_array},
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_done_last12months_array},
|
||||
{ label: I18n.t('stats.labels.avg_created'), data: @created_count_array, type: "line" },
|
||||
{ label: I18n.t('stats.labels.avg_completed'), data: @done_count_array, type: "line" },
|
||||
{ label: I18n.t('stats.labels.month_avg_completed', :months => 3), data: @actions_done_avg_last12months_array, type: "line" },
|
||||
{ label: I18n.t('stats.labels.month_avg_created', :months => 3), data: @actions_created_avg_last12months_array, type: "line" },
|
||||
{ label: I18n.t('stats.labels.created'), data: @actions_created_last12months_array },
|
||||
{ label: I18n.t('stats.labels.completed'), data: @actions_done_last12months_array },
|
||||
],
|
||||
labels: array_of_month_labels(@done_count_array.size),
|
||||
}
|
||||
|
|
@ -86,17 +86,17 @@ module Stats
|
|||
# find max for graph in both hashes
|
||||
@max = [@actions_done_last30days_array.max, @actions_created_last30days_array.max].max
|
||||
|
||||
created_count_array = Array.new(30){ |i| @actions_created_last30days.size/30.0 }
|
||||
done_count_array = Array.new(30){ |i| @actions_done_last30days.size/30.0 }
|
||||
created_count_array = Array.new(30) { |i| @actions_created_last30days.size / 30.0 }
|
||||
done_count_array = Array.new(30) { |i| @actions_done_last30days.size / 30.0 }
|
||||
# TODO: make the strftime i18n proof
|
||||
time_labels = Array.new(30){ |i| I18n.l(Time.zone.now-i.days, :format => :stats) }
|
||||
time_labels = Array.new(30) { |i| I18n.l(Time.zone.now-i.days, :format => :stats) }
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.labels.avg_created'), data: created_count_array, type: "line"},
|
||||
{label: I18n.t('stats.labels.avg_completed'), data: done_count_array, type: "line"},
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_created_last30days_array},
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_done_last30days_array},
|
||||
{ label: I18n.t('stats.labels.avg_created'), data: created_count_array, type: "line" },
|
||||
{ label: I18n.t('stats.labels.avg_completed'), data: done_count_array, type: "line" },
|
||||
{ label: I18n.t('stats.labels.created'), data: @actions_created_last30days_array },
|
||||
{ label: I18n.t('stats.labels.completed'), data: @actions_done_last30days_array },
|
||||
],
|
||||
labels: time_labels,
|
||||
}
|
||||
|
|
@ -119,14 +119,14 @@ module Stats
|
|||
# get percentage done cumulative
|
||||
@cum_percent_done = convert_to_cumulative_array(@actions_completion_time_array, @actions_completion_time.count(:all))
|
||||
|
||||
time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" }
|
||||
time_labels = Array.new(@count) { |i| "#{i}-#{i+1}" }
|
||||
time_labels[0] = I18n.t('stats.within_one')
|
||||
time_labels[@count] = "> #{@count}"
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.legend.percentage'), data: @cum_percent_done, type: "line"},
|
||||
{label: I18n.t('stats.legend.actions'), data: @actions_completion_time_array},
|
||||
{ label: I18n.t('stats.legend.percentage'), data: @cum_percent_done, type: "line" },
|
||||
{ label: I18n.t('stats.legend.actions'), data: @actions_completion_time_array },
|
||||
],
|
||||
labels: time_labels,
|
||||
}
|
||||
|
|
@ -149,14 +149,14 @@ module Stats
|
|||
# get percentage done cumulative
|
||||
@cum_percent_done = convert_to_cumulative_array(@actions_running_time_array, @actions_running_time.count )
|
||||
|
||||
time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" }
|
||||
time_labels = Array.new(@count) { |i| "#{i}-#{i+1}" }
|
||||
time_labels[0] = "< 1"
|
||||
time_labels[@count] = "> #{@count}"
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.running_time_all_legend.percentage'), data: @cum_percent_done, type: "line"},
|
||||
{label: I18n.t('stats.running_time_all_legend.actions'), data: @actions_running_time_array},
|
||||
{ label: I18n.t('stats.running_time_all_legend.percentage'), data: @cum_percent_done, type: "line" },
|
||||
{ label: I18n.t('stats.running_time_all_legend.actions'), data: @actions_running_time_array },
|
||||
],
|
||||
labels: time_labels,
|
||||
}
|
||||
|
|
@ -171,12 +171,12 @@ module Stats
|
|||
# - actions not deferred (show_from must be null)
|
||||
# - actions not pending/blocked
|
||||
|
||||
@actions_running_time = @user.todos.not_completed.not_hidden.not_deferred_or_blocked.
|
||||
select("todos.created_at").
|
||||
reorder("todos.created_at DESC")
|
||||
@actions_running_time = @user.todos.not_completed.not_hidden.not_deferred_or_blocked
|
||||
.select("todos.created_at")
|
||||
.reorder("todos.created_at DESC")
|
||||
|
||||
@max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at)
|
||||
@actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks+1, :created_at)
|
||||
@actions_running_per_week_array = convert_to_weeks_from_today_array(@actions_running_time, @max_weeks + 1, :created_at)
|
||||
|
||||
# cut off chart at 52 weeks = one year
|
||||
@count = [52, @max_weeks].min
|
||||
|
|
@ -188,23 +188,23 @@ module Stats
|
|||
# get percentage done cumulative
|
||||
@cum_percent_done = convert_to_cumulative_array(@actions_running_time_array, @actions_running_time.count )
|
||||
|
||||
time_labels = Array.new(@count){ |i| "#{i}-#{i+1}" }
|
||||
time_labels = Array.new(@count) { |i| "#{i}-#{i+1}" }
|
||||
time_labels[0] = "< 1"
|
||||
time_labels[@count] = "> #{@count}"
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.running_time_legend.percentage'), data: @cum_percent_done, type: "line"},
|
||||
{label: I18n.t('stats.running_time_legend.actions'), data: @actions_running_time_array},
|
||||
{ label: I18n.t('stats.running_time_legend.percentage'), data: @cum_percent_done, type: "line" },
|
||||
{ label: I18n.t('stats.running_time_legend.actions'), data: @actions_running_time_array },
|
||||
],
|
||||
labels: time_labels,
|
||||
}
|
||||
end
|
||||
|
||||
def open_per_week_data
|
||||
@actions_started = @user.todos.created_after(@today-53.weeks).
|
||||
select("todos.created_at, todos.completed_at").
|
||||
reorder("todos.created_at DESC")
|
||||
@actions_started = @user.todos.created_after(@today - 53.weeks)
|
||||
.select("todos.created_at, todos.completed_at")
|
||||
.reorder("todos.created_at DESC")
|
||||
|
||||
@max_weeks = difference_in_weeks(@today, @actions_started.last.created_at)
|
||||
|
||||
|
|
@ -214,12 +214,12 @@ module Stats
|
|||
@actions_open_per_week_array = convert_to_weeks_running_from_today_array(@actions_started, @max_weeks+1)
|
||||
@actions_open_per_week_array = cut_off_array(@actions_open_per_week_array, @count)
|
||||
|
||||
time_labels = Array.new(@count+1){ |i| "#{i}-#{i+1}" }
|
||||
time_labels[0] = "< 1"
|
||||
time_labels = Array.new(@count+1) { |i| "#{i}-#{i+1}" }
|
||||
time_labels[0] = "< 1"
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.open_per_week_legend.actions'), data: @actions_open_per_week_array},
|
||||
{ label: I18n.t('stats.open_per_week_legend.actions'), data: @actions_open_per_week_array },
|
||||
],
|
||||
labels: time_labels,
|
||||
}
|
||||
|
|
@ -230,18 +230,18 @@ module Stats
|
|||
@actions_completion_day = @user.todos.completed.select("completed_at")
|
||||
|
||||
# convert to array and fill in non-existing days
|
||||
@actions_creation_day_array = Array.new(7) { |i| 0}
|
||||
@actions_creation_day.each { |t| @actions_creation_day_array[ t.created_at.wday ] += 1 }
|
||||
@actions_creation_day_array = Array.new(7) { |i| 0 }
|
||||
@actions_creation_day.each { |t| @actions_creation_day_array[t.created_at.wday] += 1 }
|
||||
@max = @actions_creation_day_array.max
|
||||
|
||||
# convert to array and fill in non-existing days
|
||||
@actions_completion_day_array = Array.new(7) { |i| 0}
|
||||
@actions_completion_day.each { |t| @actions_completion_day_array[ t.completed_at.wday ] += 1 }
|
||||
@actions_completion_day_array = Array.new(7) { |i| 0 }
|
||||
@actions_completion_day.each { |t| @actions_completion_day_array[t.completed_at.wday] += 1 }
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_day_array},
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array},
|
||||
{ label: I18n.t('stats.labels.created'), data: @actions_creation_day_array },
|
||||
{ label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array },
|
||||
],
|
||||
labels: I18n.t('date.day_names'),
|
||||
}
|
||||
|
|
@ -253,17 +253,17 @@ module Stats
|
|||
|
||||
# convert to hash to be able to fill in non-existing days
|
||||
@max=0
|
||||
@actions_creation_day_array = Array.new(7) { |i| 0}
|
||||
@actions_creation_day.each { |r| @actions_creation_day_array[ r.created_at.wday ] += 1 }
|
||||
@actions_creation_day_array = Array.new(7) { |i| 0 }
|
||||
@actions_creation_day.each { |r| @actions_creation_day_array[r.created_at.wday] += 1 }
|
||||
|
||||
# convert to hash to be able to fill in non-existing days
|
||||
@actions_completion_day_array = Array.new(7) { |i| 0}
|
||||
@actions_completion_day_array = Array.new(7) { |i| 0 }
|
||||
@actions_completion_day.each { |r| @actions_completion_day_array[r.completed_at.wday] += 1 }
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_day_array},
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array},
|
||||
{ label: I18n.t('stats.labels.created'), data: @actions_creation_day_array },
|
||||
{ label: I18n.t('stats.labels.completed'), data: @actions_completion_day_array },
|
||||
],
|
||||
labels: I18n.t('date.day_names'),
|
||||
}
|
||||
|
|
@ -274,17 +274,17 @@ module Stats
|
|||
@actions_completion_hour = @user.todos.completed.select("completed_at")
|
||||
|
||||
# convert to hash to be able to fill in non-existing days
|
||||
@actions_creation_hour_array = Array.new(24) { |i| 0}
|
||||
@actions_creation_hour_array = Array.new(24) { |i| 0 }
|
||||
@actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 }
|
||||
|
||||
# convert to hash to be able to fill in non-existing days
|
||||
@actions_completion_hour_array = Array.new(24) { |i| 0}
|
||||
@actions_completion_hour_array = Array.new(24) { |i| 0 }
|
||||
@actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 }
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array},
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array},
|
||||
{ label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array },
|
||||
{ label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array },
|
||||
],
|
||||
labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] },
|
||||
}
|
||||
|
|
@ -295,17 +295,17 @@ module Stats
|
|||
@actions_completion_hour = @user.todos.completed_after(@cut_off_month).select("completed_at")
|
||||
|
||||
# convert to hash to be able to fill in non-existing days
|
||||
@actions_creation_hour_array = Array.new(24) { |i| 0}
|
||||
@actions_creation_hour_array = Array.new(24) { |i| 0 }
|
||||
@actions_creation_hour.each{|r| @actions_creation_hour_array[r.created_at.hour] += 1 }
|
||||
|
||||
# convert to hash to be able to fill in non-existing days
|
||||
@actions_completion_hour_array = Array.new(24) { |i| 0}
|
||||
@actions_completion_hour_array = Array.new(24) { |i| 0 }
|
||||
@actions_completion_hour.each{|r| @actions_completion_hour_array[r.completed_at.hour] += 1 }
|
||||
|
||||
return {
|
||||
datasets: [
|
||||
{label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array},
|
||||
{label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array},
|
||||
{ label: I18n.t('stats.labels.created'), data: @actions_creation_hour_array },
|
||||
{ label: I18n.t('stats.labels.completed'), data: @actions_completion_hour_array },
|
||||
],
|
||||
labels: @actions_creation_hour_array.each_with_index.map { |total, hour| [hour] },
|
||||
}
|
||||
|
|
@ -334,7 +334,7 @@ module Stats
|
|||
end
|
||||
|
||||
def interpolate_avg_for_current_month(set)
|
||||
(set[0]*(1/percent_of_month) + set[1] + set[2]) / 3.0
|
||||
(set[0] * (1 / percent_of_month) + set[1] + set[2]) / 3.0
|
||||
end
|
||||
|
||||
def percent_of_month
|
||||
|
|
@ -350,15 +350,15 @@ module Stats
|
|||
end
|
||||
|
||||
def put_events_into_month_buckets(records, array_size, date_method_on_todo)
|
||||
convert_to_array(records.select { |x| x.send(date_method_on_todo) }, array_size) { |r| [difference_in_months(@today, r.send(date_method_on_todo))]}
|
||||
convert_to_array(records.select { |x| x.send(date_method_on_todo) }, array_size) { |r| [difference_in_months(@today, r.send(date_method_on_todo))] }
|
||||
end
|
||||
|
||||
def convert_to_days_from_today_array(records, array_size, date_method_on_todo)
|
||||
return convert_to_array(records, array_size){ |r| [difference_in_days(@today, r.send(date_method_on_todo))]}
|
||||
return convert_to_array(records, array_size) { |r| [difference_in_days(@today, r.send(date_method_on_todo))] }
|
||||
end
|
||||
|
||||
def convert_to_weeks_from_today_array(records, array_size, date_method_on_todo)
|
||||
return convert_to_array(records, array_size) { |r| [difference_in_weeks(@today, r.send(date_method_on_todo))]}
|
||||
return convert_to_array(records, array_size) { |r| [difference_in_weeks(@today, r.send(date_method_on_todo))] }
|
||||
end
|
||||
|
||||
def convert_to_weeks_running_array(records, array_size)
|
||||
|
|
@ -373,37 +373,37 @@ module Stats
|
|||
a = []
|
||||
start_week = difference_in_weeks(@today, record.created_at)
|
||||
end_week = record.completed_at ? difference_in_weeks(@today, record.completed_at) : 0
|
||||
end_week.upto(start_week) { |i| a << i };
|
||||
end_week.upto(start_week) { |i| a << i }
|
||||
return a
|
||||
end
|
||||
|
||||
def cut_off_array_with_sum(array, cut_off)
|
||||
# +1 to hold sum of rest
|
||||
a = Array.new(cut_off+1){|i| array[i]||0}
|
||||
a = Array.new(cut_off + 1) { |i| array[i] || 0 }
|
||||
# add rest of array to last elem
|
||||
a[cut_off] += array.inject(:+) - a.inject(:+)
|
||||
return a
|
||||
end
|
||||
|
||||
def cut_off_array(array, cut_off)
|
||||
return Array.new(cut_off){|i| array[i]||0}
|
||||
return Array.new(cut_off) { |i| array[i] || 0 }
|
||||
end
|
||||
|
||||
def convert_to_cumulative_array(array, max)
|
||||
# calculate fractions
|
||||
a = Array.new(array.size){|i| array[i]*100.0/max}
|
||||
a = Array.new(array.size) {|i| array[i] * 100.0 / max}
|
||||
# make cumulative
|
||||
1.upto(array.size-1){ |i| a[i] += a[i-1] }
|
||||
1.upto(array.size-1) { |i| a[i] += a[i - 1] }
|
||||
return a
|
||||
end
|
||||
|
||||
def difference_in_months(date1, date2)
|
||||
return (date1.utc.year - date2.utc.year)*12 + (date1.utc.month - date2.utc.month)
|
||||
return (date1.utc.year - date2.utc.year) * 12 + (date1.utc.month - date2.utc.month)
|
||||
end
|
||||
|
||||
# assumes date1 > date2
|
||||
def difference_in_days(date1, date2)
|
||||
return ((date1.utc.at_midnight-date2.utc.at_midnight)/SECONDS_PER_DAY).to_i
|
||||
return ((date1.utc.at_midnight - date2.utc.at_midnight) / SECONDS_PER_DAY).to_i
|
||||
end
|
||||
|
||||
# assumes date1 > date2
|
||||
|
|
@ -412,23 +412,23 @@ module Stats
|
|||
end
|
||||
|
||||
def three_month_avg(set, i)
|
||||
(set.fetch(i){ 0 } + set.fetch(i+1){ 0 } + set.fetch(i+2){ 0 }) / 3.0
|
||||
(set.fetch(i) { 0 } + set.fetch(i+1) { 0 } + set.fetch(i + 2) { 0 }) / 3.0
|
||||
end
|
||||
|
||||
def set_three_month_avg(set,upper_bound)
|
||||
(0..upper_bound-1).map { |i| three_month_avg(set, i) }
|
||||
def set_three_month_avg(set, upper_bound)
|
||||
(0..upper_bound - 1).map { |i| three_month_avg(set, i) }
|
||||
end
|
||||
|
||||
def compute_running_avg_array(set, upper_bound)
|
||||
result = set_three_month_avg(set, upper_bound)
|
||||
result[upper_bound-1] = result[upper_bound-1] * 3 if upper_bound == set.length
|
||||
result[upper_bound-2] = result[upper_bound-2] * 3 / 2 if upper_bound > 1 and upper_bound == set.length
|
||||
result[upper_bound - 1] = result[upper_bound-1] * 3 if upper_bound == set.length
|
||||
result[upper_bound - 2] = result[upper_bound-2] * 3 / 2 if upper_bound > 1 and upper_bound == set.length
|
||||
result[0] = "null"
|
||||
result
|
||||
end # unsolved, not triggered, edge case for set.length == upper_bound + 1
|
||||
|
||||
def month_label(i)
|
||||
I18n.t('date.month_names')[ (Time.zone.now.mon - i -1 ) % 12 + 1 ]
|
||||
I18n.t('date.month_names')[(Time.zone.now.mon - i -1 ) % 12 + 1]
|
||||
end
|
||||
|
||||
def array_of_month_labels(count)
|
||||
|
|
|
|||
|
|
@ -1,8 +1,7 @@
|
|||
module Stats
|
||||
|
||||
class Chart
|
||||
|
||||
attr_reader :action, :height, :width
|
||||
|
||||
def initialize(action, dimensions = {})
|
||||
@action = action
|
||||
@height = dimensions.fetch(:height) { 250 }
|
||||
|
|
@ -12,7 +11,5 @@ module Stats
|
|||
def dimensions
|
||||
"#{width}x#{height}"
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module Stats
|
||||
class Contexts
|
||||
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module Stats
|
||||
class Projects
|
||||
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
|
@ -24,6 +24,5 @@ module Stats
|
|||
projects = user.projects.order('created_at ASC')
|
||||
projects.sort_by{ |p| p.running_time }.reverse.take(10)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@
|
|||
# http://www.juixe.com/techknow/index.php/2006/07/15/acts-as-taggable-tag-cloud/
|
||||
module Stats
|
||||
class TagCloud
|
||||
|
||||
attr_reader :levels, :tags
|
||||
|
||||
def initialize(tags)
|
||||
@levels = 10
|
||||
@tags = tags.sort_by { |tag| tag.name.downcase }
|
||||
|
|
@ -32,7 +32,7 @@ module Stats
|
|||
end
|
||||
|
||||
def counts
|
||||
@counts ||= tags.map {|t| t.count}
|
||||
@counts ||= tags.map { |t| t.count }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module Stats
|
||||
class TagCloudQuery
|
||||
|
||||
attr_reader :user, :cutoff
|
||||
|
||||
def initialize(user, cutoff = nil)
|
||||
@user = user
|
||||
@cutoff = cutoff
|
||||
|
|
@ -19,20 +19,19 @@ module Stats
|
|||
|
||||
def sql
|
||||
# TODO: parameterize limit
|
||||
query = "SELECT tags.id, tags.name AS name, count(*) AS count"
|
||||
query = "SELECT tags.id, tags.name AS name, COUNT(*) AS count"
|
||||
query << " FROM taggings, tags, todos"
|
||||
query << " WHERE tags.id = tag_id"
|
||||
query << " AND todos.user_id=? "
|
||||
query << " AND taggings.taggable_type='Todo' "
|
||||
query << " AND taggings.taggable_id=todos.id "
|
||||
query << " AND todos.user_id = ? "
|
||||
query << " AND taggings.taggable_type = 'Todo' "
|
||||
query << " AND taggings.taggable_id = todos.id "
|
||||
if cutoff
|
||||
query << " AND (todos.created_at > ? OR "
|
||||
query << " todos.completed_at > ?) "
|
||||
end
|
||||
query << " GROUP BY tags.id, tags.name"
|
||||
query << " ORDER BY count DESC, name"
|
||||
query << " ORDER BY count DESC, name "
|
||||
query << " LIMIT 100"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
module Stats
|
||||
class TimeToComplete
|
||||
|
||||
SECONDS_PER_DAY = 86400;
|
||||
SECONDS_PER_DAY = 86_400
|
||||
|
||||
attr_reader :actions
|
||||
|
||||
def initialize(actions)
|
||||
@actions = actions
|
||||
end
|
||||
|
|
@ -52,12 +52,11 @@ module Stats
|
|||
end
|
||||
|
||||
def sum
|
||||
@sum ||= durations.inject(0) {|sum, d| sum + d}
|
||||
@sum ||= durations.inject(0) { |sum, d| sum + d }
|
||||
end
|
||||
|
||||
def arbitrary_day
|
||||
@arbitrary_day ||= Time.utc(2000, 1, 1, 0, 0)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
# and visible contexts will be included.
|
||||
module Stats
|
||||
class TopContextsQuery
|
||||
|
||||
attr_reader :user, :running, :limit
|
||||
|
||||
def initialize(user, options = {})
|
||||
@user = user
|
||||
@running = options.fetch(:running) { false }
|
||||
|
|
|
|||
|
|
@ -3,8 +3,8 @@
|
|||
# or completed since that cutoff will be included.
|
||||
module Stats
|
||||
class TopProjectsQuery
|
||||
|
||||
attr_reader :user, :cutoff
|
||||
|
||||
def initialize(user, cutoff = nil)
|
||||
@user = user
|
||||
@cutoff = cutoff
|
||||
|
|
@ -34,6 +34,5 @@ module Stats
|
|||
query << "ORDER BY count DESC "
|
||||
query << "LIMIT 10"
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module Stats
|
||||
class Totals
|
||||
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
|
@ -83,6 +83,5 @@ module Stats
|
|||
def tag_ids
|
||||
@tag_ids ||= Stats::UserTagsQuery.new(user).result.map(&:id)
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module Stats
|
||||
class UserStats
|
||||
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
|
@ -38,6 +38,5 @@ module Stats
|
|||
end
|
||||
@tag_cloud_90days
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
module Stats
|
||||
class UserTagsQuery
|
||||
|
||||
attr_reader :user
|
||||
|
||||
def initialize(user)
|
||||
@user = user
|
||||
end
|
||||
|
|
@ -21,6 +21,5 @@ module Stats
|
|||
AND todos.user_id = ?
|
||||
SQL
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class Tag < ApplicationRecord
|
||||
|
||||
has_many :taggings
|
||||
has_many :taggable, :through => :taggings
|
||||
|
||||
|
|
@ -29,5 +28,4 @@ class Tag < ApplicationRecord
|
|||
def to_s
|
||||
name
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,8 +1,5 @@
|
|||
|
||||
# The Tagging join model.
|
||||
|
||||
class Tagging < ApplicationRecord
|
||||
|
||||
belongs_to :tag
|
||||
belongs_to :taggable, :polymorphic => true, :touch => true
|
||||
|
||||
|
|
@ -13,5 +10,4 @@ class Tagging < ApplicationRecord
|
|||
def delete_orphaned_tag
|
||||
tag.destroy if tag and tag.taggings.count == 0
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
class Todo < ApplicationRecord
|
||||
|
||||
MAX_DESCRIPTION_LENGTH = 300
|
||||
MAX_NOTES_LENGTH = 60000
|
||||
MAX_NOTES_LENGTH = 60_000
|
||||
|
||||
after_save :save_predecessors
|
||||
|
||||
|
|
@ -19,9 +18,9 @@ class Todo < ApplicationRecord
|
|||
has_many :successor_dependencies, :foreign_key => 'successor_id', :class_name => 'Dependency', :dependent => :destroy
|
||||
has_many :predecessors, :through => :successor_dependencies
|
||||
has_many :successors, :through => :predecessor_dependencies
|
||||
has_many :uncompleted_predecessors, -> {where('NOT (todos.state = ?)', 'completed')}, :through => :successor_dependencies,
|
||||
has_many :uncompleted_predecessors, -> { where('NOT (todos.state = ?)', 'completed') }, :through => :successor_dependencies,
|
||||
:source => :predecessor
|
||||
has_many :pending_successors, -> {where('todos.state = ?', 'pending')}, :through => :predecessor_dependencies,
|
||||
has_many :pending_successors, -> { where('todos.state = ?', 'pending') }, :through => :predecessor_dependencies,
|
||||
:source => :successor
|
||||
has_many :attachments, dependent: :destroy
|
||||
|
||||
|
|
@ -32,14 +31,14 @@ class Todo < ApplicationRecord
|
|||
scope :project_hidden, -> { joins('LEFT OUTER JOIN projects p ON p.id = todos.project_id').where('p.state = ?', 'hidden') }
|
||||
scope :completed, -> { where 'todos.state = ?', 'completed' }
|
||||
scope :deferred, -> { where 'todos.state = ?', 'deferred' }
|
||||
scope :blocked, -> {where 'todos.state = ?', 'pending' }
|
||||
scope :pending, -> {where 'todos.state = ?', 'pending' }
|
||||
scope :blocked, -> { where 'todos.state = ?', 'pending' }
|
||||
scope :pending, -> { where 'todos.state = ?', 'pending' }
|
||||
scope :deferred_or_blocked, -> { where '(todos.state = ?) OR (todos.state = ?)', 'deferred', 'pending' }
|
||||
scope :hidden, -> {
|
||||
joins('INNER JOIN contexts c_hidden ON c_hidden.id = todos.context_id').
|
||||
joins('LEFT OUTER JOIN projects p_hidden ON p_hidden.id = todos.project_id').
|
||||
where('(c_hidden.state = ? OR p_hidden.state = ?)', 'hidden', 'hidden').
|
||||
where('NOT todos.state = ?', 'completed') }
|
||||
joins('INNER JOIN contexts c_hidden ON c_hidden.id = todos.context_id')
|
||||
.joins('LEFT OUTER JOIN projects p_hidden ON p_hidden.id = todos.project_id')
|
||||
.where('(c_hidden.state = ? OR p_hidden.state = ?)', 'hidden', 'hidden')
|
||||
.where('NOT todos.state = ?', 'completed') }
|
||||
scope :not_hidden, -> { not_context_hidden.not_project_hidden }
|
||||
scope :not_deferred_or_blocked, -> { where '(NOT todos.state=?) AND (NOT todos.state = ?)', 'deferred', 'pending' }
|
||||
scope :not_project_hidden, -> { joins('LEFT OUTER JOIN projects p ON p.id = todos.project_id').where('p.id IS NULL OR NOT(p.state = ?)', 'hidden') }
|
||||
|
|
@ -50,12 +49,12 @@ class Todo < ApplicationRecord
|
|||
scope :are_due, -> { where 'NOT (todos.due IS NULL)' }
|
||||
scope :due_today, -> { where("todos.due <= ?", Time.zone.now) }
|
||||
scope :with_tag, lambda { |tag_id| joins("INNER JOIN taggings ON todos.id = taggings.taggable_id").where("taggings.tag_id = ? AND taggings.taggable_type='Todo'", tag_id) }
|
||||
scope :with_tags, lambda { |tag_ids| where("EXISTS(SELECT * from taggings t WHERE t.tag_id IN (?) AND t.taggable_id=todos.id AND t.taggable_type='Todo')", tag_ids) }
|
||||
scope :with_tags, lambda { |tag_ids| where("EXISTS(SELECT * FROM taggings t WHERE t.tag_id IN (?) AND t.taggable_id=todos.id AND t.taggable_type='Todo')", tag_ids) }
|
||||
scope :completed_after, lambda { |date| where("todos.completed_at > ?", date) }
|
||||
scope :completed_before, lambda { |date| where("todos.completed_at < ?", date) }
|
||||
scope :created_after, lambda { |date| where("todos.created_at > ?", date) }
|
||||
scope :created_before, lambda { |date| where("todos.created_at < ?", date) }
|
||||
scope :created_or_completed_after, lambda { |date| where("todos.created_at > ? or todos.completed_at > ?", date, date) }
|
||||
scope :created_or_completed_after, lambda { |date| where("todos.created_at > ? OR todos.completed_at > ?", date, date) }
|
||||
|
||||
def self.due_after(date)
|
||||
where('todos.due > ?', date)
|
||||
|
|
@ -66,16 +65,15 @@ class Todo < ApplicationRecord
|
|||
end
|
||||
|
||||
STARRED_TAG_NAME = "starred"
|
||||
DEFAULT_INCLUDES = [ :project, :context, :tags, :taggings, :pending_successors, :uncompleted_predecessors, :recurring_todo ]
|
||||
DEFAULT_INCLUDES = [:project, :context, :tags, :taggings, :pending_successors, :uncompleted_predecessors, :recurring_todo]
|
||||
|
||||
# state machine
|
||||
include AASM
|
||||
aasm_initial_state = Proc.new { (self.show_from && self.user && (self.show_from > self.user.date)) ? :deferred : :active}
|
||||
aasm_initial_state = Proc.new { (self.show_from && self.user && (self.show_from > self.user.date)) ? :deferred : :active }
|
||||
|
||||
aasm :column => :state do
|
||||
|
||||
state :active
|
||||
state :completed, :before_enter => Proc.new { self.completed_at = Time.zone.now }, :before_exit => Proc.new { self.completed_at = nil}
|
||||
state :completed, :before_enter => Proc.new { self.completed_at = Time.zone.now }, :before_exit => Proc.new { self.completed_at = nil }
|
||||
state :deferred, :before_exit => Proc.new { self[:show_from] = nil }
|
||||
state :pending
|
||||
|
||||
|
|
@ -124,7 +122,7 @@ class Todo < ApplicationRecord
|
|||
end
|
||||
|
||||
def no_uncompleted_predecessors_or_deferral?
|
||||
no_deferral = show_from.blank? or Time.zone.now > show_from
|
||||
no_deferral = show_from.blank? || Time.zone.now > show_from
|
||||
return (no_deferral && no_uncompleted_predecessors?)
|
||||
end
|
||||
|
||||
|
|
@ -141,7 +139,7 @@ class Todo < ApplicationRecord
|
|||
end
|
||||
|
||||
def not_part_of_hidden_container?
|
||||
!( (self.project && self.project.hidden?) || self.context.hidden? )
|
||||
!((self.project && self.project.hidden?) || self.context.hidden?)
|
||||
end
|
||||
|
||||
# Returns a string with description <context, project>
|
||||
|
|
@ -266,9 +264,9 @@ class Todo < ApplicationRecord
|
|||
def add_predecessor_list(predecessor_list)
|
||||
return unless predecessor_list.kind_of? String
|
||||
|
||||
@predecessor_array=predecessor_list.split(",").inject([]) do |list, todo_id|
|
||||
predecessor = self.user.todos.find( todo_id.to_i ) if todo_id.present?
|
||||
list << predecessor unless predecessor.nil?
|
||||
@predecessor_array = predecessor_list.split(",").inject([]) do |list, todo_id|
|
||||
predecessor = self.user.todos.find(todo_id.to_i) if todo_id.present?
|
||||
list << predecessor unless predecessor.nil?
|
||||
list
|
||||
end
|
||||
|
||||
|
|
@ -284,15 +282,15 @@ class Todo < ApplicationRecord
|
|||
|
||||
# activate todos that should be activated if the current todo is completed
|
||||
def activate_pending_todos
|
||||
pending_todos = successors.select { |t| t.uncompleted_predecessors.empty? and !t.completed? }
|
||||
pending_todos.each {|t| t.activate! }
|
||||
pending_todos = successors.select { |t| t.uncompleted_predecessors.empty? && !t.completed? }
|
||||
pending_todos.each { |t| t.activate! }
|
||||
return pending_todos
|
||||
end
|
||||
|
||||
# Return todos that should be blocked if the current todo is undone
|
||||
def block_successors
|
||||
active_successors = successors.select {|t| t.active? or t.deferred?}
|
||||
active_successors.each {|t| t.block!}
|
||||
active_successors = successors.select { |t| t.active? || t.deferred? }
|
||||
active_successors.each { |t| t.block! }
|
||||
return active_successors
|
||||
end
|
||||
|
||||
|
|
@ -319,7 +317,7 @@ class Todo < ApplicationRecord
|
|||
else
|
||||
c = Context.where(:name => value[:name]).first
|
||||
c = Context.create(value) if c.nil?
|
||||
self.original_context=(c)
|
||||
self.original_context = (c)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -331,13 +329,13 @@ class Todo < ApplicationRecord
|
|||
alias_method :original_project=, :project=
|
||||
def project=(value)
|
||||
if value.is_a? Project
|
||||
self.original_project=(value)
|
||||
self.original_project = (value)
|
||||
elsif !(value.nil? || value.is_a?(NullProject))
|
||||
p = Project.where(:name => value[:name]).first
|
||||
p = Project.create(value) if p.nil?
|
||||
self.original_project=(p)
|
||||
self.original_project = (p)
|
||||
else
|
||||
self.original_project=value
|
||||
self.original_project = value
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -387,5 +385,4 @@ class Todo < ApplicationRecord
|
|||
|
||||
super
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
module Todos
|
||||
class Calendar
|
||||
|
||||
attr_reader :user, :included_tables
|
||||
|
||||
def initialize(user)
|
||||
|
|
@ -48,11 +47,10 @@ module Todos
|
|||
@end_of_the_month ||= today.end_of_month
|
||||
end
|
||||
|
||||
private
|
||||
private
|
||||
|
||||
def actions
|
||||
user.todos.not_completed.includes(included_tables).reorder("due")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,8 +15,8 @@ module Todos
|
|||
end
|
||||
|
||||
not_done_todos = not_done_todos.
|
||||
reorder(Arel.sql("todos.due IS NULL, todos.due ASC, todos.created_at ASC")).
|
||||
includes(Todo::DEFAULT_INCLUDES)
|
||||
reorder(Arel.sql("todos.due IS NULL, todos.due ASC, todos.created_at ASC"))
|
||||
.includes(Todo::DEFAULT_INCLUDES)
|
||||
|
||||
not_done_todos = not_done_todos.limit(sanitize(params[:limit])) if params[:limit]
|
||||
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ class User < ApplicationRecord
|
|||
end
|
||||
end
|
||||
|
||||
has_many(:projects, -> {order 'projects.position ASC'}, dependent: :delete_all) do
|
||||
has_many(:projects, -> { order 'projects.position ASC' }, dependent: :delete_all) do
|
||||
def find_by_params(params)
|
||||
find(params['id'] || params['project_id'])
|
||||
end
|
||||
|
|
@ -46,7 +46,7 @@ class User < ApplicationRecord
|
|||
projects = self.projects_in_state_by_position(project.state)
|
||||
position = projects.index(project)
|
||||
return nil if position == 0 && offset < 0
|
||||
projects.at( position + offset)
|
||||
projects.at(position + offset)
|
||||
end
|
||||
def cache_note_counts
|
||||
project_note_counts = Note.group(:project_id).count
|
||||
|
|
@ -64,9 +64,9 @@ class User < ApplicationRecord
|
|||
todos_in_project = where(scope_conditions).includes(:todos)
|
||||
todos_in_project = todos_in_project.sort_by { |x| [-x.todos.active.count, -x.id] }
|
||||
todos_in_project.reject{ |p| p.todos.active.count > 0 }
|
||||
sorted_project_ids = todos_in_project.map {|p| p.id}
|
||||
sorted_project_ids = todos_in_project.map { |p| p.id }
|
||||
|
||||
all_project_ids = self.map {|p| p.id}
|
||||
all_project_ids = self.map { |p| p.id }
|
||||
other_project_ids = all_project_ids - sorted_project_ids
|
||||
|
||||
update_positions(sorted_project_ids + other_project_ids)
|
||||
|
|
@ -82,12 +82,12 @@ class User < ApplicationRecord
|
|||
end
|
||||
|
||||
has_many :recurring_todos,
|
||||
-> {order 'recurring_todos.completed_at DESC, recurring_todos.created_at DESC'},
|
||||
-> { order 'recurring_todos.completed_at DESC, recurring_todos.created_at DESC' },
|
||||
dependent: :delete_all
|
||||
|
||||
has_many(:deferred_todos,
|
||||
-> { where('state = ?', 'deferred').
|
||||
order('show_from ASC, todos.created_at DESC')},
|
||||
-> { where('state = ?', 'deferred')
|
||||
.order('show_from ASC, todos.created_at DESC') },
|
||||
:class_name => 'Todo') do
|
||||
def find_and_activate_ready
|
||||
where('show_from <= ?', Time.current).collect { |t| t.activate! }
|
||||
|
|
@ -196,7 +196,7 @@ class User < ApplicationRecord
|
|||
BCrypt::Password.create(s)
|
||||
end
|
||||
|
||||
protected
|
||||
protected
|
||||
|
||||
def crypt_password
|
||||
return if password.blank?
|
||||
|
|
@ -218,5 +218,4 @@ protected
|
|||
taggings = Tagging.where(taggable_id: ids).pluck(:id)
|
||||
Tagging.where(id: taggings).delete_all
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -72,5 +72,4 @@ class RichMessageExtractor
|
|||
def fix_date_string yymmdd
|
||||
"20#{yymmdd[0..1]}-#{yymmdd[2..3]}-#{yymmdd[4..5]} 00:00"
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
class TodoFromRichMessage
|
||||
|
||||
attr_reader :user, :default_context_id, :description, :notes
|
||||
|
||||
def initialize(user, default_context_id, description, notes)
|
||||
|
|
@ -21,8 +20,9 @@ class TodoFromRichMessage
|
|||
|
||||
context_id = default_context_id
|
||||
if context.present?
|
||||
found_context = user.contexts.active.where("name like ?", "%#{context}%").first
|
||||
found_context = user.contexts.where("name like ?", "%#{context}%").first if !found_context
|
||||
# TODO: Should this use ILIKE on Postgres?
|
||||
found_context = user.contexts.active.where("name LIKE ?", "%#{context}%").first
|
||||
found_context = user.contexts.where("name LIKE ?", "%#{context}%").first if !found_context
|
||||
context_id = found_context.id if found_context
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -7,17 +7,17 @@ require 'rack'
|
|||
require 'fcgi'
|
||||
|
||||
class Rack::PathInfoRewriter
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
def initialize(app)
|
||||
@app = app
|
||||
end
|
||||
|
||||
def call(env)
|
||||
env.delete('SCRIPT_NAME')
|
||||
parts = env['REQUEST_URI'].split('?')
|
||||
env['PATH_INFO'] = parts[0]
|
||||
env['QUERY_STRING'] = parts[1].to_s
|
||||
@app.call(env)
|
||||
end
|
||||
def call(env)
|
||||
env.delete('SCRIPT_NAME')
|
||||
parts = env['REQUEST_URI'].split('?')
|
||||
env['PATH_INFO'] = parts[0]
|
||||
env['QUERY_STRING'] = parts[1].to_s
|
||||
@app.call(env)
|
||||
end
|
||||
end
|
||||
|
||||
Rack::Handler::FastCGI.run Rack::PathInfoRewriter.new(Tracksapp::Application)
|
||||
|
|
|
|||
|
|
@ -7,4 +7,5 @@ require File.dirname(__FILE__) + "/../config/environment" unless defined?(RAILS_
|
|||
require "dispatcher"
|
||||
|
||||
ADDITIONAL_LOAD_PATHS.reverse.each { |dir| $:.unshift(dir) if File.directory?(dir) } if defined?(Apache::RubyRun)
|
||||
Dispatcher.dispatch
|
||||
Dispatcher.dispatch
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue