mirror of
https://github.com/TracksApp/tracks.git
synced 2026-01-02 23:38:50 +01:00
Merge https://github.com/TracksApp/tracks into upstream
This commit is contained in:
commit
23c2a2499b
25 changed files with 353 additions and 99 deletions
3
.gitmodules
vendored
3
.gitmodules
vendored
|
|
@ -1,3 +0,0 @@
|
|||
[submodule "doc/manual"]
|
||||
path = doc/manual
|
||||
url = git://github.com/bsag/tracks_manual.git
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
--title "Tracks Documentation"
|
||||
--charset utf-8
|
||||
--markup="textile"
|
||||
--private
|
||||
--protected
|
||||
|
|
|
|||
|
|
@ -69,16 +69,7 @@ class LoginController < ApplicationController
|
|||
end
|
||||
|
||||
def logout
|
||||
@user.forget_me if logged_in?
|
||||
cookies.delete :auth_token
|
||||
session['user_id'] = nil
|
||||
if ( SITE_CONFIG['authentication_schemes'].include? 'cas') && session[:cas_user]
|
||||
CASClient::Frameworks::Rails::Filter.logout(self)
|
||||
else
|
||||
reset_session
|
||||
notify :notice, t('login.logged_out')
|
||||
redirect_to_login
|
||||
end
|
||||
logout_user
|
||||
end
|
||||
|
||||
def expire_session
|
||||
|
|
@ -149,13 +140,6 @@ class LoginController < ApplicationController
|
|||
|
||||
private
|
||||
|
||||
def redirect_to_login
|
||||
respond_to do |format|
|
||||
format.html { redirect_to login_path }
|
||||
format.m { redirect_to login_path(:format => 'm') }
|
||||
end
|
||||
end
|
||||
|
||||
def should_expire_sessions?
|
||||
session['noexpiry'] != "on"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -12,8 +12,11 @@ class PreferencesController < ApplicationController
|
|||
user_updated = current_user.update_attributes(params['user'])
|
||||
prefs_updated = current_user.preference.update_attributes(params['prefs'])
|
||||
if (user_updated && prefs_updated)
|
||||
notify :notice, "Preferences updated"
|
||||
redirect_to :action => 'index'
|
||||
if !params['user']['password'].blank? # password updated?
|
||||
logout_user t('preferences.password_changed')
|
||||
else
|
||||
preference_updated
|
||||
end
|
||||
else
|
||||
msg = "Preferences could not be updated: "
|
||||
msg += "User model errors; " unless user_updated
|
||||
|
|
@ -28,4 +31,12 @@ class PreferencesController < ApplicationController
|
|||
render :text => l(Date.today, :format => format)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Display notification if preferences are successful updated
|
||||
def preference_updated
|
||||
notify :notice, t('preferences.updated')
|
||||
redirect_to :action => 'index'
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,8 +2,8 @@ class TodosController < ApplicationController
|
|||
|
||||
helper :todos
|
||||
|
||||
skip_before_filter :login_required, :only => [:index, :calendar]
|
||||
prepend_before_filter :login_or_feed_token_required, :only => [:index, :calendar]
|
||||
skip_before_filter :login_required, :only => [:index, :calendar, :tag]
|
||||
prepend_before_filter :login_or_feed_token_required, :only => [:index, :calendar, :tag]
|
||||
append_before_filter :find_and_activate_ready, :only => [:index, :list_deferred]
|
||||
|
||||
# TODO: replace :except with :only
|
||||
|
|
@ -586,34 +586,34 @@ class TodosController < ApplicationController
|
|||
|
||||
# /todos/tag/[tag_name] shows all the actions tagged with tag_name
|
||||
def tag
|
||||
init_data_for_sidebar unless mobile?
|
||||
get_params_for_tag_view
|
||||
@page_title = t('todos.tagged_page_title', :tag_name => @tag_title)
|
||||
@source_view = params['_source_view'] || 'tag'
|
||||
@tag_name = sanitize(params[:name]) # sanitize to prevent XSS vunerability!
|
||||
@page_title = t('todos.tagged_page_title', :tag_name => @tag_name)
|
||||
|
||||
# mobile tags are routed with :name ending on .m. So we need to chomp it
|
||||
@tag_name = @tag_name.chomp('.m') if mobile?
|
||||
if mobile?
|
||||
# mobile tags are routed with :name ending on .m. So we need to chomp it
|
||||
@tag_name = @tag_name.chomp('.m')
|
||||
else
|
||||
init_data_for_sidebar
|
||||
end
|
||||
|
||||
@tag = Tag.find_by_name(@tag_name)
|
||||
@tag = Tag.new(:name => @tag_name) if @tag.nil?
|
||||
todos_with_tag_ids = find_todos_with_tag_expr(@tag_expr)
|
||||
|
||||
@not_done_todos = current_user.todos.with_tag(@tag).active.not_hidden.find(:all,
|
||||
@not_done_todos = todos_with_tag_ids.active.not_hidden.find(:all,
|
||||
:order => 'todos.due IS NULL, todos.due ASC, todos.created_at ASC', :include => Todo::DEFAULT_INCLUDES)
|
||||
@hidden_todos = current_user.todos.with_tag(@tag).hidden.find(:all,
|
||||
@hidden_todos = todos_with_tag_ids.hidden.find(:all,
|
||||
:include => Todo::DEFAULT_INCLUDES,
|
||||
:order => 'todos.completed_at DESC, todos.created_at DESC')
|
||||
@deferred = current_user.todos.with_tag(@tag).deferred.find(:all,
|
||||
:order => 'show_from ASC, todos.created_at DESC', :include => Todo::DEFAULT_INCLUDES)
|
||||
@pending = current_user.todos.with_tag(@tag).blocked.find(:all,
|
||||
:order => 'show_from ASC, todos.created_at DESC', :include => Todo::DEFAULT_INCLUDES)
|
||||
@deferred = todos_with_tag_ids.deferred.find(:all,
|
||||
:order => 'todos.show_from ASC, todos.created_at DESC', :include => Todo::DEFAULT_INCLUDES)
|
||||
@pending = todos_with_tag_ids.blocked.find(:all,
|
||||
:order => 'todos.show_from ASC, todos.created_at DESC', :include => Todo::DEFAULT_INCLUDES)
|
||||
|
||||
# If you've set no_completed to zero, the completed items box isn't shown on
|
||||
# the tag page
|
||||
max_completed = current_user.prefs.show_number_completed
|
||||
@done = current_user.todos.with_tag(@tag).completed.find(:all,
|
||||
:limit => max_completed,
|
||||
:order => 'todos.completed_at DESC',
|
||||
:include => Todo::DEFAULT_INCLUDES)
|
||||
@done = todos_with_tag_ids.completed.find(:all,
|
||||
:limit => current_user.prefs.show_number_completed,
|
||||
:order => 'todos.completed_at DESC', :include => Todo::DEFAULT_INCLUDES)
|
||||
|
||||
@projects = current_user.projects
|
||||
@contexts = current_user.contexts
|
||||
|
|
@ -635,6 +635,9 @@ class TodosController < ApplicationController
|
|||
cookies[:mobile_url]= {:value => request.request_uri, :secure => SITE_CONFIG['secure_cookies']}
|
||||
render :action => "mobile_tag"
|
||||
}
|
||||
format.text {
|
||||
render :action => 'index', :layout => false, :content_type => Mime::TEXT
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -645,7 +648,7 @@ class TodosController < ApplicationController
|
|||
@tag = Tag.find_by_name(@tag_name)
|
||||
@tag = Tag.new(:name => @tag_name) if @tag.nil?
|
||||
|
||||
completed_todos = current_user.todos.completed.with_tag(@tag)
|
||||
completed_todos = current_user.todos.completed.with_tag(@tag.id)
|
||||
|
||||
@done_today = get_done_today(completed_todos)
|
||||
@done_this_week = get_done_this_week(completed_todos)
|
||||
|
|
@ -662,7 +665,7 @@ class TodosController < ApplicationController
|
|||
@tag = Tag.find_by_name(@tag_name)
|
||||
@tag = Tag.new(:name => @tag_name) if @tag.nil?
|
||||
|
||||
@done = current_user.todos.completed.with_tag(@tag).paginate :page => params[:page], :per_page => 20, :order => 'completed_at DESC', :include => Todo::DEFAULT_INCLUDES
|
||||
@done = current_user.todos.completed.with_tag(@tag.id).paginate :page => params[:page], :per_page => 20, :order => 'completed_at DESC', :include => Todo::DEFAULT_INCLUDES
|
||||
@count = @done.size
|
||||
render :template => 'todos/all_done'
|
||||
end
|
||||
|
|
@ -988,6 +991,58 @@ class TodosController < ApplicationController
|
|||
:include => [ :project, :context, :tags ])
|
||||
end
|
||||
|
||||
def tag_title(tag_expr)
|
||||
and_list = tag_expr.inject([]) { |s,tag_list| s << tag_list.join(',') }
|
||||
return and_list.join(' AND ')
|
||||
end
|
||||
|
||||
def get_params_for_tag_view
|
||||
# use sanitize to prevent XSS attacks
|
||||
|
||||
@tag_expr = []
|
||||
@tag_expr << sanitize(params[:name]).split(',')
|
||||
@tag_expr << sanitize(params[:and]).split(',') if params[:and]
|
||||
|
||||
i = 1
|
||||
while params['and'+i.to_s]
|
||||
@tag_expr << sanitize(params['and'+i.to_s]).split(',')
|
||||
i=i+1
|
||||
end
|
||||
|
||||
@single_tag = @tag_expr.size == 1 && @tag_expr[0].size == 1
|
||||
@tag_name = @tag_expr[0][0]
|
||||
@tag_title = @single_tag ? @tag_name : tag_title(@tag_expr)
|
||||
end
|
||||
|
||||
def get_ids_from_tag_expr(tag_expr)
|
||||
ids = []
|
||||
tag_expr.each do |tag_list|
|
||||
id_list = []
|
||||
tag_list.each do |tag|
|
||||
tag = Tag.find_by_name(tag)
|
||||
id_list << tag.id if tag
|
||||
end
|
||||
ids << id_list
|
||||
end
|
||||
return ids
|
||||
end
|
||||
|
||||
def find_todos_with_tag_expr(tag_expr)
|
||||
# optimize for the common case: selecting only one tag
|
||||
if @single_tag
|
||||
tag = Tag.find_by_name(@tag_name)
|
||||
tag_id = tag.nil? ? -1 : tag.id
|
||||
return current_user.todos.with_tag(tag_id)
|
||||
end
|
||||
|
||||
tag_ids = get_ids_from_tag_expr(tag_expr)
|
||||
todos = current_user.todos
|
||||
tag_ids.each do |ids|
|
||||
todos = todos.with_tags(ids) unless ids.nil? || ids.empty?
|
||||
end
|
||||
return todos
|
||||
end
|
||||
|
||||
def determine_down_count
|
||||
source_view do |from|
|
||||
from.todo do
|
||||
|
|
@ -1019,7 +1074,7 @@ class TodosController < ApplicationController
|
|||
if @tag.nil?
|
||||
@tag = Tag.new(:name => @tag_name)
|
||||
end
|
||||
@down_count = current_user.todos.with_tag(@tag).active.not_hidden.count
|
||||
@down_count = current_user.todos.with_tag(@tag.id).active.not_hidden.count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1036,10 +1091,10 @@ class TodosController < ApplicationController
|
|||
if tag.nil?
|
||||
tag = Tag.new(:name => params['tag'])
|
||||
end
|
||||
@remaining_deferred_or_pending_count = current_user.todos.with_tag(tag).deferred_or_blocked.count
|
||||
@remaining_in_context = current_user.contexts.find(context_id).todos.active.not_hidden.with_tag(tag).count
|
||||
@target_context_count = current_user.contexts.find(@todo.context_id).todos.active.not_hidden.with_tag(tag).count
|
||||
@remaining_hidden_count = current_user.todos.hidden.with_tag(tag).count
|
||||
@remaining_deferred_or_pending_count = current_user.todos.with_tag(tag.id).deferred_or_blocked.count
|
||||
@remaining_in_context = current_user.contexts.find(context_id).todos.active.not_hidden.with_tag(tag.id).count
|
||||
@target_context_count = current_user.contexts.find(@todo.context_id).todos.active.not_hidden.with_tag(tag.id).count
|
||||
@remaining_hidden_count = current_user.todos.hidden.with_tag(tag.id).count
|
||||
}
|
||||
from.project {
|
||||
project_id = @project_changed ? @original_item_project_id : @todo.project_id
|
||||
|
|
@ -1090,7 +1145,7 @@ class TodosController < ApplicationController
|
|||
end
|
||||
end
|
||||
from.tag do
|
||||
@completed_count = current_user.todos.with_tag(@tag).completed.count
|
||||
@completed_count = current_user.todos.with_tag(@tag.id).completed.count
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1098,7 +1153,7 @@ class TodosController < ApplicationController
|
|||
def determine_deferred_tag_count(tag_name)
|
||||
tag = Tag.find_by_name(tag_name)
|
||||
# tag.nil? should normally not happen, but is a workaround for #929
|
||||
@remaining_deferred_or_pending_count = tag.nil? ? 0 : current_user.todos.deferred.with_tag(tag).count
|
||||
@remaining_deferred_or_pending_count = tag.nil? ? 0 : current_user.todos.deferred.with_tag(tag.id).count
|
||||
end
|
||||
|
||||
def render_todos_html
|
||||
|
|
|
|||
|
|
@ -28,17 +28,18 @@ class Todo < ActiveRecord::Base
|
|||
named_scope :deferred_or_blocked, :conditions => ["(todos.completed_at IS NULL AND NOT(todos.show_from IS NULL)) OR (todos.state = ?)", "pending"]
|
||||
named_scope :not_deferred_or_blocked, :conditions => ["todos.completed_at IS NULL AND todos.show_from IS NULL AND NOT(todos.state = ?)", "pending"]
|
||||
named_scope :hidden,
|
||||
:joins => :context,
|
||||
:conditions => ["todos.state = ? OR (contexts.hide = ? AND (todos.state = ? OR todos.state = ? OR todos.state = ?))",
|
||||
:joins => "INNER JOIN contexts c_hidden ON c_hidden.id = todos.context_id",
|
||||
:conditions => ["todos.state = ? OR (c_hidden.hide = ? AND (todos.state = ? OR todos.state = ? OR todos.state = ?))",
|
||||
'project_hidden', true, 'active', 'deferred', 'pending']
|
||||
named_scope :not_hidden,
|
||||
:joins => [:context],
|
||||
:conditions => ['NOT(todos.state = ? OR (contexts.hide = ? AND (todos.state = ? OR todos.state = ? OR todos.state = ?)))',
|
||||
:joins => "INNER JOIN contexts c_hidden ON c_hidden.id = todos.context_id",
|
||||
:conditions => ['NOT(todos.state = ? OR (c_hidden.hide = ? AND (todos.state = ? OR todos.state = ? OR todos.state = ?)))',
|
||||
'project_hidden', true, 'active', 'deferred', 'pending']
|
||||
|
||||
# other scopes
|
||||
named_scope :are_due, :conditions => ['NOT (todos.due IS NULL)']
|
||||
named_scope :with_tag, lambda { |tag| {:joins => :taggings, :conditions => ["taggings.tag_id = ? ", tag.id] } }
|
||||
named_scope :with_tag, lambda { |tag_id| {:joins => :taggings, :conditions => ["taggings.tag_id = ? ", tag_id] } }
|
||||
named_scope :with_tags, lambda { |tag_ids| {:conditions => ["EXISTS(SELECT * from taggings t WHERE t.tag_id IN (?) AND t.taggable_id=todos.id AND t.taggable_type='Todo')", tag_ids] } }
|
||||
named_scope :of_user, lambda { |user_id| {:conditions => ["todos.user_id = ? ", user_id] } }
|
||||
named_scope :completed_after, lambda { |date| {:conditions => ["todos.completed_at > ? ", date] } }
|
||||
named_scope :completed_before, lambda { |date| {:conditions => ["todos.completed_at < ? ", date] } }
|
||||
|
|
|
|||
|
|
@ -38,7 +38,10 @@
|
|||
</head>
|
||||
|
||||
<body class="<%= @controller.controller_name %>">
|
||||
|
||||
<div id="topbar">
|
||||
<%= NOTIFY_BAR %>
|
||||
|
||||
<div id="date">
|
||||
<h1>
|
||||
<% if @count -%>
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ function update_project_page() {
|
|||
remove_project_edit_form();
|
||||
update_and_show_project_settings();
|
||||
TracksForm.set_project_name("<%= escape_javascript(@project.name)%>");
|
||||
$("h2#project_name").html("<%= escape_javascript(@project.name)%>");
|
||||
$("h2 div#project_name").html("<%= escape_javascript(@project.name)%>");
|
||||
<% if @project.default_context %>
|
||||
TracksForm.set_context_name_and_default_context_name("<%= escape_javascript(@project.default_context.name)%>");
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -2,24 +2,24 @@
|
|||
<% if @not_done_todos.empty? -%>
|
||||
<div class="container context">
|
||||
<h2><%= t('todos.no_actions_found_title') %></h2>
|
||||
<div class="message"><%= t('todos.no_actions_with', :tag_name => @tag_name) %></div>
|
||||
<div class="message"><%= t('todos.no_actions_with', :tag_name => @tag_title) %></div>
|
||||
</div>
|
||||
<% end -%>
|
||||
<%= render :partial => "contexts/mobile_context", :collection => @contexts_to_show -%>
|
||||
<h2><%= t('todos.deferred_actions_with', :tag_name=> @tag_name) %></h2>
|
||||
<h2><%= t('todos.deferred_actions_with', :tag_name=> @tag_title) %></h2>
|
||||
<% unless (@deferred.nil? or @deferred.size == 0) -%>
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<%= render :partial => "todos/mobile_todo", :collection => @deferred, :locals => { :parent_container_type => "tag" } -%>
|
||||
</table>
|
||||
</table>
|
||||
<% else -%>
|
||||
<%= t('todos.no_deferred_actions_with', :tag_name => @tag_name) %>
|
||||
<%= t('todos.no_deferred_actions_with', :tag_name => @tag_title) %>
|
||||
<% end -%>
|
||||
<h2><%= t('todos.completed_actions_with', :tag_name => @tag_name) %></h2>
|
||||
<h2><%= t('todos.completed_actions_with', :tag_name => @tag_title) %></h2>
|
||||
<% unless (@done.nil? or @done.size == 0) -%>
|
||||
<table cellpadding="0" cellspacing="0" border="0">
|
||||
<%= render :partial => "todos/mobile_todo", :collection => @done, :locals => { :parent_container_type => "tag" } %>
|
||||
</table>
|
||||
<% else -%>
|
||||
<%= t('todos.no_completed_actions_with', :tag_name => @tag_name) %>
|
||||
<%= t('todos.no_completed_actions_with', :tag_name => @tag_title) %>
|
||||
<% end -%>
|
||||
</div>
|
||||
|
|
@ -8,22 +8,22 @@
|
|||
:locals => { :collapsible => true } %>
|
||||
|
||||
<% unless @deferred.nil? -%>
|
||||
<%= render :partial => "todos/deferred", :locals => {
|
||||
:deferred => @deferred,
|
||||
<%= render :partial => "todos/deferred", :locals => {
|
||||
:deferred => @deferred,
|
||||
:pending => @pending,
|
||||
:collapsible => true,
|
||||
:append_descriptor => t('todos.tagged_with', :tag_name => @tag_name),
|
||||
:parent_container_type => 'tag'
|
||||
:collapsible => true,
|
||||
:append_descriptor => t('todos.tagged_with', :tag_name => @tag_title),
|
||||
:parent_container_type => 'tag'
|
||||
} %>
|
||||
<% end -%>
|
||||
|
||||
<% unless @hidden_todos.nil? -%>
|
||||
<%= render :partial => "todos/hidden", :object => @hidden_todos, :locals => { :collapsible => true, :append_descriptor => t('todos.tagged_with', :tag_name => @tag_name) } %>
|
||||
<%= render :partial => "todos/hidden", :object => @hidden_todos, :locals => { :collapsible => true, :append_descriptor => t('todos.tagged_with', :tag_name => @tag_title) } %>
|
||||
<% end -%>
|
||||
|
||||
<% unless @done.nil? -%>
|
||||
<%= render :partial => "todos/completed", :object => @done,
|
||||
:locals => { :collapsible => true, :append_descriptor => t('todos.tagged_with', :tag_name => @tag_name) } %>
|
||||
:locals => { :collapsible => true, :append_descriptor => t('todos.tagged_with', :tag_name => @tag_title) } %>
|
||||
<% end -%>
|
||||
</div><!-- End of display_box -->
|
||||
|
||||
|
|
|
|||
|
|
@ -107,6 +107,9 @@ if ( SITE_CONFIG['authentication_schemes'].include? 'cas')
|
|||
end
|
||||
end
|
||||
|
||||
# changed in development.rb to show under_construction bar
|
||||
NOTIFY_BAR = "" unless defined?(NOTIFY_BAR)
|
||||
|
||||
tracks_version='2.1devel'
|
||||
# comment out next two lines if you do not want (or can not) the date of the
|
||||
# last git commit in the footer
|
||||
|
|
|
|||
|
|
@ -14,4 +14,6 @@ config.action_controller.perform_caching = false
|
|||
config.action_mailer.raise_delivery_errors = false
|
||||
|
||||
# Unique cookies
|
||||
config.action_controller.session = { :key => 'TracksDev' }
|
||||
config.action_controller.session = { :key => 'TracksDev' }
|
||||
|
||||
NOTIFY_BAR="<div id=\"develop-notify-bar\"> </div>"
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ def check_mongrel_around_115
|
|||
begin
|
||||
# Gem.available? is deprecated from rubygems 1.8.2
|
||||
Gem::Specification::find_by_name "mongrel", "~>1.1.5"
|
||||
rescue Gem::LoadError
|
||||
rescue
|
||||
if RUBY_VERSION[2] == "9"
|
||||
false
|
||||
else
|
||||
|
|
|
|||
|
|
@ -391,10 +391,10 @@ en:
|
|||
all_completed: All completed actions
|
||||
feed_title_in_context: in context '%{context}'
|
||||
older_than_days: ""
|
||||
completed_tagged_page_title: TRACKS::Completed tasks with tag %{tag_name}
|
||||
completed_tagged_page_title: TRACKS::Completed tasks with tag '%{tag_name}'
|
||||
edit: Edit
|
||||
pending: Pending
|
||||
completed_actions_with: Completed actions with the tag %{tag_name}
|
||||
completed_actions_with: Completed actions with the tag '%{tag_name}'
|
||||
deleted_success: The action was deleted succesfully.
|
||||
completed_tasks_title: TRACKS::Completed tasks
|
||||
feed_title_in_project: in project '%{project}'
|
||||
|
|
@ -659,6 +659,8 @@ en:
|
|||
staleness_starts_after: Staleness starts after %{days} days
|
||||
change_identity_url: Change Your Identity URL
|
||||
change_password: Change your password
|
||||
password_changed: You password has been changed, please log on again.
|
||||
updated: Preferences updated
|
||||
page_title: TRACKS::Preferences
|
||||
title: Your preferences
|
||||
token_description: Token (for feeds and API use)
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ ActionController::Routing::Routes.draw do |map|
|
|||
# UPDATE: added support for mobile view. All tags ending on .m will be
|
||||
# routed to mobile view of tags.
|
||||
todos.mobile_tag 'todos/tag/:name.m', :action => "tag", :format => 'm'
|
||||
todos.text_tag 'todos/tag/:name.txt', :action => "tag", :format => 'txt'
|
||||
todos.tag 'todos/tag/:name', :action => "tag", :name => /.*/
|
||||
todos.done_tag 'todos/done/tag/:name', :action => "done_tag"
|
||||
todos.all_done_tag 'todos/all_done/tag/:name', :action => "all_done_tag"
|
||||
|
|
|
|||
|
|
@ -1 +0,0 @@
|
|||
Subproject commit 8cb3847448223c5f0397a98e92a93a6af656e69d
|
||||
|
|
@ -95,7 +95,7 @@ Feature: Add new next action from every page
|
|||
| tickler page | not see |
|
||||
| "test project" project | see |
|
||||
| context page for "test context" | see |
|
||||
| tag page for "starred" | not see |
|
||||
| tag page for "starred" | see |
|
||||
|
||||
@selenium
|
||||
Scenario Outline: I can add multiple todos from several pages
|
||||
|
|
|
|||
|
|
@ -274,7 +274,7 @@ end
|
|||
|
||||
Then /^the project title should be "(.*)"$/ do |title|
|
||||
wait_for :timeout => 2 do
|
||||
selenium.get_text("css=h2#project_name") == title
|
||||
selenium.get_text("css=h2#project_name_container div#project_name") == title
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,22 @@ module LoginSystem
|
|||
def prefs
|
||||
current_user.prefs unless current_user.nil?
|
||||
end
|
||||
|
||||
# Logout the {#current_user} and redirect to login page
|
||||
#
|
||||
# @param [String] message notification to display
|
||||
def logout_user message=t('login.logged_out')
|
||||
@user.forget_me if logged_in?
|
||||
cookies.delete :auth_token
|
||||
session['user_id'] = nil
|
||||
if ( SITE_CONFIG['authentication_schemes'].include? 'cas') && session[:cas_user]
|
||||
CASClient::Frameworks::Rails::Filter.logout(self)
|
||||
else
|
||||
reset_session
|
||||
notify :notice, message
|
||||
redirect_to_login
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
|
|
@ -132,7 +148,7 @@ module LoginSystem
|
|||
def set_current_user(user)
|
||||
@user = user
|
||||
end
|
||||
|
||||
|
||||
# overwrite if you want to have special behavior in case the user is not authorized
|
||||
# to access the current operation.
|
||||
# the default action is to redirect to the login screen
|
||||
|
|
@ -192,4 +208,14 @@ module LoginSystem
|
|||
render :text => t('login.unsuccessful'), :status => 401
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Redirect the user to the login page.
|
||||
def redirect_to_login
|
||||
respond_to do |format|
|
||||
format.html { redirect_to login_path }
|
||||
format.m { redirect_to login_path(:format => 'm') }
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
@ -24,7 +24,7 @@
|
|||
<!-- This file lives in public/500.html -->
|
||||
<div class="dialog">
|
||||
<h1>We're sorry, but something went wrong.</h1>
|
||||
<p>We've been notified about this issue and we'll take a look at it shortly.</p>
|
||||
<p>The Tracks application failed with error 500. More details can be found in the log file of Tracks</p>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
BIN
public/images/construction.gif
Normal file
BIN
public/images/construction.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -305,19 +305,19 @@ var TracksPages = {
|
|||
$(".todo_notes").toggle();
|
||||
});
|
||||
|
||||
|
||||
|
||||
/* Poor man's perspectives, allows to hide any context that is collapsed */
|
||||
$("#toggle-contexts-nav").click(function () {
|
||||
/* Need to keep a single toggle across all contexts */
|
||||
$(this).toggleClass("context_visibility");
|
||||
$(this).toggleClass("context_visibility");
|
||||
if ($(this).hasClass("context_visibility")) {
|
||||
$(".context_collapsed").hide(); /* Hide all collapsed contexts together*/
|
||||
}
|
||||
else {
|
||||
$(".context_collapsed").show();
|
||||
$(".context_collapsed").show();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* fade flashes and alerts in automatically */
|
||||
$(".alert").fadeOut(8000);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -277,6 +277,12 @@ a.show_successors:hover, a.link_to_successors:hover {background-image: url(../im
|
|||
|
||||
#navlist a:hover { color: #CCC; }
|
||||
|
||||
#develop-notify-bar {
|
||||
line-height:0.5;
|
||||
background-image: url(/images/construction.gif);
|
||||
background-repeat: repeat-x;
|
||||
}
|
||||
|
||||
#topbar {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
|
|
|
|||
|
|
@ -492,7 +492,7 @@ class TodosControllerTest < ActionController::TestCase
|
|||
recurring_todo_1 = RecurringTodo.find(1)
|
||||
set_user_to_current_time_zone(recurring_todo_1.user)
|
||||
todo_1 = Todo.find_by_recurring_todo_id(1)
|
||||
today = Time.now.at_midnight
|
||||
today = Time.zone.now.at_midnight
|
||||
|
||||
# change recurrence pattern to monthly and set show_from to today
|
||||
recurring_todo_1.target = 'show_from_date'
|
||||
|
|
@ -644,4 +644,69 @@ class TodosControllerTest < ActionController::TestCase
|
|||
assert_select("div#notes_todo_#{todo.id} a", 'link me to onenote')
|
||||
assert_select("div#notes_todo_#{todo.id} a[href=onenote:///E:\\OneNote\\dir\\notes.one#PAGE&section-id={FD597D3A-3793-495F-8345-23D34A00DD3B}&page-id={1C95A1C7-6408-4804-B3B5-96C28426022B}&end]", 'link me to onenote')
|
||||
end
|
||||
|
||||
def test_get_boolean_expression_from_parameters_of_tag_view_single_tag
|
||||
login_as(:admin_user)
|
||||
get :tag, :name => "single"
|
||||
assert_equal true, assigns['single_tag'], "should recognize it is a single tag name"
|
||||
assert_equal "single", assigns['tag_expr'][0][0], "should store the single tag"
|
||||
assert_equal "single", assigns['tag_name'], "should store the single tag name"
|
||||
end
|
||||
|
||||
def test_get_boolean_expression_from_parameters_of_tag_view_multiple_tags
|
||||
login_as(:admin_user)
|
||||
get :tag, :name => "multiple", :and => "tags", :and1 => "present", :and2 => "here"
|
||||
assert_equal false, assigns['single_tag'], "should recognize it has multiple tags"
|
||||
assert_equal 4, assigns['tag_expr'].size, "should have 4 AND expressions"
|
||||
end
|
||||
|
||||
def test_get_boolean_expression_from_parameters_of_tag_view_multiple_tags_without_digitless_and
|
||||
login_as(:admin_user)
|
||||
get :tag, :name => "multiple", :and1 => "tags", :and2 => "present", :and3 => "here"
|
||||
assert_equal false, assigns['single_tag'], "should recognize it has multiple tags"
|
||||
assert_equal 4, assigns['tag_expr'].size, "should have 4 AND expressions"
|
||||
end
|
||||
|
||||
def test_get_boolean_expression_from_parameters_of_tag_view_multiple_ORs
|
||||
login_as(:admin_user)
|
||||
get :tag, :name => "multiple,tags,present"
|
||||
assert_equal false, assigns['single_tag'], "should recognize it has multiple tags"
|
||||
assert_equal 1, assigns['tag_expr'].size, "should have 1 expressions"
|
||||
assert_equal 3, assigns['tag_expr'][0].size, "should have 3 ORs in 1st expression"
|
||||
end
|
||||
|
||||
def test_get_boolean_expression_from_parameters_of_tag_view_multiple_ORs_and_ANDS
|
||||
login_as(:admin_user)
|
||||
get :tag, :name => "multiple,tags,present", :and => "here,is,two", :and1=>"and,three"
|
||||
assert_equal false, assigns['single_tag'], "should recognize it has multiple tags"
|
||||
assert_equal 3, assigns['tag_expr'].size, "should have 3 expressions"
|
||||
assert_equal 3, assigns['tag_expr'][0].size, "should have 3 ORs in 1st expression"
|
||||
assert_equal 3, assigns['tag_expr'][1].size, "should have 3 ORs in 2nd expression"
|
||||
assert_equal 2, assigns['tag_expr'][2].size, "should have 2 ORs in 3rd expression"
|
||||
end
|
||||
|
||||
def test_set_right_title
|
||||
login_as(:admin_user)
|
||||
|
||||
get :tag, :name => "foo"
|
||||
assert_equal "foo", assigns['tag_title']
|
||||
get :tag, :name => "foo,bar", :and => "baz"
|
||||
assert_equal "foo,bar AND baz", assigns['tag_title']
|
||||
end
|
||||
|
||||
def test_set_default_tag
|
||||
login_as(:admin_user)
|
||||
|
||||
get :tag, :name => "foo"
|
||||
assert_equal "foo", assigns['initial_tags']
|
||||
get :tag, :name => "foo,bar", :and => "baz"
|
||||
assert_equal "foo", assigns['initial_tags']
|
||||
end
|
||||
|
||||
def test_tag_text_feed_not_accessible_to_anonymous_user_without_token
|
||||
login_as nil
|
||||
get :tag, {:name => "foo", :format => "txt" }
|
||||
assert_response 401
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
@not_completed2 = Todo.find(2).reload
|
||||
@completed = Todo.find(8).reload
|
||||
end
|
||||
|
||||
|
||||
# Test loading a todo item
|
||||
def test_load
|
||||
assert_kind_of Todo, @not_completed1
|
||||
|
|
@ -24,13 +24,13 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert_nil @not_completed1.completed_at
|
||||
assert_equal 1, @not_completed1.user_id
|
||||
end
|
||||
|
||||
|
||||
def test_completed
|
||||
assert_kind_of Todo, @completed
|
||||
assert @completed.completed?
|
||||
assert_not_nil @completed.completed_at
|
||||
end
|
||||
|
||||
|
||||
def test_completed_at_cleared_after_toggle_to_active
|
||||
assert_kind_of Todo, @completed
|
||||
assert @completed.completed?
|
||||
|
|
@ -38,8 +38,8 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert @completed.active?
|
||||
assert_nil @completed.completed_at
|
||||
end
|
||||
|
||||
|
||||
|
||||
|
||||
# Validation tests
|
||||
#
|
||||
def test_validate_presence_of_description
|
||||
|
|
@ -49,7 +49,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert_equal 1, @not_completed2.errors.count
|
||||
assert_equal "can't be blank", @not_completed2.errors.on(:description)
|
||||
end
|
||||
|
||||
|
||||
def test_validate_length_of_description
|
||||
assert_equal "Call dinosaur exterminator", @not_completed2.description
|
||||
@not_completed2.description = generate_random_string(101)
|
||||
|
|
@ -57,7 +57,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert_equal 1, @not_completed2.errors.count
|
||||
assert_equal "is too long (maximum is 100 characters)", @not_completed2.errors.on(:description)
|
||||
end
|
||||
|
||||
|
||||
def test_validate_length_of_notes
|
||||
assert_equal "Ask him if I need to hire a skip for the corpses.", @not_completed2.notes
|
||||
@not_completed2.notes = generate_random_string(60001)
|
||||
|
|
@ -74,7 +74,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert_equal 1, t.errors.count
|
||||
assert_equal "must be a date in the future", t.errors.on(:show_from)
|
||||
end
|
||||
|
||||
|
||||
def test_defer_an_existing_todo
|
||||
@not_completed2
|
||||
assert_equal :active, @not_completed2.aasm_current_state
|
||||
|
|
@ -82,20 +82,20 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert @not_completed2.save, "should have saved successfully" + @not_completed2.errors.to_xml
|
||||
assert_equal :deferred, @not_completed2.aasm_current_state
|
||||
end
|
||||
|
||||
|
||||
def test_create_a_new_deferred_todo
|
||||
user = users(:other_user)
|
||||
todo = user.todos.build
|
||||
todo.show_from = next_week
|
||||
todo.context_id = 1
|
||||
todo.description = 'foo'
|
||||
todo.description = 'foo'
|
||||
assert todo.save, "should have saved successfully" + todo.errors.to_xml
|
||||
assert_equal :deferred, todo.aasm_current_state
|
||||
end
|
||||
|
||||
def test_create_a_new_deferred_todo_by_passing_attributes
|
||||
user = users(:other_user)
|
||||
todo = user.todos.build(:show_from => next_week, :context_id => 1, :description => 'foo')
|
||||
todo = user.todos.build(:show_from => next_week, :context_id => 1, :description => 'foo')
|
||||
assert todo.save, "should have saved successfully" + todo.errors.to_xml
|
||||
assert_equal :deferred, todo.aasm_current_state
|
||||
end
|
||||
|
|
@ -167,15 +167,15 @@ class TodoTest < ActiveSupport::TestCase
|
|||
t.reload
|
||||
assert_equal :deferred, t.aasm_current_state
|
||||
end
|
||||
|
||||
|
||||
def test_todo_is_not_starred
|
||||
assert !@not_completed1.starred?
|
||||
end
|
||||
|
||||
|
||||
def test_todo_2_is_not_starred
|
||||
assert !Todo.find(2).starred?
|
||||
end
|
||||
|
||||
|
||||
def test_todo_is_starred_after_starred_tag_is_added
|
||||
@not_completed1._add_tags('starred')
|
||||
assert @not_completed1.starred?
|
||||
|
|
@ -185,7 +185,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
@not_completed1.toggle_star!
|
||||
assert @not_completed1.starred?
|
||||
end
|
||||
|
||||
|
||||
def test_todo_is_not_starred_after_toggle_starred_twice
|
||||
@not_completed1.toggle_star!
|
||||
@not_completed1.toggle_star!
|
||||
|
|
@ -239,4 +239,101 @@ class TodoTest < ActiveSupport::TestCase
|
|||
assert_equal 2, @predecessor_array.size
|
||||
end
|
||||
|
||||
def test_finding_todos_with_a_tag
|
||||
todo = @not_completed1
|
||||
todo.tag_list = "a, b, c"
|
||||
todo.save!
|
||||
|
||||
tag_a = Tag.find_by_name("a")
|
||||
tag_b = Tag.find_by_name("b")
|
||||
tag_c = Tag.find_by_name("c")
|
||||
|
||||
todos_with_a = Todo.with_tag(tag_a)
|
||||
assert 1, todos_with_a.count
|
||||
assert_equal todo.description, todos_with_a.first.description
|
||||
|
||||
todos_with_b = Todo.with_tag(tag_b)
|
||||
assert 1, todos_with_b.count
|
||||
assert_equal todo.id, todos_with_b.first.id
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_d = Tag.find_by_name("d")
|
||||
|
||||
todos_with_a = Todo.with_tag(tag_a)
|
||||
assert 2, todos_with_a.count
|
||||
|
||||
todos_with_d = Todo.with_tag(tag_d)
|
||||
assert 1, todos_with_a.count
|
||||
end
|
||||
|
||||
def test_finding_todos_with_more_tags_using_OR
|
||||
todo1 = @not_completed1
|
||||
todo1.tag_list = "a, b, c"
|
||||
todo1.save!
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_a = Tag.find_by_name("a")
|
||||
tag_b = Tag.find_by_name("b")
|
||||
tag_c = Tag.find_by_name("c")
|
||||
tag_d = Tag.find_by_name("d")
|
||||
|
||||
# overlapping tags
|
||||
tag_ids = [tag_a.id, tag_c.id]
|
||||
todos_with_a_or_c = Todo.with_tags(tag_ids)
|
||||
assert 2, todos_with_a_or_c.count
|
||||
|
||||
# non-overlapping tags
|
||||
tag_ids = [tag_b.id, tag_d.id]
|
||||
todos_with_b_or_d = Todo.with_tags(tag_ids)
|
||||
assert 2, todos_with_b_or_d.count
|
||||
end
|
||||
|
||||
def test_finding_todos_with_more_tags_using_AND
|
||||
todo1 = @not_completed1
|
||||
todo1.tag_list = "a, b, c"
|
||||
todo1.save!
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_a_id = Tag.find_by_name("a").id
|
||||
tag_b_id = Tag.find_by_name("b").id
|
||||
|
||||
todos_with_a_and_b = Todo.with_tags([tag_a_id]).with_tags([tag_b_id])
|
||||
assert 1, todos_with_a_and_b.count
|
||||
assert todo1.id, todos_with_a_and_b.first.id
|
||||
end
|
||||
|
||||
def test_finding_todos_with_more_tags_using_AND_and_OR
|
||||
todo1 = @not_completed1
|
||||
todo1.tag_list = "a, b, c"
|
||||
todo1.save!
|
||||
|
||||
todo2 = @not_completed2
|
||||
todo2.tag_list = "a, c, d"
|
||||
todo2.save!
|
||||
|
||||
tag_a_id = Tag.find_by_name("a").id
|
||||
tag_b_id = Tag.find_by_name("b").id
|
||||
tag_c_id = Tag.find_by_name("c").id
|
||||
|
||||
todos_with_aORc_and_b = Todo.with_tags([tag_a_id, tag_c_id]).with_tags([tag_b_id])
|
||||
assert 1, todos_with_aORc_and_b.count
|
||||
assert todo1.id, todos_with_aORc_and_b.first.id
|
||||
|
||||
# let todo2 fit the expression
|
||||
todo2.tag_list = "a, b, r"
|
||||
todo2.save!
|
||||
todos_with_aORc_and_b = Todo.with_tags([tag_a_id, tag_c_id]).with_tags([tag_b_id])
|
||||
assert 2, todos_with_aORc_and_b.count
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue