taskwarrior-web 1.0.7 → 1.0.8

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,3 +1,7 @@
1
+ ## v1.0.8 (11/18/12)
2
+
3
+ * Better layout for projects listing page.
4
+
1
5
  ## v1.0.7 (11/17/12)
2
6
 
3
7
  * Moving `task` version parsing to Verionomy library. Should be much more
data/Rakefile CHANGED
@@ -4,4 +4,12 @@ require 'rspec/core/rake_task'
4
4
  Bundler::GemHelper.install_tasks
5
5
  RSpec::Core::RakeTask.new(:spec)
6
6
 
7
+ desc 'Uninstalls the current version of taskwarrior-web'
8
+ task :uninstall do
9
+ `gem uninstall -x taskwarrior-web`
10
+ end
7
11
 
12
+ desc 'Reloads the gem (useful for local development)'
13
+ task :refresh => [:uninstall, :install] do
14
+ `task-web -F`
15
+ end
@@ -3,6 +3,15 @@ $:.unshift(File.dirname(__FILE__)) unless
3
3
 
4
4
  require 'rubygems'
5
5
 
6
- require 'taskwarrior-web/app'
7
- require 'taskwarrior-web/task'
8
- require 'taskwarrior-web/config'
6
+ module TaskwarriorWeb
7
+ autoload :App, 'taskwarrior-web/app'
8
+ autoload :Helpers, 'taskwarrior-web/helpers'
9
+ autoload :Task, 'taskwarrior-web/task'
10
+ autoload :Config, 'taskwarrior-web/config'
11
+ autoload :CommandBuilder, 'taskwarrior-web/command_builder'
12
+ autoload :Command, 'taskwarrior-web/command'
13
+ autoload :Runner, 'taskwarrior-web/runner'
14
+ autoload :Parser, 'taskwarrior-web/parser'
15
+
16
+ class UnrecognizedTaskVersion < Exception; end
17
+ end
@@ -4,145 +4,141 @@ require 'sinatra'
4
4
  require 'erb'
5
5
  require 'time'
6
6
  require 'rinku'
7
- require 'taskwarrior-web/config'
8
- require 'taskwarrior-web/helpers'
9
7
  require 'digest'
10
8
 
11
- module TaskwarriorWeb
12
- class App < Sinatra::Base
13
-
14
- @@root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
15
- set :root, @@root
16
- set :app_file, __FILE__
17
- set :public_folder, File.dirname(__FILE__) + '/public'
18
- set :views, File.dirname(__FILE__) + '/views'
19
-
20
- def protected!
21
- response['WWW-Authenticate'] = %(Basic realm="Taskworrior Web") and throw(:halt, [401, "Not authorized\n"]) and return unless authorized?
22
- end
9
+ class TaskwarriorWeb::App < Sinatra::Base
10
+ autoload :Helpers, 'taskwarrior-web/helpers'
11
+
12
+ @@root = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
13
+ set :root, @@root
14
+ set :app_file, __FILE__
15
+ set :public_folder, File.dirname(__FILE__) + '/public'
16
+ set :views, File.dirname(__FILE__) + '/views'
17
+
18
+ def protected!
19
+ response['WWW-Authenticate'] = %(Basic realm="Taskworrior Web") and throw(:halt, [401, "Not authorized\n"]) and return unless authorized?
20
+ end
23
21
 
24
- def authorized?
25
- @auth ||= Rack::Auth::Basic::Request.new(request.env)
26
- values = [TaskwarriorWeb::Config.property('task-web.user'), TaskwarriorWeb::Config.property('task-web.passwd')]
27
- @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == values
28
- end
22
+ def authorized?
23
+ @auth ||= Rack::Auth::Basic::Request.new(request.env)
24
+ values = [TaskwarriorWeb::Config.property('task-web.user'), TaskwarriorWeb::Config.property('task-web.passwd')]
25
+ @auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == values
26
+ end
29
27
 
30
- # Before filter
31
- before do
32
- @current_page = request.path_info
33
- protected! if TaskwarriorWeb::Config.property('task-web.user')
34
- end
28
+ # Before filter
29
+ before do
30
+ @current_page = request.path_info
31
+ protected! if TaskwarriorWeb::Config.property('task-web.user')
32
+ end
35
33
 
36
- # Helpers
37
- helpers TaskwarriorWeb::App::Helpers
34
+ # Helpers
35
+ helpers Helpers
38
36
 
39
- # Redirects
40
- get '/' do
41
- redirect '/tasks/pending'
42
- end
43
- get '/tasks/?' do
44
- redirect '/tasks/pending'
45
- end
37
+ # Redirects
38
+ get '/' do
39
+ redirect '/tasks/pending'
40
+ end
41
+ get '/tasks/?' do
42
+ redirect '/tasks/pending'
43
+ end
46
44
 
47
- # Task routes
48
- get '/tasks/:status/?' do
49
- pass unless ['pending', 'waiting', 'completed', 'deleted'].include?(params[:status])
50
- @title = "Tasks"
51
- @subnav = subnav('tasks')
52
- @tasks = TaskwarriorWeb::Task.find_by_status(params[:status]).sort_by! { |x| [x.priority.nil?.to_s, x.priority.to_s, x.due.nil?.to_s, x.due.to_s, x.project.to_s] }
53
- erb :listing
54
- end
45
+ # Task routes
46
+ get '/tasks/:status/?' do
47
+ pass unless ['pending', 'waiting', 'completed', 'deleted'].include?(params[:status])
48
+ @title = "Tasks"
49
+ @subnav = subnav('tasks')
50
+ @tasks = TaskwarriorWeb::Task.find_by_status(params[:status]).sort_by! { |x| [x.priority.nil?.to_s, x.priority.to_s, x.due.nil?.to_s, x.due.to_s, x.project.to_s] }
51
+ erb :listing
52
+ end
53
+
54
+ get '/tasks/new/?' do
55
+ @title = 'New Task'
56
+ @date_format = TaskwarriorWeb::Config.dateformat || 'm/d/yy'
57
+ @date_format.gsub!('Y', 'yy')
58
+ erb :task_form
59
+ end
55
60
 
56
- get '/tasks/new/?' do
61
+ post '/tasks/?' do
62
+ results = passes_validation(params[:task], :task)
63
+ if results.empty?
64
+ task = TaskwarriorWeb::Task.new(params[:task])
65
+ task.save!.to_s
66
+ redirect '/tasks'
67
+ else
68
+ @task = params[:task]
57
69
  @title = 'New Task'
58
70
  @date_format = TaskwarriorWeb::Config.dateformat || 'm/d/yy'
59
71
  @date_format.gsub!('Y', 'yy')
60
- erb :task_form
61
- end
62
-
63
- post '/tasks/?' do
64
- results = passes_validation(params[:task], :task)
65
- if results.empty?
66
- task = TaskwarriorWeb::Task.new(params[:task])
67
- task.save!.to_s
68
- redirect '/tasks'
69
- else
70
- @task = params[:task]
71
- @title = 'New Task'
72
- @date_format = TaskwarriorWeb::Config.dateformat || 'm/d/yy'
73
- @date_format.gsub!('Y', 'yy')
74
- @messages = []
75
- results.each do |result|
76
- @messages << { :severity => 'alert-error', :message => result }
77
- end
78
- erb :task_form
72
+ @messages = []
73
+ results.each do |result|
74
+ @messages << { :severity => 'alert-error', :message => result }
79
75
  end
76
+ erb :task_form
80
77
  end
78
+ end
81
79
 
82
- # Projects
83
- get '/projects' do
84
- redirect '/projects/overview'
85
- end
86
-
87
- get '/projects/overview/?' do
88
- @title = 'Projects'
89
- @subnav = subnav('projects')
90
- @tasks = TaskwarriorWeb::Task.query('status.not' => 'deleted', 'project.not' => '').sort_by! { |x| [x.priority.nil?.to_s, x.priority.to_s, x.due.nil?.to_s, x.due.to_s] }.group_by { |x| x.project.to_s }
91
- erb :projects
92
- end
80
+ # Projects
81
+ get '/projects' do
82
+ redirect '/projects/overview'
83
+ end
93
84
 
94
- get '/projects/:name/?' do
95
- @subnav = subnav('projects')
96
- subbed = params[:name].gsub('--', '.')
97
- @tasks = TaskwarriorWeb::Task.query('status.not' => 'deleted', :project => subbed).sort_by! { |x| [x.priority.nil?.to_s, x.priority.to_s, x.due.nil?.to_s, x.due.to_s] }
98
- @title = @tasks.select { |t| t.project.match(/^#{subbed}$/i) }.first.project
99
- erb :project
100
- end
85
+ get '/projects/overview/?' do
86
+ @title = 'Projects'
87
+ @subnav = subnav('projects')
88
+ @tasks = TaskwarriorWeb::Task.query('status.not' => 'deleted', 'project.not' => '').sort_by! { |x| [x.priority.nil?.to_s, x.priority.to_s, x.due.nil?.to_s, x.due.to_s] }.group_by { |x| x.project.to_s }
89
+ erb :projects
90
+ end
101
91
 
102
- # AJAX callbacks
103
- get '/ajax/projects/?' do
104
- TaskwarriorWeb::Command.new(:projects).run.split("\n").to_json
105
- end
92
+ get '/projects/:name/?' do
93
+ @subnav = subnav('projects')
94
+ subbed = params[:name].gsub('--', '.')
95
+ @tasks = TaskwarriorWeb::Task.query('status.not' => 'deleted', :project => subbed).sort_by! { |x| [x.priority.nil?.to_s, x.priority.to_s, x.due.nil?.to_s, x.due.to_s] }
96
+ @title = @tasks.select { |t| t.project.match(/^#{subbed}$/i) }.first.project
97
+ erb :project
98
+ end
106
99
 
107
- get '/ajax/tags/?' do
108
- tags = TaskwarriorWeb::Command.new(:tags).run.split("\n")
109
- tags.keep_if { |tag| tag.include?(params[:query]) }
100
+ # AJAX callbacks
101
+ get '/ajax/projects/?' do
102
+ TaskwarriorWeb::Command.new(:projects).run.split("\n").to_json
103
+ end
110
104
 
111
- json = []
112
- tags.each do |tag|
113
- json << { :name => tag, :id => tag }
114
- end
105
+ get '/ajax/tags/?' do
106
+ tags = TaskwarriorWeb::Command.new(:tags).run.split("\n")
107
+ tags.keep_if { |tag| tag.include?(params[:query]) }
115
108
 
116
- json.to_json
109
+ json = []
110
+ tags.each do |tag|
111
+ json << { :name => tag, :id => tag }
117
112
  end
118
113
 
119
- get '/ajax/count/?' do
120
- TaskwarriorWeb::Task.count(:status => :pending).to_s
121
- end
114
+ json.to_json
115
+ end
122
116
 
123
- post '/ajax/task-complete/:id/?' do
124
- # Bummer that we have to directly use Command here, but apparently tasks
125
- # cannot be filtered by UUID.
126
- TaskwarriorWeb::Command.new(:complete, params[:id]).run
127
- end
117
+ get '/ajax/count/?' do
118
+ TaskwarriorWeb::Task.count(:status => :pending).to_s
119
+ end
128
120
 
129
- # Error handling
130
- not_found do
131
- @title = 'Page Not Found'
132
- @referrer = request.referrer
133
- erb :'404'
134
- end
121
+ post '/ajax/task-complete/:id/?' do
122
+ # Bummer that we have to directly use Command here, but apparently tasks
123
+ # cannot be filtered by UUID.
124
+ TaskwarriorWeb::Command.new(:complete, params[:id]).run
125
+ end
135
126
 
136
- def passes_validation(item, method)
137
- results = []
138
- case method
139
- when :task
140
- if item['description'].empty?
141
- results << 'You must provide a description'
142
- end
143
- end
144
- results
145
- end
127
+ # Error handling
128
+ not_found do
129
+ @title = 'Page Not Found'
130
+ @referrer = request.referrer
131
+ erb :'404'
132
+ end
146
133
 
134
+ def passes_validation(item, method)
135
+ results = []
136
+ case method
137
+ when :task
138
+ if item['description'].empty?
139
+ results << 'You must provide a description'
140
+ end
141
+ end
142
+ results
147
143
  end
148
144
  end
@@ -1,19 +1,12 @@
1
- require 'taskwarrior-web/command_builder'
2
- require 'taskwarrior-web/runner'
1
+ class TaskwarriorWeb::Command
2
+ include TaskwarriorWeb::CommandBuilder
3
+ include TaskwarriorWeb::Runner
3
4
 
4
- module TaskwarriorWeb
5
- class Command
6
-
7
- include TaskwarriorWeb::CommandBuilder
8
- include TaskwarriorWeb::Runner
9
-
10
- attr_accessor :command, :id, :params, :built, :command_string
11
-
12
- def initialize(command, id = nil, *args)
13
- @command = command if command
14
- @id = id if id
15
- @params = args.last.is_a?(::Hash) ? args.pop : {}
16
- end
5
+ attr_accessor :command, :id, :params, :built, :command_string
17
6
 
7
+ def initialize(command, id = nil, *args)
8
+ @command = command if command
9
+ @id = id if id
10
+ @params = args.last.is_a?(::Hash) ? args.pop : {}
18
11
  end
19
12
  end
@@ -1,22 +1,22 @@
1
- require 'taskwarrior-web/config'
1
+ module TaskwarriorWeb::CommandBuilder
2
+ autoload :Base, 'taskwarrior-web/command_builders/base'
3
+ autoload :V1, 'taskwarrior-web/command_builders/v1'
4
+ autoload :V2, 'taskwarrior-web/command_builders/v2'
2
5
 
3
- module TaskwarriorWeb
4
- module CommandBuilder
5
- def self.included(class_name)
6
- class_name.class_eval do
7
- case TaskwarriorWeb::Config.version.major
8
- when 2
9
- require 'taskwarrior-web/command_builders/v2'
10
- include TaskwarriorWeb::CommandBuilder::V2
11
- when 1
12
- require 'taskwarrior-web/command_builders/v1'
13
- include TaskwarriorWeb::CommandBuilder::V1
14
- else
15
- raise TaskwarriorWeb::UnrecognizedTaskVersion
16
- end
6
+ class InvalidCommandError < Exception; end
7
+ class MissingTaskIDError < Exception; end
8
+
9
+ def self.included(class_name)
10
+ class_name.class_eval do
11
+ case TaskwarriorWeb::Config.version.major
12
+ when 2
13
+ include TaskwarriorWeb::CommandBuilder::V2
14
+ when 1
15
+ include TaskwarriorWeb::CommandBuilder::V1
16
+ else
17
+ raise TaskwarriorWeb::UnrecognizedTaskVersion
17
18
  end
18
19
  end
19
20
  end
20
21
 
21
- class UnrecognizedTaskVersion < Exception; end
22
22
  end
@@ -1,66 +1,60 @@
1
1
  require 'shellwords'
2
2
 
3
- module TaskwarriorWeb::CommandBuilder
4
- module Base
5
-
6
- TASK_COMMANDS = {
7
- :add => 'add',
8
- :query => TaskwarriorWeb::Config.version > Versionomy.parse('1.9.2') ? '_query' : 'export',
9
- :count => 'count',
10
- :complete => ':id done',
11
- :projects => '_projects',
12
- :tags => '_tags'
13
- }
14
-
15
- def build
16
- unless @command_string
17
- task_command
18
- substitute_parts if @command_string =~ /:id/
19
- end
20
- parse_params
21
- @built = "#{@command_string}#{@params}"
3
+ module TaskwarriorWeb::CommandBuilder::Base
4
+
5
+ TASK_COMMANDS = {
6
+ :add => 'add',
7
+ :query => TaskwarriorWeb::Config.version > Versionomy.parse('1.9.2') ? '_query' : 'export',
8
+ :complete => ':id done',
9
+ :projects => '_projects',
10
+ :tags => '_tags'
11
+ }
12
+
13
+ def build
14
+ unless @command_string
15
+ task_command
16
+ substitute_parts if @command_string =~ /:id/
22
17
  end
18
+ parse_params
19
+ @built = "#{@command_string}#{@params}"
20
+ end
23
21
 
24
- def task_command
25
- if TASK_COMMANDS.has_key?(@command.to_sym)
26
- @command_string = TASK_COMMANDS[@command.to_sym].clone
27
- else
28
- raise InvalidCommandError
29
- end
22
+ def task_command
23
+ if TASK_COMMANDS.has_key?(@command.to_sym)
24
+ @command_string = TASK_COMMANDS[@command.to_sym].clone
25
+ else
26
+ raise InvalidCommandError
30
27
  end
28
+ end
31
29
 
32
- def substitute_parts
33
- if @id
34
- @command_string.gsub!(':id', "uuid:#{@id.to_s}")
35
- return self
36
- else
37
- raise TaskwarriorWeb::CommandBuilder::MissingTaskIDError
38
- end
30
+ def substitute_parts
31
+ if @id
32
+ @command_string.gsub!(':id', "uuid:#{@id.to_s}")
33
+ return self
34
+ else
35
+ raise TaskwarriorWeb::CommandBuilder::MissingTaskIDError
39
36
  end
37
+ end
40
38
 
41
- def parse_params
42
- string = ''
43
- string << %Q( #{@params.delete(:description).shellescape}) if @params.has_key?(:description)
39
+ def parse_params
40
+ string = ''
41
+ string << %Q( #{@params.delete(:description).shellescape}) if @params.has_key?(:description)
44
42
 
45
- if tags = @params.delete(:tags)
46
- tag_indicator = TaskwarriorWeb::Config.property('tag.indicator') || '+'
47
- tags.each { |tag| string << %Q( #{tag_indicator}#{tag.to_s.shellescape}) }
48
- end
43
+ if tags = @params.delete(:tags)
44
+ tag_indicator = TaskwarriorWeb::Config.property('tag.indicator') || '+'
45
+ tags.each { |tag| string << %Q( #{tag_indicator}#{tag.to_s.shellescape}) }
46
+ end
49
47
 
50
- @params.each do |attr, value|
51
- if value.respond_to? :each
52
- value.each { |val| string << %Q( #{attr.to_s}:\\"#{val.to_s.shellescape}\\") }
53
- else
54
- string << %Q( #{attr.to_s}:\\"#{value.to_s.shellescape}\\")
55
- end
48
+ @params.each do |attr, value|
49
+ if value.respond_to? :each
50
+ value.each { |val| string << %Q( #{attr.to_s}:\\"#{val.to_s.shellescape}\\") }
51
+ else
52
+ string << %Q( #{attr.to_s}:\\"#{value.to_s.shellescape}\\")
56
53
  end
57
-
58
- @params = string
59
- return self
60
54
  end
61
55
 
56
+ @params = string
57
+ return self
62
58
  end
63
59
 
64
- class InvalidCommandError < Exception; end
65
- class MissingTaskIDError < Exception; end
66
60
  end