taskwarrior-web 1.0.7 → 1.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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