taskwarrior-web 0.0.1

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.
Files changed (49) hide show
  1. data/.gitignore +1 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +4 -0
  4. data/README.md +6 -0
  5. data/Rakefile +2 -0
  6. data/bin/task-web +10 -0
  7. data/config.ru +9 -0
  8. data/lib/taskwarrior-web/app.rb +172 -0
  9. data/lib/taskwarrior-web/config.rb +11 -0
  10. data/lib/taskwarrior-web/task.rb +131 -0
  11. data/lib/taskwarrior-web/version.rb +3 -0
  12. data/lib/taskwarrior-web.rb +8 -0
  13. data/public/css/gh-buttons.css +388 -0
  14. data/public/css/jquery-ui.css +738 -0
  15. data/public/css/jquery.tagsinput.css +6 -0
  16. data/public/css/styles.css +283 -0
  17. data/public/css/tipsy.css +7 -0
  18. data/public/favicon.ico +0 -0
  19. data/public/images/ajax-loader.gif +0 -0
  20. data/public/images/arrow_right_black.png +0 -0
  21. data/public/images/arrow_right_grey.png +0 -0
  22. data/public/images/bg_fallback.png +0 -0
  23. data/public/images/gh-icons.png +0 -0
  24. data/public/images/grid-view.png +0 -0
  25. data/public/images/icon_sprite.png +0 -0
  26. data/public/images/list-view.png +0 -0
  27. data/public/images/logo.png +0 -0
  28. data/public/images/progress_bar.gif +0 -0
  29. data/public/images/slider_handles.png +0 -0
  30. data/public/images/subnav_background.gif +0 -0
  31. data/public/images/tab_background.gif +0 -0
  32. data/public/images/tipsy.gif +0 -0
  33. data/public/images/ui-icons_222222_256x240.png +0 -0
  34. data/public/images/ui-icons_454545_256x240.png +0 -0
  35. data/public/js/application.js +130 -0
  36. data/public/js/jquery-ui.min.js +163 -0
  37. data/public/js/jquery.cookie.js +96 -0
  38. data/public/js/jquery.min.js +16 -0
  39. data/public/js/jquery.tagsinput.js +218 -0
  40. data/public/js/jquery.tipsy.js +104 -0
  41. data/taskwarrior-web.gemspec +25 -0
  42. data/views/404.erb +3 -0
  43. data/views/_navigation.erb +21 -0
  44. data/views/layout.erb +47 -0
  45. data/views/listing.erb +29 -0
  46. data/views/project.erb +25 -0
  47. data/views/projects.erb +35 -0
  48. data/views/task_form.erb +28 -0
  49. metadata +134 -0
@@ -0,0 +1,6 @@
1
+ div.tagsinput { border:1px solid #CCC; background: #FFF; padding:5px; width:300px; height:100px; overflow-y: auto;}
2
+ div.tagsinput span.tag { border: 1px solid #a5d24a; -moz-border-radius:2px; -webkit-border-radius:2px; display: block; float: left; padding: 5px; text-decoration:none; background: #cde69c; color: #638421; margin-right: 5px; margin-bottom:5px;font-family: helvetica; font-size:13px;}
3
+ div.tagsinput span.tag a { font-weight: bold; color: #82ad2b; text-decoration:none; font-size: 11px; }
4
+ div.tagsinput input { width:80px; margin:0px; font-family: helvetica; font-size: 13px; border:1px solid transparent; padding:5px; background: transparent; color: #000; outline:0px; margin-right:5px; margin-bottom:5px; }
5
+ div.tagsinput div { display:block; float: left; }
6
+ .tags_clear { clear: both; width: 100%; height: 0px; }
@@ -0,0 +1,283 @@
1
+ /* http://meyerweb.com/eric/tools/css/reset/
2
+ v2.0 | 20110126
3
+ License: none (public domain)
4
+ */
5
+
6
+ html, body, div, span, applet, object, iframe,
7
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
8
+ a, abbr, acronym, address, big, cite, code,
9
+ del, dfn, em, img, ins, kbd, q, s, samp,
10
+ small, strike, strong, sub, sup, tt, var,
11
+ b, u, i, center,
12
+ dl, dt, dd, ol, ul, li,
13
+ fieldset, form, label, legend,
14
+ table, caption, tbody, tfoot, thead, tr, th, td,
15
+ article, aside, canvas, details, embed,
16
+ figure, figcaption, footer, header, hgroup,
17
+ menu, nav, output, ruby, section, summary,
18
+ time, mark, audio, video {
19
+ margin: 0;
20
+ padding: 0;
21
+ border: 0;
22
+ font-size: 100%;
23
+ font: inherit;
24
+ vertical-align: baseline;
25
+ }
26
+ /* HTML5 display-role reset for older browsers */
27
+ article, aside, details, figcaption, figure,
28
+ footer, header, hgroup, menu, nav, section {
29
+ display: block;
30
+ }
31
+ body {
32
+ line-height: 1;
33
+ }
34
+ ol, ul {
35
+ list-style: none;
36
+ }
37
+ blockquote, q {
38
+ quotes: none;
39
+ }
40
+ blockquote:before, blockquote:after,
41
+ q:before, q:after {
42
+ content: '';
43
+ content: none;
44
+ }
45
+ table {
46
+ border-collapse: collapse;
47
+ border-spacing: 0;
48
+ }
49
+
50
+ /********************************
51
+ * UTILITY CLASSES
52
+ *******************************/
53
+ .clearer { clear: both; }
54
+
55
+ body {
56
+ font: 13.34px helvetica,arial,sans-serif;
57
+ }
58
+
59
+ #page { width: 960px; margin: 30px auto; }
60
+
61
+ h1 {
62
+ float: left;
63
+ padding-top: 0px;
64
+ margin-top: 0px;
65
+ width: 270px;
66
+ height: 55px;
67
+ background: url(/images/logo.png) no-repeat center center;
68
+ text-indent: -9999px;
69
+ }
70
+
71
+ h2 { font-size: 1.5em; font-weight: bold; margin: 20px 0; width: 70%; float: left; }
72
+ h3 { font-size: 1.25em; font-weight: bold; margin: 20px 0; }
73
+
74
+ th { text-align: left; }
75
+
76
+ /********************************
77
+ * POLLING
78
+ *******************************/
79
+ #polling-info {
80
+ width: auto;
81
+ float: right;
82
+ position:relative;
83
+ top: 15px;
84
+ }
85
+
86
+ /********************************
87
+ * NAVIGATION
88
+ *******************************/
89
+ #navigation ul.tabs {
90
+ background: url("/images/tab_background.gif") repeat-x scroll 0 0 transparent;
91
+ border: 1px solid #DDDDDD;
92
+ border-radius: 5px 5px 0 0;
93
+ height: 26px;
94
+ margin: 10px 0 0;
95
+ padding: 6px 10px;
96
+ position: relative;
97
+ }
98
+ #navigation ul.tabs li {
99
+ display: inline;
100
+ list-style-type: none;
101
+ margin: 0;
102
+ }
103
+ #navigation ul.tabs li a {
104
+ border-radius: 4px 4px 4px 4px;
105
+ color: #666666;
106
+ float: left;
107
+ font-size: 14px;
108
+ height: 26px;
109
+ line-height: 26px;
110
+ margin-right: 10px;
111
+ padding: 0 8px;
112
+ text-decoration: none;
113
+ text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.7);
114
+ }
115
+ #navigation ul.tabs li a:hover {
116
+ background-color: #CCCCCC;
117
+ color: #333333;
118
+ text-decoration: none;
119
+ }
120
+ #navigation ul.tabs li a.selected {
121
+ -moz-border-bottom-colors: none;
122
+ -moz-border-image: none;
123
+ -moz-border-left-colors: none;
124
+ -moz-border-right-colors: none;
125
+ -moz-border-top-colors: none;
126
+ background: none repeat scroll 0 0 #FFFFFF;
127
+ border-color: #CCCCCC #EEEEEE #EEEEEE #CCCCCC;
128
+ border-style: solid;
129
+ border-width: 1px;
130
+ color: #333333;
131
+ font-weight: bold;
132
+ position: relative;
133
+ top: -1px;
134
+ }
135
+
136
+ /********************************
137
+ * SUB-NAVIGATION
138
+ *******************************/
139
+ #subnav-bar {
140
+ -moz-border-bottom-colors: none;
141
+ -moz-border-image: none;
142
+ -moz-border-left-colors: none;
143
+ -moz-border-right-colors: none;
144
+ -moz-border-top-colors: none;
145
+ background: url("/images/subnav_background.gif") repeat-x scroll 0 0 transparent;
146
+ border-bottom-left-radius: 5px;
147
+ border-bottom-right-radius: 5px;
148
+ border-color: #FAFAFA #DDDDDD #D2D2D2;
149
+ border-left: 1px solid #DDDDDD;
150
+ border-right: 1px solid #DDDDDD;
151
+ border-style: solid;
152
+ border-width: 1px;
153
+ height: 30px;
154
+ padding: 0 10px;
155
+ position: relative;
156
+ z-index: 3;
157
+ }
158
+ #subnav-bar > ul {
159
+ margin: 4px 0 0 1px;
160
+ position: relative;
161
+ }
162
+ #subnav-bar > ul > li {
163
+ float: left;
164
+ list-style-type: none;
165
+ margin-right: 10px;
166
+ position: relative;
167
+ }
168
+ #subnav-bar > ul > li > a {
169
+ border: 1px solid transparent;
170
+ border-radius: 3px 3px 3px 3px;
171
+ color: #666666;
172
+ display: block;
173
+ font-size: 11px;
174
+ height: 15px;
175
+ padding: 3px 5px;
176
+ position: relative;
177
+ text-decoration: none;
178
+ z-index: 5;
179
+ }
180
+ #subnav-bar > ul > li:hover > a {
181
+ background-color: #F8F8F8;
182
+ border-color: #CCCCCC;
183
+ color: #333333;
184
+ }
185
+ #subnav-bar > ul > li > a.selected {
186
+ background: none repeat scroll 0 0 #DDDDDD;
187
+ border-color: #C5C5C5 #EEEEEE #EEEEEE #C5C5C5;
188
+ color: #000000;
189
+ cursor: default;
190
+ font-weight: bold;
191
+ text-shadow: 1px 1px 0 rgba(255, 255, 255, 0.6);
192
+ }
193
+ #subnav-bar > ul > li > ul {
194
+ background: none repeat scroll 0 0 #F8F8F8;
195
+ border: 1px solid #CCCCCC;
196
+ display: none;
197
+ max-height: 275px;
198
+ overflow: auto;
199
+ position: absolute;
200
+ top: 22px;
201
+ z-index: 4;
202
+ }
203
+ #subnav-bar > ul > li:hover > ul {
204
+ display: block;
205
+ margin: 0;
206
+ min-width: 180px;
207
+ }
208
+ #subnav-bar > ul > li > ul > li {
209
+ border-top: 1px solid #E2E2E2;
210
+ font-size: 11px;
211
+ list-style-type: none;
212
+ margin: 0;
213
+ }
214
+ #subnav-bar > ul > li > ul > li:first-child {
215
+ border-top: medium none;
216
+ }
217
+ #subnav-bar > ul > li > ul > li > a, .subnav-bar > ul > li > ul > li > strong {
218
+ display: block;
219
+ font-weight: normal;
220
+ padding: 4px 5px;
221
+ }
222
+ #subnav-bar > ul > li > ul > li > a {
223
+ font-weight: bold;
224
+ }
225
+ #subnav-bar > ul > li > ul > li > a:hover {
226
+ background-color: #EEEEEE;
227
+ text-decoration: none;
228
+ }
229
+
230
+ ul.view-mode-group { float: right; position: relative; top: -32px; right: 10px; }
231
+ li.view-mode a { height: 12px; width: 12px; }
232
+
233
+ a#task-add { float: right; margin: 20px 0; }
234
+ /********************************
235
+ * LISTING STYLES
236
+ *******************************/
237
+ #listing table { width: 100%; }
238
+ #listing table tr th { background: #eaeaea; color: #222; }
239
+ #listing table tr td,
240
+ #listing table tr th { padding: 10px 10px 10px 0; border-bottom: 1px solid #ddd; }
241
+ #listing table tr td:first-child,
242
+ #listing table tr th:first-child { padding-left: 10px; }
243
+
244
+ /********************************
245
+ * TASK COLORS
246
+ *******************************/
247
+ #listing table tr.overdue { background: #fdd; }
248
+ #listing table tr.today { background: #ffc; }
249
+ #listing table tr.due { background: #BBFFB6; }
250
+ #listing table tr.completed { text-decoration: line-through; }
251
+ #listing table tr.deleted { }
252
+
253
+ #listing .project-container { margin-bottom: 10px; }
254
+ h3.project a {
255
+ color: #000;
256
+ text-decoration: none;
257
+ width: auto;
258
+ float: left;
259
+ margin-bottom: 10px;
260
+ background: url(/images/arrow_right_grey.png) no-repeat right center;
261
+ padding-right: 20px;
262
+ }
263
+ h3.project a:hover {
264
+ background: url(/images/arrow_right_black.png) no-repeat right center;
265
+ }
266
+ h3.project.done a { color: #ddd; }
267
+ .doneness-container { border: 1px solid #eee; float: right; margin-top: 20px; width: 200px; height: 20px; }
268
+ .doneness-measure { background: #BBFFB6; height: 16px; text-align: center; padding-top: 4px; color: #bbb; font-size: 0.8em; }
269
+
270
+ /********************************
271
+ * INPLACE EDITING
272
+ *******************************/
273
+ .inplace-text { width: 250px; height: 30px; padding: 5px; }
274
+ .inplace-edit, .inplace-cancel { font-style: italic; }
275
+
276
+ /********************************
277
+ * TASK FORM
278
+ *******************************/
279
+ .form-element { padding: 10px 0; }
280
+ .form-element label { width: 200px; }
281
+ input[type=textfield] { width: 300px; height: 25px; padding: 5px; }
282
+ .form-element .description { font-size: 0.8em; font-style: italic; color: #999; }
283
+ #task-tags_tag { border: none; -webkit-box-shadow: none, -moz-box-shadow: none; box-shadow: none; }
@@ -0,0 +1,7 @@
1
+ .tipsy { padding: 5px; font-size: 10px; opacity: 0.8; filter: alpha(opacity=80); background-repeat: no-repeat; background-image: url(../images/tipsy.gif); }
2
+ .tipsy-inner { padding: 5px 8px 4px 8px; background-color: black; color: white; max-width: 200px; text-align: center; }
3
+ .tipsy-inner { -moz-border-radius:3px; -webkit-border-radius:3px; }
4
+ .tipsy-north { background-position: top center; }
5
+ .tipsy-south { background-position: bottom center; }
6
+ .tipsy-east { background-position: right center; }
7
+ .tipsy-west { background-position: left center; }
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,130 @@
1
+ $(document).ready(function() {
2
+ initPolling();
3
+ initTooltips();
4
+ initCompleteTask();
5
+ initDatePicker();
6
+ initAutocomplete();
7
+ });
8
+
9
+ var initPolling = function() {
10
+ var polling;
11
+ if (polling = $.cookie('taskwarrior-web-polling')) {
12
+ var pollingInterval = startPolling();
13
+ } else {
14
+ $('#polling-info a').text('Start polling');
15
+ }
16
+
17
+ $('#polling-info a').click(function(e) {
18
+ if (polling) {
19
+ window.clearInterval(pollingInterval);
20
+ polling = false;
21
+ $(this).text('Start polling');
22
+ $.cookie('taskwarrior-web-polling', null);
23
+ } else {
24
+ pollingInterval = startPolling();
25
+ polling = true;
26
+ $(this).text('Stop polling');
27
+ $.cookie('taskwarrior-web-polling', true);
28
+ }
29
+ e.preventDefault();
30
+ });
31
+ };
32
+
33
+ var startPolling = function() {
34
+ var pollingInterval = window.setInterval('refreshPageContents()', 3000);
35
+ return pollingInterval;
36
+ };
37
+
38
+ var refreshPageContents = function() {
39
+ $.ajax({
40
+ url: window.location,
41
+ success: function(data) {
42
+ $('#listing').replaceWith($('#listing', data));
43
+ }
44
+ });
45
+ };
46
+
47
+ var initTooltips = function() {
48
+ $('.tooltip').tipsy({
49
+ title: 'data-tooltip',
50
+ gravity: 's'
51
+ });
52
+ };
53
+
54
+ var initCompleteTask = function() {
55
+ $('input.pending').live('change', function() {
56
+ var checkbox = $(this);
57
+ var row = checkbox.closest('tr');
58
+ var task_id = $(this).data('task');
59
+ $.ajax({
60
+ url: '/tasks/' + task_id + '/complete',
61
+ type: 'post',
62
+ beforeSend: function() {
63
+ checkbox.replaceWith('<img src="/images/ajax-loader.gif" />');
64
+ },
65
+ success: function(data) {
66
+ row.fadeOut('slow', function() {
67
+ row.remove();
68
+ // TODO: Wow. This is nasty.
69
+ var subnavItem = $('#subnav-bar ul li:first-child a');
70
+ var oldCount = subnavItem.text().match(/((\d))/);
71
+ var newCount = parseInt(oldCount[0]) - 1
72
+ var newVal = subnavItem.text().replace(oldCount[0], newCount);
73
+ console.log(newVal);
74
+ subnavItem.text(newVal);
75
+ });
76
+ }
77
+ });
78
+ });
79
+ };
80
+
81
+ var initInPlaceEditing = function() {
82
+ // Hide it initially.
83
+ $('.inplace-edit').hide();
84
+ $('#listing table td').live('mouseover mouseout', function(e) {
85
+ if (e.type == 'mouseover') {
86
+ $('.inplace-edit', this).show();
87
+ } else {
88
+ $('.inplace-edit', this).hide();
89
+ }
90
+ });
91
+
92
+ $('.inplace-edit').live('click', function() {
93
+ var field = $($(this).siblings('span')[0]);
94
+ var formElement = '<input type="text" class="inplace-text" value="'+field.text()+'" />';
95
+ formElement += '<button type="submit" class="inplace-submit">Update</button>';
96
+ formElement += '<a href="javascript:void(0);" class="inplace-cancel">Cancel</a>';
97
+ field.replaceWith(formElement);
98
+ $(this).remove();
99
+ });
100
+
101
+ $('.inplace-cancel').live('click', function() {
102
+ var td = $(this).closest('td');
103
+ var oldField = '<span class="description">'+$($(this).siblings('.inplace-text')[0]).val()+'</span>';
104
+ oldField += '<a class="inplace-edit" href="javascript:void(0);">Edit</a>';
105
+ td.html(oldField);
106
+ });
107
+ };
108
+
109
+ var initDatePicker = function() {
110
+ $('.datefield input').datepicker({
111
+ dateFormat: $('.datefield input').data('format'),
112
+ autoSize: true
113
+ });
114
+ };
115
+
116
+ var initAutocomplete = function() {
117
+ $('#task-project').autocomplete({
118
+ source: '/ajax/projects'
119
+ });
120
+
121
+ $('#task-tags').tagsInput({
122
+ autocomplete_url: '/ajax/tags',
123
+ defaultText: ''
124
+ });
125
+ };
126
+
127
+ function set_message(msg, severity) {
128
+ severity = severity ? severity : 'info';
129
+ $('#flash-messages').append('<div class="message ' + severity + '">' + msg + '</div>');
130
+ }