taskwarrior-web 1.0.3 → 1.0.4

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/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## v1.0.4 (9/25/12)
2
+
3
+ * Added TokenInput plugin for tagging tasks
4
+ * Fixed form validation when saving a task
5
+
6
+ ## v1.0.3 (8/27/12)
7
+
8
+ * Moved to new theme based on Twitter Bootstrap. Hopefully, this will make
9
+ a mobile theme easier.
10
+ * Fixed bug when completing tasks
11
+
1
12
  ## v1.0.2 (4/3/12)
2
13
 
3
14
  * Hotfix for error in JS file.
data/README.md CHANGED
@@ -4,6 +4,8 @@ A lightweight, Sinatra-based web interface for the
4
4
  wonderful [Taskwarrior](http://taskwarrior.org/) todo application.
5
5
 
6
6
  **Now compatible with ALL versions of Taskwarrior, including the new 2.0.0**
7
+ **Also, now including a NEW theme based on Twitter Bootstrap. Mobile version
8
+ forthcoming!**
7
9
 
8
10
  [![Build Status](https://secure.travis-ci.org/theunraveler/taskwarrior-web.png)](http://travis-ci.org/theunraveler/taskwarrior-web)
9
11
 
@@ -68,11 +68,14 @@ module TaskwarriorWeb
68
68
  redirect '/tasks'
69
69
  else
70
70
  @task = params[:task]
71
+ @title = 'New Task'
72
+ @date_format = TaskwarriorWeb::Config.dateformat || 'm/d/yy'
73
+ @date_format.gsub!('Y', 'yy')
71
74
  @messages = []
72
75
  results.each do |result|
73
76
  @messages << { :severity => 'alert-error', :message => result }
74
77
  end
75
- redirect '/tasks/new'
78
+ erb :task_form
76
79
  end
77
80
  end
78
81
 
@@ -102,7 +105,15 @@ module TaskwarriorWeb
102
105
  end
103
106
 
104
107
  get '/ajax/tags/?' do
105
- TaskwarriorWeb::Command.new(:tags).run.split("\n").to_json
108
+ tags = TaskwarriorWeb::Command.new(:tags).run.split("\n")
109
+ tags.keep_if { |tag| tag.include?(params[:query]) }
110
+
111
+ json = []
112
+ tags.each do |tag|
113
+ json << { :name => tag, :id => tag }
114
+ end
115
+
116
+ json.to_json
106
117
  end
107
118
 
108
119
  get '/ajax/count/?' do
@@ -38,17 +38,17 @@ module TaskwarriorWeb::CommandBuilder
38
38
 
39
39
  def parse_params
40
40
  string = ''
41
- string << " '#{@params.delete(:description)}'" if @params.has_key?(:description)
41
+ string << " #{@params.delete(:description).shellescape}" if @params.has_key?(:description)
42
42
 
43
43
  if @params.has_key?(:tags)
44
44
  tags = @params.delete(:tags)
45
45
  tag_indicator = TaskwarriorWeb::Config.property('tag.indicator') || '+'
46
- tags.each { |tag| string << " #{tag_indicator}#{tag.to_s}" }
46
+ tags.each { |tag| string << " #{tag_indicator}#{tag.to_s.shellescape}" }
47
47
  end
48
48
 
49
49
  @params.each do |attr, value|
50
50
  if value.respond_to? :each
51
- value.each { |val| string << " #{attr.to_s}:#{val.to_s}" }
51
+ value.each { |val| string << " #{attr.to_s}:#{val.to_s.shellescape}" }
52
52
  else
53
53
  string << " #{attr.to_s}:#{value.to_s}"
54
54
  end
@@ -0,0 +1,122 @@
1
+ /* Example tokeninput style #2: Facebook style */
2
+ ul.token-input-list-facebook {
3
+ overflow: hidden;
4
+ height: auto !important;
5
+ height: 1%;
6
+ width: 400px;
7
+ border: 1px solid #8496ba;
8
+ cursor: text;
9
+ font-size: 12px;
10
+ font-family: Verdana, sans-serif;
11
+ min-height: 1px;
12
+ z-index: 999;
13
+ margin: 0;
14
+ padding: 0;
15
+ background-color: #fff;
16
+ list-style-type: none;
17
+ clear: left;
18
+ }
19
+
20
+ ul.token-input-list-facebook li input {
21
+ border: 0;
22
+ width: 100px;
23
+ padding: 3px 8px;
24
+ background-color: white;
25
+ margin: 2px 0;
26
+ -webkit-appearance: caret;
27
+ }
28
+
29
+ li.token-input-token-facebook {
30
+ overflow: hidden;
31
+ height: auto !important;
32
+ height: 15px;
33
+ margin: 3px;
34
+ padding: 1px 3px;
35
+ background-color: #eff2f7;
36
+ color: #000;
37
+ cursor: default;
38
+ border: 1px solid #ccd5e4;
39
+ font-size: 11px;
40
+ border-radius: 5px;
41
+ -moz-border-radius: 5px;
42
+ -webkit-border-radius: 5px;
43
+ float: left;
44
+ white-space: nowrap;
45
+ }
46
+
47
+ li.token-input-token-facebook p {
48
+ display: inline;
49
+ padding: 0;
50
+ margin: 0;
51
+ }
52
+
53
+ li.token-input-token-facebook span {
54
+ color: #a6b3cf;
55
+ margin-left: 5px;
56
+ font-weight: bold;
57
+ cursor: pointer;
58
+ }
59
+
60
+ li.token-input-selected-token-facebook {
61
+ background-color: #5670a6;
62
+ border: 1px solid #3b5998;
63
+ color: #fff;
64
+ }
65
+
66
+ li.token-input-input-token-facebook {
67
+ float: left;
68
+ margin: 0;
69
+ padding: 0;
70
+ list-style-type: none;
71
+ }
72
+
73
+ div.token-input-dropdown-facebook {
74
+ position: absolute;
75
+ width: 400px;
76
+ background-color: #fff;
77
+ overflow: hidden;
78
+ border-left: 1px solid #ccc;
79
+ border-right: 1px solid #ccc;
80
+ border-bottom: 1px solid #ccc;
81
+ cursor: default;
82
+ font-size: 11px;
83
+ font-family: Verdana, sans-serif;
84
+ z-index: 1;
85
+ }
86
+
87
+ div.token-input-dropdown-facebook p {
88
+ margin: 0;
89
+ padding: 5px;
90
+ font-weight: bold;
91
+ color: #777;
92
+ }
93
+
94
+ div.token-input-dropdown-facebook ul {
95
+ margin: 0;
96
+ padding: 0;
97
+ }
98
+
99
+ div.token-input-dropdown-facebook ul li {
100
+ background-color: #fff;
101
+ padding: 3px;
102
+ margin: 0;
103
+ list-style-type: none;
104
+ }
105
+
106
+ div.token-input-dropdown-facebook ul li.token-input-dropdown-item-facebook {
107
+ background-color: #fff;
108
+ }
109
+
110
+ div.token-input-dropdown-facebook ul li.token-input-dropdown-item2-facebook {
111
+ background-color: #fff;
112
+ }
113
+
114
+ div.token-input-dropdown-facebook ul li em {
115
+ font-weight: bold;
116
+ font-style: normal;
117
+ }
118
+
119
+ div.token-input-dropdown-facebook ul li.token-input-selected-dropdown-item-facebook {
120
+ background-color: #3b5998;
121
+ color: #fff;
122
+ }
@@ -0,0 +1,127 @@
1
+ /* Example tokeninput style #1: Token vertical list*/
2
+ ul.token-input-list {
3
+ overflow: hidden;
4
+ height: auto !important;
5
+ height: 1%;
6
+ width: 400px;
7
+ border: 1px solid #999;
8
+ cursor: text;
9
+ font-size: 12px;
10
+ font-family: Verdana, sans-serif;
11
+ z-index: 999;
12
+ margin: 0;
13
+ padding: 0;
14
+ background-color: #fff;
15
+ list-style-type: none;
16
+ clear: left;
17
+ }
18
+
19
+ ul.token-input-list li {
20
+ list-style-type: none;
21
+ }
22
+
23
+ ul.token-input-list li input {
24
+ border: 0;
25
+ width: 350px;
26
+ padding: 3px 8px;
27
+ background-color: white;
28
+ -webkit-appearance: caret;
29
+ }
30
+
31
+ ul.token-input-disabled,
32
+ ul.token-input-disabled li input {
33
+ background-color: #E8E8E8;
34
+ }
35
+
36
+ ul.token-input-disabled li.token-input-token {
37
+ background-color: #D9E3CA;
38
+ color: #7D7D7D
39
+ }
40
+
41
+ ul.token-input-disabled li.token-input-token span {
42
+ color: #CFCFCF;
43
+ cursor: default;
44
+ }
45
+
46
+ li.token-input-token {
47
+ overflow: hidden;
48
+ height: auto !important;
49
+ height: 1%;
50
+ margin: 3px;
51
+ padding: 3px 5px;
52
+ background-color: #d0efa0;
53
+ color: #000;
54
+ font-weight: bold;
55
+ cursor: default;
56
+ display: block;
57
+ }
58
+
59
+ li.token-input-token p {
60
+ float: left;
61
+ padding: 0;
62
+ margin: 0;
63
+ }
64
+
65
+ li.token-input-token span {
66
+ float: right;
67
+ color: #777;
68
+ cursor: pointer;
69
+ }
70
+
71
+ li.token-input-selected-token {
72
+ background-color: #08844e;
73
+ color: #fff;
74
+ }
75
+
76
+ li.token-input-selected-token span {
77
+ color: #bbb;
78
+ }
79
+
80
+ div.token-input-dropdown {
81
+ position: absolute;
82
+ width: 400px;
83
+ background-color: #fff;
84
+ overflow: hidden;
85
+ border-left: 1px solid #ccc;
86
+ border-right: 1px solid #ccc;
87
+ border-bottom: 1px solid #ccc;
88
+ cursor: default;
89
+ font-size: 12px;
90
+ font-family: Verdana, sans-serif;
91
+ z-index: 1;
92
+ }
93
+
94
+ div.token-input-dropdown p {
95
+ margin: 0;
96
+ padding: 5px;
97
+ font-weight: bold;
98
+ color: #777;
99
+ }
100
+
101
+ div.token-input-dropdown ul {
102
+ margin: 0;
103
+ padding: 0;
104
+ }
105
+
106
+ div.token-input-dropdown ul li {
107
+ background-color: #fff;
108
+ padding: 3px;
109
+ list-style-type: none;
110
+ }
111
+
112
+ div.token-input-dropdown ul li.token-input-dropdown-item {
113
+ background-color: #fafafa;
114
+ }
115
+
116
+ div.token-input-dropdown ul li.token-input-dropdown-item2 {
117
+ background-color: #fff;
118
+ }
119
+
120
+ div.token-input-dropdown ul li em {
121
+ font-weight: bold;
122
+ font-style: normal;
123
+ }
124
+
125
+ div.token-input-dropdown ul li.token-input-selected-dropdown-item {
126
+ background-color: #d0efa0;
127
+ }
@@ -4,9 +4,7 @@ $(document).ready(function() {
4
4
  initTaskCompletion();
5
5
 
6
6
  // Fluid-specific stuff.
7
- //if (typeof window.fluid !== undefined) {
8
- //refreshDockBadge();
9
- //}
7
+ refreshDockBadge();
10
8
  });
11
9
 
12
10
  var refreshPageContents = function() {
@@ -36,10 +34,12 @@ var initAutocomplete = function() {
36
34
  }
37
35
  });
38
36
 
39
- //$('#task-tags').tagsInput({
40
- //autocomplete_url: '/ajax/tags',
41
- //defaultText: ''
42
- //});
37
+ $('#task-tags').tokenInput('/ajax/tags', {
38
+ theme: 'facebook',
39
+ queryParam: 'query',
40
+ noResultsText: 'No matching tags',
41
+ allowFreeTagging: true
42
+ });
43
43
  };
44
44
 
45
45
  var initTaskCompletion = function() {
@@ -76,9 +76,11 @@ var getCount = function(callback) {
76
76
  };
77
77
 
78
78
  var refreshDockBadge = function() {
79
- getCount(function(data) {
80
- window.fluid.dockBadge = data;
81
- });
79
+ if (window.hasOwnProperty('fluid')) {
80
+ getCount(function(data) {
81
+ window.fluid.dockBadge = data;
82
+ });
83
+ }
82
84
  };
83
85
 
84
86
  var refreshSubnavCount = function() {