taskwarrior-web 1.0.14 → 1.1.0
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.
- data/.travis.yml +2 -1
- data/CHANGELOG.md +7 -0
- data/README.md +2 -5
- data/lib/taskwarrior-web.rb +1 -0
- data/lib/taskwarrior-web/app.rb +59 -49
- data/lib/taskwarrior-web/config/navigation.rb +1 -1
- data/lib/taskwarrior-web/helpers.rb +40 -3
- data/lib/taskwarrior-web/model/config.rb +8 -1
- data/lib/taskwarrior-web/model/task.rb +10 -2
- data/lib/taskwarrior-web/public/js/application.js +4 -2
- data/lib/taskwarrior-web/services/builder/base.rb +7 -1
- data/lib/taskwarrior-web/services/runner.rb +1 -1
- data/lib/taskwarrior-web/views/_flash.erb +7 -0
- data/lib/taskwarrior-web/views/_task_form.erb +28 -0
- data/lib/taskwarrior-web/views/delete_confirm.erb +4 -0
- data/lib/taskwarrior-web/views/edit_task.erb +13 -0
- data/lib/taskwarrior-web/views/layout.erb +1 -7
- data/lib/taskwarrior-web/views/listing.erb +4 -0
- data/lib/taskwarrior-web/views/new_task.erb +11 -0
- data/lib/taskwarrior-web/views/project.erb +2 -0
- data/lib/taskwarrior-web/views/projects.erb +2 -0
- data/spec/app/app_spec.rb +127 -20
- data/spec/model/task_spec.rb +20 -0
- data/spec/services/builder/base_spec.rb +6 -0
- data/spec/services/runner_spec.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/taskwarrior-web.gemspec +3 -2
- metadata +48 -33
- data/lib/taskwarrior-web/views/task_form.erb +0 -38
data/.travis.yml
CHANGED
@@ -4,6 +4,7 @@ rvm:
|
|
4
4
|
- 1.9.3
|
5
5
|
script: "rake spec"
|
6
6
|
before_install:
|
7
|
-
- sudo apt-get
|
7
|
+
- sudo apt-get update -qq
|
8
|
+
- sudo apt-get install task -qq
|
8
9
|
- cp -v /home/vagrant/builds/theunraveler/taskwarrior-web/spec/files/taskrc /home/vagrant/.taskrc
|
9
10
|
- mkdir /home/vagrant/.task
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
## v1.1.0 (12/7/12)
|
2
|
+
|
3
|
+
* Editing and deleting tasks! (If you are using task >= 2.0).
|
4
|
+
* Fixing status messages. They should now be consistent.
|
5
|
+
* Added safeguards for xterm.title and color .taskrc settings. You should now
|
6
|
+
be able to safely set both of those options.
|
7
|
+
|
1
8
|
## v1.0.14 (11/22/12)
|
2
9
|
|
3
10
|
* Fixed a bug when colorizing tasks based on "due" setting.
|
data/README.md
CHANGED
@@ -13,10 +13,6 @@ forthcoming!**
|
|
13
13
|
|
14
14
|
* `ruby` >= 1.9 (support for `ruby` < 1.9 is very unlikely, but pull requests
|
15
15
|
are gladly accepted).
|
16
|
-
* In your `.taskrc` file, `xterm.title` cannot be enabled. Either remove that
|
17
|
-
line from `.taskrc` or set it to `off`. If you have a very compelling reason
|
18
|
-
for needing this to be enabled, submit a bug report and I'll reconsider
|
19
|
-
adding support for it.
|
20
16
|
|
21
17
|
## Installation
|
22
18
|
|
@@ -37,8 +33,9 @@ an executable, so all options for Vegas are valid for `task-web`. Type
|
|
37
33
|
|
38
34
|
The current featureset includes:
|
39
35
|
|
40
|
-
* Viewing tasks
|
36
|
+
* Viewing tasks sorted and grouped in various ways.
|
41
37
|
* Creating a new task with a due date, project, and tags.
|
38
|
+
* Editing and deleting tasks (only task >= 2.0).
|
42
39
|
* `task-web` will pull your `task` config (from `.taskrc`) and use it to
|
43
40
|
determine date formatting and when an upcoming task should be marked as
|
44
41
|
"due".
|
data/lib/taskwarrior-web.rb
CHANGED
@@ -4,6 +4,7 @@ $:.unshift(File.dirname(__FILE__)) unless
|
|
4
4
|
require 'rubygems'
|
5
5
|
require 'active_support/core_ext/object/blank'
|
6
6
|
require 'active_support/core_ext/string/inflections'
|
7
|
+
require 'active_support/core_ext/string/filters'
|
7
8
|
|
8
9
|
module TaskwarriorWeb
|
9
10
|
autoload :App, 'taskwarrior-web/app'
|
data/lib/taskwarrior-web/app.rb
CHANGED
@@ -6,6 +6,7 @@ require 'time'
|
|
6
6
|
require 'rinku'
|
7
7
|
require 'digest'
|
8
8
|
require 'sinatra/simple-navigation'
|
9
|
+
require 'rack-flash'
|
9
10
|
|
10
11
|
class TaskwarriorWeb::App < Sinatra::Base
|
11
12
|
autoload :Helpers, 'taskwarrior-web/helpers'
|
@@ -15,34 +16,25 @@ class TaskwarriorWeb::App < Sinatra::Base
|
|
15
16
|
set :app_file, __FILE__
|
16
17
|
set :public_folder, File.dirname(__FILE__) + '/public'
|
17
18
|
set :views, File.dirname(__FILE__) + '/views'
|
19
|
+
set :method_override, true
|
20
|
+
enable :sessions
|
18
21
|
|
19
22
|
# Helpers
|
20
23
|
helpers Helpers
|
21
24
|
register Sinatra::SimpleNavigation
|
25
|
+
use Rack::Flash
|
22
26
|
|
23
|
-
def protected!
|
24
|
-
response['WWW-Authenticate'] = %(Basic realm="Taskworrior Web") and throw(:halt, [401, "Not authorized\n"]) and return unless authorized?
|
25
|
-
end
|
26
|
-
|
27
|
-
def authorized?
|
28
|
-
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
29
|
-
values = [TaskwarriorWeb::Config.property('task-web.user'), TaskwarriorWeb::Config.property('task-web.passwd')]
|
30
|
-
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == values
|
31
|
-
end
|
32
|
-
|
33
27
|
# Before filter
|
34
28
|
before do
|
35
29
|
@current_page = request.path_info
|
30
|
+
@can_edit = TaskwarriorWeb::Config.supports? :editing
|
36
31
|
protected! if TaskwarriorWeb::Config.property('task-web.user')
|
37
32
|
end
|
38
33
|
|
39
34
|
# Redirects
|
40
|
-
get '/'
|
41
|
-
|
42
|
-
|
43
|
-
get '/tasks/?' do
|
44
|
-
redirect '/tasks/pending'
|
45
|
-
end
|
35
|
+
get('/') { redirect to('/tasks/pending') }
|
36
|
+
get('/tasks/?') { redirect to('/tasks/pending') }
|
37
|
+
get('/projects/?') { redirect to('/projects/overview') }
|
46
38
|
|
47
39
|
# Task routes
|
48
40
|
get '/tasks/:status/?' do
|
@@ -60,26 +52,63 @@ class TaskwarriorWeb::App < Sinatra::Base
|
|
60
52
|
get '/tasks/new/?' do
|
61
53
|
@title = 'New Task'
|
62
54
|
@date_format = (TaskwarriorWeb::Config.dateformat || 'm/d/yy').gsub('Y', 'yy')
|
63
|
-
erb :
|
55
|
+
erb :new_task
|
64
56
|
end
|
65
57
|
|
66
58
|
post '/tasks/?' do
|
67
59
|
@task = TaskwarriorWeb::Task.new(params[:task])
|
68
60
|
|
69
61
|
if @task.is_valid?
|
70
|
-
@task.save!
|
71
|
-
redirect '/tasks'
|
62
|
+
flash[:success] = @task.save! || %Q{New task "#{@task.description.truncate(20)}" created}
|
63
|
+
redirect to('/tasks')
|
72
64
|
end
|
73
65
|
|
74
|
-
|
75
|
-
|
66
|
+
flash.now[:error] = @task._errors.join(', ')
|
67
|
+
forward '/tasks/new'
|
76
68
|
end
|
77
69
|
|
78
|
-
|
79
|
-
|
80
|
-
|
70
|
+
get '/tasks/:uuid/?' do
|
71
|
+
not_found if !TaskwarriorWeb::Config.supports?(:editing)
|
72
|
+
tasks = TaskwarriorWeb::Task.find_by_uuid(params[:uuid])
|
73
|
+
not_found if tasks.empty?
|
74
|
+
@task = tasks.first
|
75
|
+
@title = %Q{Editing "#{@task.description.truncate(20)}"}
|
76
|
+
erb :edit_task
|
81
77
|
end
|
82
78
|
|
79
|
+
patch '/tasks/:uuid/?' do
|
80
|
+
not_found if !TaskwarriorWeb::Config.supports?(:editing)
|
81
|
+
not_found if TaskwarriorWeb::Task.find_by_uuid(params[:uuid]).empty?
|
82
|
+
|
83
|
+
@task = TaskwarriorWeb::Task.new(params[:task])
|
84
|
+
if @task.is_valid?
|
85
|
+
flash[:success] = @task.save! || %Q{Task "#{@task.description.truncate(20)}" was successfully updated}
|
86
|
+
redirect to('/tasks')
|
87
|
+
end
|
88
|
+
|
89
|
+
flash.now[:error] = @task._errors.join(', ')
|
90
|
+
forward "/tasks/#{@task.uuid}"
|
91
|
+
end
|
92
|
+
|
93
|
+
get '/tasks/:uuid/delete/?' do
|
94
|
+
not_found if !TaskwarriorWeb::Config.supports?(:editing)
|
95
|
+
tasks = TaskwarriorWeb::Task.find_by_uuid(params[:uuid])
|
96
|
+
not_found if tasks.empty?
|
97
|
+
@task = tasks.first
|
98
|
+
@title = %Q{Are you sure you want to delete the task "#{@task.description.truncate(20)}"?}
|
99
|
+
erb :delete_confirm
|
100
|
+
end
|
101
|
+
|
102
|
+
delete '/tasks/:uuid' do
|
103
|
+
not_found if !TaskwarriorWeb::Config.supports?(:editing)
|
104
|
+
tasks = TaskwarriorWeb::Task.find_by_uuid(params[:uuid])
|
105
|
+
not_found if tasks.empty?
|
106
|
+
@task = tasks.first
|
107
|
+
flash[:success] = @task.delete! || %Q{The task "#{@task.description.truncate(20)}" was successfully deleted}
|
108
|
+
redirect to('/tasks')
|
109
|
+
end
|
110
|
+
|
111
|
+
# Projects
|
83
112
|
get '/projects/overview/?' do
|
84
113
|
@title = 'Projects'
|
85
114
|
@tasks = TaskwarriorWeb::Task.query('status.not' => :deleted, 'project.not' => '')
|
@@ -90,49 +119,30 @@ class TaskwarriorWeb::App < Sinatra::Base
|
|
90
119
|
end
|
91
120
|
|
92
121
|
get '/projects/:name/?' do
|
93
|
-
@title = params[:name]
|
122
|
+
@title = unlinkify(params[:name])
|
94
123
|
@tasks = TaskwarriorWeb::Task.query('status.not' => 'deleted', :project => @title)
|
95
124
|
.sort_by! { |x| [x.priority.nil?.to_s, x.priority.to_s, x.due.nil?.to_s, x.due.to_s] }
|
96
125
|
erb :project
|
97
126
|
end
|
98
127
|
|
99
128
|
# AJAX callbacks
|
100
|
-
get
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
get '/ajax/count/?' do
|
105
|
-
self.class.task_count
|
106
|
-
end
|
129
|
+
get('/ajax/projects/?') { TaskwarriorWeb::Command.new(:projects).run.split("\n").to_json }
|
130
|
+
get('/ajax/count/?') { task_count }
|
131
|
+
post('/ajax/task-complete/:id/?') { TaskwarriorWeb::Command.new(:complete, params[:id]).run }
|
107
132
|
|
108
|
-
get '/ajax/badge
|
133
|
+
get '/ajax/badge/?' do
|
109
134
|
if filter = TaskwarriorWeb::Config.property('task-web.filter.badge')
|
110
135
|
total = TaskwarriorWeb::Task.query(:description => filter).count
|
111
136
|
else
|
112
|
-
total =
|
137
|
+
total = task_count
|
113
138
|
end
|
114
139
|
total == 0 ? '' : total.to_s
|
115
140
|
end
|
116
141
|
|
117
|
-
post '/ajax/task-complete/:id/?' do
|
118
|
-
# Bummer that we have to directly use Command here, but apparently tasks
|
119
|
-
# cannot be filtered by UUID.
|
120
|
-
TaskwarriorWeb::Command.new(:complete, params[:id]).run
|
121
|
-
end
|
122
|
-
|
123
142
|
# Error handling
|
124
143
|
not_found do
|
125
144
|
@title = 'Page Not Found'
|
126
145
|
@referrer = request.referrer
|
127
146
|
erb :'404'
|
128
147
|
end
|
129
|
-
|
130
|
-
def self.task_count
|
131
|
-
if filter = TaskwarriorWeb::Config.property('task-web.filter')
|
132
|
-
total = TaskwarriorWeb::Task.query(:description => filter).count
|
133
|
-
else
|
134
|
-
total = TaskwarriorWeb::Task.count(:status => :pending)
|
135
|
-
end
|
136
|
-
total.to_s
|
137
|
-
end
|
138
148
|
end
|
@@ -5,7 +5,7 @@ SimpleNavigation::Configuration.run do |navigation|
|
|
5
5
|
primary.dom_class = 'nav'
|
6
6
|
primary.item :tasks, 'Tasks', '/tasks' do |tasks|
|
7
7
|
tasks.dom_class = 'nav nav-pills'
|
8
|
-
tasks.item :pending, "Pending <span class=\"badge\">#{
|
8
|
+
tasks.item :pending, "Pending <span class=\"badge\">#{task_count}</span>", '/tasks/pending'
|
9
9
|
tasks.item :waiting, 'Waiting', '/tasks/waiting'
|
10
10
|
tasks.item :completed, 'Completed', '/tasks/completed'
|
11
11
|
tasks.item :deleted, 'Deleted', '/tasks/deleted'
|
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'active_support/core_ext/date/calculations'
|
2
2
|
|
3
3
|
module TaskwarriorWeb::App::Helpers
|
4
|
-
|
5
4
|
def format_date(timestamp)
|
6
5
|
format = TaskwarriorWeb::Config.dateformat || '%-m/%-d/%Y'
|
7
6
|
Time.parse(timestamp).strftime(format)
|
@@ -20,11 +19,49 @@ module TaskwarriorWeb::App::Helpers
|
|
20
19
|
end
|
21
20
|
|
22
21
|
def linkify(item)
|
23
|
-
|
24
|
-
|
22
|
+
item.gsub('.', '--') unless item.nil? unless item.nil?
|
23
|
+
end
|
24
|
+
|
25
|
+
def unlinkify(item)
|
26
|
+
item.gsub('--', '.') unless item.nil?
|
25
27
|
end
|
26
28
|
|
27
29
|
def auto_link(text)
|
28
30
|
Rinku.auto_link(text, :all, 'target="_blank"')
|
29
31
|
end
|
32
|
+
|
33
|
+
def flash_types
|
34
|
+
[:success, :info, :warning, :error]
|
35
|
+
end
|
36
|
+
|
37
|
+
def task_count
|
38
|
+
if filter = TaskwarriorWeb::Config.property('task-web.filter')
|
39
|
+
total = TaskwarriorWeb::Task.query(:description => filter).count
|
40
|
+
else
|
41
|
+
total = TaskwarriorWeb::Task.count(:status => :pending)
|
42
|
+
end
|
43
|
+
total.to_s
|
44
|
+
end
|
45
|
+
|
46
|
+
def crud_links(task)
|
47
|
+
string = %Q{<a href="/tasks/#{task.uuid}">Edit</a>}
|
48
|
+
string << %Q{ | }
|
49
|
+
string << %Q{<a href="/tasks/#{task.uuid}/delete">Delete</a>}
|
50
|
+
string
|
51
|
+
end
|
52
|
+
|
53
|
+
# Authentication
|
54
|
+
def protected!
|
55
|
+
response['WWW-Authenticate'] = %(Basic realm="Taskworrior Web") and throw(:halt, [401, "Not authorized\n"]) and return unless authorized?
|
56
|
+
end
|
57
|
+
|
58
|
+
def authorized?
|
59
|
+
@auth ||= Rack::Auth::Basic::Request.new(request.env)
|
60
|
+
values = [TaskwarriorWeb::Config.property('task-web.user'), TaskwarriorWeb::Config.property('task-web.passwd')]
|
61
|
+
@auth.provided? && @auth.basic? && @auth.credentials && @auth.credentials == values
|
62
|
+
end
|
63
|
+
|
64
|
+
def forward(url, method = 'GET')
|
65
|
+
call env.merge('REQUEST_METHOD' => method, 'PATH_INFO' => url)
|
66
|
+
end
|
30
67
|
end
|
@@ -22,7 +22,7 @@ module TaskwarriorWeb::Config
|
|
22
22
|
}
|
23
23
|
|
24
24
|
def self.version
|
25
|
-
@version ||= Versionomy.parse(
|
25
|
+
@version ||= Versionomy.parse(`#{TaskwarriorWeb::Runner::TASK_BIN} _version`.strip)
|
26
26
|
end
|
27
27
|
|
28
28
|
def self.file
|
@@ -37,6 +37,13 @@ module TaskwarriorWeb::Config
|
|
37
37
|
self.file['dateformat'].gsub(/(\w)/, DATEFORMATS) unless self.file['dateformat'].nil?
|
38
38
|
end
|
39
39
|
|
40
|
+
def self.supports?(feature)
|
41
|
+
case feature.to_sym
|
42
|
+
when :editing then self.version.major > 1
|
43
|
+
else false
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
40
47
|
def self.method_missing(method)
|
41
48
|
self.file[method.to_s]
|
42
49
|
end
|
@@ -7,7 +7,7 @@ module TaskwarriorWeb
|
|
7
7
|
|
8
8
|
attr_accessor :entry, :project, :priority, :uuid, :description, :status,
|
9
9
|
:due, :start, :end, :tags, :depends, :wait, :annotations,
|
10
|
-
:_errors
|
10
|
+
:_errors, :remove_tags
|
11
11
|
alias :annotate= :annotations=
|
12
12
|
|
13
13
|
####################################
|
@@ -24,16 +24,24 @@ module TaskwarriorWeb
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def save!
|
27
|
-
Command.new(:add, nil, self.to_hash).run
|
27
|
+
@uuid ? Command.new(:update, uuid, self.to_hash).run : Command.new(:add, nil, self.to_hash).run
|
28
28
|
end
|
29
29
|
|
30
30
|
def complete!
|
31
31
|
Command.new(:complete, self.uuid).run
|
32
32
|
end
|
33
33
|
|
34
|
+
def delete!
|
35
|
+
Command.new(:delete, self.uuid).run
|
36
|
+
end
|
37
|
+
|
34
38
|
# Make sure that the tags are an array.
|
35
39
|
def tags=(value)
|
36
40
|
@tags = value.is_a?(String) ? value.split(/[, ]+/).reject(&:empty?) : value
|
41
|
+
|
42
|
+
if @uuid
|
43
|
+
@remove_tags = Task.find_by_uuid(uuid).first.tags - @tags
|
44
|
+
end
|
37
45
|
end
|
38
46
|
|
39
47
|
def is_valid?
|
@@ -71,7 +71,7 @@ var initTaskCompletion = function() {
|
|
71
71
|
|
72
72
|
var refreshDockBadge = function() {
|
73
73
|
if (window.hasOwnProperty('fluid')) {
|
74
|
-
$.get('/ajax/badge
|
74
|
+
$.get('/ajax/badge', function(data) {
|
75
75
|
window.fluid.dockBadge = data;
|
76
76
|
});
|
77
77
|
}
|
@@ -90,5 +90,7 @@ var refreshSubnavCount = function() {
|
|
90
90
|
* @param string [severity] The severity of the message.
|
91
91
|
*/
|
92
92
|
function set_message(msg, severity) {
|
93
|
-
$('
|
93
|
+
$('<div style="display: none;" class="alert alert-' + (severity || 'success') + '">' + msg + '</div>')
|
94
|
+
.appendTo('#flash-messages')
|
95
|
+
.fadeIn();
|
94
96
|
}
|
@@ -4,6 +4,8 @@ module TaskwarriorWeb::CommandBuilder::Base
|
|
4
4
|
|
5
5
|
TASK_COMMANDS = {
|
6
6
|
:add => 'add',
|
7
|
+
:update => TaskwarriorWeb::Config.version.major >= 2 ? ':id mod' : nil,
|
8
|
+
:delete => 'rc.confirmation=no :id delete',
|
7
9
|
:query => TaskwarriorWeb::Config.version > Versionomy.parse('1.9.2') ? '_query' : 'export',
|
8
10
|
:complete => ':id done',
|
9
11
|
:projects => '_projects',
|
@@ -20,7 +22,7 @@ module TaskwarriorWeb::CommandBuilder::Base
|
|
20
22
|
end
|
21
23
|
|
22
24
|
def task_command
|
23
|
-
if TASK_COMMANDS
|
25
|
+
if TASK_COMMANDS[@command.to_sym]
|
24
26
|
@command_string = TASK_COMMANDS[@command.to_sym].clone
|
25
27
|
return self
|
26
28
|
else
|
@@ -45,6 +47,10 @@ module TaskwarriorWeb::CommandBuilder::Base
|
|
45
47
|
tags.each { |tag| string << %Q( #{tag_indicator}#{tag.to_s.shellescape}) }
|
46
48
|
end
|
47
49
|
|
50
|
+
if tags = @params.delete(:remove_tags)
|
51
|
+
tags.each { |tag| string << %Q( -#{tag.to_s.shellescape}) }
|
52
|
+
end
|
53
|
+
|
48
54
|
@params.each do |attr, value|
|
49
55
|
if value.respond_to? :each
|
50
56
|
value.each { |val| string << %Q( #{attr.to_s}:\\"#{val.to_s.shellescape}\\") }
|
@@ -0,0 +1,28 @@
|
|
1
|
+
<div class="control-group">
|
2
|
+
<label for="task-description" class="control-label">Description</label>
|
3
|
+
<div class="controls">
|
4
|
+
<input type="textfield" id="task-description" name="task[description]" value="<%= @task.description unless @task.nil? %>" />
|
5
|
+
</div>
|
6
|
+
</div>
|
7
|
+
|
8
|
+
<div class="control-group">
|
9
|
+
<label for="task-project" class="control-label">Project</label>
|
10
|
+
<div class="controls">
|
11
|
+
<input type="textfield" id="task-project" name="task[project]" value="<%= @task.project unless @task.nil? %>" autocomplete="off" />
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<div class="control-group">
|
16
|
+
<label for="task-due" class="control-label">Due Date</label>
|
17
|
+
<div class="controls">
|
18
|
+
<input class="date-picker" type="textfield" id="task-due" name="task[due]" value="<%= format_date(@task.due) unless @task.nil? || @task.due.blank? %>" data-date-format="<%= @date_format %>" />
|
19
|
+
</div>
|
20
|
+
</div>
|
21
|
+
|
22
|
+
<div class="control-group">
|
23
|
+
<label for="task-tags" class="control-label">Tags</label>
|
24
|
+
<div class="controls">
|
25
|
+
<input type="textfield" id="task-tags" name="task[tags]" value="<%= @task.tags.join(', ') unless @task.nil? %>" autocomplete="off" />
|
26
|
+
<span class="help-block">Enter tags separated by commas or spaces (e.g. <em>each, word will,be a tag</em>)</span>
|
27
|
+
</div>
|
28
|
+
</div>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<form id="new-task-form" class="form-horizontal" action="/tasks/<%= @task.uuid %>" method="post">
|
2
|
+
<input type="hidden" name="task[uuid]" value="<%= @task.uuid %>" />
|
3
|
+
|
4
|
+
<%= erb :_task_form %>
|
5
|
+
|
6
|
+
<div class="control-group">
|
7
|
+
<div class="controls">
|
8
|
+
<button type="submit" class="btn btn-primary">Update Task</button>
|
9
|
+
<input type="hidden" name="_method" value="patch" />
|
10
|
+
</div>
|
11
|
+
</div>
|
12
|
+
|
13
|
+
</form>
|
@@ -19,13 +19,7 @@
|
|
19
19
|
<%= erb :_topbar %>
|
20
20
|
<%= erb :_subnav %>
|
21
21
|
<section class="content">
|
22
|
-
|
23
|
-
<% if @messages %>
|
24
|
-
<% @messages.each do |message| %>
|
25
|
-
<div class="alert <%= message[:severity] %>"><%= message[:message] %></div>
|
26
|
-
<% end %>
|
27
|
-
<% end %>
|
28
|
-
</div>
|
22
|
+
<%= erb :_flash %>
|
29
23
|
<%= yield %>
|
30
24
|
</section>
|
31
25
|
</div>
|
@@ -1,3 +1,5 @@
|
|
1
|
+
<% can_edit = @can_edit && params[:status] == 'pending' %>
|
2
|
+
|
1
3
|
<div id="listing">
|
2
4
|
<table class="table table-striped table-hover">
|
3
5
|
<thead>
|
@@ -10,6 +12,7 @@
|
|
10
12
|
<th>Due</th>
|
11
13
|
<th>Tags</th>
|
12
14
|
<th>Priority</th>
|
15
|
+
<% if @can_edit %><th></th><% end %>
|
13
16
|
</tr>
|
14
17
|
</thead>
|
15
18
|
<tbody>
|
@@ -36,6 +39,7 @@
|
|
36
39
|
<td><%= format_date(task.due) unless task.due.nil? %></td>
|
37
40
|
<td><%= task.tags.join(', ') unless task.tags.nil? %></td>
|
38
41
|
<td><%= task.priority unless task.priority.nil? %></td>
|
42
|
+
<% if can_edit %><td><%= crud_links(task) %></td><% end %>
|
39
43
|
</tr>
|
40
44
|
<% end %>
|
41
45
|
</tbody>
|
@@ -0,0 +1,11 @@
|
|
1
|
+
<form id="new-task-form" class="form-horizontal" action="/tasks" method="post">
|
2
|
+
|
3
|
+
<%= erb :_task_form %>
|
4
|
+
|
5
|
+
<div class="control-group">
|
6
|
+
<div class="controls">
|
7
|
+
<button type="submit" class="btn btn-primary">Create Task</button>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
|
11
|
+
</form>
|
@@ -6,6 +6,7 @@
|
|
6
6
|
<th>Due</th>
|
7
7
|
<th>Tags</th>
|
8
8
|
<th>Priority</th>
|
9
|
+
<% if @can_edit %><th></th><% end %>
|
9
10
|
</tr>
|
10
11
|
</thead>
|
11
12
|
<tbody>
|
@@ -16,6 +17,7 @@
|
|
16
17
|
<td><%= format_date(task.due) unless task.due.nil? %></td>
|
17
18
|
<td><%= task.tags.join(', ') unless task.tags.nil? %></td>
|
18
19
|
<td><%= task.priority unless task.priority.nil? %></td>
|
20
|
+
<% if @can_edit %><td><%= crud_links(task) %></td><% end %>
|
19
21
|
</tr>
|
20
22
|
<% end %>
|
21
23
|
<% end %>
|
@@ -28,6 +28,7 @@
|
|
28
28
|
<th>Due</th>
|
29
29
|
<th>Tags</th>
|
30
30
|
<th>Priority</th>
|
31
|
+
<% if @can_edit %><th></th><% end %>
|
31
32
|
</tr>
|
32
33
|
</thead>
|
33
34
|
<tbody>
|
@@ -38,6 +39,7 @@
|
|
38
39
|
<td><%= format_date(task.due) unless task.due.nil? %></td>
|
39
40
|
<td><%= task.tags.join(', ') unless task.tags.nil? %></td>
|
40
41
|
<td><%= task.priority unless task.priority.nil? %></td>
|
42
|
+
<% if @can_edit %><td><%= crud_links(task) %></td><% end %>
|
41
43
|
</tr>
|
42
44
|
<% end %>
|
43
45
|
<% end %>
|
data/spec/app/app_spec.rb
CHANGED
@@ -22,26 +22,16 @@ describe TaskwarriorWeb::App do
|
|
22
22
|
get path
|
23
23
|
follow_redirect!
|
24
24
|
|
25
|
-
last_request.url.should
|
25
|
+
last_request.url.should match(/tasks\/pending$/)
|
26
26
|
last_response.should be_ok
|
27
27
|
end
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
describe 'GET /projects' do
|
32
|
-
it 'should redirect to /projects/overview' do
|
33
|
-
get '/projects'
|
34
|
-
follow_redirect!
|
35
|
-
|
36
|
-
last_request.url.should =~ /projects\/overview/
|
37
|
-
last_response.should be_ok
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
31
|
describe 'GET /tasks/new' do
|
42
32
|
it 'should display a new task form' do
|
43
33
|
get '/tasks/new'
|
44
|
-
last_response.body.should
|
34
|
+
last_response.body.should include('<form')
|
45
35
|
end
|
46
36
|
|
47
37
|
it 'should display a 200 status code' do
|
@@ -60,13 +50,13 @@ describe TaskwarriorWeb::App do
|
|
60
50
|
end
|
61
51
|
|
62
52
|
it 'should redirect to the task listing page' do
|
63
|
-
task = TaskwarriorWeb::Task.new
|
53
|
+
task = TaskwarriorWeb::Task.new({:description => 'Test task'})
|
64
54
|
task.should_receive(:is_valid?).and_return(true)
|
65
55
|
task.should_receive(:save!)
|
66
56
|
TaskwarriorWeb::Task.should_receive(:new).once.and_return(task)
|
67
|
-
post '/tasks', :task => {}
|
57
|
+
post '/tasks', :task => {:description => 'Test task'}
|
68
58
|
follow_redirect!
|
69
|
-
last_request.url.should
|
59
|
+
last_request.url.should match(/tasks$/)
|
70
60
|
end
|
71
61
|
end
|
72
62
|
|
@@ -82,17 +72,134 @@ describe TaskwarriorWeb::App do
|
|
82
72
|
task = TaskwarriorWeb::Task.new({:tags => 'tag1, tag2'})
|
83
73
|
TaskwarriorWeb::Task.should_receive(:new).once.and_return(task)
|
84
74
|
post '/tasks', :task => {}
|
85
|
-
last_response.body.should
|
86
|
-
last_response.body.should
|
75
|
+
last_response.body.should include('form')
|
76
|
+
last_response.body.should include('tag1, tag2')
|
87
77
|
end
|
88
78
|
|
89
79
|
it 'should display errors messages' do
|
90
80
|
task = TaskwarriorWeb::Task.new
|
91
81
|
TaskwarriorWeb::Task.should_receive(:new).once.and_return(task)
|
92
82
|
post '/tasks', :task => {}
|
93
|
-
last_response.body.should
|
83
|
+
last_response.body.should include('You must provide a description')
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe 'GET /tasks/:uuid' do
|
89
|
+
context 'given a non-existant task' do
|
90
|
+
it 'should return a 404' do
|
91
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([])
|
92
|
+
get '/tasks/1'
|
93
|
+
last_response.should be_not_found
|
94
94
|
end
|
95
95
|
end
|
96
|
+
|
97
|
+
context 'given an existing task' do
|
98
|
+
before do
|
99
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([
|
100
|
+
TaskwarriorWeb::Task.new({:uuid => 246, :description => 'Test task with a longer description'})
|
101
|
+
])
|
102
|
+
get '/tasks/246'
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'should render an edit form' do
|
106
|
+
last_response.body.should have_tag('form', :with => { :action => '/tasks/246', :method => 'post' }) do
|
107
|
+
with_tag('input', :with => { :name => '_method', :value => 'patch' })
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
it 'should set the HTTP method in the form' do
|
112
|
+
end
|
113
|
+
|
114
|
+
it 'should truncate the task description' do
|
115
|
+
last_response.body.should have_tag('title', :text => /Test task with a .../)
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'should fill the form fields with existing data' do
|
119
|
+
last_response.body.should have_tag('input', :with => { :name => 'task[description]', :value => 'Test task with a longer description' })
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'PATCH /tasks/:uuid' do
|
125
|
+
context 'given a non-existant task' do
|
126
|
+
it 'should return a 404' do
|
127
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([])
|
128
|
+
patch '/tasks/429897527'
|
129
|
+
last_response.should be_not_found
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
describe 'GET /tasks/:uuid/delete' do
|
135
|
+
context 'given a non-existant task' do
|
136
|
+
it 'should return a 404' do
|
137
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([])
|
138
|
+
get '/tasks/429897527/delete'
|
139
|
+
last_response.should be_not_found
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
context 'given an existing task' do
|
144
|
+
before do
|
145
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([
|
146
|
+
TaskwarriorWeb::Task.new({:uuid => 246, :description => 'Test task with a longer description'})
|
147
|
+
])
|
148
|
+
get '/tasks/246/delete'
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'should show a delete form' do
|
152
|
+
last_response.body.should have_tag('form', :with => { :action => '/tasks/246', :method => 'post' }) do
|
153
|
+
with_tag('input', :with => { :name => '_method', :value => 'delete' })
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it 'should display a delete button' do
|
158
|
+
last_response.body.should have_tag('input', :with => { :type => 'submit', :value => 'Delete' })
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'DELETE /tasks/:uuid' do
|
164
|
+
context 'given a non-existant task' do
|
165
|
+
it 'should return a 404' do
|
166
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([])
|
167
|
+
delete '/tasks/429897527'
|
168
|
+
last_response.should be_not_found
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
context 'given an existing task' do
|
173
|
+
before do
|
174
|
+
@task = TaskwarriorWeb::Task.new
|
175
|
+
@task.should_receive(:delete!).once.and_return('Success')
|
176
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([@task])
|
177
|
+
delete '/tasks/246'
|
178
|
+
end
|
179
|
+
|
180
|
+
it 'should redirect to the task overview page' do
|
181
|
+
follow_redirect!
|
182
|
+
last_request.url.should match(/tasks$/)
|
183
|
+
end
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe 'GET /projects' do
|
188
|
+
it 'should redirect to /projects/overview' do
|
189
|
+
get '/projects'
|
190
|
+
follow_redirect!
|
191
|
+
|
192
|
+
last_request.url.should match(/projects\/overview$/)
|
193
|
+
last_response.should be_ok
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
describe 'GET /projects/:name' do
|
198
|
+
it 'should replace characters in the title' do
|
199
|
+
TaskwarriorWeb::Task.should_receive(:query).any_number_of_times.and_return([])
|
200
|
+
get '/projects/Test--Project'
|
201
|
+
last_response.body.should include('<title>Test.Project')
|
202
|
+
end
|
96
203
|
end
|
97
204
|
|
98
205
|
describe 'GET /ajax/projects' do
|
@@ -126,12 +233,12 @@ describe TaskwarriorWeb::App do
|
|
126
233
|
describe 'not_found' do
|
127
234
|
it 'should set the title to "Not Found"' do
|
128
235
|
get '/page-not-found'
|
129
|
-
last_response.body.should
|
236
|
+
last_response.body.should include('<title>Page Not Found')
|
130
237
|
end
|
131
238
|
|
132
239
|
it 'should have a status code of 404' do
|
133
240
|
get '/page-not-found'
|
134
|
-
last_response.
|
241
|
+
last_response.should be_not_found
|
135
242
|
end
|
136
243
|
end
|
137
244
|
end
|
data/spec/model/task_spec.rb
CHANGED
@@ -38,6 +38,16 @@ describe TaskwarriorWeb::Task do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
+
describe '#delete!' do
|
42
|
+
it 'should delete the task' do
|
43
|
+
task = TaskwarriorWeb::Task.new({:uuid => 15})
|
44
|
+
command = TaskwarriorWeb::Command.new(:delete)
|
45
|
+
command.should_receive(:run).once
|
46
|
+
TaskwarriorWeb::Command.should_receive(:new).once.with(:delete, 15).and_return(command)
|
47
|
+
task.delete!
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
41
51
|
describe '.query' do
|
42
52
|
before do
|
43
53
|
@command = TaskwarriorWeb::Command.new(:query)
|
@@ -82,6 +92,16 @@ describe TaskwarriorWeb::Task do
|
|
82
92
|
task = TaskwarriorWeb::Task.new(:tags => '@hi, -twice, !again, ~when')
|
83
93
|
task.tags.should eq(['@hi', '-twice', '!again', '~when'])
|
84
94
|
end
|
95
|
+
|
96
|
+
it 'should properly set tags for removal' do
|
97
|
+
task = TaskwarriorWeb::Task.new({:tags => ['hello', 'goodbye']})
|
98
|
+
TaskwarriorWeb::Task.should_receive(:find_by_uuid).and_return([task])
|
99
|
+
task2 = TaskwarriorWeb::Task.new
|
100
|
+
task2.uuid = 15
|
101
|
+
task2.tags = ['goodbye']
|
102
|
+
task2.tags.should eq(['goodbye'])
|
103
|
+
task2.remove_tags.should eq(['hello'])
|
104
|
+
end
|
85
105
|
end
|
86
106
|
|
87
107
|
describe '#to_hash' do
|
@@ -51,6 +51,12 @@ describe TaskwarriorWeb::CommandBuilder::Base do
|
|
51
51
|
command.params.should eq(' +today +tomorrow')
|
52
52
|
end
|
53
53
|
|
54
|
+
it 'should remove tags using a -' do
|
55
|
+
command = TaskwarriorWeb::Command.new(:add, nil, :remove_tags => [:test, :tag])
|
56
|
+
command.parse_params
|
57
|
+
command.params.should eq(' -test -tag')
|
58
|
+
end
|
59
|
+
|
54
60
|
it 'should pull out the description parameter' do
|
55
61
|
command = TaskwarriorWeb::Command.new(:add, nil, :description => 'Hello', :status => :pending)
|
56
62
|
command.parse_params
|
data/spec/spec_helper.rb
CHANGED
data/taskwarrior-web.gemspec
CHANGED
@@ -3,7 +3,7 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
|
4
4
|
Gem::Specification.new do |s|
|
5
5
|
s.name = "taskwarrior-web"
|
6
|
-
s.version = '1.0
|
6
|
+
s.version = '1.1.0'
|
7
7
|
s.platform = Gem::Platform::RUBY
|
8
8
|
s.authors = ["Jake Bell"]
|
9
9
|
s.email = ["jake@theunraveler.com"]
|
@@ -16,17 +16,18 @@ Gem::Specification.new do |s|
|
|
16
16
|
s.required_ruby_version = '>= 1.9.0'
|
17
17
|
|
18
18
|
s.add_dependency('sinatra')
|
19
|
-
s.add_dependency('thin')
|
20
19
|
s.add_dependency('parseconfig')
|
21
20
|
s.add_dependency('vegas')
|
22
21
|
s.add_dependency('rinku')
|
23
22
|
s.add_dependency('versionomy')
|
24
23
|
s.add_dependency('activesupport')
|
25
24
|
s.add_dependency('sinatra-simple-navigation')
|
25
|
+
s.add_dependency('rack-flash3')
|
26
26
|
|
27
27
|
s.add_development_dependency('rake')
|
28
28
|
s.add_development_dependency('rack-test')
|
29
29
|
s.add_development_dependency('rspec')
|
30
|
+
s.add_development_dependency('rspec-html-matchers')
|
30
31
|
|
31
32
|
s.files = `git ls-files`.split("\n")
|
32
33
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: taskwarrior-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sinatra
|
16
|
-
requirement: &
|
16
|
+
requirement: &70274029036160 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '0'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70274029036160
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement: &
|
26
|
+
name: parseconfig
|
27
|
+
requirement: &70274029035440 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ! '>='
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '0'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70274029035440
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
|
-
name:
|
38
|
-
requirement: &
|
37
|
+
name: vegas
|
38
|
+
requirement: &70274029034480 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ! '>='
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: '0'
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70274029034480
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
|
-
name:
|
49
|
-
requirement: &
|
48
|
+
name: rinku
|
49
|
+
requirement: &70274029033940 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: '0'
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70274029033940
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
|
-
name:
|
60
|
-
requirement: &
|
59
|
+
name: versionomy
|
60
|
+
requirement: &70274029032960 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70274029032960
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
|
-
name:
|
71
|
-
requirement: &
|
70
|
+
name: activesupport
|
71
|
+
requirement: &70274029031920 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :runtime
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70274029031920
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
|
-
name:
|
82
|
-
requirement: &
|
81
|
+
name: sinatra-simple-navigation
|
82
|
+
requirement: &70274029031060 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :runtime
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70274029031060
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
|
-
name:
|
93
|
-
requirement: &
|
92
|
+
name: rack-flash3
|
93
|
+
requirement: &70274029030180 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :runtime
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70274029030180
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rake
|
104
|
-
requirement: &
|
104
|
+
requirement: &70274029029420 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70274029029420
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: rack-test
|
115
|
-
requirement: &
|
115
|
+
requirement: &70274029028620 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,10 +120,21 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70274029028620
|
124
124
|
- !ruby/object:Gem::Dependency
|
125
125
|
name: rspec
|
126
|
-
requirement: &
|
126
|
+
requirement: &70274029027800 !ruby/object:Gem::Requirement
|
127
|
+
none: false
|
128
|
+
requirements:
|
129
|
+
- - ! '>='
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: *70274029027800
|
135
|
+
- !ruby/object:Gem::Dependency
|
136
|
+
name: rspec-html-matchers
|
137
|
+
requirement: &70274029027120 !ruby/object:Gem::Requirement
|
127
138
|
none: false
|
128
139
|
requirements:
|
129
140
|
- - ! '>='
|
@@ -131,7 +142,7 @@ dependencies:
|
|
131
142
|
version: '0'
|
132
143
|
type: :development
|
133
144
|
prerelease: false
|
134
|
-
version_requirements: *
|
145
|
+
version_requirements: *70274029027120
|
135
146
|
description: This gem provides a graphical frontend for the Taskwarrior task manager.
|
136
147
|
It is based on Sinatra.
|
137
148
|
email:
|
@@ -179,13 +190,17 @@ files:
|
|
179
190
|
- lib/taskwarrior-web/services/parser/json.rb
|
180
191
|
- lib/taskwarrior-web/services/runner.rb
|
181
192
|
- lib/taskwarrior-web/views/404.erb
|
193
|
+
- lib/taskwarrior-web/views/_flash.erb
|
182
194
|
- lib/taskwarrior-web/views/_subnav.erb
|
195
|
+
- lib/taskwarrior-web/views/_task_form.erb
|
183
196
|
- lib/taskwarrior-web/views/_topbar.erb
|
197
|
+
- lib/taskwarrior-web/views/delete_confirm.erb
|
198
|
+
- lib/taskwarrior-web/views/edit_task.erb
|
184
199
|
- lib/taskwarrior-web/views/layout.erb
|
185
200
|
- lib/taskwarrior-web/views/listing.erb
|
201
|
+
- lib/taskwarrior-web/views/new_task.erb
|
186
202
|
- lib/taskwarrior-web/views/project.erb
|
187
203
|
- lib/taskwarrior-web/views/projects.erb
|
188
|
-
- lib/taskwarrior-web/views/task_form.erb
|
189
204
|
- spec/app/app_spec.rb
|
190
205
|
- spec/app/helpers_spec.rb
|
191
206
|
- spec/files/taskrc
|
@@ -219,7 +234,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
234
|
version: '0'
|
220
235
|
segments:
|
221
236
|
- 0
|
222
|
-
hash:
|
237
|
+
hash: 649655695520079499
|
223
238
|
requirements: []
|
224
239
|
rubyforge_project: taskwarrior-web
|
225
240
|
rubygems_version: 1.8.11
|
@@ -1,38 +0,0 @@
|
|
1
|
-
<form id="new-task-form" class="form-horizontal" action="/tasks" method="post">
|
2
|
-
|
3
|
-
<div class="control-group">
|
4
|
-
<label for="task-description" class="control-label">Description</label>
|
5
|
-
<div class="controls">
|
6
|
-
<input type="textfield" id="task-description" name="task[description]" value="<%= @task.description unless @task.nil? %>" />
|
7
|
-
</div>
|
8
|
-
</div>
|
9
|
-
|
10
|
-
<div class="control-group">
|
11
|
-
<label for="task-project" class="control-label">Project</label>
|
12
|
-
<div class="controls">
|
13
|
-
<input type="textfield" id="task-project" name="task[project]" value="<%= @task.project unless @task.nil? %>" autocomplete="off" />
|
14
|
-
</div>
|
15
|
-
</div>
|
16
|
-
|
17
|
-
<div class="control-group">
|
18
|
-
<label for="task-due" class="control-label">Due Date</label>
|
19
|
-
<div class="controls">
|
20
|
-
<input class="date-picker" type="textfield" id="task-due" name="task[due]" value="<%= @task.due unless @task.nil? %>" data-date-format="<%= @date_format %>" />
|
21
|
-
</div>
|
22
|
-
</div>
|
23
|
-
|
24
|
-
<div class="control-group">
|
25
|
-
<label for="task-tags" class="control-label">Tags</label>
|
26
|
-
<div class="controls">
|
27
|
-
<input type="textfield" id="task-tags" name="task[tags]" value="<%= @task.tags.join(', ') unless @task.nil? %>" autocomplete="off" />
|
28
|
-
<span class="help-block">Enter tags separated by commas or spaces (e.g. <em>each, word will,be a tag</em>)</span>
|
29
|
-
</div>
|
30
|
-
</div>
|
31
|
-
|
32
|
-
<div class="control-group">
|
33
|
-
<div class="controls">
|
34
|
-
<button type="submit" class="btn">Create Task</button>
|
35
|
-
</div>
|
36
|
-
</div>
|
37
|
-
|
38
|
-
</form>
|