todoist 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +20 -0
- data/README +22 -0
- data/Rakefile +38 -4
- data/bin/todoist +91 -0
- data/lib/todoist.rb +4 -16
- data/lib/todoist/base.rb +38 -0
- data/lib/todoist/project.rb +126 -0
- data/lib/todoist/task.rb +252 -0
- data/spec/spec_helper.rb +2 -10
- data/spec/todoist_spec.rb +4 -7
- metadata +42 -56
- data/History.txt +0 -4
- data/License.txt +0 -20
- data/Manifest.txt +0 -30
- data/README.txt +0 -55
- data/config/hoe.rb +0 -73
- data/config/requirements.rb +0 -15
- data/lib/todoist/connection.rb +0 -109
- data/lib/todoist/errors.rb +0 -6
- data/lib/todoist/version.rb +0 -9
- data/script/console +0 -10
- data/script/destroy +0 -14
- data/script/generate +0 -14
- data/script/txt2html +0 -82
- data/setup.rb +0 -1585
- data/spec/spec.opts +0 -1
- data/tasks/deployment.rake +0 -34
- data/tasks/environment.rake +0 -7
- data/tasks/rspec.rake +0 -21
- data/tasks/website.rake +0 -17
- data/test/test_helper.rb +0 -2
- data/test/test_todoist.rb +0 -11
- data/website/index.html +0 -11
- data/website/index.txt +0 -81
- data/website/javascripts/rounded_corners_lite.inc.js +0 -285
- data/website/stylesheets/screen.css +0 -138
- data/website/template.html.erb +0 -48
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2008-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009-2009 Jonathan Stott
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
todoist
|
2
|
+
=======
|
3
|
+
|
4
|
+
The todoist gem is intended to facilitate access to the todoist (http://todoist.com)
|
5
|
+
task management service, offering methods to directly query the API and also
|
6
|
+
convinient wrapper objects around the responses.
|
7
|
+
|
8
|
+
|
9
|
+
example
|
10
|
+
-------
|
11
|
+
|
12
|
+
|
13
|
+
Todoist::Base.setup(api_token)
|
14
|
+
|
15
|
+
Todoist::Task.all.each do |task|
|
16
|
+
puts task
|
17
|
+
end
|
18
|
+
|
19
|
+
COPYRIGHT
|
20
|
+
=========
|
21
|
+
|
22
|
+
Copyright (c) 2008 Jonathan Stott. See LICENSE for details.
|
data/Rakefile
CHANGED
@@ -1,4 +1,38 @@
|
|
1
|
-
require '
|
2
|
-
require '
|
3
|
-
|
4
|
-
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = "todoist"
|
9
|
+
s.summary = "a library for interacting with the Todoist public API"
|
10
|
+
s.email = "jonathan.stott@gmail.com"
|
11
|
+
s.homepage = "http://github.com/namelessjon/todoist"
|
12
|
+
s.description = "The todoist gem offers convinience methods and wrappers for the todoist list management service, easing retrival and parsing of the responses. It also offers a simple command-line client."
|
13
|
+
s.authors = ["Jonathan Stott"]
|
14
|
+
s.files = FileList["lib/**/*.rb", "spec/**/*.rb", 'Rakefile', "[A-Z]+"]
|
15
|
+
s.add_dependency('highline', '~> 1.5')
|
16
|
+
s.add_dependency('thor', '~> 0.9')
|
17
|
+
s.add_dependency('httparty', '~> 0.3')
|
18
|
+
end
|
19
|
+
Jeweler::GemcutterTasks.new
|
20
|
+
rescue LoadError
|
21
|
+
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
22
|
+
end
|
23
|
+
|
24
|
+
Rake::TestTask.new(:spec) do |t|
|
25
|
+
t.libs << 'lib'
|
26
|
+
t.pattern = 'spec/**/*_spec.rb'
|
27
|
+
t.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
Rake::RDocTask.new do |rdoc|
|
31
|
+
rdoc.rdoc_dir = 'rdoc'
|
32
|
+
rdoc.title = 'Todoist'
|
33
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
34
|
+
rdoc.rdoc_files.include('README*')
|
35
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
36
|
+
end
|
37
|
+
|
38
|
+
task :default => :spec
|
data/bin/todoist
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'highline'
|
3
|
+
|
4
|
+
HighLine.track_eof = false
|
5
|
+
|
6
|
+
dir = File.dirname(__FILE__)
|
7
|
+
require File.join(dir, '..', 'lib', 'todoist')
|
8
|
+
|
9
|
+
class TodoistCLI < Thor
|
10
|
+
|
11
|
+
desc "tasks", "list of projects with uncompleted tasks, and their tasks"
|
12
|
+
def tasks(name=nil)
|
13
|
+
setup_todoist_base
|
14
|
+
|
15
|
+
Todoist::Project.all.each do |project|
|
16
|
+
next if name and project.name !~ /#{name}/
|
17
|
+
|
18
|
+
if project.task_count > 0
|
19
|
+
print_project(project)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
desc "complete", "Completes the task with the given content"
|
25
|
+
method_options :all => :boolean
|
26
|
+
def complete(content)
|
27
|
+
setup_todoist_base
|
28
|
+
|
29
|
+
@h = HighLine.new
|
30
|
+
|
31
|
+
to_complete = []
|
32
|
+
Todoist::Task.all.each do |task|
|
33
|
+
next if task.content !~ /#{content}/
|
34
|
+
to_complete << task
|
35
|
+
end
|
36
|
+
|
37
|
+
tasks = []
|
38
|
+
if to_complete.size > 1 and !options[:all]
|
39
|
+
@h.say("Choose tasks to delete:")
|
40
|
+
to_complete.each do |task|
|
41
|
+
if @h.agree("Delete #{task} (#{task.project})?")
|
42
|
+
tasks << task
|
43
|
+
end
|
44
|
+
end
|
45
|
+
else
|
46
|
+
tasks = to_complete
|
47
|
+
end
|
48
|
+
|
49
|
+
Todoist::Task.complete(tasks)
|
50
|
+
end
|
51
|
+
|
52
|
+
desc "overdue", "Fetch all overdue tasks"
|
53
|
+
def overdue
|
54
|
+
setup_todoist_base
|
55
|
+
Todoist::Task.overdue.each do |task|
|
56
|
+
puts task
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
def print_project(project)
|
62
|
+
puts project
|
63
|
+
project.tasks.each do |task|
|
64
|
+
next if task.complete?
|
65
|
+
print " " * (task.indent.to_i - 1)
|
66
|
+
print (task.content =~ /\* /) ? '' : '- '
|
67
|
+
puts task
|
68
|
+
end
|
69
|
+
puts ""
|
70
|
+
end
|
71
|
+
|
72
|
+
def setup_todoist_base
|
73
|
+
if File.file?(File.expand_path('~/.todoistrc'))
|
74
|
+
require 'yaml'
|
75
|
+
conf = YAML.load_file(File.expand_path('~/.todoistrc'))
|
76
|
+
Todoist::Base.setup(conf['token'], conf['premium'])
|
77
|
+
else
|
78
|
+
puts <<-eos
|
79
|
+
You need to setup ~/.todoistrc, for example:
|
80
|
+
token: 91b1ce9e153fc5390ac3db4f0ded9f31a1a7ba23 # use your api key
|
81
|
+
premium: false # if this is true, ssl will be used.
|
82
|
+
eos
|
83
|
+
exit(1)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
TodoistCLI.start
|
90
|
+
|
91
|
+
# vim: set ft=ruby:
|
data/lib/todoist.rb
CHANGED
@@ -1,20 +1,8 @@
|
|
1
|
-
$:.unshift(File.dirname(__FILE__)) unless
|
2
|
-
$:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
|
3
|
-
|
4
1
|
module Todoist
|
5
|
-
|
6
2
|
end
|
7
3
|
|
8
|
-
|
9
|
-
require 'json'
|
10
|
-
rescue LoadError
|
11
|
-
require 'rubygems'
|
12
|
-
require 'json'
|
13
|
-
end
|
4
|
+
dir = File.dirname(__FILE__)
|
14
5
|
|
15
|
-
require '
|
16
|
-
require '
|
17
|
-
require '
|
18
|
-
require 'todoist/errors'
|
19
|
-
require 'todoist/connection'
|
20
|
-
require 'todoist/project'
|
6
|
+
require File.join(dir, 'todoist', 'base')
|
7
|
+
require File.join(dir, 'todoist', 'project')
|
8
|
+
require File.join(dir, 'todoist', 'task')
|
data/lib/todoist/base.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'json'
|
3
|
+
module Todoist
|
4
|
+
##
|
5
|
+
# The Todoist::Base class is responsible for making all queries to the
|
6
|
+
# todoist web API.
|
7
|
+
class Base
|
8
|
+
include HTTParty
|
9
|
+
format :json
|
10
|
+
|
11
|
+
##
|
12
|
+
# Sets up the Todoist::Base class for making requests, setting the API key
|
13
|
+
# and if the account is a premium one or not.
|
14
|
+
def self.setup(token, premium = false)
|
15
|
+
self.default_params :token => token
|
16
|
+
@@premium = premium
|
17
|
+
set_base_uri
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
def self.set_base_uri
|
22
|
+
if premium?
|
23
|
+
base_uri 'https://todoist.com/API'
|
24
|
+
else
|
25
|
+
base_uri 'http://todoist.com/API'
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.premium?
|
30
|
+
(@@premium) ? true : false
|
31
|
+
end
|
32
|
+
|
33
|
+
def id_array(ids)
|
34
|
+
ids.flatten.map {|i| i.to_i }.to_json
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
module Todoist
|
2
|
+
##
|
3
|
+
# Project
|
4
|
+
#
|
5
|
+
# A todoist project.
|
6
|
+
class Project
|
7
|
+
attr_reader :name, :id, :user_id, :color, :collapsed, :order, :indent
|
8
|
+
|
9
|
+
##
|
10
|
+
# Get all projects
|
11
|
+
#
|
12
|
+
# Fetches all the user's todist projects.
|
13
|
+
#
|
14
|
+
# @return [Array] An Array of todoist project instances.
|
15
|
+
def self.all
|
16
|
+
projects = []
|
17
|
+
Base.get('/getProjects').each do |project|
|
18
|
+
projects << new_from_api_request(project)
|
19
|
+
end
|
20
|
+
projects
|
21
|
+
end
|
22
|
+
|
23
|
+
##
|
24
|
+
# Get a project
|
25
|
+
#
|
26
|
+
# Fetches a todoist project
|
27
|
+
#
|
28
|
+
# @param [Integer,Todoist::Project] id The id, or project, to fetch
|
29
|
+
#
|
30
|
+
# @return [Todoist::Project] The fetched project.
|
31
|
+
def self.get(id)
|
32
|
+
new_from_api_request(get_project(id))
|
33
|
+
end
|
34
|
+
|
35
|
+
##
|
36
|
+
# Create a new project
|
37
|
+
#
|
38
|
+
# Creates a new Todoist project.
|
39
|
+
#
|
40
|
+
# @param [String] name The name of the project
|
41
|
+
#
|
42
|
+
# @param [Hash] parameters The other parameters which make up the project.
|
43
|
+
#
|
44
|
+
# @return [Todoist::Project] The new todoist project.
|
45
|
+
def initialize(name, parameters={})
|
46
|
+
@name = name
|
47
|
+
@id = parameters['id']
|
48
|
+
@user_id = parameters['user_id']
|
49
|
+
@color = parameters['color']
|
50
|
+
@collapsed = parameters['collapsed']
|
51
|
+
@order = parameters['item_order']
|
52
|
+
@count = parameters['cache_count']
|
53
|
+
@indent = parameters['indent']
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
def to_s
|
58
|
+
"#{name}"
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_i
|
62
|
+
id
|
63
|
+
end
|
64
|
+
|
65
|
+
def inspect
|
66
|
+
"<Project:#{name}:#{id}:#{task_count}:user_id=#{user_id} color='#{color}' collapsed=#{collapsed?} order=#{order} indent=#{indent}>"
|
67
|
+
end
|
68
|
+
|
69
|
+
def collapsed?
|
70
|
+
(collapsed == 1) ? true : false
|
71
|
+
end
|
72
|
+
|
73
|
+
|
74
|
+
##
|
75
|
+
# The task count
|
76
|
+
#
|
77
|
+
# The number of tasks a project has, according to its cache_count when it was fetched
|
78
|
+
#
|
79
|
+
# @return [Integer] The number of tasks this project has
|
80
|
+
def task_count
|
81
|
+
@count
|
82
|
+
end
|
83
|
+
|
84
|
+
##
|
85
|
+
# Get uncompleted tasks for the project
|
86
|
+
#
|
87
|
+
# @return [Array] An Array of Todoist::Tasks
|
88
|
+
def tasks
|
89
|
+
Task.uncompleted(self)
|
90
|
+
end
|
91
|
+
|
92
|
+
##
|
93
|
+
# Get completed tasks for the project
|
94
|
+
#
|
95
|
+
# @return [Array] An Array of completed Todoist::Tasks
|
96
|
+
def completed_tasks
|
97
|
+
Task.completed(self)
|
98
|
+
end
|
99
|
+
|
100
|
+
##
|
101
|
+
# Add task
|
102
|
+
#
|
103
|
+
# Adds a task to the project.
|
104
|
+
#
|
105
|
+
# @param [String] content The content of the new task
|
106
|
+
#
|
107
|
+
# @param [Hash] opts The options for the new task
|
108
|
+
#
|
109
|
+
# @return [Todoist::Task] The new task.
|
110
|
+
def add_task(content, opts={})
|
111
|
+
Task.new(content, self, opts).save
|
112
|
+
end
|
113
|
+
|
114
|
+
private
|
115
|
+
|
116
|
+
def self.new_from_api_request(project)
|
117
|
+
name = project.delete('name')
|
118
|
+
new(name, project)
|
119
|
+
end
|
120
|
+
|
121
|
+
def self.get_project(id)
|
122
|
+
Base.get('/getProject', :query => {:project_id => id.to_i })
|
123
|
+
end
|
124
|
+
|
125
|
+
end
|
126
|
+
end
|
data/lib/todoist/task.rb
ADDED
@@ -0,0 +1,252 @@
|
|
1
|
+
require 'time'
|
2
|
+
module Todoist
|
3
|
+
##
|
4
|
+
# Todoist Task
|
5
|
+
#
|
6
|
+
# A todoist task.
|
7
|
+
class Task
|
8
|
+
attr_accessor :content, :priority, :task_details, :project_id
|
9
|
+
attr_reader :date, :id
|
10
|
+
##
|
11
|
+
# Get tasks for a project
|
12
|
+
#
|
13
|
+
# Retrieves all uncompleted tasks from the todoist service for the project id.
|
14
|
+
#
|
15
|
+
# @param [Integer,Todoist::Project] project The project to get tasks for
|
16
|
+
#
|
17
|
+
# @return [Array] An array of todoist tasks.
|
18
|
+
def self.uncompleted(project)
|
19
|
+
make_tasks(Base.get('/getUncompletedItems', :query => { :project_id => project.to_i }))
|
20
|
+
end
|
21
|
+
|
22
|
+
##
|
23
|
+
# Get completed tasks for project
|
24
|
+
#
|
25
|
+
# Retrieves completed tasks from the todoist service for the project id.
|
26
|
+
#
|
27
|
+
# @param [Integer,Todoist::Project] project The project to get tasks for
|
28
|
+
#
|
29
|
+
# @return [Array] An array of todoist tasks.
|
30
|
+
def self.completed(project)
|
31
|
+
make_tasks(Base.get('/getCompletedItems', :query => { :project_id => project.to_i }))
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Complete tasks
|
36
|
+
#
|
37
|
+
# Completes a list of tasks
|
38
|
+
#
|
39
|
+
# @param [Array,Integer,Todist::Task] ids A list of tasks to complete.
|
40
|
+
def self.complete(*ids)
|
41
|
+
make_tasks(Base.get('/completeItems', :query => {:ids => id_array(ids)}))
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Get Tasks by ID
|
46
|
+
#
|
47
|
+
# Retrives a list of tasks from the todoist service.
|
48
|
+
#
|
49
|
+
# @param [Array,Integer,Todist::Task] ids A list of tasks to retrieve
|
50
|
+
#
|
51
|
+
# @return [Array] An array of Todist::Tasks
|
52
|
+
def self.get(*ids)
|
53
|
+
make_tasks(Base.get('/getItemsById', :query => {:ids => id_array(ids)}))
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Get all tasks
|
58
|
+
#
|
59
|
+
# Retrieves all the uncompleted tasks
|
60
|
+
#
|
61
|
+
# @return [Array] An array of Todist::Tasks
|
62
|
+
def self.all
|
63
|
+
query('viewall')['viewall']
|
64
|
+
end
|
65
|
+
|
66
|
+
##
|
67
|
+
# Get overdue tasks
|
68
|
+
#
|
69
|
+
# Retrieves all the overdue tasks
|
70
|
+
#
|
71
|
+
# @return [Array] An array of overdue Todist::Tasks
|
72
|
+
def self.overdue
|
73
|
+
query('overdue')['overdue']
|
74
|
+
end
|
75
|
+
|
76
|
+
|
77
|
+
##
|
78
|
+
# Query
|
79
|
+
#
|
80
|
+
# Use the task query API to get back several arrays of tasks.
|
81
|
+
#
|
82
|
+
# @param [String,Array] query A query or a list of queries to perform
|
83
|
+
#
|
84
|
+
# @return [Hash] a hash keyed on query, containing arrays of tasks.
|
85
|
+
#
|
86
|
+
# Allowed queries
|
87
|
+
# viewall:: All tasks
|
88
|
+
# overdue:: All overdue tasks
|
89
|
+
# p[123]:: All tasks of priority 1, 2 ,3
|
90
|
+
def self.query(*queries)
|
91
|
+
query = '["' + queries.flatten.map { |q| q.to_s }.join('","') + '"]'
|
92
|
+
results = {}
|
93
|
+
response = Base.get('/query', :query => { :queries => query })
|
94
|
+
|
95
|
+
response.each do |q|
|
96
|
+
if q['type'] == 'viewall'
|
97
|
+
tasks = []
|
98
|
+
q['data'].each do |stuff|
|
99
|
+
tasks << make_tasks(stuff['uncompleted'])
|
100
|
+
end
|
101
|
+
results[q['type']] = tasks.flatten
|
102
|
+
else
|
103
|
+
results[q['type']] = make_tasks(q['data'])
|
104
|
+
end
|
105
|
+
end
|
106
|
+
results
|
107
|
+
end
|
108
|
+
|
109
|
+
##
|
110
|
+
# Create a new task
|
111
|
+
#
|
112
|
+
# @param [String] content The content of the new task.
|
113
|
+
#
|
114
|
+
# @param [Integer,Todoist::Project] project The project to create the new task in
|
115
|
+
#
|
116
|
+
# @param [Hash] opts Optional priority and due date for creation.
|
117
|
+
def self.create(content, project, opts={})
|
118
|
+
query = {:project_id => project.to_i, :content => content.to_s }
|
119
|
+
query['priority'] = opts.delete('priority') if opts.has_key?('priority')
|
120
|
+
query['date_string'] = opts.delete('date_string') if opts.has_key?('date_string')
|
121
|
+
|
122
|
+
new_from_api(Base.get('/addItem', :query => query))
|
123
|
+
end
|
124
|
+
|
125
|
+
##
|
126
|
+
# Updates a task
|
127
|
+
#
|
128
|
+
# @param [String] content The new content of the task.
|
129
|
+
#
|
130
|
+
# @param [Integer,Todoist::Task] id The task to update
|
131
|
+
#
|
132
|
+
# @param [Hash] opts Optional priority and due date for creation.
|
133
|
+
def self.update(content, id, opts={})
|
134
|
+
query = {:id => project.to_i, :content => content.to_s }
|
135
|
+
query['priority'] = opts.delete('priority') if opts.has_key?('priority')
|
136
|
+
query['date_string'] = opts.delete('date_string') if opts.has_key?('date_string')
|
137
|
+
|
138
|
+
new_from_api(Base.get('/updateItem', :query => query))
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
|
143
|
+
def initialize(content, project_id, d={})
|
144
|
+
@content = content
|
145
|
+
@project_id = project_id.to_i
|
146
|
+
@date = d.delete('date') || d.delete('date_string')
|
147
|
+
@priority = d.delete('priority')
|
148
|
+
@id = d.delete('id')
|
149
|
+
@task_details = d
|
150
|
+
end
|
151
|
+
|
152
|
+
##
|
153
|
+
# Is the task complete
|
154
|
+
def complete?
|
155
|
+
(@task_details['in_history'] == 1) ? true : false
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
##
|
160
|
+
# Complete
|
161
|
+
#
|
162
|
+
# Completes the todoist task
|
163
|
+
def complete
|
164
|
+
self.class.complete(self) unless complete?
|
165
|
+
@task_details['in_history'] = 1
|
166
|
+
end
|
167
|
+
|
168
|
+
##
|
169
|
+
# Is the task overdue?
|
170
|
+
def overdue?
|
171
|
+
return false unless due_date
|
172
|
+
Time.now > Time.parse(due_date)
|
173
|
+
end
|
174
|
+
|
175
|
+
##
|
176
|
+
# Project
|
177
|
+
#
|
178
|
+
# Retreives the project for the task
|
179
|
+
def project
|
180
|
+
Project.get(project_id)
|
181
|
+
end
|
182
|
+
|
183
|
+
##
|
184
|
+
# Saves the task
|
185
|
+
#
|
186
|
+
# Save the task, either creating a new task on the todoist service, or
|
187
|
+
# updating a previously retrieved task with new content, priority etc.
|
188
|
+
def save
|
189
|
+
opts = {}
|
190
|
+
opts['priority'] = priority if priority
|
191
|
+
opts['date_string'] = date if date
|
192
|
+
# if we don't have an id, then we can assume this is a new task.
|
193
|
+
unless (task_details.has_key?('id'))
|
194
|
+
result = self.class.create(self.content, self.project_id, opts)
|
195
|
+
else
|
196
|
+
result = self.class.update(self.content, self.id, opts)
|
197
|
+
end
|
198
|
+
|
199
|
+
self.content = result.content
|
200
|
+
self.project_id = result.project_id
|
201
|
+
self.task_details = result.task_details
|
202
|
+
self
|
203
|
+
end
|
204
|
+
|
205
|
+
|
206
|
+
|
207
|
+
def to_s
|
208
|
+
@content
|
209
|
+
end
|
210
|
+
|
211
|
+
def to_i
|
212
|
+
id
|
213
|
+
end
|
214
|
+
|
215
|
+
def inspect
|
216
|
+
"<Todoist::Task:#{content}:#{id}:#{project_id}:#{task_details.inspect}>"
|
217
|
+
end
|
218
|
+
|
219
|
+
def method_missing(*args, &block)
|
220
|
+
# the method name
|
221
|
+
m = args.shift
|
222
|
+
if @task_details.has_key?(m.to_s)
|
223
|
+
return @task_details[m.to_s]
|
224
|
+
else
|
225
|
+
raise NoMethodError, "undefined method `#{m}' for #{self.inspect}"
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
private
|
230
|
+
|
231
|
+
def self.new_from_api(task)
|
232
|
+
content = task.delete('content')
|
233
|
+
project_id = task.delete('project_id')
|
234
|
+
new(content, project_id, task)
|
235
|
+
end
|
236
|
+
|
237
|
+
def self.make_tasks(tasks)
|
238
|
+
new_tasks = []
|
239
|
+
tasks.each do |task|
|
240
|
+
new_tasks << new_from_api(task)
|
241
|
+
end
|
242
|
+
new_tasks
|
243
|
+
end
|
244
|
+
|
245
|
+
def self.id_array(*ids)
|
246
|
+
"[" + ids.flatten.map { |q| q.to_i }.join(",") + "]"
|
247
|
+
end
|
248
|
+
|
249
|
+
|
250
|
+
# {"due_date": null, "collapsed": 0, "labels": [], "is_dst": 0, "has_notifications": 0, "checked": 0, "indent": 1, "children": null, "content": "Finish this gem", "user_id": 34615, "mm_offset": 0, "in_history": 0, "id": 4152190, "priority": 4, "item_order": 1, "project_id": 528294, "chains": null, "date_string": ""}
|
251
|
+
end
|
252
|
+
end
|