mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-18 00:00:12 +01:00
all unit and functional tests are passing
This commit is contained in:
parent
96db48dd86
commit
13b58f3a10
40 changed files with 1107 additions and 1494 deletions
261
README.rdoc
261
README.rdoc
|
|
@ -1,261 +0,0 @@
|
||||||
== Welcome to Rails
|
|
||||||
|
|
||||||
Rails is a web-application framework that includes everything needed to create
|
|
||||||
database-backed web applications according to the Model-View-Control pattern.
|
|
||||||
|
|
||||||
This pattern splits the view (also called the presentation) into "dumb"
|
|
||||||
templates that are primarily responsible for inserting pre-built data in between
|
|
||||||
HTML tags. The model contains the "smart" domain objects (such as Account,
|
|
||||||
Product, Person, Post) that holds all the business logic and knows how to
|
|
||||||
persist themselves to a database. The controller handles the incoming requests
|
|
||||||
(such as Save New Account, Update Product, Show Post) by manipulating the model
|
|
||||||
and directing data to the view.
|
|
||||||
|
|
||||||
In Rails, the model is handled by what's called an object-relational mapping
|
|
||||||
layer entitled Active Record. This layer allows you to present the data from
|
|
||||||
database rows as objects and embellish these data objects with business logic
|
|
||||||
methods. You can read more about Active Record in
|
|
||||||
link:files/vendor/rails/activerecord/README.html.
|
|
||||||
|
|
||||||
The controller and view are handled by the Action Pack, which handles both
|
|
||||||
layers by its two parts: Action View and Action Controller. These two layers
|
|
||||||
are bundled in a single package due to their heavy interdependence. This is
|
|
||||||
unlike the relationship between the Active Record and Action Pack that is much
|
|
||||||
more separate. Each of these packages can be used independently outside of
|
|
||||||
Rails. You can read more about Action Pack in
|
|
||||||
link:files/vendor/rails/actionpack/README.html.
|
|
||||||
|
|
||||||
|
|
||||||
== Getting Started
|
|
||||||
|
|
||||||
1. At the command prompt, create a new Rails application:
|
|
||||||
<tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
|
|
||||||
|
|
||||||
2. Change directory to <tt>myapp</tt> and start the web server:
|
|
||||||
<tt>cd myapp; rails server</tt> (run with --help for options)
|
|
||||||
|
|
||||||
3. Go to http://localhost:3000/ and you'll see:
|
|
||||||
"Welcome aboard: You're riding Ruby on Rails!"
|
|
||||||
|
|
||||||
4. Follow the guidelines to start developing your application. You can find
|
|
||||||
the following resources handy:
|
|
||||||
|
|
||||||
* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
|
|
||||||
* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
|
|
||||||
|
|
||||||
|
|
||||||
== Debugging Rails
|
|
||||||
|
|
||||||
Sometimes your application goes wrong. Fortunately there are a lot of tools that
|
|
||||||
will help you debug it and get it back on the rails.
|
|
||||||
|
|
||||||
First area to check is the application log files. Have "tail -f" commands
|
|
||||||
running on the server.log and development.log. Rails will automatically display
|
|
||||||
debugging and runtime information to these files. Debugging info will also be
|
|
||||||
shown in the browser on requests from 127.0.0.1.
|
|
||||||
|
|
||||||
You can also log your own messages directly into the log file from your code
|
|
||||||
using the Ruby logger class from inside your controllers. Example:
|
|
||||||
|
|
||||||
class WeblogController < ActionController::Base
|
|
||||||
def destroy
|
|
||||||
@weblog = Weblog.find(params[:id])
|
|
||||||
@weblog.destroy
|
|
||||||
logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
The result will be a message in your log file along the lines of:
|
|
||||||
|
|
||||||
Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
|
|
||||||
|
|
||||||
More information on how to use the logger is at http://www.ruby-doc.org/core/
|
|
||||||
|
|
||||||
Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
|
|
||||||
several books available online as well:
|
|
||||||
|
|
||||||
* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
|
|
||||||
* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
|
|
||||||
|
|
||||||
These two books will bring you up to speed on the Ruby language and also on
|
|
||||||
programming in general.
|
|
||||||
|
|
||||||
|
|
||||||
== Debugger
|
|
||||||
|
|
||||||
Debugger support is available through the debugger command when you start your
|
|
||||||
Mongrel or WEBrick server with --debugger. This means that you can break out of
|
|
||||||
execution at any point in the code, investigate and change the model, and then,
|
|
||||||
resume execution! You need to install ruby-debug to run the server in debugging
|
|
||||||
mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:
|
|
||||||
|
|
||||||
class WeblogController < ActionController::Base
|
|
||||||
def index
|
|
||||||
@posts = Post.all
|
|
||||||
debugger
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
So the controller will accept the action, run the first line, then present you
|
|
||||||
with a IRB prompt in the server window. Here you can do things like:
|
|
||||||
|
|
||||||
>> @posts.inspect
|
|
||||||
=> "[#<Post:0x14a6be8
|
|
||||||
@attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
|
|
||||||
#<Post:0x14a6620
|
|
||||||
@attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
|
|
||||||
>> @posts.first.title = "hello from a debugger"
|
|
||||||
=> "hello from a debugger"
|
|
||||||
|
|
||||||
...and even better, you can examine how your runtime objects actually work:
|
|
||||||
|
|
||||||
>> f = @posts.first
|
|
||||||
=> #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
|
|
||||||
>> f.
|
|
||||||
Display all 152 possibilities? (y or n)
|
|
||||||
|
|
||||||
Finally, when you're ready to resume execution, you can enter "cont".
|
|
||||||
|
|
||||||
|
|
||||||
== Console
|
|
||||||
|
|
||||||
The console is a Ruby shell, which allows you to interact with your
|
|
||||||
application's domain model. Here you'll have all parts of the application
|
|
||||||
configured, just like it is when the application is running. You can inspect
|
|
||||||
domain models, change values, and save to the database. Starting the script
|
|
||||||
without arguments will launch it in the development environment.
|
|
||||||
|
|
||||||
To start the console, run <tt>rails console</tt> from the application
|
|
||||||
directory.
|
|
||||||
|
|
||||||
Options:
|
|
||||||
|
|
||||||
* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
|
|
||||||
made to the database.
|
|
||||||
* Passing an environment name as an argument will load the corresponding
|
|
||||||
environment. Example: <tt>rails console production</tt>.
|
|
||||||
|
|
||||||
To reload your controllers and models after launching the console run
|
|
||||||
<tt>reload!</tt>
|
|
||||||
|
|
||||||
More information about irb can be found at:
|
|
||||||
link:http://www.rubycentral.org/pickaxe/irb.html
|
|
||||||
|
|
||||||
|
|
||||||
== dbconsole
|
|
||||||
|
|
||||||
You can go to the command line of your database directly through <tt>rails
|
|
||||||
dbconsole</tt>. You would be connected to the database with the credentials
|
|
||||||
defined in database.yml. Starting the script without arguments will connect you
|
|
||||||
to the development database. Passing an argument will connect you to a different
|
|
||||||
database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
|
|
||||||
PostgreSQL and SQLite 3.
|
|
||||||
|
|
||||||
== Description of Contents
|
|
||||||
|
|
||||||
The default directory structure of a generated Ruby on Rails application:
|
|
||||||
|
|
||||||
|-- app
|
|
||||||
| |-- assets
|
|
||||||
| |-- images
|
|
||||||
| |-- javascripts
|
|
||||||
| `-- stylesheets
|
|
||||||
| |-- controllers
|
|
||||||
| |-- helpers
|
|
||||||
| |-- mailers
|
|
||||||
| |-- models
|
|
||||||
| `-- views
|
|
||||||
| `-- layouts
|
|
||||||
|-- config
|
|
||||||
| |-- environments
|
|
||||||
| |-- initializers
|
|
||||||
| `-- locales
|
|
||||||
|-- db
|
|
||||||
|-- doc
|
|
||||||
|-- lib
|
|
||||||
| `-- tasks
|
|
||||||
|-- log
|
|
||||||
|-- public
|
|
||||||
|-- script
|
|
||||||
|-- test
|
|
||||||
| |-- fixtures
|
|
||||||
| |-- functional
|
|
||||||
| |-- integration
|
|
||||||
| |-- performance
|
|
||||||
| `-- unit
|
|
||||||
|-- tmp
|
|
||||||
| |-- cache
|
|
||||||
| |-- pids
|
|
||||||
| |-- sessions
|
|
||||||
| `-- sockets
|
|
||||||
`-- vendor
|
|
||||||
|-- assets
|
|
||||||
`-- stylesheets
|
|
||||||
`-- plugins
|
|
||||||
|
|
||||||
app
|
|
||||||
Holds all the code that's specific to this particular application.
|
|
||||||
|
|
||||||
app/assets
|
|
||||||
Contains subdirectories for images, stylesheets, and JavaScript files.
|
|
||||||
|
|
||||||
app/controllers
|
|
||||||
Holds controllers that should be named like weblogs_controller.rb for
|
|
||||||
automated URL mapping. All controllers should descend from
|
|
||||||
ApplicationController which itself descends from ActionController::Base.
|
|
||||||
|
|
||||||
app/models
|
|
||||||
Holds models that should be named like post.rb. Models descend from
|
|
||||||
ActiveRecord::Base by default.
|
|
||||||
|
|
||||||
app/views
|
|
||||||
Holds the template files for the view that should be named like
|
|
||||||
weblogs/index.html.erb for the WeblogsController#index action. All views use
|
|
||||||
eRuby syntax by default.
|
|
||||||
|
|
||||||
app/views/layouts
|
|
||||||
Holds the template files for layouts to be used with views. This models the
|
|
||||||
common header/footer method of wrapping views. In your views, define a layout
|
|
||||||
using the <tt>layout :default</tt> and create a file named default.html.erb.
|
|
||||||
Inside default.html.erb, call <% yield %> to render the view using this
|
|
||||||
layout.
|
|
||||||
|
|
||||||
app/helpers
|
|
||||||
Holds view helpers that should be named like weblogs_helper.rb. These are
|
|
||||||
generated for you automatically when using generators for controllers.
|
|
||||||
Helpers can be used to wrap functionality for your views into methods.
|
|
||||||
|
|
||||||
config
|
|
||||||
Configuration files for the Rails environment, the routing map, the database,
|
|
||||||
and other dependencies.
|
|
||||||
|
|
||||||
db
|
|
||||||
Contains the database schema in schema.rb. db/migrate contains all the
|
|
||||||
sequence of Migrations for your schema.
|
|
||||||
|
|
||||||
doc
|
|
||||||
This directory is where your application documentation will be stored when
|
|
||||||
generated using <tt>rake doc:app</tt>
|
|
||||||
|
|
||||||
lib
|
|
||||||
Application specific libraries. Basically, any kind of custom code that
|
|
||||||
doesn't belong under controllers, models, or helpers. This directory is in
|
|
||||||
the load path.
|
|
||||||
|
|
||||||
public
|
|
||||||
The directory available for the web server. Also contains the dispatchers and the
|
|
||||||
default HTML files. This should be set as the DOCUMENT_ROOT of your web
|
|
||||||
server.
|
|
||||||
|
|
||||||
script
|
|
||||||
Helper scripts for automation and generation.
|
|
||||||
|
|
||||||
test
|
|
||||||
Unit and functional tests along with fixtures. When using the rails generate
|
|
||||||
command, template test files will be generated for you and placed in this
|
|
||||||
directory.
|
|
||||||
|
|
||||||
vendor
|
|
||||||
External libraries that the application depends on. Also includes the plugins
|
|
||||||
subdirectory. If the app has frozen rails, those gems also go here, under
|
|
||||||
vendor/rails/. This directory is in the load path.
|
|
||||||
|
|
@ -18,7 +18,7 @@ class DataController < ApplicationController
|
||||||
def yaml_export
|
def yaml_export
|
||||||
all_tables = {}
|
all_tables = {}
|
||||||
|
|
||||||
all_tables['todos'] = current_user.todos.includes(:tags)
|
all_tables['todos'] = current_user.todos.includes(:tags).all
|
||||||
all_tables['contexts'] = current_user.contexts.all
|
all_tables['contexts'] = current_user.contexts.all
|
||||||
all_tables['projects'] = current_user.projects.all
|
all_tables['projects'] = current_user.projects.all
|
||||||
|
|
||||||
|
|
@ -37,10 +37,10 @@ class DataController < ApplicationController
|
||||||
tags = Tag.where("id IN (?) OR id IN (?)", todo_tag_ids, rec_todo_tag_ids)
|
tags = Tag.where("id IN (?) OR id IN (?)", todo_tag_ids, rec_todo_tag_ids)
|
||||||
taggings = Tagging.where("tag_id IN (?) OR tag_id IN(?)", todo_tag_ids, rec_todo_tag_ids)
|
taggings = Tagging.where("tag_id IN (?) OR tag_id IN(?)", todo_tag_ids, rec_todo_tag_ids)
|
||||||
|
|
||||||
all_tables['tags'] = tags
|
all_tables['tags'] = tags.all
|
||||||
all_tables['taggings'] = taggings
|
all_tables['taggings'] = taggings.all
|
||||||
all_tables['notes'] = current_user.notes
|
all_tables['notes'] = current_user.notes.all
|
||||||
all_tables['recurring_todos'] = current_user.recurring_todos
|
all_tables['recurring_todos'] = current_user.recurring_todos.all
|
||||||
|
|
||||||
result = all_tables.to_yaml
|
result = all_tables.to_yaml
|
||||||
result.gsub!(/\n/, "\r\n") # TODO: general functionality for line endings
|
result.gsub!(/\n/, "\r\n") # TODO: general functionality for line endings
|
||||||
|
|
@ -72,13 +72,13 @@ class DataController < ApplicationController
|
||||||
|
|
||||||
def csv_notes
|
def csv_notes
|
||||||
content_type = 'text/csv'
|
content_type = 'text/csv'
|
||||||
CSV::Writer.generate(result = "") do |csv|
|
CSV.generate(result = "") do |csv|
|
||||||
csv << ["id", "User ID", "Project", "Note",
|
csv << ["id", "User ID", "Project", "Note",
|
||||||
"Created at", "Updated at"]
|
"Created at", "Updated at"]
|
||||||
# had to remove project include because it's association order is leaking
|
# had to remove project include because it's association order is leaking
|
||||||
# through and causing an ambiguous column ref even with_exclusive_scope
|
# through and causing an ambiguous column ref even with_exclusive_scope
|
||||||
# didn't seem to help -JamesKebinger
|
# didn't seem to help -JamesKebinger
|
||||||
current_user.notes.order("notes.created_at").each do |note|
|
current_user.notes.reorder("notes.created_at").each do |note|
|
||||||
# Format dates in ISO format for easy sorting in spreadsheet Print
|
# Format dates in ISO format for easy sorting in spreadsheet Print
|
||||||
# context and project names for easy viewing
|
# context and project names for easy viewing
|
||||||
csv << [note.id, note.user_id,
|
csv << [note.id, note.user_id,
|
||||||
|
|
|
||||||
|
|
@ -113,7 +113,7 @@ class ProjectsController < ApplicationController
|
||||||
|
|
||||||
@done = {}
|
@done = {}
|
||||||
@done = @project.todos.completed.
|
@done = @project.todos.completed.
|
||||||
order("todos.completed_at DESC").
|
reorder("todos.completed_at DESC").
|
||||||
limit(current_user.prefs.show_number_completed).
|
limit(current_user.prefs.show_number_completed).
|
||||||
includes(Todo::DEFAULT_INCLUDES) unless current_user.prefs.show_number_completed == 0
|
includes(Todo::DEFAULT_INCLUDES) unless current_user.prefs.show_number_completed == 0
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,12 +10,12 @@ class SearchController < ApplicationController
|
||||||
@found_not_complete_todos = current_user.todos.
|
@found_not_complete_todos = current_user.todos.
|
||||||
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND todos.completed_at IS NULL", terms, terms).
|
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND todos.completed_at IS NULL", terms, terms).
|
||||||
includes(Todo::DEFAULT_INCLUDES).
|
includes(Todo::DEFAULT_INCLUDES).
|
||||||
order("todos.due IS NULL, todos.due ASC, todos.created_at ASC")
|
reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC")
|
||||||
|
|
||||||
@found_complete_todos = current_user.todos.
|
@found_complete_todos = current_user.todos.
|
||||||
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND NOT (todos.completed_at IS NULL)", terms, terms).
|
where("(todos.description LIKE ? OR todos.notes LIKE ?) AND NOT (todos.completed_at IS NULL)", terms, terms).
|
||||||
includes(Todo::DEFAULT_INCLUDES).
|
includes(Todo::DEFAULT_INCLUDES).
|
||||||
order("todos.completed_at DESC")
|
reorder("todos.completed_at DESC")
|
||||||
|
|
||||||
@found_todos = @found_not_complete_todos + @found_complete_todos
|
@found_todos = @found_not_complete_todos + @found_complete_todos
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,10 @@ class StatsController < ApplicationController
|
||||||
def index
|
def index
|
||||||
@page_title = t('stats.index_title')
|
@page_title = t('stats.index_title')
|
||||||
|
|
||||||
|
@first_action = current_user.todos.reorder("created_at ASC").first
|
||||||
@tags_count = get_total_number_of_tags_of_user
|
@tags_count = get_total_number_of_tags_of_user
|
||||||
@unique_tags_count = get_unique_tags_of_user.size
|
@unique_tags_count = get_unique_tags_of_user.size
|
||||||
@hidden_contexts = current_user.contexts.hidden
|
@hidden_contexts = current_user.contexts.hidden
|
||||||
@first_action = current_user.todos.order("created_at ASC").first
|
|
||||||
|
|
||||||
get_stats_actions
|
get_stats_actions
|
||||||
get_stats_contexts
|
get_stats_contexts
|
||||||
|
|
@ -55,8 +55,8 @@ class StatsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def actions_done_lastyears_data
|
def actions_done_lastyears_data
|
||||||
@actions_done_last_months = current_user.todos.completed.select("completed_at").order("completed_at DESC")
|
@actions_done_last_months = current_user.todos.completed.select("completed_at").reorder("completed_at DESC")
|
||||||
@actions_created_last_months = current_user.todos.select("created_at").order("created_at DESC" )
|
@actions_created_last_months = current_user.todos.select("created_at").reorder("created_at DESC" )
|
||||||
|
|
||||||
# query is sorted, so use last todo to calculate number of months
|
# query is sorted, so use last todo to calculate number of months
|
||||||
@month_count = [difference_in_months(@today, @actions_created_last_months.last.created_at),
|
@month_count = [difference_in_months(@today, @actions_created_last_months.last.created_at),
|
||||||
|
|
@ -101,7 +101,7 @@ class StatsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def actions_completion_time_data
|
def actions_completion_time_data
|
||||||
@actions_completion_time = current_user.todos.completed.select("completed_at, created_at").order("completed_at DESC" )
|
@actions_completion_time = current_user.todos.completed.select("completed_at, created_at").reorder("completed_at DESC" )
|
||||||
|
|
||||||
# convert to array and fill in non-existing weeks with 0
|
# convert to array and fill in non-existing weeks with 0
|
||||||
@max_weeks = difference_in_weeks(@today, @actions_completion_time.last.completed_at)
|
@max_weeks = difference_in_weeks(@today, @actions_completion_time.last.completed_at)
|
||||||
|
|
@ -121,7 +121,7 @@ class StatsController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def actions_running_time_data
|
def actions_running_time_data
|
||||||
@actions_running_time = current_user.todos.not_completed.select("created_at").order("created_at DESC")
|
@actions_running_time = current_user.todos.not_completed.select("created_at").reorder("created_at DESC")
|
||||||
|
|
||||||
# convert to array and fill in non-existing weeks with 0
|
# convert to array and fill in non-existing weeks with 0
|
||||||
@max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at)
|
@max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at)
|
||||||
|
|
@ -151,7 +151,7 @@ class StatsController < ApplicationController
|
||||||
|
|
||||||
@actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked.
|
@actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked.
|
||||||
select("todos.created_at").
|
select("todos.created_at").
|
||||||
order("todos.created_at DESC")
|
reorder("todos.created_at DESC")
|
||||||
|
|
||||||
@max_weeks = difference_in_weeks(@today, @actions_running_time.last.created_at)
|
@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)
|
||||||
|
|
@ -172,7 +172,7 @@ class StatsController < ApplicationController
|
||||||
def actions_open_per_week_data
|
def actions_open_per_week_data
|
||||||
@actions_started = current_user.todos.created_after(@today-53.weeks).
|
@actions_started = current_user.todos.created_after(@today-53.weeks).
|
||||||
select("todos.created_at, todos.completed_at").
|
select("todos.created_at, todos.completed_at").
|
||||||
order("todos.created_at DESC")
|
reorder("todos.created_at DESC")
|
||||||
|
|
||||||
@max_weeks = difference_in_weeks(@today, @actions_started.last.created_at)
|
@max_weeks = difference_in_weeks(@today, @actions_started.last.created_at)
|
||||||
|
|
||||||
|
|
@ -358,7 +358,7 @@ class StatsController < ApplicationController
|
||||||
# get all running actions that are visible
|
# get all running actions that are visible
|
||||||
@actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked.
|
@actions_running_time = current_user.todos.not_completed.not_hidden.not_deferred_or_blocked.
|
||||||
select("todos.id, todos.created_at").
|
select("todos.id, todos.created_at").
|
||||||
order("todos.created_at DESC")
|
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(",") + ")")
|
@selected_actions = selected_todo_ids.size == 0 ? [] : current_user.todos.where("id in (" + selected_todo_ids.join(",") + ")")
|
||||||
|
|
@ -399,10 +399,10 @@ class StatsController < ApplicationController
|
||||||
|
|
||||||
init_not_done_counts
|
init_not_done_counts
|
||||||
|
|
||||||
@done_recently = current_user.todos.completed.limit(10).order('completed_at DESC').includes(Todo::DEFAULT_INCLUDES)
|
@done_recently = current_user.todos.completed.limit(10).reorder('completed_at DESC').includes(Todo::DEFAULT_INCLUDES)
|
||||||
@last_completed_projects = current_user.projects.completed.limit(10).order('completed_at DESC').includes(:todos, :notes)
|
@last_completed_projects = current_user.projects.completed.limit(10).reorder('completed_at DESC').includes(:todos, :notes)
|
||||||
@last_completed_contexts = []
|
@last_completed_contexts = []
|
||||||
@last_completed_recurring_todos = current_user.recurring_todos.completed.limit(10).order('completed_at DESC').includes(:tags, :taggings)
|
@last_completed_recurring_todos = current_user.recurring_todos.completed.limit(10).reorder('completed_at DESC').includes(:tags, :taggings)
|
||||||
#TODO: @last_completed_contexts = current_user.contexts.completed.all(:limit => 10, :order => 'completed_at DESC')
|
#TODO: @last_completed_contexts = current_user.contexts.completed.all(:limit => 10, :order => 'completed_at DESC')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,36 +1,152 @@
|
||||||
class TodosController < ApplicationController
|
class TodosController < ApplicationController
|
||||||
|
|
||||||
helper :todos
|
|
||||||
|
|
||||||
skip_before_filter :login_required, :only => [:index, :calendar, :tag]
|
skip_before_filter :login_required, :only => [:index, :calendar, :tag]
|
||||||
prepend_before_filter :login_or_feed_token_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]
|
append_before_filter :find_and_activate_ready, :only => [:index, :list_deferred]
|
||||||
|
|
||||||
# TODO: replace :except with :only
|
# # TODO: replace :except with :only
|
||||||
append_before_filter :init, :except => [ :tag, :tags, :destroy, :done,
|
# append_before_filter :init, :except => [ :tag, :tags, :destroy, :done,
|
||||||
:check_deferred, :toggle_check, :toggle_star, :edit, :update, :defer, :create,
|
# :check_deferred, :toggle_check, :toggle_star, :edit, :update, :defer, :create,
|
||||||
:calendar, :auto_complete_for_predecessor, :remove_predecessor, :add_predecessor]
|
# :calendar, :auto_complete_for_predecessor, :remove_predecessor, :add_predecessor]
|
||||||
|
|
||||||
protect_from_forgery :except => :check_deferred
|
protect_from_forgery :except => :check_deferred
|
||||||
|
|
||||||
# these are needed for todo_feed_content. TODO: remove this view stuff from controller
|
# # these are needed for todo_feed_content. TODO: remove this view stuff from controller
|
||||||
include ActionView::Helpers::SanitizeHelper
|
# include ActionView::Helpers::SanitizeHelper
|
||||||
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
# extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
||||||
|
|
||||||
|
def with_feed_query_scope(&block)
|
||||||
|
unless TodosController.is_feed_request(request)
|
||||||
|
Todo.send(:where, ['todos.state = ?', 'active']) do
|
||||||
|
yield
|
||||||
|
return
|
||||||
|
end
|
||||||
|
end
|
||||||
|
condition_builder = FindConditionBuilder.new
|
||||||
|
|
||||||
|
if params.key?('done')
|
||||||
|
condition_builder.add 'todos.state = ?', 'completed'
|
||||||
|
else
|
||||||
|
condition_builder.add 'todos.state = ?', 'active'
|
||||||
|
end
|
||||||
|
|
||||||
|
@title = t('todos.next_actions_title')
|
||||||
|
@description = t('todos.next_actions_description')
|
||||||
|
|
||||||
|
if params.key?('due')
|
||||||
|
due_within = params['due'].to_i
|
||||||
|
due_within_when = Time.zone.now + due_within.days
|
||||||
|
condition_builder.add('todos.due <= ?', due_within_when)
|
||||||
|
due_within_date_s = due_within_when.strftime("%Y-%m-%d")
|
||||||
|
@title << t('todos.next_actions_title_additions.due_today') if (due_within == 0)
|
||||||
|
@title << t('todos.next_actions_title_additions.due_within_a_week') if (due_within == 6)
|
||||||
|
@description << t('todos.next_actions_description_additions.due_date', :due_date => due_within_date_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
if params.key?('done')
|
||||||
|
done_in_last = params['done'].to_i
|
||||||
|
condition_builder.add('todos.completed_at >= ?', Time.zone.now - done_in_last.days)
|
||||||
|
@title << t('todos.next_actions_title_additions.completed')
|
||||||
|
@description << t('todos.next_actions_description_additions.completed', :count => done_in_last.to_s)
|
||||||
|
end
|
||||||
|
|
||||||
|
if params.key?('tag')
|
||||||
|
tag = Tag.find_by_name(params['tag'])
|
||||||
|
if tag.nil?
|
||||||
|
tag = Tag.new(:name => params['tag'])
|
||||||
|
end
|
||||||
|
condition_builder.add('taggings.tag_id = ?', tag.id)
|
||||||
|
end
|
||||||
|
|
||||||
|
Todo.send :where, condition_builder.to_conditions do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_parent_resource_scope(&block)
|
||||||
|
@feed_title = t('common.actions')
|
||||||
|
if (params[:context_id])
|
||||||
|
@context = current_user.contexts.find_by_params(params)
|
||||||
|
@feed_title = @feed_title + t('todos.feed_title_in_context', :context => @context.name)
|
||||||
|
Todo.send :where, ['todos.context_id = ?', @context.id] do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
elsif (params[:project_id])
|
||||||
|
@project = current_user.projects.find_by_params(params)
|
||||||
|
@feed_title = @feed_title + t('todos.feed_title_in_project', :project => @project.name)
|
||||||
|
@project_feed = true
|
||||||
|
Todo.send :where, ['todos.project_id = ?', @project.id] do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
else
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def with_limit_scope(&block)
|
||||||
|
if params.key?('limit')
|
||||||
|
Todo.send :with_scope, :find => { :limit => params['limit'] } do
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
if TodosController.is_feed_request(request) && @description
|
||||||
|
if params.key?('limit')
|
||||||
|
@description << t('todos.list_incomplete_next_actions_with_limit', :count => params['limit'])
|
||||||
|
else
|
||||||
|
@description << t('todos.list_incomplete_next_actions')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
else
|
||||||
|
yield
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def index
|
def index
|
||||||
|
@source_view = params['_source_view'] || 'todo'
|
||||||
|
init_data_for_sidebar unless mobile?
|
||||||
|
|
||||||
|
if mobile?
|
||||||
|
@not_done_todos = current_user.todos.
|
||||||
|
where('todos.state = ? AND contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', 'active', false, 'active').
|
||||||
|
reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC").
|
||||||
|
includes(:project, :context, :tags)
|
||||||
|
else
|
||||||
|
@todos = current_user.todos.includes(Todo::DEFAULT_INCLUDES)
|
||||||
|
@not_done_todos = current_user.todos.
|
||||||
|
where('contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', false, 'active').
|
||||||
|
reorder("todos.due IS NULL, todos.due ASC, todos.created_at ASC").
|
||||||
|
includes(Todo::DEFAULT_INCLUDES)
|
||||||
|
end
|
||||||
|
|
||||||
@projects = current_user.projects.includes(:default_context)
|
@projects = current_user.projects.includes(:default_context)
|
||||||
@contexts = current_user.contexts
|
@contexts = current_user.contexts
|
||||||
|
|
||||||
@contexts_to_show = current_user.contexts.active
|
@contexts_to_show = current_user.contexts.active
|
||||||
|
|
||||||
|
# If you've set no_completed to zero, the completed items box isn't shown
|
||||||
|
# on the home page
|
||||||
|
max_completed = current_user.prefs.show_number_completed
|
||||||
|
@done = current_user.todos.completed.limit(max_completed).includes(Todo::DEFAULT_INCLUDES) unless max_completed == 0
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html &render_todos_html
|
format.html do
|
||||||
format.m &render_todos_mobile
|
@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)
|
||||||
|
end
|
||||||
|
format.m do
|
||||||
|
@page_title = t('todos.mobile_todos_page_title')
|
||||||
|
@home = true
|
||||||
|
|
||||||
|
cookies[:mobile_url]= { :value => request.request_uri, :secure => SITE_CONFIG['secure_cookies']}
|
||||||
|
determine_down_count
|
||||||
|
|
||||||
|
render :action => 'index'
|
||||||
|
end
|
||||||
format.xml { render :xml => @todos.to_xml( *to_xml_params ) }
|
format.xml { render :xml => @todos.to_xml( *to_xml_params ) }
|
||||||
format.rss &render_rss_feed
|
format.rss
|
||||||
format.atom &render_atom_feed
|
format.atom
|
||||||
format.text &render_text_feed
|
format.text
|
||||||
format.ics &render_ical_feed
|
format.ics
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -315,7 +431,7 @@ class TodosController < ApplicationController
|
||||||
# Toggles the 'done' status of the action
|
# Toggles the 'done' status of the action
|
||||||
#
|
#
|
||||||
def toggle_check
|
def toggle_check
|
||||||
@todo = current_user.todos.find_by_id(params['id'])
|
@todo = current_user.todos.find(params['id'])
|
||||||
@source_view = params['_source_view'] || 'todo'
|
@source_view = params['_source_view'] || 'todo'
|
||||||
@original_item_due = @todo.due
|
@original_item_due = @todo.due
|
||||||
@original_item_was_deferred = @todo.deferred?
|
@original_item_was_deferred = @todo.deferred?
|
||||||
|
|
@ -565,7 +681,7 @@ class TodosController < ApplicationController
|
||||||
@source_view = 'done'
|
@source_view = 'done'
|
||||||
@page_title = t('todos.completed_tasks_title')
|
@page_title = t('todos.completed_tasks_title')
|
||||||
|
|
||||||
@done = current_user.todos.completed.includes(Todo::DEFAULT_INCLUDES).order('completed_at DESC').paginate :page => params[:page], :per_page => 20
|
@done = current_user.todos.completed.includes(Todo::DEFAULT_INCLUDES).reorder('completed_at DESC').paginate :page => params[:page], :per_page => 20
|
||||||
@count = @done.size
|
@count = @done.size
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -624,26 +740,26 @@ class TodosController < ApplicationController
|
||||||
|
|
||||||
@not_done_todos = todos_with_tag_ids.
|
@not_done_todos = todos_with_tag_ids.
|
||||||
active.not_hidden.
|
active.not_hidden.
|
||||||
order('todos.due IS NULL, todos.due ASC, todos.created_at ASC').
|
reorder('todos.due IS NULL, todos.due ASC, todos.created_at ASC').
|
||||||
includes(Todo::DEFAULT_INCLUDES)
|
includes(Todo::DEFAULT_INCLUDES)
|
||||||
@hidden_todos = todos_with_tag_ids.
|
@hidden_todos = todos_with_tag_ids.
|
||||||
hidden.
|
hidden.
|
||||||
order('todos.completed_at DESC, todos.created_at DESC').
|
reorder('todos.completed_at DESC, todos.created_at DESC').
|
||||||
includes(Todo::DEFAULT_INCLUDES)
|
includes(Todo::DEFAULT_INCLUDES)
|
||||||
@deferred = todos_with_tag_ids.
|
@deferred = todos_with_tag_ids.
|
||||||
deferred.
|
deferred.
|
||||||
order('todos.show_from ASC, todos.created_at DESC').
|
reorder('todos.show_from ASC, todos.created_at DESC').
|
||||||
includes(Todo::DEFAULT_INCLUDES)
|
includes(Todo::DEFAULT_INCLUDES)
|
||||||
@pending = todos_with_tag_ids.
|
@pending = todos_with_tag_ids.
|
||||||
blocked.
|
blocked.
|
||||||
order('todos.show_from ASC, todos.created_at DESC').
|
reorder('todos.show_from ASC, todos.created_at DESC').
|
||||||
includes(Todo::DEFAULT_INCLUDES)
|
includes(Todo::DEFAULT_INCLUDES)
|
||||||
|
|
||||||
# If you've set no_completed to zero, the completed items box isn't shown on
|
# If you've set no_completed to zero, the completed items box isn't shown on
|
||||||
# the tag page
|
# the tag page
|
||||||
@done = todos_with_tag_ids.completed.
|
@done = todos_with_tag_ids.completed.
|
||||||
limit(current_user.prefs.show_number_completed).
|
limit(current_user.prefs.show_number_completed).
|
||||||
order('todos.completed_at DESC').
|
reorder('todos.completed_at DESC').
|
||||||
includes(Todo::DEFAULT_INCLUDES)
|
includes(Todo::DEFAULT_INCLUDES)
|
||||||
|
|
||||||
@projects = current_user.projects
|
@projects = current_user.projects
|
||||||
|
|
@ -696,7 +812,7 @@ class TodosController < ApplicationController
|
||||||
@tag = Tag.find_by_name(@tag_name)
|
@tag = Tag.find_by_name(@tag_name)
|
||||||
@tag = Tag.new(:name => @tag_name) if @tag.nil?
|
@tag = Tag.new(:name => @tag_name) if @tag.nil?
|
||||||
|
|
||||||
@done = current_user.todos.completed.with_tag(@tag.id).order('completed_at DESC').includes(Todo::DEFAULT_INCLUDES).paginate :page => params[:page], :per_page => 20
|
@done = current_user.todos.completed.with_tag(@tag.id).reorder('completed_at DESC').includes(Todo::DEFAULT_INCLUDES).paginate :page => params[:page], :per_page => 20
|
||||||
@count = @done.size
|
@count = @done.size
|
||||||
render :template => 'todos/all_done'
|
render :template => 'todos/all_done'
|
||||||
end
|
end
|
||||||
|
|
@ -772,34 +888,34 @@ class TodosController < ApplicationController
|
||||||
@due_today = current_user.todos.not_completed.
|
@due_today = current_user.todos.not_completed.
|
||||||
where('todos.due <= ?', due_today_date).
|
where('todos.due <= ?', due_today_date).
|
||||||
includes(included_tables).
|
includes(included_tables).
|
||||||
order("due")
|
reorder("due")
|
||||||
@due_this_week = current_user.todos.not_completed.
|
@due_this_week = current_user.todos.not_completed.
|
||||||
where('todos.due > ? AND todos.due <= ?', due_today_date, due_this_week_date).
|
where('todos.due > ? AND todos.due <= ?', due_today_date, due_this_week_date).
|
||||||
includes(included_tables).
|
includes(included_tables).
|
||||||
order("due")
|
reorder("due")
|
||||||
@due_next_week = current_user.todos.not_completed.
|
@due_next_week = current_user.todos.not_completed.
|
||||||
where('todos.due > ? AND todos.due <= ?', due_this_week_date, due_next_week_date).
|
where('todos.due > ? AND todos.due <= ?', due_this_week_date, due_next_week_date).
|
||||||
includes(included_tables).
|
includes(included_tables).
|
||||||
order("due")
|
reorder("due")
|
||||||
@due_this_month = current_user.todos.not_completed.
|
@due_this_month = current_user.todos.not_completed.
|
||||||
where('todos.due > ? AND todos.due <= ?', due_next_week_date, due_this_month_date).
|
where('todos.due > ? AND todos.due <= ?', due_next_week_date, due_this_month_date).
|
||||||
includes(included_tables).
|
includes(included_tables).
|
||||||
order("due")
|
reorder("due")
|
||||||
@due_after_this_month = current_user.todos.not_completed.
|
@due_after_this_month = current_user.todos.not_completed.
|
||||||
where('todos.due > ?', due_this_month_date).
|
where('todos.due > ?', due_this_month_date).
|
||||||
includes(included_tables).
|
includes(included_tables).
|
||||||
order("due")
|
reorder("due")
|
||||||
|
|
||||||
@count = current_user.todos.not_completed.are_due.count
|
@count = current_user.todos.not_completed.are_due.count
|
||||||
|
|
||||||
respond_to do |format|
|
respond_to do |format|
|
||||||
format.html
|
format.html
|
||||||
format.ics {
|
format.ics {
|
||||||
@due_all = current_user.todos.not_completed.are_due.order("due")
|
@due_all = current_user.todos.not_completed.are_due.reorder("due")
|
||||||
render :action => 'calendar', :layout => false, :content_type => Mime::ICS
|
render :action => 'calendar', :layout => false, :content_type => Mime::ICS
|
||||||
}
|
}
|
||||||
format.xml {
|
format.xml {
|
||||||
@due_all = current_user.todos.not_completed.are_due.order("due")
|
@due_all = current_user.todos.not_completed.are_due.reorder("due")
|
||||||
render :xml => @due_all.to_xml( *to_xml_params )
|
render :xml => @due_all.to_xml( *to_xml_params )
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
@ -821,26 +937,26 @@ class TodosController < ApplicationController
|
||||||
@items = @todo.project.todos.not_completed.
|
@items = @todo.project.todos.not_completed.
|
||||||
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
||||||
includes(:context, :project).
|
includes(:context, :project).
|
||||||
order('description ASC').
|
reorder('description ASC').
|
||||||
limit(10) unless @todo.project.nil?
|
limit(10) unless @todo.project.nil?
|
||||||
# Then look in the current context, excluding @todo itself
|
# Then look in the current context, excluding @todo itself
|
||||||
@items = @todo.context.todos.not_completed
|
@items = @todo.context.todos.not_completed
|
||||||
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
||||||
includes(:context, :project).
|
includes(:context, :project).
|
||||||
order('description ASC').
|
reorder('description ASC').
|
||||||
limit(10) unless !@items.empty? || @todo.context.nil?
|
limit(10) unless !@items.empty? || @todo.context.nil?
|
||||||
# Match todos in other projects, excluding @todo itself
|
# Match todos in other projects, excluding @todo itself
|
||||||
@items = current_user.todos.not_completed.
|
@items = current_user.todos.not_completed.
|
||||||
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
||||||
includes(:context, :project).
|
includes(:context, :project).
|
||||||
order('description ASC').
|
reorder('description ASC').
|
||||||
limit(10) unless !@items.empty?
|
limit(10) unless !@items.empty?
|
||||||
else
|
else
|
||||||
# New todo - TODO: Filter on current project in project view
|
# New todo - TODO: Filter on current project in project view
|
||||||
@items = current_user.todos.not_completed.
|
@items = current_user.todos.not_completed.
|
||||||
where('(LOWER(todos.description) LIKE ?)', "%#{params[:term].downcase}%").
|
where('(LOWER(todos.description) LIKE ?)', "%#{params[:term].downcase}%").
|
||||||
includes(:context, :project).
|
includes(:context, :project).
|
||||||
order('description ASC').
|
reorder('description ASC').
|
||||||
limit(10)
|
limit(10)
|
||||||
end
|
end
|
||||||
render :inline => format_dependencies_as_json_for_auto_complete(@items)
|
render :inline => format_dependencies_as_json_for_auto_complete(@items)
|
||||||
|
|
@ -894,136 +1010,6 @@ class TodosController < ApplicationController
|
||||||
current_user.deferred_todos.find_and_activate_ready
|
current_user.deferred_todos.find_and_activate_ready
|
||||||
end
|
end
|
||||||
|
|
||||||
def init
|
|
||||||
@source_view = params['_source_view'] || 'todo'
|
|
||||||
init_data_for_sidebar unless mobile?
|
|
||||||
init_todos
|
|
||||||
end
|
|
||||||
|
|
||||||
def with_feed_query_scope(&block)
|
|
||||||
unless TodosController.is_feed_request(request)
|
|
||||||
Todo.send(:where, ['todos.state = ?', 'active']) do
|
|
||||||
yield
|
|
||||||
return
|
|
||||||
end
|
|
||||||
end
|
|
||||||
condition_builder = FindConditionBuilder.new
|
|
||||||
|
|
||||||
if params.key?('done')
|
|
||||||
condition_builder.add 'todos.state = ?', 'completed'
|
|
||||||
else
|
|
||||||
condition_builder.add 'todos.state = ?', 'active'
|
|
||||||
end
|
|
||||||
|
|
||||||
@title = t('todos.next_actions_title')
|
|
||||||
@description = t('todos.next_actions_description')
|
|
||||||
|
|
||||||
if params.key?('due')
|
|
||||||
due_within = params['due'].to_i
|
|
||||||
due_within_when = Time.zone.now + due_within.days
|
|
||||||
condition_builder.add('todos.due <= ?', due_within_when)
|
|
||||||
due_within_date_s = due_within_when.strftime("%Y-%m-%d")
|
|
||||||
@title << t('todos.next_actions_title_additions.due_today') if (due_within == 0)
|
|
||||||
@title << t('todos.next_actions_title_additions.due_within_a_week') if (due_within == 6)
|
|
||||||
@description << t('todos.next_actions_description_additions.due_date', :due_date => due_within_date_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
if params.key?('done')
|
|
||||||
done_in_last = params['done'].to_i
|
|
||||||
condition_builder.add('todos.completed_at >= ?', Time.zone.now - done_in_last.days)
|
|
||||||
@title << t('todos.next_actions_title_additions.completed')
|
|
||||||
@description << t('todos.next_actions_description_additions.completed', :count => done_in_last.to_s)
|
|
||||||
end
|
|
||||||
|
|
||||||
if params.key?('tag')
|
|
||||||
tag = Tag.find_by_name(params['tag'])
|
|
||||||
if tag.nil?
|
|
||||||
tag = Tag.new(:name => params['tag'])
|
|
||||||
end
|
|
||||||
condition_builder.add('taggings.tag_id = ?', tag.id)
|
|
||||||
end
|
|
||||||
|
|
||||||
Todo.send :where, condition_builder.to_conditions do
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
def with_parent_resource_scope(&block)
|
|
||||||
@feed_title = t('common.actions')
|
|
||||||
if (params[:context_id])
|
|
||||||
@context = current_user.contexts.find_by_params(params)
|
|
||||||
@feed_title = @feed_title + t('todos.feed_title_in_context', :context => @context.name)
|
|
||||||
Todo.send :where, ['todos.context_id = ?', @context.id] do
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
elsif (params[:project_id])
|
|
||||||
@project = current_user.projects.find_by_params(params)
|
|
||||||
@feed_title = @feed_title + t('todos.feed_title_in_project', :project => @project.name)
|
|
||||||
@project_feed = true
|
|
||||||
Todo.send :where, ['todos.project_id = ?', @project.id] do
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
else
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def with_limit_scope(&block)
|
|
||||||
if params.key?('limit')
|
|
||||||
Todo.send :with_scope, :find => { :limit => params['limit'] } do
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
if TodosController.is_feed_request(request) && @description
|
|
||||||
if params.key?('limit')
|
|
||||||
@description << t('todos.list_incomplete_next_actions_with_limit', :count => params['limit'])
|
|
||||||
else
|
|
||||||
@description << t('todos.list_incomplete_next_actions')
|
|
||||||
end
|
|
||||||
end
|
|
||||||
else
|
|
||||||
yield
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def init_todos
|
|
||||||
with_feed_query_scope do
|
|
||||||
with_parent_resource_scope do # @context or @project may get defined here
|
|
||||||
with_limit_scope do
|
|
||||||
|
|
||||||
if mobile?
|
|
||||||
init_todos_for_mobile_view
|
|
||||||
else
|
|
||||||
|
|
||||||
# Note: these next two finds were previously using
|
|
||||||
# current_users.todos.find but that broke with_scope for :limit
|
|
||||||
|
|
||||||
# Exclude hidden projects from count on home page
|
|
||||||
@todos = current_user.todos.includes(Todo::DEFAULT_INCLUDES)
|
|
||||||
|
|
||||||
# Exclude hidden projects from the home page
|
|
||||||
@not_done_todos = current_user.todos.
|
|
||||||
where('contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', false, 'active').
|
|
||||||
order("todos.due IS NULL, todos.due ASC, todos.created_at ASC").
|
|
||||||
includes(Todo::DEFAULT_INCLUDES)
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def init_todos_for_mobile_view
|
|
||||||
# Note: these next two finds were previously using current_users.todos.find
|
|
||||||
# but that broke with_scope for :limit
|
|
||||||
|
|
||||||
# Exclude hidden projects from the home page
|
|
||||||
@not_done_todos = current_user.todos.
|
|
||||||
where('todos.state = ? AND contexts.hide = ? AND (projects.state = ? OR todos.project_id IS NULL)', 'active', false, 'active').
|
|
||||||
order("todos.due IS NULL, todos.due ASC, todos.created_at ASC").
|
|
||||||
includes(:project, :context, :tags)
|
|
||||||
end
|
|
||||||
|
|
||||||
def tag_title(tag_expr)
|
def tag_title(tag_expr)
|
||||||
and_list = tag_expr.inject([]) { |s,tag_list| s << tag_list.join(',') }
|
and_list = tag_expr.inject([]) { |s,tag_list| s << tag_list.join(',') }
|
||||||
return and_list.join(' AND ')
|
return and_list.join(' AND ')
|
||||||
|
|
@ -1194,99 +1180,6 @@ class TodosController < ApplicationController
|
||||||
@remaining_deferred_or_pending_count = tag.nil? ? 0 : current_user.todos.deferred.with_tag(tag.id).count
|
@remaining_deferred_or_pending_count = tag.nil? ? 0 : current_user.todos.deferred.with_tag(tag.id).count
|
||||||
end
|
end
|
||||||
|
|
||||||
def render_todos_html
|
|
||||||
lambda do
|
|
||||||
@page_title = t('todos.task_list_title')
|
|
||||||
|
|
||||||
# If you've set no_completed to zero, the completed items box isn't shown
|
|
||||||
# on the home page
|
|
||||||
max_completed = current_user.prefs.show_number_completed
|
|
||||||
@done = current_user.todos.completed.limit(max_completed).includes(Todo::DEFAULT_INCLUDES) unless max_completed == 0
|
|
||||||
|
|
||||||
# Set count badge to number of not-done, not hidden context items
|
|
||||||
@count = current_user.todos.active.not_hidden.count(:all)
|
|
||||||
|
|
||||||
render
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_todos_mobile
|
|
||||||
lambda do
|
|
||||||
@page_title = t('todos.mobile_todos_page_title')
|
|
||||||
@home = true
|
|
||||||
|
|
||||||
max_completed = current_user.prefs.show_number_completed
|
|
||||||
@done = current_user.todos.completed.limit(max_completed).includes(Todo::DEFAULT_INCLUDES) unless max_completed == 0
|
|
||||||
|
|
||||||
cookies[:mobile_url]= { :value => request.request_uri, :secure => SITE_CONFIG['secure_cookies']}
|
|
||||||
determine_down_count
|
|
||||||
|
|
||||||
render :action => 'index'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_rss_feed
|
|
||||||
lambda do
|
|
||||||
render_rss_feed_for @todos, :feed => todo_feed_options,
|
|
||||||
:item => {
|
|
||||||
:title => :description,
|
|
||||||
:link => lambda { |t| @project_feed.nil? ? context_url(t.context) : project_url(t.project) },
|
|
||||||
:guid => lambda { |t| todo_url(t) },
|
|
||||||
:description => todo_feed_content
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def todo_feed_options
|
|
||||||
options = Todo.feed_options(current_user)
|
|
||||||
options[:title] = @feed_title
|
|
||||||
return options
|
|
||||||
end
|
|
||||||
|
|
||||||
def todo_feed_content
|
|
||||||
# TODO: move view stuff into view, also the includes at the top
|
|
||||||
lambda do |i|
|
|
||||||
item_notes = i.rendered_notes if i.notes?
|
|
||||||
due = "<div>#{t('todos.feeds.due', :date => format_date(i.due))}</div>\n" if i.due?
|
|
||||||
done = "<div>#{t('todos.feeds.completed', :date => format_date(i.completed_at))}</div>\n" if i.completed?
|
|
||||||
context_link = "<a href=\"#{ context_url(i.context) }\">#{ i.context.name }</a>"
|
|
||||||
if i.project_id?
|
|
||||||
project_link = "<a href=\"#{ project_url(i.project) }\">#{ i.project.name }</a>"
|
|
||||||
else
|
|
||||||
project_link = "<em>#{t('common.none')}</em>"
|
|
||||||
end
|
|
||||||
"#{done||''}#{due||''}#{item_notes||''}\n<div>#{t('common.project')}: #{project_link}</div>\n<div>#{t('common.context')}: #{context_link}</div>"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_atom_feed
|
|
||||||
lambda do
|
|
||||||
render_atom_feed_for @todos, :feed => todo_feed_options,
|
|
||||||
:item => {
|
|
||||||
:title => :description,
|
|
||||||
:link => lambda { |t| context_url(t.context) },
|
|
||||||
:description => todo_feed_content,
|
|
||||||
:author => lambda { |p| nil }
|
|
||||||
}
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_text_feed
|
|
||||||
lambda do
|
|
||||||
render :action => 'index', :layout => false, :content_type => Mime::TEXT
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def render_ical_feed
|
|
||||||
lambda do
|
|
||||||
render :action => 'index', :layout => false, :content_type => Mime::ICS
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def self.is_feed_request(req)
|
|
||||||
['rss','atom','txt','ics'].include?(req.parameters[:format])
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_for_next_todo(todo)
|
def check_for_next_todo(todo)
|
||||||
# check if this todo has a related recurring_todo. If so, create next todo
|
# check if this todo has a related recurring_todo. If so, create next todo
|
||||||
new_recurring_todo = nil
|
new_recurring_todo = nil
|
||||||
|
|
@ -1434,7 +1327,7 @@ class TodosController < ApplicationController
|
||||||
begin
|
begin
|
||||||
params["todo"]["due"] = parse_date_per_user_prefs(params["todo"]["due"])
|
params["todo"]["due"] = parse_date_per_user_prefs(params["todo"]["due"])
|
||||||
rescue
|
rescue
|
||||||
@todo.errors.add_to_base("Invalid due date")
|
@todo.errors[:base] << "Invalid due date"
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
params["todo"]["due"] = ""
|
params["todo"]["due"] = ""
|
||||||
|
|
@ -1443,7 +1336,7 @@ class TodosController < ApplicationController
|
||||||
begin
|
begin
|
||||||
params['todo']['show_from'] = parse_date_per_user_prefs(params['todo']['show_from'])
|
params['todo']['show_from'] = parse_date_per_user_prefs(params['todo']['show_from'])
|
||||||
rescue
|
rescue
|
||||||
@todo.errors.add_to_base("Invalid show from date")
|
@todo.errors[:base] << "Invalid show from date"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -1530,23 +1423,84 @@ class TodosController < ApplicationController
|
||||||
|
|
||||||
return !( all_list_uniq_ids.length == all_list_count )
|
return !( all_list_uniq_ids.length == all_list_count )
|
||||||
end
|
end
|
||||||
|
|
||||||
class FindConditionBuilder
|
# def render_text_feed
|
||||||
|
# lambda do
|
||||||
def initialize
|
# render :action => 'index', :layout => false, :content_type => Mime::TEXT
|
||||||
@queries = Array.new
|
# end
|
||||||
@params = Array.new
|
# end
|
||||||
end
|
#
|
||||||
|
# def render_ical_feed
|
||||||
def add(query, param)
|
# lambda do
|
||||||
@queries << query
|
# render :action => 'index', :layout => false, :content_type => Mime::ICS
|
||||||
@params << param
|
# end
|
||||||
end
|
# end
|
||||||
|
#
|
||||||
def to_conditions
|
# def self.is_feed_request(req)
|
||||||
[@queries.join(' AND ')] + @params
|
# ['rss','atom','txt','ics'].include?(req.parameters[:format])
|
||||||
end
|
# end
|
||||||
end
|
#
|
||||||
|
# class FindConditionBuilder
|
||||||
|
#
|
||||||
|
# def initialize
|
||||||
|
# @queries = Array.new
|
||||||
|
# @params = Array.new
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# def add(query, param)
|
||||||
|
# @queries << query
|
||||||
|
# @params << param
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# def to_conditions
|
||||||
|
# [@queries.join(' AND ')] + @params
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
# def render_rss_feed
|
||||||
|
# lambda do
|
||||||
|
# render_rss_feed_for @todos, :feed => todo_feed_options,
|
||||||
|
# :item => {
|
||||||
|
# :title => :description,
|
||||||
|
# :link => lambda { |t| @project_feed.nil? ? context_url(t.context) : project_url(t.project) },
|
||||||
|
# :guid => lambda { |t| todo_url(t) },
|
||||||
|
# :description => todo_feed_content
|
||||||
|
# }
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# def todo_feed_options
|
||||||
|
# options = Todo.feed_options(current_user)
|
||||||
|
# options[:title] = @feed_title
|
||||||
|
# return options
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# def todo_feed_content
|
||||||
|
# # TODO: move view stuff into view, also the includes at the top
|
||||||
|
# lambda do |i|
|
||||||
|
# item_notes = i.rendered_notes if i.notes?
|
||||||
|
# due = "<div>#{t('todos.feeds.due', :date => format_date(i.due))}</div>\n" if i.due?
|
||||||
|
# done = "<div>#{t('todos.feeds.completed', :date => format_date(i.completed_at))}</div>\n" if i.completed?
|
||||||
|
# context_link = "<a href=\"#{ context_url(i.context) }\">#{ i.context.name }</a>"
|
||||||
|
# if i.project_id?
|
||||||
|
# project_link = "<a href=\"#{ project_url(i.project) }\">#{ i.project.name }</a>"
|
||||||
|
# else
|
||||||
|
# project_link = "<em>#{t('common.none')}</em>"
|
||||||
|
# end
|
||||||
|
# "#{done||''}#{due||''}#{item_notes||''}\n<div>#{t('common.project')}: #{project_link}</div>\n<div>#{t('common.context')}: #{context_link}</div>"
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
#
|
||||||
|
# def render_atom_feed
|
||||||
|
# lambda do
|
||||||
|
# render_atom_feed_for @todos, :feed => todo_feed_options,
|
||||||
|
# :item => {
|
||||||
|
# :title => :description,
|
||||||
|
# :link => lambda { |t| context_url(t.context) },
|
||||||
|
# :description => todo_feed_content,
|
||||||
|
# :author => lambda { |p| nil }
|
||||||
|
# }
|
||||||
|
# end
|
||||||
|
# end
|
||||||
|
|
||||||
class TodoCreateParamsHelper
|
class TodoCreateParamsHelper
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,7 @@ class UsersController < ApplicationController
|
||||||
|
|
||||||
# GET /users/id GET /users/id.xml
|
# GET /users/id GET /users/id.xml
|
||||||
def show
|
def show
|
||||||
@user = User.find_by_id(params[:id])
|
@user = User.find(params[:id])
|
||||||
render :xml => @user.to_xml(:except => [ :password ])
|
render :xml => @user.to_xml(:except => [ :password ])
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -83,7 +83,7 @@ class UsersController < ApplicationController
|
||||||
user.auth_type == 'ldap' &&
|
user.auth_type == 'ldap' &&
|
||||||
!SimpleLdapAuthenticator.valid?(user.login, params['user']['password'])
|
!SimpleLdapAuthenticator.valid?(user.login, params['user']['password'])
|
||||||
notify :warning, "Incorrect password"
|
notify :warning, "Incorrect password"
|
||||||
redirect_to :action => 'new'
|
redirect_to signup_path
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -137,7 +137,7 @@ class UsersController < ApplicationController
|
||||||
|
|
||||||
# DELETE /users/id DELETE /users/id.xml
|
# DELETE /users/id DELETE /users/id.xml
|
||||||
def destroy
|
def destroy
|
||||||
@deleted_user = User.find_by_id(params[:id])
|
@deleted_user = User.find(params[:id])
|
||||||
@saved = @deleted_user.destroy
|
@saved = @deleted_user.destroy
|
||||||
@total_users = User.all.size
|
@total_users = User.all.size
|
||||||
|
|
||||||
|
|
@ -155,19 +155,18 @@ class UsersController < ApplicationController
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
def change_password
|
def change_password
|
||||||
@page_title = t('users.change_password_title')
|
@page_title = t('users.change_password_title')
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_password
|
def update_password
|
||||||
# is used for focing password change after sha->bcrypt upgrade
|
# is used for focing password change after sha->bcrypt upgrade
|
||||||
@user.change_password(params[:user][:password], params[:user][:password_confirmation])
|
current_user.change_password(params[:user][:password], params[:user][:password_confirmation])
|
||||||
notify :notice, t('users.password_updated')
|
notify :notice, t('users.password_updated')
|
||||||
redirect_to preferences_path
|
redirect_to preferences_path
|
||||||
rescue Exception => error
|
rescue Exception => error
|
||||||
notify :error, error.message
|
notify :error, error.message
|
||||||
redirect_to :action => 'change_password'
|
redirect_to change_password_user_path(current_user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def change_auth_type
|
def change_auth_type
|
||||||
|
|
@ -175,40 +174,19 @@ class UsersController < ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_auth_type
|
def update_auth_type
|
||||||
if (params[:open_id_complete] || (params[:user][:auth_type] == 'open_id')) && openid_enabled?
|
current_user.auth_type = params[:user][:auth_type]
|
||||||
authenticate_with_open_id do |result, identity_url|
|
if current_user.save
|
||||||
if result.successful?
|
|
||||||
# Success means that the transaction completed without error. If info
|
|
||||||
# is nil, it means that the user cancelled the verification.
|
|
||||||
@user.auth_type = 'open_id'
|
|
||||||
@user.open_id_url = identity_url
|
|
||||||
if @user.save
|
|
||||||
notify :notice, t('users.openid_url_verified', :url => identity_url)
|
|
||||||
else
|
|
||||||
debugger
|
|
||||||
notify :warning, t('users.openid_ok_pref_failed', :url => identity_url)
|
|
||||||
end
|
|
||||||
redirect_to preferences_path
|
|
||||||
else
|
|
||||||
notify :warning, result.message
|
|
||||||
redirect_to :action => 'change_auth_type'
|
|
||||||
end
|
|
||||||
end
|
|
||||||
return
|
|
||||||
end
|
|
||||||
@user.auth_type = params[:user][:auth_type]
|
|
||||||
if @user.save
|
|
||||||
notify :notice, t('users.auth_type_updated')
|
notify :notice, t('users.auth_type_updated')
|
||||||
redirect_to preferences_path
|
redirect_to preferences_path
|
||||||
else
|
else
|
||||||
notify :warning, t('users.auth_type_update_error', :error_messages => @user.errors.full_messages.join(', '))
|
notify :warning, t('users.auth_type_update_error', :error_messages => current_user.errors.full_messages.join(', '))
|
||||||
redirect_to :action => 'change_auth_type'
|
redirect_to change_auth_type_user_path(current_user)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def refresh_token
|
def refresh_token
|
||||||
@user.generate_token
|
current_user.generate_token
|
||||||
@user.save!
|
current_user.save!
|
||||||
notify :notice, t('users.new_token_generated')
|
notify :notice, t('users.new_token_generated')
|
||||||
redirect_to preferences_path
|
redirect_to preferences_path
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,25 @@
|
||||||
class MessageGateway < ActionMailer::Base
|
class MessageGateway < ActionMailer::Base
|
||||||
# include ActionView::Helpers::SanitizeHelper
|
include ActionView::Helpers::SanitizeHelper
|
||||||
# extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
||||||
|
|
||||||
def receive(email)
|
def receive(email)
|
||||||
puts "email = #{email}"
|
user = get_user_from_email_address(email)
|
||||||
address = ''
|
|
||||||
if SITE_CONFIG['email_dispatch'] == 'to'
|
|
||||||
address = email.to[0]
|
|
||||||
else
|
|
||||||
address = email.from[0]
|
|
||||||
end
|
|
||||||
|
|
||||||
user = User.where("preferences.sms_email" => address.strip).first(:include => [:preference])
|
|
||||||
if user.nil?
|
|
||||||
user = User.where("preferences.sms_email" => address.strip[1.100]).first(:include => [:preference])
|
|
||||||
end
|
|
||||||
return if user.nil?
|
return if user.nil?
|
||||||
|
|
||||||
context = user.prefs.sms_context
|
context = user.prefs.sms_context
|
||||||
|
|
||||||
description = nil
|
description = nil
|
||||||
notes = nil
|
notes = nil
|
||||||
|
|
||||||
if email.content_type == "multipart/related"
|
if email.multipart?
|
||||||
description = sanitize email.subject
|
description = get_text_or_nil(email.subject)
|
||||||
body_part = email.parts.find{|m| m.content_type == "text/plain"}
|
notes = get_first_text_plain_part(email)
|
||||||
notes = sanitize body_part.body.strip
|
|
||||||
else
|
else
|
||||||
if email.subject && email.subject.blank?
|
if email.subject.blank?
|
||||||
description = sanitize email.body.strip
|
description = get_decoded_text_or_nil(email.body)
|
||||||
notes = nil
|
notes = nil
|
||||||
else
|
else
|
||||||
description = sanitize email.subject.strip
|
description = get_text_or_nil(email.subject)
|
||||||
notes = sanitize email.body.strip
|
notes = get_decoded_text_or_nil(email.body)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -41,4 +29,33 @@ class MessageGateway < ActionMailer::Base
|
||||||
todo = Todo.from_rich_message(user, context.id, description, notes)
|
todo = Todo.from_rich_message(user, context.id, description, notes)
|
||||||
todo.save!
|
todo.save!
|
||||||
end
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def get_address(email)
|
||||||
|
return SITE_CONFIG['email_dispatch'] == 'to' ? email.to[0] : email.from[0]
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_user_from_email_address(email)
|
||||||
|
address = get_address(email)
|
||||||
|
user = User.where("preferences.sms_email" => address.strip).includes(:preference).first
|
||||||
|
if user.nil?
|
||||||
|
user = User.where("preferences.sms_email" => address.strip[1.100]).includes(:preference).first
|
||||||
|
end
|
||||||
|
return user
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_text_or_nil(text)
|
||||||
|
return text ? sanitize(text.strip) : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_decoded_text_or_nil(text)
|
||||||
|
return text ? sanitize(text.decoded.strip) : nil
|
||||||
|
end
|
||||||
|
|
||||||
|
def get_first_text_plain_part(email)
|
||||||
|
parts = email.parts.reject{|part| !part.content_type.start_with?("text/plain") }
|
||||||
|
return parts ? sanitize(parts[0].decoded.strip) : ""
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@ class Preference < ActiveRecord::Base
|
||||||
belongs_to :sms_context, :class_name => 'Context'
|
belongs_to :sms_context, :class_name => 'Context'
|
||||||
|
|
||||||
attr_accessible :date_format, :week_starts, :show_number_completed, :show_completed_projects_in_sidebar,
|
attr_accessible :date_format, :week_starts, :show_number_completed, :show_completed_projects_in_sidebar,
|
||||||
:show_hidden_contexts_in_sidebar, :staleness_starts, :due_style, :admin_email
|
:show_hidden_contexts_in_sidebar, :staleness_starts, :due_style, :admin_email, :locale
|
||||||
|
|
||||||
def self.due_styles
|
def self.due_styles
|
||||||
{ :due_in_n_days => 0, :due_on => 1}
|
{ :due_in_n_days => 0, :due_on => 1}
|
||||||
|
|
|
||||||
|
|
@ -51,30 +51,30 @@ class RecurringTodo < ActiveRecord::Base
|
||||||
|
|
||||||
def validate_daily
|
def validate_daily
|
||||||
if (!only_work_days) && (daily_every_x_days.nil? || daily_every_x_days.blank?)
|
if (!only_work_days) && (daily_every_x_days.nil? || daily_every_x_days.blank?)
|
||||||
errors.add_to_base("Every other nth day may not be empty for recurrence setting")
|
errors[:base] << "Every other nth day may not be empty for recurrence setting"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_weekly
|
def validate_weekly
|
||||||
if weekly_every_x_week.nil? || weekly_every_x_week.blank?
|
if weekly_every_x_week.nil? || weekly_every_x_week.blank?
|
||||||
errors.add_to_base("Every other nth week may not be empty for recurrence setting")
|
errors[:base] << "Every other nth week may not be empty for recurrence setting"
|
||||||
end
|
end
|
||||||
something_set = false
|
something_set = false
|
||||||
%w{sunday monday tuesday wednesday thursday friday saturday}.each do |day|
|
%w{sunday monday tuesday wednesday thursday friday saturday}.each do |day|
|
||||||
something_set ||= self.send("on_#{day}")
|
something_set ||= self.send("on_#{day}")
|
||||||
end
|
end
|
||||||
errors.add_to_base("You must specify at least one day on which the todo recurs") if !something_set
|
errors[:base] << "You must specify at least one day on which the todo recurs" if !something_set
|
||||||
end
|
end
|
||||||
|
|
||||||
def validate_monthly
|
def validate_monthly
|
||||||
case recurrence_selector
|
case recurrence_selector
|
||||||
when 0 # 'monthly_every_x_day'
|
when 0 # 'monthly_every_x_day'
|
||||||
errors.add_to_base("The day of the month may not be empty for recurrence setting") if monthly_every_x_day.nil? || monthly_every_x_day.blank?
|
errors[:base] << "The day of the month may not be empty for recurrence setting" if monthly_every_x_day.nil? || monthly_every_x_day.blank?
|
||||||
errors.add_to_base("Every other nth month may not be empty for recurrence setting") if monthly_every_x_month.nil? || monthly_every_x_month.blank?
|
errors[:base] << "Every other nth month may not be empty for recurrence setting" if monthly_every_x_month.nil? || monthly_every_x_month.blank?
|
||||||
when 1 # 'monthly_every_xth_day'
|
when 1 # 'monthly_every_xth_day'
|
||||||
errors.add_to_base("Every other nth month may not be empty for recurrence setting") if monthly_every_x_month2.nil? || monthly_every_x_month2.blank?
|
errors[:base] <<"Every other nth month may not be empty for recurrence setting" if monthly_every_x_month2.nil? || monthly_every_x_month2.blank?
|
||||||
errors.add_to_base("The nth day of the month may not be empty for recurrence setting") if monthly_every_xth_day.nil? || monthly_every_xth_day.blank?
|
errors[:base] <<"The nth day of the month may not be empty for recurrence setting" if monthly_every_xth_day.nil? || monthly_every_xth_day.blank?
|
||||||
errors.add_to_base("The day of the month may not be empty for recurrence setting") if monthly_day_of_week.nil? || monthly_day_of_week.blank?
|
errors[:base] <<"The day of the month may not be empty for recurrence setting" if monthly_day_of_week.nil? || monthly_day_of_week.blank?
|
||||||
else
|
else
|
||||||
raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'"
|
raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'"
|
||||||
end
|
end
|
||||||
|
|
@ -83,26 +83,26 @@ class RecurringTodo < ActiveRecord::Base
|
||||||
def validate_yearly
|
def validate_yearly
|
||||||
case recurrence_selector
|
case recurrence_selector
|
||||||
when 0 # 'yearly_every_x_day'
|
when 0 # 'yearly_every_x_day'
|
||||||
errors.add_to_base("The month of the year may not be empty for recurrence setting") if yearly_month_of_year.nil? || yearly_month_of_year.blank?
|
errors[:base] << "The month of the year may not be empty for recurrence setting" if yearly_month_of_year.nil? || yearly_month_of_year.blank?
|
||||||
errors.add_to_base("The day of the month may not be empty for recurrence setting") if yearly_every_x_day.nil? || yearly_every_x_day.blank?
|
errors[:base] << "The day of the month may not be empty for recurrence setting" if yearly_every_x_day.nil? || yearly_every_x_day.blank?
|
||||||
when 1 # 'yearly_every_xth_day'
|
when 1 # 'yearly_every_xth_day'
|
||||||
errors.add_to_base("The month of the year may not be empty for recurrence setting") if yearly_month_of_year2.nil? || yearly_month_of_year2.blank?
|
errors[:base] << "The month of the year may not be empty for recurrence setting" if yearly_month_of_year2.nil? || yearly_month_of_year2.blank?
|
||||||
errors.add_to_base("The nth day of the month may not be empty for recurrence setting") if yearly_every_xth_day.nil? || yearly_every_xth_day.blank?
|
errors[:base] << "The nth day of the month may not be empty for recurrence setting" if yearly_every_xth_day.nil? || yearly_every_xth_day.blank?
|
||||||
errors.add_to_base("The day of the week may not be empty for recurrence setting") if yearly_day_of_week.nil? || yearly_day_of_week.blank?
|
errors[:base] << "The day of the week may not be empty for recurrence setting" if yearly_day_of_week.nil? || yearly_day_of_week.blank?
|
||||||
else
|
else
|
||||||
raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'"
|
raise Exception.new, "unexpected value of recurrence selector '#{self.recurrence_selector}'"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def starts_and_ends_on_validations
|
def starts_and_ends_on_validations
|
||||||
errors.add_to_base("The start date needs to be filled in") if start_from.nil? || start_from.blank?
|
errors[:base] << "The start date needs to be filled in" if start_from.nil? || start_from.blank?
|
||||||
case self.ends_on
|
case self.ends_on
|
||||||
when 'ends_on_number_of_times'
|
when 'ends_on_number_of_times'
|
||||||
errors.add_to_base("The number of recurrences needs to be filled in for 'Ends on'") if number_of_occurences.nil? || number_of_occurences.blank?
|
errors[:base] << "The number of recurrences needs to be filled in for 'Ends on'" if number_of_occurences.nil? || number_of_occurences.blank?
|
||||||
when "ends_on_end_date"
|
when "ends_on_end_date"
|
||||||
errors.add_to_base("The end date needs to be filled in for 'Ends on'") if end_date.nil? || end_date.blank?
|
errors[:base] << "The end date needs to be filled in for 'Ends on'" if end_date.nil? || end_date.blank?
|
||||||
else
|
else
|
||||||
errors.add_to_base("The end of the recurrence is not selected") unless ends_on == "no_end_date"
|
errors[:base] << "The end of the recurrence is not selected" unless ends_on == "no_end_date"
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
@ -112,9 +112,9 @@ class RecurringTodo < ActiveRecord::Base
|
||||||
when 'show_from_date'
|
when 'show_from_date'
|
||||||
# no validations
|
# no validations
|
||||||
when 'due_date'
|
when 'due_date'
|
||||||
errors.add_to_base("Please select when to show the action") if show_always.nil?
|
errors[:base] << "Please select when to show the action" if show_always.nil?
|
||||||
unless show_always
|
unless show_always
|
||||||
errors.add_to_base("Please fill in the number of days to show the todo before the due date") if show_from_delta.nil? || show_from_delta.blank?
|
errors[:base] << "Please fill in the number of days to show the todo before the due date" if show_from_delta.nil? || show_from_delta.blank?
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
raise Exception.new, "unexpected value of recurrence target selector '#{self.recurrence_target}'"
|
raise Exception.new, "unexpected value of recurrence target selector '#{self.recurrence_target}'"
|
||||||
|
|
|
||||||
|
|
@ -372,9 +372,9 @@ class Todo < ActiveRecord::Base
|
||||||
|
|
||||||
context_id = default_context_id
|
context_id = default_context_id
|
||||||
unless(context.nil?)
|
unless(context.nil?)
|
||||||
found_context = user.contexts.active.find_by_namepart(context)
|
found_context = user.contexts.active.where("name like ?", "%#{context}%").first
|
||||||
found_context = user.contexts.find_by_namepart(context) if found_context.nil?
|
found_context = user.contexts.where("name like ?", "%#{context}%").first if !found_context
|
||||||
context_id = found_context.id unless found_context.nil?
|
context_id = found_context.id if found_context
|
||||||
end
|
end
|
||||||
|
|
||||||
unless user.contexts.exists? context_id
|
unless user.contexts.exists? context_id
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,11 @@ class User < ActiveRecord::Base
|
||||||
# Virtual attribute for the unencrypted password
|
# Virtual attribute for the unencrypted password
|
||||||
attr_accessor :password
|
attr_accessor :password
|
||||||
attr_protected :is_admin # don't allow mass-assignment for this
|
attr_protected :is_admin # don't allow mass-assignment for this
|
||||||
|
|
||||||
|
attr_accessible :login, :first_name, :last_name, :password_confirmation, :password, :auth_type, :open_id_url
|
||||||
|
#for will_paginate plugin
|
||||||
|
cattr_accessor :per_page
|
||||||
|
@@per_page = 5
|
||||||
|
|
||||||
has_many :contexts,
|
has_many :contexts,
|
||||||
:order => 'position ASC',
|
:order => 'position ASC',
|
||||||
|
|
@ -91,8 +96,6 @@ class User < ActiveRecord::Base
|
||||||
has_many :notes, :order => "created_at DESC", :dependent => :delete_all
|
has_many :notes, :order => "created_at DESC", :dependent => :delete_all
|
||||||
has_one :preference, :dependent => :destroy
|
has_one :preference, :dependent => :destroy
|
||||||
|
|
||||||
attr_protected :is_admin
|
|
||||||
|
|
||||||
validates_presence_of :login
|
validates_presence_of :login
|
||||||
validates_presence_of :password, :if => :password_required?
|
validates_presence_of :password, :if => :password_required?
|
||||||
validates_length_of :password, :within => 5..40, :if => :password_required?
|
validates_length_of :password, :within => 5..40, :if => :password_required?
|
||||||
|
|
@ -105,10 +108,6 @@ class User < ActiveRecord::Base
|
||||||
before_create :crypt_password, :generate_token
|
before_create :crypt_password, :generate_token
|
||||||
before_update :crypt_password
|
before_update :crypt_password
|
||||||
|
|
||||||
#for will_paginate plugin
|
|
||||||
cattr_accessor :per_page
|
|
||||||
@@per_page = 5
|
|
||||||
|
|
||||||
def validate_auth_type
|
def validate_auth_type
|
||||||
unless Tracks::Config.auth_schemes.include?(auth_type)
|
unless Tracks::Config.auth_schemes.include?(auth_type)
|
||||||
errors.add("auth_type", "not a valid authentication type (#{auth_type})")
|
errors.add("auth_type", "not a valid authentication type (#{auth_type})")
|
||||||
|
|
|
||||||
|
|
@ -19,5 +19,5 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="input_box">
|
<div id="input_box">
|
||||||
<%= render :file => "sidebar/sidebar.html.erb" %>
|
<%= render :file => "sidebar/sidebar" %>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<%- reset_tab_index %>
|
<%- reset_tab_index %>
|
||||||
<div class="recurring_container">
|
<div class="recurring_container">
|
||||||
<%= form_for(@new_recurring_todo, :html=> { :id=>'recurring-todo-form-new-action', :name=>'recurring_todo', :class => 'inline-form' }) do -%>
|
<%= form_for(@new_recurring_todo, :html=> { :id=>'recurring-todo-form-new-action', :name=>'recurring_todo', :class => 'inline-form' }) do -%>
|
||||||
<div id="error_status"><%= error_messages_for("item", :object_name => 'action') %></div>
|
<div id="error_status"><%= get_list_of_error_messages_for(@new_recurring_todo) %></div>
|
||||||
|
|
||||||
<div id="recurring_todo_form_container">
|
<div id="recurring_todo_form_container">
|
||||||
<div id="recurring_todo">
|
<div id="recurring_todo">
|
||||||
|
|
@ -13,5 +13,5 @@
|
||||||
</div><!-- End of display_box -->
|
</div><!-- End of display_box -->
|
||||||
<div id="input_box">
|
<div id="input_box">
|
||||||
<%= render :partial => "shared/add_new_item_form" %>
|
<%= render :partial => "shared/add_new_item_form" %>
|
||||||
<%= render :file => "sidebar/sidebar.html.erb" %>
|
<%= render :file => "sidebar/sidebar" %>
|
||||||
</div><!-- End of input box -->
|
</div><!-- End of input box -->
|
||||||
|
|
@ -184,14 +184,26 @@ function remove_source_container(next_steps) {
|
||||||
<% end %>
|
<% end %>
|
||||||
}
|
}
|
||||||
|
|
||||||
function html_for_todo() {
|
function html_for_recurring_todo() {
|
||||||
return "<%= @saved && !source_view_is(:done) ? escape_javascript(render(:partial => @todo, :locals => {
|
<%-
|
||||||
:parent_container_type => parent_container_type,
|
js = @saved && @new_recurring_todo ? escape_javascript(render(:partial => @new_recurring_todo, :locals => { :parent_container_type => parent_container_type })) : ""
|
||||||
:suppress_project => source_view_is(:project),
|
-%>
|
||||||
:suppress_context => source_view_is(:context)
|
return "<%= js %>";
|
||||||
})) : "" %>";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function html_for_recurring_todo() {
|
function html_for_todo() {
|
||||||
return "<%= @saved ? escape_javascript(render(:partial => @new_recurring_todo, :locals => { :parent_container_type => parent_container_type })) : "" %>";
|
<%-
|
||||||
|
js = ""
|
||||||
|
if @saved && !source_view_is(:done)
|
||||||
|
js = escape_javascript(render(
|
||||||
|
:partial => @todo,
|
||||||
|
:locals => {
|
||||||
|
:parent_container_type => parent_container_type,
|
||||||
|
:suppress_project => source_view_is(:project),
|
||||||
|
:suppress_context => source_view_is(:context)
|
||||||
|
}
|
||||||
|
))
|
||||||
|
end
|
||||||
|
-%>
|
||||||
|
return "<%= js %>";
|
||||||
}
|
}
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
<h2><%= @page_title %></h2>
|
<h2><%= @page_title %></h2>
|
||||||
|
|
||||||
<%= error_messages_for 'user' %>
|
<%= get_list_of_error_messages_for @user %>
|
||||||
|
|
||||||
<p><%= t('users.change_password_prompt') %></p>
|
<p><%= t('users.change_password_prompt') %></p>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -51,7 +51,7 @@ Tracksapp::Application.routes.draw do
|
||||||
# root :to => 'welcome#index'
|
# root :to => 'welcome#index'
|
||||||
|
|
||||||
# See how all your routes lay out with "rake routes"
|
# See how all your routes lay out with "rake routes"
|
||||||
|
|
||||||
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
# This is a legacy wild controller route that's not recommended for RESTful applications.
|
||||||
# Note: This route will make all actions in every controller accessible via GET requests.
|
# Note: This route will make all actions in every controller accessible via GET requests.
|
||||||
# match ':controller(/:action(/:id))(.:format)'
|
# match ':controller(/:action(/:id))(.:format)'
|
||||||
|
|
@ -64,6 +64,7 @@ Tracksapp::Application.routes.draw do
|
||||||
match 'login_cas' => 'users#login_cas'
|
match 'login_cas' => 'users#login_cas'
|
||||||
match 'logout' => 'users#logout'
|
match 'logout' => 'users#logout'
|
||||||
match 'calendar' => "todos#calendar"
|
match 'calendar' => "todos#calendar"
|
||||||
|
match 'stats' => 'stats#index'
|
||||||
match 'done' => "stats#done", :as => 'done_overview'
|
match 'done' => "stats#done", :as => 'done_overview'
|
||||||
match 'integrations' => "integrations#index"
|
match 'integrations' => "integrations#index"
|
||||||
match 'integrations/rest_api' => "integrations#rest_api", :as => 'rest_api_docs'
|
match 'integrations/rest_api' => "integrations#rest_api", :as => 'rest_api_docs'
|
||||||
|
|
@ -113,6 +114,16 @@ Tracksapp::Application.routes.draw do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
match 'todos/tag/:name' => 'todos#tag', :as => :tag
|
match 'todos/tag/:name' => 'todos#tag', :as => :tag
|
||||||
|
|
||||||
|
resources :recurring_todos do
|
||||||
|
member do
|
||||||
|
put 'toggle_check'
|
||||||
|
put 'toggle_star'
|
||||||
|
end
|
||||||
|
collection do
|
||||||
|
get 'done'
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
resources :users do
|
resources :users do
|
||||||
member do
|
member do
|
||||||
|
|
|
||||||
2
test/fixtures/sample_mms.txt
vendored
2
test/fixtures/sample_mms.txt
vendored
|
|
@ -1,6 +1,6 @@
|
||||||
Return-Path: <15555555555/TYPE=PLMN@tmomail.net>
|
Return-Path: <15555555555/TYPE=PLMN@tmomail.net>
|
||||||
Date: Fri, 6 Jun 2008 21:38:26 -0400
|
Date: Fri, 6 Jun 2008 21:38:26 -0400
|
||||||
From: 15555555555@tmomail.net
|
From: 5555555555@tmomail.net
|
||||||
To: gtd@tracks.com
|
To: gtd@tracks.com
|
||||||
Message-ID: <3645873.13759311212802713215.JavaMail.mms@rlyatl28>
|
Message-ID: <3645873.13759311212802713215.JavaMail.mms@rlyatl28>
|
||||||
Subject: This is the subject
|
Subject: This is the subject
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,17 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
require 'feedlist_controller'
|
|
||||||
|
|
||||||
# Re-raise errors caught by the controller.
|
|
||||||
class FeedlistController; def rescue_action(e) raise e end; end
|
|
||||||
|
|
||||||
class FeedlistControllerTest < ActionController::TestCase
|
class FeedlistControllerTest < ActionController::TestCase
|
||||||
fixtures :users, :preferences, :projects, :contexts, :todos, :recurring_todos, :notes
|
|
||||||
|
|
||||||
def setup
|
|
||||||
assert_equal "test", ENV['RAILS_ENV']
|
|
||||||
assert_equal "change-me", Tracks::Config.salt
|
|
||||||
@controller = FeedlistController.new
|
|
||||||
@request = ActionController::TestRequest.new
|
|
||||||
@response = ActionController::TestResponse.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_get_index_when_not_logged_in
|
def test_get_index_when_not_logged_in
|
||||||
get :index
|
get :index
|
||||||
assert_redirected_to :controller => 'login', :action => 'login'
|
assert_redirected_to login_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_get_index_by_logged_in_user
|
def test_get_index_by_logged_in_user
|
||||||
login_as :other_user
|
login_as :other_user
|
||||||
get :index
|
get :index
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_equal "TRACKS::Feeds", assigns['page_title']
|
assert_equal "TRACKS::Feeds", assigns['page_title']
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
|
|
||||||
class MessageGatewayTest < ActiveSupport::TestCase
|
class MessageGatewayTest < ActiveSupport::TestCase
|
||||||
fixtures :users, :contexts, :todos
|
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
@user = users(:sms_user)
|
@user = users(:sms_user)
|
||||||
|
|
@ -14,18 +13,18 @@ class MessageGatewayTest < ActiveSupport::TestCase
|
||||||
|
|
||||||
def test_sms_with_no_subject
|
def test_sms_with_no_subject
|
||||||
todo_count = Todo.count
|
todo_count = Todo.count
|
||||||
|
|
||||||
load_message('sample_sms.txt')
|
load_message('sample_sms.txt')
|
||||||
# assert some stuff about it being created
|
# assert some stuff about it being created
|
||||||
assert_equal(todo_count+1, Todo.count)
|
assert_equal(todo_count+1, Todo.count)
|
||||||
|
|
||||||
message_todo = Todo.find(:first, :conditions => {:description => "message_content"})
|
message_todo = Todo.find(:first, :conditions => {:description => "message_content"})
|
||||||
assert_not_nil(message_todo)
|
assert_not_nil(message_todo)
|
||||||
|
|
||||||
assert_equal(@inbox, message_todo.context)
|
assert_equal(@inbox, message_todo.context)
|
||||||
assert_equal(@user, message_todo.user)
|
assert_equal(@user, message_todo.user)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_double_sms
|
def test_double_sms
|
||||||
todo_count = Todo.count
|
todo_count = Todo.count
|
||||||
load_message('sample_sms.txt')
|
load_message('sample_sms.txt')
|
||||||
|
|
@ -56,18 +55,18 @@ class MessageGatewayTest < ActiveSupport::TestCase
|
||||||
MessageGateway.receive(badmessage)
|
MessageGateway.receive(badmessage)
|
||||||
assert_equal(todo_count, Todo.count)
|
assert_equal(todo_count, Todo.count)
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_direct_to_context
|
def test_direct_to_context
|
||||||
message = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_sms.txt'))
|
message = File.read(File.join(Rails.root, 'test', 'fixtures', 'sample_sms.txt'))
|
||||||
|
|
||||||
valid_context_msg = message.gsub('message_content', 'this is a task @ anothercontext')
|
valid_context_msg = message.gsub('message_content', 'this is a task @ anothercontext')
|
||||||
invalid_context_msg = message.gsub('message_content', 'this is also a task @ notacontext')
|
invalid_context_msg = message.gsub('message_content', 'this is also a task @ notacontext')
|
||||||
|
|
||||||
MessageGateway.receive(valid_context_msg)
|
MessageGateway.receive(valid_context_msg)
|
||||||
valid_context_todo = Todo.find(:first, :conditions => {:description => "this is a task"})
|
valid_context_todo = Todo.find(:first, :conditions => {:description => "this is a task"})
|
||||||
assert_not_nil(valid_context_todo)
|
assert_not_nil(valid_context_todo)
|
||||||
assert_equal(contexts(:anothercontext), valid_context_todo.context)
|
assert_equal(contexts(:anothercontext), valid_context_todo.context)
|
||||||
|
|
||||||
MessageGateway.receive(invalid_context_msg)
|
MessageGateway.receive(invalid_context_msg)
|
||||||
invalid_context_todo = Todo.find(:first, :conditions => {:description => 'this is also a task'})
|
invalid_context_todo = Todo.find(:first, :conditions => {:description => 'this is also a task'})
|
||||||
assert_not_nil(invalid_context_todo)
|
assert_not_nil(invalid_context_todo)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
|
|
||||||
class PreferencesControllerTest < ActionController::TestCase
|
class PreferencesControllerTest < ActionController::TestCase
|
||||||
fixtures :users, :preferences
|
|
||||||
|
|
||||||
def setup
|
def setup
|
||||||
|
super
|
||||||
assert_equal "test", Rails.env
|
assert_equal "test", Rails.env
|
||||||
assert_equal "change-me", Tracks::Config.salt
|
assert_equal "change-me", Tracks::Config.salt
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,10 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
|
|
||||||
class RecurringTodosControllerTest < ActionController::TestCase
|
class RecurringTodosControllerTest < ActionController::TestCase
|
||||||
fixtures :users, :preferences, :projects, :contexts, :todos, :tags, :taggings, :recurring_todos
|
|
||||||
|
|
||||||
def setup
|
|
||||||
@controller = RecurringTodosController.new
|
|
||||||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_get_index_when_not_logged_in
|
def test_get_index_when_not_logged_in
|
||||||
get :index
|
get :index
|
||||||
assert_redirected_to :controller => 'login', :action => 'login'
|
assert_redirected_to login_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_destroy_recurring_todo
|
def test_destroy_recurring_todo
|
||||||
|
|
|
||||||
|
|
@ -1,21 +1,10 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
require 'stats_controller'
|
|
||||||
|
|
||||||
# Re-raise errors caught by the controller.
|
|
||||||
class StatsController; def rescue_action(e) raise e end; end
|
|
||||||
|
|
||||||
class StatsControllerTest < ActionController::TestCase
|
class StatsControllerTest < ActionController::TestCase
|
||||||
fixtures :users, :preferences, :projects, :contexts, :todos, :recurring_todos, :recurring_todos, :tags, :taggings
|
|
||||||
|
|
||||||
def setup
|
|
||||||
@controller = StatsController.new
|
|
||||||
@request = ActionController::TestRequest.new
|
|
||||||
@response = ActionController::TestResponse.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_get_index_when_not_logged_in
|
def test_get_index_when_not_logged_in
|
||||||
get :index
|
get :index
|
||||||
assert_redirected_to :controller => 'login', :action => 'login'
|
assert_redirected_to login_url
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_get_index
|
def test_get_index
|
||||||
|
|
|
||||||
|
|
@ -1,21 +0,0 @@
|
||||||
class TodoContainerControllerTestBase < ActionController::TestCase
|
|
||||||
|
|
||||||
def setup_controller_request_and_response
|
|
||||||
# ## override with empty
|
|
||||||
# TODO: remove these ugly hacks
|
|
||||||
end
|
|
||||||
|
|
||||||
def perform_setup(container_class, controller_class)
|
|
||||||
@controller = controller_class.new
|
|
||||||
@request, @response = ActionController::TestRequest.new, ActionController::TestResponse.new
|
|
||||||
login_as :other_user
|
|
||||||
@initial_count = container_class.count
|
|
||||||
@container_class = container_class
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_truth
|
|
||||||
assert true
|
|
||||||
end
|
|
||||||
|
|
||||||
|
|
||||||
end
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,23 +1,10 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
require 'users_controller'
|
|
||||||
|
|
||||||
# Re-raise errors caught by the controller.
|
|
||||||
class UsersController; def rescue_action(e) raise e end; end
|
|
||||||
|
|
||||||
class UsersControllerTest < ActionController::TestCase
|
class UsersControllerTest < ActionController::TestCase
|
||||||
fixtures :preferences, :users
|
|
||||||
|
|
||||||
def setup
|
|
||||||
assert_equal "test", ENV['RAILS_ENV']
|
|
||||||
assert_equal "change-me", Tracks::Config.salt
|
|
||||||
@controller = UsersController.new
|
|
||||||
@request = ActionController::TestRequest.new
|
|
||||||
@response = ActionController::TestResponse.new
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_get_index_when_not_logged_in
|
def test_get_index_when_not_logged_in
|
||||||
get :index
|
get :index
|
||||||
assert_redirected_to :controller => 'login', :action => 'login'
|
assert_redirected_to login_path
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_get_index_by_nonadmin
|
def test_get_index_by_nonadmin
|
||||||
|
|
@ -32,7 +19,7 @@ class UsersControllerTest < ActionController::TestCase
|
||||||
assert_response :success
|
assert_response :success
|
||||||
assert_equal "TRACKS::Manage Users", assigns['page_title']
|
assert_equal "TRACKS::Manage Users", assigns['page_title']
|
||||||
assert_equal 5, assigns['total_users']
|
assert_equal 5, assigns['total_users']
|
||||||
assert_equal "/users", session['return-to']
|
assert_equal users_url, session['return-to']
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_index_pagination_page_1
|
def test_index_pagination_page_1
|
||||||
|
|
@ -59,7 +46,7 @@ class UsersControllerTest < ActionController::TestCase
|
||||||
|
|
||||||
def test_update_password_successful
|
def test_update_password_successful
|
||||||
get :change_password # should fail because no login
|
get :change_password # should fail because no login
|
||||||
assert_redirected_to :controller => 'login', :action => 'login'
|
assert_redirected_to login_path
|
||||||
login_as :admin_user
|
login_as :admin_user
|
||||||
@user = @request.session['user_id']
|
@user = @request.session['user_id']
|
||||||
get :change_password # should now pass because we're logged in
|
get :change_password # should now pass because we're logged in
|
||||||
|
|
@ -74,21 +61,19 @@ class UsersControllerTest < ActionController::TestCase
|
||||||
|
|
||||||
def test_update_password_no_confirmation
|
def test_update_password_no_confirmation
|
||||||
post :update_password # should fail because no login
|
post :update_password # should fail because no login
|
||||||
assert_redirected_to :controller => 'login', :action => 'login'
|
assert_redirected_to login_path
|
||||||
login_as :admin_user
|
login_as :admin_user
|
||||||
post :update_password, :user => {:password => 'newpassword', :password_confirmation => 'wrong'}
|
post :update_password, :user => {:password => 'newpassword', :password_confirmation => 'wrong'}
|
||||||
assert_redirected_to :controller => 'users', :action => 'change_password'
|
assert_redirected_to change_password_user_path(users(:admin_user))
|
||||||
assert users(:admin_user).save, false
|
|
||||||
assert_equal 'Validation failed: Password doesn\'t match confirmation', flash[:error]
|
assert_equal 'Validation failed: Password doesn\'t match confirmation', flash[:error]
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_update_password_validation_errors
|
def test_update_password_validation_errors
|
||||||
post :update_password # should fail because no login
|
post :update_password # should fail because no login
|
||||||
assert_redirected_to :controller => 'login', :action => 'login'
|
assert_redirected_to login_path
|
||||||
login_as :admin_user
|
login_as :admin_user
|
||||||
post :update_password, :user => {:password => 'ba', :password_confirmation => 'ba'}
|
post :update_password, :user => {:password => 'ba', :password_confirmation => 'ba'}
|
||||||
assert_redirected_to :controller => 'users', :action => 'change_password'
|
assert_redirected_to change_password_user_path(User.find(users(:admin_user).id))
|
||||||
assert users(:admin_user).save, false
|
|
||||||
# For some reason, no errors are being raised now.
|
# For some reason, no errors are being raised now.
|
||||||
#assert_equal 1, users(:admin_user).errors.count
|
#assert_equal 1, users(:admin_user).errors.count
|
||||||
#assert_equal users(:admin_user).errors.on(:password), "is too short (min is 5 characters)"
|
#assert_equal users(:admin_user).errors.on(:password), "is too short (min is 5 characters)"
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ ENV["RAILS_ENV"] = "test"
|
||||||
require File.expand_path('../../config/environment', __FILE__)
|
require File.expand_path('../../config/environment', __FILE__)
|
||||||
require 'rails/test_help'
|
require 'rails/test_help'
|
||||||
|
|
||||||
{ :salt => "change-me", :authentication_schemes => ["database", "open_id"], :prefered_auth => "database"}.each{|k,v| SITE_CONFIG[k]=v}
|
# set config for tests. Overwrite those read from config/site.yml. Use inject to avoid warning about changing CONSTANT
|
||||||
|
{"salt" => "change-me", "authentication_schemes" => ["database", "open_id", "ldap"], "prefered_auth" => "database"}.inject( SITE_CONFIG ) { |h, elem| h[elem[0]] = elem[1]; h }
|
||||||
|
|
||||||
class ActiveSupport::TestCase
|
class ActiveSupport::TestCase
|
||||||
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
# Setup all fixtures in test/fixtures/*.(yml|csv) for all tests in alphabetical order.
|
||||||
|
|
@ -10,17 +11,35 @@ class ActiveSupport::TestCase
|
||||||
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
# Note: You'll currently still have to declare fixtures explicitly in integration tests
|
||||||
# -- they do not yet inherit this setting
|
# -- they do not yet inherit this setting
|
||||||
fixtures :all
|
fixtures :all
|
||||||
|
|
||||||
# Add more helper methods to be used by all tests here...
|
# Add more helper methods to be used by all tests here...
|
||||||
def assert_value_changed(object, method = nil)
|
def assert_value_changed(object, method = nil)
|
||||||
initial_value = object.send(method)
|
initial_value = object.send(method)
|
||||||
yield
|
yield
|
||||||
assert_not_equal initial_value, object.send(method), "#{object}##{method}"
|
assert_not_equal initial_value, object.send(method), "#{object}##{method}"
|
||||||
end
|
end
|
||||||
|
# Generates a random string of ascii characters (a-z, "1 0")
|
||||||
|
# of a given length for testing assignment to fields
|
||||||
|
# for validation purposes
|
||||||
|
#
|
||||||
|
def generate_random_string(length)
|
||||||
|
string = ""
|
||||||
|
characters = %w(a b c d e f g h i j k l m n o p q r s t u v w z y z 1\ 0)
|
||||||
|
length.times do
|
||||||
|
pick = characters[rand(26)]
|
||||||
|
string << pick
|
||||||
|
end
|
||||||
|
return string
|
||||||
|
end
|
||||||
|
|
||||||
|
def assert_equal_dmy(date1, date2)
|
||||||
|
assert_equal date1.strftime("%d-%m-%y"), date2.strftime("%d-%m-%y")
|
||||||
|
end
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class ActionController::TestCase
|
class ActionController::TestCase
|
||||||
|
|
||||||
def login_as(user)
|
def login_as(user)
|
||||||
@request.session['user_id'] = user ? users(user).id : nil
|
@request.session['user_id'] = user ? users(user).id : nil
|
||||||
end
|
end
|
||||||
|
|
@ -61,26 +80,4 @@ class ActionController::TestCase
|
||||||
eval("#{get_model_class}.count")
|
eval("#{get_model_class}.count")
|
||||||
end
|
end
|
||||||
|
|
||||||
end
|
|
||||||
|
|
||||||
class ActiveSupport::TestCase
|
|
||||||
|
|
||||||
# Generates a random string of ascii characters (a-z, "1 0")
|
|
||||||
# of a given length for testing assignment to fields
|
|
||||||
# for validation purposes
|
|
||||||
#
|
|
||||||
def generate_random_string(length)
|
|
||||||
string = ""
|
|
||||||
characters = %w(a b c d e f g h i j k l m n o p q r s t u v w z y z 1\ 0)
|
|
||||||
length.times do
|
|
||||||
pick = characters[rand(26)]
|
|
||||||
string << pick
|
|
||||||
end
|
|
||||||
return string
|
|
||||||
end
|
|
||||||
|
|
||||||
def assert_equal_dmy(date1, date2)
|
|
||||||
assert_equal date1.strftime("%d-%m-%y"), date2.strftime("%d-%m-%y")
|
|
||||||
end
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
@ -54,12 +54,6 @@ class ContextTest < ActiveSupport::TestCase
|
||||||
assert_equal @agenda.name, @agenda.title
|
assert_equal @agenda.name, @agenda.title
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_feed_options
|
|
||||||
opts = Context.feed_options(users(:admin_user))
|
|
||||||
assert_equal 'Tracks Contexts', opts[:title], 'Unexpected value for :title key of feed_options'
|
|
||||||
assert_equal 'Lists all the contexts for Admin Schmadmin', opts[:description], 'Unexpected value for :description key of feed_options'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_hidden_attr_reader
|
def test_hidden_attr_reader
|
||||||
assert !@agenda.hidden?
|
assert !@agenda.hidden?
|
||||||
@agenda.hide = true
|
@agenda.hide = true
|
||||||
|
|
|
||||||
|
|
@ -128,12 +128,6 @@ class ProjectTest < ActiveSupport::TestCase
|
||||||
assert p.nil?
|
assert p.nil?
|
||||||
assert_nil p.id
|
assert_nil p.id
|
||||||
end
|
end
|
||||||
|
|
||||||
def test_feed_options
|
|
||||||
opts = Project.feed_options(users(:admin_user))
|
|
||||||
assert_equal 'Tracks Projects', opts[:title], 'Unexpected value for :title key of feed_options'
|
|
||||||
assert_equal 'Lists all the projects for Admin Schmadmin', opts[:description], 'Unexpected value for :description key of feed_options'
|
|
||||||
end
|
|
||||||
|
|
||||||
def test_name_removes_extra_spaces
|
def test_name_removes_extra_spaces
|
||||||
newproj = Project.new
|
newproj = Project.new
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,4 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
require 'date'
|
|
||||||
|
|
||||||
class TodoTest < ActiveSupport::TestCase
|
class TodoTest < ActiveSupport::TestCase
|
||||||
fixtures :todos, :recurring_todos, :users, :contexts, :preferences, :tags, :taggings, :projects
|
fixtures :todos, :recurring_todos, :users, :contexts, :preferences, :tags, :taggings, :projects
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,5 @@
|
||||||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||||
|
|
||||||
module Tracks
|
|
||||||
class Config
|
|
||||||
def self.auth_schemes
|
|
||||||
['database', 'ldap']
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
class SimpleLdapAuthenticator
|
class SimpleLdapAuthenticator
|
||||||
cattr_accessor :fake_success
|
cattr_accessor :fake_success
|
||||||
|
|
||||||
|
|
@ -22,7 +14,7 @@ class UserTest < ActiveSupport::TestCase
|
||||||
def setup
|
def setup
|
||||||
assert_equal "test", ENV['RAILS_ENV']
|
assert_equal "test", ENV['RAILS_ENV']
|
||||||
assert_equal "change-me", Tracks::Config.salt
|
assert_equal "change-me", Tracks::Config.salt
|
||||||
assert_equal ['database', 'ldap'], Tracks::Config.auth_schemes
|
assert Tracks::Config.auth_schemes.include?('ldap')
|
||||||
@admin_user = User.find(1)
|
@admin_user = User.find(1)
|
||||||
@other_user = User.find(2)
|
@other_user = User.find(2)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue