mirror of
https://github.com/TracksApp/tracks.git
synced 2025-12-24 19:20:13 +01:00
Merge branch 'master' into new-gui
Conflicts: Gemfile.lock
This commit is contained in:
parent
fa537fbeb0
commit
eb1502d4e0
28 changed files with 385 additions and 221 deletions
|
|
@ -1,9 +1,15 @@
|
|||
language: ruby
|
||||
|
||||
rvm:
|
||||
- 1.9.3
|
||||
- 2.0.0
|
||||
- 2.1
|
||||
|
||||
bundler_args: --without development
|
||||
|
||||
before_install:
|
||||
before_install:
|
||||
- "gem install bundler -v=1.5.1"
|
||||
- "mysql -e 'create database tracks_test;'"
|
||||
- "export DISPLAY=:99.0"
|
||||
- "sh -e /etc/init.d/xvfb start"
|
||||
|
|
@ -12,7 +18,6 @@ before_install:
|
|||
|
||||
script: "CODECLIMATE_REPO_TOKEN=5c52fdd2bbcd0734d56ddb2c3cbaac782da345273e8689d25f54a065ccc3397c bundle exec rake ci RACK_ENV=test"
|
||||
|
||||
bundler_args: --without development
|
||||
notifications:
|
||||
email: false
|
||||
|
||||
|
|
|
|||
156
Gemfile.lock
156
Gemfile.lock
|
|
@ -1,6 +1,6 @@
|
|||
GIT
|
||||
remote: https://github.com/cucumber/aruba
|
||||
revision: adbfc240d69254d7b525876b4c5bff6b721b7d65
|
||||
revision: 7afbc5c0cbae9c9a946d70c4c2735ccb86e00f08
|
||||
specs:
|
||||
aruba (0.5.3)
|
||||
childprocess (>= 0.3.6)
|
||||
|
|
@ -9,35 +9,35 @@ GIT
|
|||
|
||||
GIT
|
||||
remote: https://github.com/rails/actionpack-xml_parser
|
||||
revision: 246653ab3670f329176c1e77e6cd1a632466f06e
|
||||
revision: e1516064761ea26502cd79b283f6af0fa2b1edf5
|
||||
specs:
|
||||
actionpack-xml_parser (1.0.0)
|
||||
actionpack (>= 4.0.0.rc1, < 4.1)
|
||||
actionpack-xml_parser (1.0.1)
|
||||
actionpack (>= 4.0.0, < 5)
|
||||
|
||||
GEM
|
||||
remote: https://rubygems.org/
|
||||
specs:
|
||||
RedCloth (4.2.9)
|
||||
aasm (3.0.22)
|
||||
actionmailer (4.0.0)
|
||||
actionpack (= 4.0.0)
|
||||
mail (~> 2.5.3)
|
||||
actionpack (4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
aasm (3.0.25)
|
||||
actionmailer (4.0.2)
|
||||
actionpack (= 4.0.2)
|
||||
mail (~> 2.5.4)
|
||||
actionpack (4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
builder (~> 3.1.0)
|
||||
erubis (~> 2.7.0)
|
||||
rack (~> 1.5.2)
|
||||
rack-test (~> 0.6.2)
|
||||
activemodel (4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
activemodel (4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
builder (~> 3.1.0)
|
||||
activerecord (4.0.0)
|
||||
activemodel (= 4.0.0)
|
||||
activerecord (4.0.2)
|
||||
activemodel (= 4.0.2)
|
||||
activerecord-deprecated_finders (~> 1.0.2)
|
||||
activesupport (= 4.0.0)
|
||||
activesupport (= 4.0.2)
|
||||
arel (~> 4.0.0)
|
||||
activerecord-deprecated_finders (1.0.3)
|
||||
activesupport (4.0.0)
|
||||
activesupport (4.0.2)
|
||||
i18n (~> 0.6, >= 0.6.4)
|
||||
minitest (~> 4.2)
|
||||
multi_json (~> 1.3)
|
||||
|
|
@ -45,16 +45,17 @@ GEM
|
|||
tzinfo (~> 0.3.37)
|
||||
acts_as_list (0.3.0)
|
||||
activerecord (>= 3.0)
|
||||
arel (4.0.0)
|
||||
arel (4.0.1)
|
||||
atomic (1.1.14)
|
||||
bcrypt-ruby (3.0.1)
|
||||
builder (3.1.4)
|
||||
bullet (4.6.0)
|
||||
uniform_notifier
|
||||
bullet (4.7.1)
|
||||
activesupport
|
||||
uniform_notifier (>= 1.4.0)
|
||||
cache_digests (0.3.1)
|
||||
actionpack (>= 3.2)
|
||||
thread_safe
|
||||
capybara (2.1.0)
|
||||
capybara (2.2.1)
|
||||
mime-types (>= 1.16)
|
||||
nokogiri (>= 1.3.3)
|
||||
rack (>= 1.0.0)
|
||||
|
|
@ -62,20 +63,20 @@ GEM
|
|||
xpath (~> 2.0)
|
||||
childprocess (0.3.9)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
codeclimate-test-reporter (0.1.1)
|
||||
codeclimate-test-reporter (0.2.0)
|
||||
simplecov (>= 0.7.1, < 1.0.0)
|
||||
coffee-rails (4.0.0)
|
||||
coffee-rails (4.0.1)
|
||||
coffee-script (>= 2.2.0)
|
||||
railties (>= 4.0.0.beta, < 5.0)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
coffee-script (2.2.0)
|
||||
coffee-script-source
|
||||
execjs
|
||||
coffee-script-source (1.6.3)
|
||||
commonjs (0.2.7)
|
||||
cucumber (1.3.8)
|
||||
cucumber (1.3.10)
|
||||
builder (>= 2.1.2)
|
||||
diff-lcs (>= 1.1.3)
|
||||
gherkin (~> 2.12.1)
|
||||
gherkin (~> 2.12)
|
||||
multi_json (>= 1.7.5, < 2.0)
|
||||
multi_test (>= 0.0.2)
|
||||
cucumber-rails (1.4.0)
|
||||
|
|
@ -83,25 +84,26 @@ GEM
|
|||
cucumber (>= 1.2.0)
|
||||
nokogiri (>= 1.5.0)
|
||||
rails (>= 3.0.0)
|
||||
database_cleaner (1.1.1)
|
||||
diff-lcs (1.2.4)
|
||||
database_cleaner (1.2.0)
|
||||
diff-lcs (1.2.5)
|
||||
docile (1.1.1)
|
||||
erubis (2.7.0)
|
||||
execjs (2.0.1)
|
||||
factory_girl (4.2.0)
|
||||
execjs (2.0.2)
|
||||
factory_girl (4.3.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_girl_rails (4.2.1)
|
||||
factory_girl (~> 4.2.0)
|
||||
factory_girl_rails (4.3.0)
|
||||
factory_girl (~> 4.3.0)
|
||||
railties (>= 3.0.0)
|
||||
ffi (1.9.0)
|
||||
gherkin (2.12.1)
|
||||
ffi (1.9.3)
|
||||
gherkin (2.12.2)
|
||||
multi_json (~> 1.3)
|
||||
hike (1.2.3)
|
||||
htmlentities (4.3.1)
|
||||
i18n (0.6.5)
|
||||
i18n (0.6.9)
|
||||
jquery-rails (3.0.4)
|
||||
railties (>= 3.0, < 5.0)
|
||||
thor (>= 0.14, < 2.0)
|
||||
json (1.8.0)
|
||||
json (1.8.1)
|
||||
less (2.4.0)
|
||||
commonjs (~> 0.2.7)
|
||||
less-rails (2.4.2)
|
||||
|
|
@ -112,66 +114,69 @@ GEM
|
|||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
metaclass (0.0.1)
|
||||
mime-types (1.25)
|
||||
mini_portile (0.5.1)
|
||||
mime-types (1.25.1)
|
||||
mini_portile (0.5.2)
|
||||
minitest (4.7.5)
|
||||
mocha (0.14.0)
|
||||
metaclass (~> 0.0.1)
|
||||
mousetrap-rails (0.0.12)
|
||||
multi_json (1.8.0)
|
||||
multi_test (0.0.2)
|
||||
mysql2 (0.3.13)
|
||||
nokogiri (1.6.0)
|
||||
mousetrap-rails (1.4.6)
|
||||
multi_json (1.8.2)
|
||||
multi_test (0.0.3)
|
||||
mysql2 (0.3.14)
|
||||
nokogiri (1.6.1)
|
||||
mini_portile (~> 0.5.0)
|
||||
polyglot (0.3.3)
|
||||
protected_attributes (1.0.5)
|
||||
activemodel (>= 4.0.1, < 5.0)
|
||||
rack (1.5.2)
|
||||
rack-mini-profiler (0.1.31)
|
||||
rack-mini-profiler (0.9.0)
|
||||
rack (>= 1.1.3)
|
||||
rack-test (0.6.2)
|
||||
rack (>= 1.0)
|
||||
rails (4.0.0)
|
||||
actionmailer (= 4.0.0)
|
||||
actionpack (= 4.0.0)
|
||||
activerecord (= 4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
rails (4.0.2)
|
||||
actionmailer (= 4.0.2)
|
||||
actionpack (= 4.0.2)
|
||||
activerecord (= 4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
bundler (>= 1.3.0, < 2.0)
|
||||
railties (= 4.0.0)
|
||||
railties (= 4.0.2)
|
||||
sprockets-rails (~> 2.0.0)
|
||||
rails_autolink (1.1.4)
|
||||
rails_autolink (1.1.5)
|
||||
rails (> 3.1)
|
||||
railties (4.0.0)
|
||||
actionpack (= 4.0.0)
|
||||
activesupport (= 4.0.0)
|
||||
railties (4.0.2)
|
||||
actionpack (= 4.0.2)
|
||||
activesupport (= 4.0.2)
|
||||
rake (>= 0.8.7)
|
||||
thor (>= 0.18.1, < 2.0)
|
||||
rake (10.1.0)
|
||||
rake (10.1.1)
|
||||
ref (1.0.5)
|
||||
rspec-expectations (2.14.3)
|
||||
rspec-expectations (2.14.4)
|
||||
diff-lcs (>= 1.1.3, < 2.0)
|
||||
rubyzip (0.9.9)
|
||||
rubyzip (1.1.0)
|
||||
safe_yaml (0.9.7)
|
||||
sanitize (2.0.6)
|
||||
nokogiri (>= 1.4.4)
|
||||
sass (3.2.10)
|
||||
sass-rails (4.0.0)
|
||||
railties (>= 4.0.0.beta, < 5.0)
|
||||
sass (3.2.13)
|
||||
sass-rails (4.0.1)
|
||||
railties (>= 4.0.0, < 5.0)
|
||||
sass (>= 3.1.10)
|
||||
sprockets-rails (~> 2.0.0)
|
||||
selenium-webdriver (2.35.1)
|
||||
selenium-webdriver (2.39.0)
|
||||
childprocess (>= 0.2.5)
|
||||
multi_json (~> 1.0)
|
||||
rubyzip (< 1.0.0)
|
||||
rubyzip (~> 1.0)
|
||||
websocket (~> 1.0.4)
|
||||
simplecov (0.7.1)
|
||||
multi_json (~> 1.0)
|
||||
simplecov-html (~> 0.7.1)
|
||||
simplecov-html (0.7.1)
|
||||
sprockets (2.10.0)
|
||||
simplecov (0.8.2)
|
||||
docile (~> 1.1.0)
|
||||
multi_json
|
||||
simplecov-html (~> 0.8.0)
|
||||
simplecov-html (0.8.0)
|
||||
sprockets (2.10.1)
|
||||
hike (~> 1.2)
|
||||
multi_json (~> 1.0)
|
||||
rack (~> 1.0)
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
sprockets-rails (2.0.0)
|
||||
sprockets-rails (2.0.1)
|
||||
actionpack (>= 3.0)
|
||||
activesupport (>= 3.0)
|
||||
sprockets (~> 2.8)
|
||||
|
|
@ -187,31 +192,32 @@ GEM
|
|||
atomic
|
||||
tilt (1.4.1)
|
||||
timecop (0.6.3)
|
||||
tolk (1.3.11)
|
||||
tolk (1.4.00)
|
||||
protected_attributes
|
||||
safe_yaml (~> 0.8)
|
||||
will_paginate
|
||||
treetop (1.4.15)
|
||||
polyglot
|
||||
polyglot (>= 0.3.1)
|
||||
turbolinks (1.3.0)
|
||||
turbolinks (2.1.0)
|
||||
coffee-rails
|
||||
twitter-bootstrap-rails (2.2.8)
|
||||
actionpack (>= 3.1)
|
||||
execjs
|
||||
rails (>= 3.1)
|
||||
railties (>= 3.1)
|
||||
tzinfo (0.3.37)
|
||||
uglifier (2.2.1)
|
||||
tzinfo (0.3.38)
|
||||
uglifier (2.4.0)
|
||||
execjs (>= 0.3.0)
|
||||
multi_json (~> 1.0, >= 1.0.2)
|
||||
uniform_notifier (1.3.0)
|
||||
json (>= 1.8.0)
|
||||
uniform_notifier (1.4.0)
|
||||
websocket (1.0.7)
|
||||
will_paginate (3.0.5)
|
||||
will_paginate-bootstrap (0.2.5)
|
||||
will_paginate-bootstrap (1.0.0)
|
||||
will_paginate (>= 3.0.3)
|
||||
xpath (2.0.0)
|
||||
nokogiri (~> 1.3)
|
||||
yard (0.8.7.2)
|
||||
yard (0.8.7.3)
|
||||
|
||||
PLATFORMS
|
||||
ruby
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ class ApplicationController < ActionController::Base
|
|||
if todos_parent.nil?
|
||||
count = 0
|
||||
elsif (todos_parent.is_a?(Project) && todos_parent.hidden?)
|
||||
count = eval "@project_project_hidden_todo_counts[#{todos_parent.id}]"
|
||||
count = @project_project_hidden_todo_counts[todos_parent.id]
|
||||
else
|
||||
count = eval "@#{todos_parent.class.to_s.downcase}_not_done_counts[#{todos_parent.id}]"
|
||||
end
|
||||
|
|
|
|||
|
|
@ -747,34 +747,29 @@ class TodosController < ApplicationController
|
|||
end
|
||||
end
|
||||
|
||||
def get_not_completed_for_predecessor(relation, todo_id=nil)
|
||||
items = relation.todos.not_completed.
|
||||
where('(LOWER(todos.description) LIKE ?)', "%#{params[:term].downcase}%")
|
||||
items = items.where("AND NOT(todos.id=?)", todo_id) unless todo_id.nil?
|
||||
|
||||
items.
|
||||
includes(:context, :project).
|
||||
reorder('description ASC').
|
||||
limit(10)
|
||||
end
|
||||
|
||||
def auto_complete_for_predecessor
|
||||
unless params['id'].nil?
|
||||
get_todo_from_params
|
||||
# Begin matching todos in current project, excluding @todo itself
|
||||
@items = @todo.project.todos.not_completed.
|
||||
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
||||
includes(:context, :project).
|
||||
reorder('description ASC').
|
||||
limit(10) unless @todo.project.nil?
|
||||
@items = get_not_completed_for_predecessor(@todo.project, @todo.id) unless @todo.project.nil?
|
||||
# Then look in the current context, excluding @todo itself
|
||||
@items = @todo.context.todos.not_completed.
|
||||
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
||||
includes(:context, :project).
|
||||
reorder('description ASC').
|
||||
limit(10) unless !@items.empty? || @todo.context.nil?
|
||||
@items = get_not_completed_for_predecessor(@todo.context, @todo.id) unless !@items.empty? || @todo.context.nil?
|
||||
# Match todos in other projects, excluding @todo itself
|
||||
@items = current_user.todos.not_completed.
|
||||
where('(LOWER(todos.description) LIKE ?) AND NOT(todos.id=?)', "%#{params[:term].downcase}%", @todo.id).
|
||||
includes(:context, :project).
|
||||
reorder('description ASC').
|
||||
limit(10) unless !@items.empty?
|
||||
@items = get_not_completed_for_predecessor(current_user, @todo.id) unless !@items.empty?
|
||||
else
|
||||
# New todo - TODO: Filter on current project in project view
|
||||
@items = current_user.todos.not_completed.
|
||||
where('(LOWER(todos.description) LIKE ?)', "%#{params[:term].downcase}%").
|
||||
includes(:context, :project).
|
||||
reorder('description ASC').
|
||||
limit(10)
|
||||
@items = get_not_complete_for_predecessor(current_user)
|
||||
end
|
||||
render :inline => format_dependencies_as_json_for_auto_complete(@items)
|
||||
end
|
||||
|
|
@ -1020,27 +1015,23 @@ end
|
|||
end
|
||||
end
|
||||
|
||||
def find_completed(relation, id, include_hidden)
|
||||
todos = relation.find(id).todos.completed
|
||||
todos = todos.not_hidden if !include_hidden
|
||||
return todos
|
||||
end
|
||||
|
||||
def determine_completed_count
|
||||
todos=nil
|
||||
|
||||
source_view do |from|
|
||||
from.todo do
|
||||
@completed_count = current_user.todos.not_hidden.completed.count
|
||||
end
|
||||
from.context do
|
||||
todos = current_user.contexts.find(@todo.context_id).todos.completed
|
||||
todos = todos.not_hidden if !@todo.context.hidden?
|
||||
@completed_count = todos.count
|
||||
end
|
||||
from.project do
|
||||
unless @todo.project_id == nil
|
||||
todos = current_user.projects.find(@todo.project_id).todos.completed
|
||||
todos = todos.not_hidden if !@todo.project.hidden?
|
||||
@completed_count = todos.count
|
||||
end
|
||||
end
|
||||
from.tag do
|
||||
@completed_count = current_user.todos.with_tag(@tag.id).completed.count
|
||||
end
|
||||
from.todo { todos = current_user.todos.not_hidden.completed }
|
||||
from.context { todos = find_completed(current_user.contexts, @todo.context_id, @todo.context.hidden?) }
|
||||
from.project { todos = find_completed(current_user.projects, @todo.project_id, @todo.project.hidden?) unless @todo.project_id.nil? }
|
||||
from.tag { todos = current_user.todos.with_tag(@tag.id).completed }
|
||||
end
|
||||
|
||||
@completed_count = todos.nil? ? 0 : todos.count
|
||||
end
|
||||
|
||||
def determine_deferred_tag_count(tag_name)
|
||||
|
|
@ -1195,23 +1186,20 @@ end
|
|||
end
|
||||
end
|
||||
|
||||
def parse_date_for_update(date, error_msg)
|
||||
begin
|
||||
parse_date_per_user_prefs(date)
|
||||
rescue
|
||||
@todo.errors[:base] << error_msg
|
||||
end
|
||||
end
|
||||
|
||||
def update_date_for_update(key)
|
||||
params['todo'][key] = params["todo"].has_key?(key) ? parse_date_for_update(params["todo"][key], t("todos.error.invalid_#{key}_date")) : ""
|
||||
end
|
||||
|
||||
def update_due_and_show_from_dates
|
||||
if params["todo"].has_key?("due")
|
||||
begin
|
||||
params["todo"]["due"] = parse_date_per_user_prefs(params["todo"]["due"])
|
||||
rescue
|
||||
@todo.errors[:base] << "Invalid due date"
|
||||
end
|
||||
else
|
||||
params["todo"]["due"] = ""
|
||||
end
|
||||
if params['todo']['show_from']
|
||||
begin
|
||||
params['todo']['show_from'] = parse_date_per_user_prefs(params['todo']['show_from'])
|
||||
rescue
|
||||
@todo.errors[:base] << "Invalid show from date"
|
||||
end
|
||||
end
|
||||
%w{ due show_from }.each {|date| update_date_for_update(date) }
|
||||
end
|
||||
|
||||
def update_completed_state
|
||||
|
|
@ -1283,18 +1271,18 @@ end
|
|||
completed_todos.completed_after(start_of_this_day).includes(includes[:include])
|
||||
end
|
||||
|
||||
def get_done_in_period(before, after, includes = {:include => Todo::DEFAULT_INCLUDES})
|
||||
completed_todos.completed_before(before).completed_after(after).includes(includes[:include])
|
||||
end
|
||||
|
||||
# all completed todos [begin_of_week, start_of_today]
|
||||
def get_done_rest_of_week(completed_todos, includes = {:include => Todo::DEFAULT_INCLUDES})
|
||||
start_of_this_week = Time.zone.now.beginning_of_week
|
||||
start_of_this_day = Time.zone.now.beginning_of_day
|
||||
completed_todos.completed_before(start_of_this_day).completed_after(start_of_this_week).includes(includes[:include])
|
||||
get_done_in_period(Time.zone.now.beginning_of_day, Time.zone.now.beginning_of_week)
|
||||
end
|
||||
|
||||
# all completed todos [begin_of_month, begin_of_week]
|
||||
def get_done_rest_of_month(completed_todos, includes = {:include => Todo::DEFAULT_INCLUDES})
|
||||
start_of_this_month = Time.zone.now.beginning_of_month
|
||||
start_of_this_week = Time.zone.now.beginning_of_week
|
||||
completed_todos.completed_before(start_of_this_week).completed_after(start_of_this_month).includes(includes[:include])
|
||||
get_done_in_period(Time.zone.now.beginning_of_week, Time.zone.now.beginning_of_month)
|
||||
end
|
||||
|
||||
def get_not_done_todos
|
||||
|
|
|
|||
|
|
@ -1,6 +1,4 @@
|
|||
class MessageGateway < ActionMailer::Base
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
||||
|
||||
def receive(email)
|
||||
user = get_receiving_user_from_email_address(email)
|
||||
|
|
@ -85,11 +83,11 @@ class MessageGateway < ActionMailer::Base
|
|||
end
|
||||
|
||||
def get_text_or_nil(text)
|
||||
return text ? sanitize(text.strip) : nil
|
||||
return text ? text.strip : nil
|
||||
end
|
||||
|
||||
def get_decoded_text_or_nil(text)
|
||||
return text ? sanitize(text.decoded.strip) : nil
|
||||
return text ? text.decoded.strip : nil
|
||||
end
|
||||
|
||||
def get_first_text_plain_part(email)
|
||||
|
|
@ -99,7 +97,7 @@ class MessageGateway < ActionMailer::Base
|
|||
# remove all parts that are not text/plain
|
||||
parts.reject{|part| !part.content_type.start_with?("text/plain") }
|
||||
|
||||
return parts.count > 0 ? sanitize(parts[0].decoded.strip) : ""
|
||||
return parts.count > 0 ? parts[0].decoded.strip : ""
|
||||
end
|
||||
|
||||
def get_all_parts(parts)
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ class Project < ActiveRecord::Base
|
|||
scope :uncompleted, -> { where("NOT(state = ?)", 'completed') }
|
||||
|
||||
scope :with_name_or_description, lambda { |body| where("name LIKE ? OR description LIKE ?", body, body) }
|
||||
scope :with_namepart, lambda { |body| where("name LIKE ?", body + '%') }
|
||||
|
||||
validates_presence_of :name
|
||||
validates_length_of :name, :maximum => 255
|
||||
|
|
@ -88,7 +89,7 @@ class Project < ActiveRecord::Base
|
|||
# as a result of acts_as_state_machine calling state=() to update the attribute
|
||||
def transition_to(candidate_state)
|
||||
case candidate_state.to_sym
|
||||
when aasm_current_state
|
||||
when aasm.current_state
|
||||
return
|
||||
when :hidden
|
||||
hide!
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ class Todo < ActiveRecord::Base
|
|||
|
||||
# state machine
|
||||
include AASM
|
||||
aasm_initial_state Proc.new { |t| (t.show_from && t.user && (t.show_from > t.user.date)) ? :deferred : :active}
|
||||
aasm_initial_state = Proc.new { |t| (t.show_from && t.user && (t.show_from > t.user.date)) ? :deferred : :active}
|
||||
|
||||
aasm :column => :state do
|
||||
|
||||
|
|
|
|||
|
|
@ -1,28 +1,72 @@
|
|||
require 'date'
|
||||
class RichMessageExtractor
|
||||
include ActionView::Helpers::SanitizeHelper
|
||||
extend ActionView::Helpers::SanitizeHelper::ClassMethods
|
||||
|
||||
RICH_MESSAGE_FIELDS_REGEX = /([^>@]*)@?([^>]*)>?(.*)/
|
||||
PROJECT_MARKER = '~'
|
||||
CONTEXT_MARKER = '@'
|
||||
TICKLER_MARKER = '>'
|
||||
DUE_MARKER = '<'
|
||||
TAG_MARKER = '#'
|
||||
STAR_MARKER = '*'
|
||||
|
||||
ALL_MARKERS = [
|
||||
PROJECT_MARKER,
|
||||
CONTEXT_MARKER,
|
||||
TICKLER_MARKER,
|
||||
DUE_MARKER,
|
||||
TAG_MARKER,
|
||||
STAR_MARKER
|
||||
]
|
||||
|
||||
def initialize(message)
|
||||
@message = message
|
||||
end
|
||||
|
||||
def description
|
||||
fields[1].strip
|
||||
desc = select_for('')
|
||||
desc.blank? ? '' : sanitize(desc[1].strip)
|
||||
end
|
||||
|
||||
def context
|
||||
fields[2].strip
|
||||
context = select_for(CONTEXT_MARKER)
|
||||
context.blank? ? '' : sanitize(context[1].strip)
|
||||
end
|
||||
|
||||
def project
|
||||
stripped = fields[3].strip
|
||||
stripped.blank? ? nil : stripped
|
||||
project = select_for PROJECT_MARKER
|
||||
project.blank? ? nil : sanitize(project[1].strip)
|
||||
end
|
||||
|
||||
def tags
|
||||
string = @message.dup
|
||||
tags = []
|
||||
# Regex only matches one tag, so recurse until we have them all
|
||||
while string.match /#(.*?)(?=[#{ALL_MARKERS.join}]|\Z)/
|
||||
tags << sanitize($1)
|
||||
string.gsub!(/##{$1}/,'')
|
||||
end
|
||||
tags.empty? ? nil : tags
|
||||
end
|
||||
|
||||
def due
|
||||
due = select_for DUE_MARKER
|
||||
due.blank? ? nil : Date.parse(due[1].strip)
|
||||
end
|
||||
|
||||
def show_from
|
||||
show_from = select_for TICKLER_MARKER
|
||||
show_from.blank? ? nil : Date.parse(show_from[1].strip)
|
||||
end
|
||||
|
||||
def starred?
|
||||
@message.include? '*'
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fields
|
||||
@message.match(RICH_MESSAGE_FIELDS_REGEX)
|
||||
end
|
||||
def select_for symbol
|
||||
@message.match /#{symbol}(.*?)(?=[#{ALL_MARKERS.join}]|\Z)/
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -14,6 +14,10 @@ class TodoFromRichMessage
|
|||
description = extractor.description
|
||||
context = extractor.context
|
||||
project = extractor.project
|
||||
show_from = extractor.show_from
|
||||
due = extractor.due
|
||||
tags = extractor.tags
|
||||
star = extractor.starred?
|
||||
|
||||
context_id = default_context_id
|
||||
if context.present?
|
||||
|
|
@ -33,17 +37,21 @@ class TodoFromRichMessage
|
|||
found_project.name = project[4..259].strip
|
||||
found_project.save!
|
||||
else
|
||||
found_project = user.projects.active.find_by_namepart(project)
|
||||
found_project = user.projects.find_by_namepart(project) if found_project.nil?
|
||||
found_project = user.projects.active.with_namepart(project).first
|
||||
found_project = user.projects.with_namepart(project).first if found_project.nil?
|
||||
end
|
||||
project_id = found_project.id unless found_project.nil?
|
||||
end
|
||||
|
||||
todo = user.todos.build
|
||||
todo = user.todos.build
|
||||
todo.description = description
|
||||
todo.raw_notes = notes
|
||||
todo.context_id = context_id
|
||||
todo.project_id = project_id unless project_id.nil?
|
||||
todo.raw_notes = notes
|
||||
todo.context_id = context_id
|
||||
todo.project_id = project_id unless project_id.nil?
|
||||
todo.show_from = show_from if show_from.is_a? Date
|
||||
todo.due = due if due.is_a? Date
|
||||
todo.tag_with tags unless tags.nil? || tags.empty?
|
||||
todo.starred = star
|
||||
todo
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -131,5 +131,5 @@
|
|||
<li>Enable the "Add any gadget by URL" feature. You will find it at bottom of the list. Select Enable radio button and click Save Changes button.</li>
|
||||
<li>Now you can see Gadgets tab added to Gmail Settings. Go to the Gadgets tab</li>
|
||||
<li>Paste following link to the Add a gadget by its URL: and then click Add button:<br/>
|
||||
<pre><%= integrations_url + "/google_gadget" %></pre></li>
|
||||
<pre><%= integrations_url + "/google_gadget.xml" %></pre></li>
|
||||
</ul>
|
||||
|
|
@ -14,6 +14,7 @@
|
|||
<li><a href="#email-cron-section">Automatically Email Yourself Upcoming Actions</a></li>
|
||||
<li><a href="#message_gateway">Integrate Tracks with an email server to be able to send an action through email to Tracks</a></li>
|
||||
<li><a href="#mailgun">Send emails to Tracks with Mailgun</a>
|
||||
<li><a href="#todo_rich_message_format">Rich Todo Message email format</a>
|
||||
<li><a href="#google_gadget">Add Tracks as a Google Gmail gadget</a></li>
|
||||
</ul><br/>
|
||||
<p>Do you have one of your own to add?
|
||||
|
|
@ -122,6 +123,7 @@
|
|||
|
||||
<a name="mailgun"> </a>
|
||||
<h2>Send emails to Tracks with Mailgun</h2>
|
||||
<p>
|
||||
If you want to email tasks to Tracks, but cannot run a mailserver on the same host,
|
||||
you could use the <a href='www.mailgun.com'>Mailgun</a> support built in to Tracks.
|
||||
</p>
|
||||
|
|
@ -155,6 +157,36 @@ mailmap:
|
|||
<p>All the comments about the email format from the section above apply to the
|
||||
Mailgun handling, as the data is processed the same way</p>
|
||||
|
||||
<a name="todo_rich_message_format"> </a>
|
||||
<h2>Rich Todo Message Format</h2>
|
||||
<p> For both of the above methods, the follow format can be used:</p>
|
||||
<pre>my awesome todo @context ~project <131012 >131009 #tag1 #tag2 *</pre>
|
||||
<p>The fields are:</p>
|
||||
<table>
|
||||
<tr>
|
||||
<th>Symbol</th><th>Meaning</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>@</td><td>The context to place the Todo in</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>~</td><td>The project to place the Todo in</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><</td><td>The due date for the Todo (may be 2 digits for day, 4 digits for month-day, or 6 digits for yeah-month-day)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>></td><td>The due date for the Todo (may be 2 digits for day, 4 digits for month-day, or 6 digits for yeah-month-day)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>#</td><td>A tag to apply to the Todo - may be used multiple times</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>*</td><td>Flag to star the Todo</td>
|
||||
</tr>
|
||||
</table>
|
||||
<p>All symbols are optional, and text up to the first symbol (or end of string) is used as the description of the todo</p>
|
||||
|
||||
<a name="google_gadget"> </a>
|
||||
<h2>Add Tracks as a Google Gmail gadget</h2>
|
||||
<p>
|
||||
|
|
|
|||
|
|
@ -28,4 +28,4 @@
|
|||
<% else -%><%= render :partial => "notes/notes_summary", :collection => @project.notes %>
|
||||
<% end -%>
|
||||
<h2><%= t('projects.settings') %></h2>
|
||||
<%= t('projects.state', :state => project.aasm_current_state.to_s) %>. <%= @project_default_context %>
|
||||
<%= t('projects.state', :state => project.aasm.current_state.to_s) %>. <%= @project_default_context %>
|
||||
|
|
|
|||
|
|
@ -1,11 +1,11 @@
|
|||
# TODO: is this dead code?
|
||||
page.select('#project_status .active span').each do |element|
|
||||
element.className = @project.aasm_current_state == :active ? 'active_state' : 'inactive_state'
|
||||
element.className = @project.aasm.current_state == :active ? 'active_state' : 'inactive_state'
|
||||
end
|
||||
page.select('#project_status .hidden span').each do |element|
|
||||
element.className = @project.aasm_current_state == :hidden ? 'active_state' : 'inactive_state'
|
||||
element.className = @project.aasm.current_state == :hidden ? 'active_state' : 'inactive_state'
|
||||
end
|
||||
page.select('#project_status .completed span').each do |element|
|
||||
element.className = @project.aasm_current_state == :completed ? 'active_state' : 'inactive_state'
|
||||
element.className = @project.aasm.current_state == :completed ? 'active_state' : 'inactive_state'
|
||||
end
|
||||
page.notify :notice, "Set project status to #{@project.aasm_current_state}", 5.0
|
||||
page.notify :notice, "Set project status to #{@project.aasm.current_state}", 5.0
|
||||
|
|
|
|||
|
|
@ -4,36 +4,42 @@
|
|||
<h2><Actions><%= t('common.actions') %></h2>
|
||||
|
||||
<form method="get" action="<%= edit_todo_path(@todo, :format => :m)%>">
|
||||
<button><%=t('todos.edit_action')%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<button><%=t('todos.edit_action')%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
</form>
|
||||
|
||||
<form method="post" action="<%=toggle_star_todo_path(@todo, :format=>:m)%>">
|
||||
<button><%=t('todos.star_action')%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<button><%=t('todos.star_action')%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<%= token_tag %>
|
||||
</form>
|
||||
|
||||
<form method="post" action="<%=toggle_check_todo_path(@todo, :format=>:m)%>">
|
||||
<button><%= t('todos.mark_complete')%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<button><%= t('todos.mark_complete')%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<%= token_tag %>
|
||||
</form>
|
||||
|
||||
<form method="post" action="<%=defer_todo_path(@todo, :format=>:m, :days => 1)%>">
|
||||
<button><%=t('todos.defer_x_days', :count => 1)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<button><%=t('todos.defer_x_days', :count => 1)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<%= token_tag %>
|
||||
</form>
|
||||
|
||||
<form method="post" action="<%=defer_todo_path(@todo, :format=>:m, :days => 2)%>">
|
||||
<button><%=t('todos.defer_x_days', :count => 2)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<button><%=t('todos.defer_x_days', :count => 2)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<%= token_tag %>
|
||||
</form>
|
||||
|
||||
<form method="post" action="<%=defer_todo_path(@todo, :format=>:m, :days => 3)%>">
|
||||
<button><%=t('todos.defer_x_days', :count => 3)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<button><%=t('todos.defer_x_days', :count => 3)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<%= token_tag %>
|
||||
</form>
|
||||
|
||||
<form method="post" action="<%=defer_todo_path(@todo, :format=>:m, :days => 7)%>">
|
||||
<button><%=t('todos.defer_x_days', :count => 7)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<button><%=t('todos.defer_x_days', :count => 7)%></button>
|
||||
<input type="hidden" name="_method" value="put" />
|
||||
<%= token_tag %>
|
||||
</form>
|
||||
|
|
|
|||
|
|
@ -68,5 +68,8 @@ module Tracksapp
|
|||
config.action_view.sanitized_allowed_protocols = 'onenote', 'message'
|
||||
|
||||
config.middleware.insert_after ActionDispatch::ParamsParser, ActionDispatch::XmlParamsParser
|
||||
|
||||
# if a locale is invalid, the Rails app will raise an error
|
||||
config.i18n.enforce_available_locales = true
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -471,6 +471,9 @@ en:
|
|||
project_completed: Completed actions in this project
|
||||
context_completed: Completed actions in this context
|
||||
tag_hidden: "Hidden actions tagged with '%{param}'"
|
||||
error:
|
||||
invalid_due_date: "Invalid due date"
|
||||
invalid_show_from_date: "Invalid show from date"
|
||||
completed_today: Completed today
|
||||
completed_rest_of_week: Completed in the rest of this week
|
||||
completed_rest_of_month: Completed in the rest of this month
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ class FixIncorrectlyHiddenTodos < ActiveRecord::Migration
|
|||
hidden_todos_without_project =
|
||||
Todo.where(:state => 'project_hidden', :project_id => nil)
|
||||
|
||||
active_projects = Project.where(:state => 'active')
|
||||
active_projects = Project.where(:state => 'active').select("id")
|
||||
hidden_todos_in_active_projects =
|
||||
Todo.where(:state => 'project_hidden').where("project_id IN (?)", active_projects)
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ There are two methods of downloading Tracks:
|
|||
# If you want to live on the edge, you can get the latest development version from GitHub using git (bear in mind that this may be less stable than the released versions):
|
||||
|
||||
bc. cd ~/Sites
|
||||
git clone git://github.com/tracksapp/tracks.git
|
||||
git clone https://github.com/TracksApp/tracks.git
|
||||
cd tracks
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ class PreferencesControllerTest < ActionController::TestCase
|
|||
|
||||
def setup
|
||||
super
|
||||
assert_equal "test", Rails.env
|
||||
assert_equal "change-me", Tracks::Config.salt
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ class ProjectsControllerTest < ActionController::TestCase
|
|||
login_as(:admin_user)
|
||||
xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"hidden"}
|
||||
todos.each do |t|
|
||||
assert_equal :project_hidden, t.reload().aasm_current_state
|
||||
assert_equal :project_hidden, t.reload().aasm.current_state
|
||||
end
|
||||
assert p.reload().hidden?
|
||||
end
|
||||
|
|
@ -60,7 +60,7 @@ class ProjectsControllerTest < ActionController::TestCase
|
|||
xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"hidden"}
|
||||
xhr :post, :update, :id => 1, "project"=>{"name"=>p.name, "description"=>p.description, "state"=>"active"}
|
||||
todos.each do |t|
|
||||
assert_equal :active, t.reload().aasm_current_state
|
||||
assert_equal :active, t.reload().aasm.current_state
|
||||
end
|
||||
assert p.reload().active?
|
||||
end
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ class RecurringTodosControllerTest < ActionController::TestCase
|
|||
xhr :post, :toggle_check, :id=>1, :_source_view=>""
|
||||
|
||||
recurring_todo_1 = RecurringTodo.find(1) # reload seems to not work
|
||||
assert recurring_todo_1.active?, "recurring todo should be active but is #{recurring_todo_1.aasm_current_state}"
|
||||
assert recurring_todo_1.active?, "recurring todo should be active but is #{recurring_todo_1.aasm.current_state}"
|
||||
|
||||
# by making active, a new todo should be created from the pattern
|
||||
assert_equal todo_count+1, Todo.count
|
||||
|
|
|
|||
2
test/fixtures/recurring_todos.yml
vendored
2
test/fixtures/recurring_todos.yml
vendored
|
|
@ -20,7 +20,7 @@ def two_weeks_hence
|
|||
end
|
||||
|
||||
def way_back
|
||||
Time.zone.local(2008,1,1)
|
||||
Time.zone.local(2008,1,1).to_s(:db)
|
||||
end
|
||||
|
||||
%>
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ class PreferenceTest < ActiveSupport::TestCase
|
|||
fixtures :users, :preferences
|
||||
|
||||
def setup
|
||||
assert_equal "test", ENV['RAILS_ENV']
|
||||
assert_equal "change-me", Tracks::Config.salt
|
||||
@admin_user = User.find(1)
|
||||
@other_user = User.find(2)
|
||||
|
|
|
|||
|
|
@ -48,36 +48,36 @@ class ProjectTest < ActiveSupport::TestCase
|
|||
# state machine
|
||||
|
||||
def test_project_initial_state_is_active
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert_equal :active, @timemachine.aasm.current_state
|
||||
assert @timemachine.active?
|
||||
end
|
||||
|
||||
def test_hide_project
|
||||
@timemachine.hide!
|
||||
assert_equal :hidden, @timemachine.aasm_current_state
|
||||
assert_equal :hidden, @timemachine.aasm.current_state
|
||||
assert @timemachine.hidden?
|
||||
end
|
||||
|
||||
def test_activate_project
|
||||
@timemachine.activate!
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert_equal :active, @timemachine.aasm.current_state
|
||||
assert @timemachine.active?
|
||||
end
|
||||
|
||||
def test_transition_to_another_state
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert_equal :active, @timemachine.aasm.current_state
|
||||
@timemachine.transition_to(:hidden)
|
||||
assert_equal :hidden, @timemachine.aasm_current_state
|
||||
assert_equal :hidden, @timemachine.aasm.current_state
|
||||
@timemachine.transition_to(:completed)
|
||||
assert_equal :completed, @timemachine.aasm_current_state
|
||||
assert_equal :completed, @timemachine.aasm.current_state
|
||||
@timemachine.transition_to(:active)
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert_equal :active, @timemachine.aasm.current_state
|
||||
end
|
||||
|
||||
def test_transition_to_same_state
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert_equal :active, @timemachine.aasm.current_state
|
||||
@timemachine.transition_to(:active)
|
||||
assert_equal :active, @timemachine.aasm_current_state
|
||||
assert_equal :active, @timemachine.aasm.current_state
|
||||
end
|
||||
|
||||
# other tests
|
||||
|
|
@ -95,7 +95,7 @@ class ProjectTest < ActiveSupport::TestCase
|
|||
def test_complete_project
|
||||
assert_nil @timemachine.completed_at
|
||||
@timemachine.complete!
|
||||
assert_equal :completed, @timemachine.aasm_current_state
|
||||
assert_equal :completed, @timemachine.aasm.current_state
|
||||
assert @timemachine.completed?
|
||||
assert_not_nil @timemachine.completed_at, "completed_at not expected to be nil"
|
||||
assert_in_delta Time.now, @timemachine.completed_at, 1
|
||||
|
|
@ -150,7 +150,7 @@ class ProjectTest < ActiveSupport::TestCase
|
|||
first_todo = @moremoney.todos[0]
|
||||
first_todo.show_from = Time.zone.now + 1.week
|
||||
first_todo.save!
|
||||
assert_equal :deferred, @moremoney.todos[0].aasm_current_state
|
||||
assert_equal :deferred, @moremoney.todos[0].aasm.current_state
|
||||
|
||||
assert_equal 1, @moremoney.todos.deferred.count
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
require 'date'
|
||||
require 'test/unit'
|
||||
require 'active_support/core_ext/object/blank'
|
||||
require_relative '../../app/services/rich_message_extractor.rb'
|
||||
|
|
@ -5,11 +6,15 @@ require_relative '../../app/services/rich_message_extractor.rb'
|
|||
class RichMessageExtractorTest < Test::Unit::TestCase
|
||||
|
||||
def test_message_with_all_options
|
||||
message = "ohai@some-context>in-this-project"
|
||||
message = "ohai@some-context~this-project>131012<131014#tag1#tag2*"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal "ohai", extractor.description
|
||||
assert_equal "some-context", extractor.context
|
||||
assert_equal "in-this-project", extractor.project
|
||||
assert_equal "this-project", extractor.project
|
||||
assert_equal "2013-10-12", extractor.show_from.to_s
|
||||
assert_equal "2013-10-14", extractor.due.to_s
|
||||
assert_equal ["tag1","tag2"], extractor.tags
|
||||
assert extractor.starred?
|
||||
end
|
||||
|
||||
def test_message_without_project
|
||||
|
|
@ -20,12 +25,12 @@ class RichMessageExtractorTest < Test::Unit::TestCase
|
|||
assert_equal nil, extractor.project
|
||||
end
|
||||
|
||||
def test_message_without_project
|
||||
message = " ohai @ some-context"
|
||||
def test_message_without_context
|
||||
message = " ohai ~ some-project"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal "ohai", extractor.description
|
||||
assert_equal "some-context", extractor.context
|
||||
assert_equal nil, extractor.project
|
||||
assert_equal "", extractor.context
|
||||
assert_equal "some-project", extractor.project
|
||||
end
|
||||
|
||||
def test_message_without_project_or_context
|
||||
|
|
@ -52,4 +57,52 @@ class RichMessageExtractorTest < Test::Unit::TestCase
|
|||
assert_equal nil, extractor.project
|
||||
end
|
||||
|
||||
def test_message_with_tags
|
||||
message = "some tags#tag 1#tag2"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal ["tag 1","tag2"], extractor.tags
|
||||
end
|
||||
|
||||
def test_message_with_no_tags
|
||||
message = "no tags"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal nil, extractor.tags
|
||||
end
|
||||
|
||||
def test_message_with_due_date
|
||||
message = "datetest<141013"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal "2014-10-13", extractor.due.to_s
|
||||
end
|
||||
|
||||
def test_message_with_no_due_date
|
||||
message = "no date"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal nil, extractor.due
|
||||
end
|
||||
|
||||
def test_message_with_show_from
|
||||
message = "datetest>161013"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal "2016-10-13", extractor.show_from.to_s
|
||||
end
|
||||
|
||||
def test_message_with_no_show_from
|
||||
message = "no tickler"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert_equal nil, extractor.show_from
|
||||
end
|
||||
|
||||
def test_message_with_star
|
||||
message = "star test*"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
assert extractor.starred?
|
||||
end
|
||||
|
||||
def test_message_with_no_star
|
||||
message = "no star test"
|
||||
extractor = RichMessageExtractor.new(message)
|
||||
refute extractor.starred?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -18,4 +18,23 @@ class TodoFromRichMessageTest < ActiveSupport::TestCase
|
|||
assert_equal default_context_id, new_todo.context_id
|
||||
end
|
||||
|
||||
def test_from_rich_message_adds_all_fields
|
||||
user = @completed.user
|
||||
context = Context.create(:name => 'context')
|
||||
project = Project.create(:name => 'project')
|
||||
message = "description@context~project>131014<131017#tag1#tag2*"
|
||||
builder = TodoFromRichMessage.new(user, context.id, message, "notes")
|
||||
new_todo = builder.construct
|
||||
|
||||
assert_not_nil new_todo
|
||||
assert_equal "description", new_todo.description
|
||||
assert_equal "notes", new_todo.notes
|
||||
assert_equal context.id, new_todo.context_id
|
||||
assert_equal project.id, new_todo.project_id
|
||||
assert_equal "2013-10-14 00:00:00 +0100", new_todo.show_from.to_s
|
||||
assert_equal "2013-10-17 00:00:00 +0100", new_todo.due.to_s
|
||||
assert_equal "starred, tag1, tag2", new_todo.tags.to_s
|
||||
assert new_todo.starred?
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -97,10 +97,10 @@ class TodoTest < ActiveSupport::TestCase
|
|||
|
||||
def test_defer_an_existing_todo
|
||||
@not_completed2
|
||||
assert_equal :active, @not_completed2.aasm_current_state
|
||||
assert_equal :active, @not_completed2.aasm.current_state
|
||||
@not_completed2.show_from = Time.zone.now + 1.week
|
||||
assert @not_completed2.save, "should have saved successfully" + @not_completed2.errors.to_xml
|
||||
assert_equal :deferred, @not_completed2.aasm_current_state
|
||||
assert_equal :deferred, @not_completed2.aasm.current_state
|
||||
end
|
||||
|
||||
def test_create_a_new_deferred_todo
|
||||
|
|
@ -110,41 +110,41 @@ class TodoTest < ActiveSupport::TestCase
|
|||
todo.context_id = 1
|
||||
todo.description = 'foo'
|
||||
assert todo.save, "should have saved successfully" + todo.errors.to_xml
|
||||
assert_equal :deferred, todo.aasm_current_state
|
||||
assert_equal :deferred, todo.aasm.current_state
|
||||
end
|
||||
|
||||
def test_create_a_new_deferred_todo_by_passing_attributes
|
||||
user = users(:other_user)
|
||||
todo = user.todos.build(:show_from => next_week, :context_id => 1, :description => 'foo')
|
||||
assert todo.save, "should have saved successfully" + todo.errors.to_xml
|
||||
assert_equal :deferred, todo.aasm_current_state
|
||||
assert_equal :deferred, todo.aasm.current_state
|
||||
end
|
||||
|
||||
def test_toggle_completion
|
||||
t = @not_completed1
|
||||
assert_equal :active, t.aasm_current_state
|
||||
assert_equal :active, t.aasm.current_state
|
||||
t.toggle_completion!
|
||||
assert_equal :completed, t.aasm_current_state
|
||||
assert_equal :completed, t.aasm.current_state
|
||||
t.toggle_completion!
|
||||
assert_equal :active, t.aasm_current_state
|
||||
assert_equal :active, t.aasm.current_state
|
||||
end
|
||||
|
||||
def test_toggle_completion_with_show_from_in_future
|
||||
t = @not_completed1
|
||||
t.show_from= 1.week.from_now
|
||||
t.save!
|
||||
assert_equal :deferred, t.aasm_current_state
|
||||
assert_equal :deferred, t.aasm.current_state
|
||||
t.toggle_completion!
|
||||
assert_equal :completed, t.aasm_current_state
|
||||
assert_equal :completed, t.aasm.current_state
|
||||
end
|
||||
|
||||
def test_toggle_completion_with_show_from_in_past
|
||||
t = @not_completed1
|
||||
t.update_attribute(:show_from, 1.week.ago)
|
||||
assert_equal :active, t.aasm_current_state
|
||||
assert_equal :active, t.aasm.current_state
|
||||
|
||||
assert t.toggle_completion!, "shoud be able to mark active todo complete even if show_from is set in the past"
|
||||
assert_equal :completed, t.aasm_current_state
|
||||
assert_equal :completed, t.aasm.current_state
|
||||
end
|
||||
|
||||
def test_activate_also_saves
|
||||
|
|
@ -225,7 +225,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
t.context_id = 1
|
||||
t.save!
|
||||
t.reload
|
||||
assert_equal :active, t.aasm_current_state
|
||||
assert_equal :active, t.aasm.current_state
|
||||
end
|
||||
|
||||
def test_initial_state_is_deferred_when_show_from_in_future
|
||||
|
|
@ -236,7 +236,7 @@ class TodoTest < ActiveSupport::TestCase
|
|||
t.show_from = 1.week.from_now.to_date
|
||||
t.save!
|
||||
t.reload
|
||||
assert_equal :deferred, t.aasm_current_state
|
||||
assert_equal :deferred, t.aasm.current_state
|
||||
end
|
||||
|
||||
def test_todo_is_not_starred
|
||||
|
|
|
|||
|
|
@ -1,10 +1,10 @@
|
|||
require File.expand_path(File.dirname(__FILE__) + '/../test_helper')
|
||||
require 'timecop'
|
||||
|
||||
class UserTest < ActiveSupport::TestCase
|
||||
fixtures :users, :preferences, :projects, :contexts, :todos, :recurring_todos
|
||||
|
||||
def setup
|
||||
assert_equal "test", ENV['RAILS_ENV']
|
||||
assert_equal "change-me", Tracks::Config.salt
|
||||
@admin_user = User.find(1)
|
||||
@other_user = User.find(2)
|
||||
|
|
@ -374,16 +374,16 @@ class UserTest < ActiveSupport::TestCase
|
|||
|
||||
# test group counts for projects and contexts
|
||||
project_counts = u.todos.count_by_group(:project_id)
|
||||
assert_equal "6,3,4,4", project_counts.map{|pc|pc[1]}.join(",")
|
||||
assert_equal [6,3,4,4], project_counts.values
|
||||
|
||||
context_counts = u.todos.count_by_group(:context_id)
|
||||
assert_equal "7,3,1,3,1,2", context_counts.map{|cc|cc[1]}.join(",")
|
||||
assert_equal [7,3,1,3,1,2], context_counts.values
|
||||
|
||||
# add a todo to the first context and check that the count is increased
|
||||
u.todos.create!(:description => "yet another todo", :context => u.contexts.first)
|
||||
|
||||
context_counts = u.todos.reload.count_by_group(:context_id)
|
||||
assert_equal "8,3,1,3,1,2", context_counts.map{|cc|cc[1]}.join(",")
|
||||
assert_equal [8,3,1,3,1,2], context_counts.values
|
||||
end
|
||||
|
||||
protected
|
||||
|
|
@ -393,4 +393,4 @@ class UserTest < ActiveSupport::TestCase
|
|||
User.create({ :login => 'quire', :password => 'quire', :password_confirmation => 'quire' }.merge(options))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue