watch_tower 0.0.0.1 → 0.0.1.beta1

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 (106) hide show
  1. data/.todo +3 -0
  2. data/.travis.yml +4 -0
  3. data/Gemfile +0 -4
  4. data/README.md +48 -2
  5. data/TODO +3 -0
  6. data/ci/travis.rb +4 -1
  7. data/lib/watch_tower/appscript.rb +65 -7
  8. data/lib/watch_tower/cli/install.rb +27 -3
  9. data/lib/watch_tower/cli/open.rb +2 -0
  10. data/lib/watch_tower/cli/start.rb +3 -1
  11. data/lib/watch_tower/cli.rb +2 -0
  12. data/lib/watch_tower/config.rb +2 -0
  13. data/lib/watch_tower/core_ext.rb +2 -0
  14. data/lib/watch_tower/editor/base_appscript.rb +28 -1
  15. data/lib/watch_tower/editor/base_ps.rb +25 -0
  16. data/lib/watch_tower/editor/textmate.rb +2 -0
  17. data/lib/watch_tower/editor/xcode.rb +2 -0
  18. data/lib/watch_tower/editor.rb +2 -0
  19. data/lib/watch_tower/errors.rb +2 -0
  20. data/lib/watch_tower/eye.rb +13 -2
  21. data/lib/watch_tower/file_tree.rb +78 -0
  22. data/lib/watch_tower/project/any_based.rb +2 -0
  23. data/lib/watch_tower/project/git_based.rb +2 -0
  24. data/lib/watch_tower/project/init.rb +2 -0
  25. data/lib/watch_tower/project/path_based.rb +2 -0
  26. data/lib/watch_tower/project.rb +2 -0
  27. data/lib/watch_tower/server/app.rb +37 -7
  28. data/lib/watch_tower/server/assets/javascripts/application.js +4 -0
  29. data/lib/watch_tower/server/assets/javascripts/datepicker.coffee +21 -0
  30. data/lib/watch_tower/server/assets/javascripts/file_tree.coffee +30 -0
  31. data/lib/watch_tower/server/assets/javascripts/percentage.coffee +15 -5
  32. data/lib/watch_tower/server/assets/stylesheets/application.css +1 -0
  33. data/lib/watch_tower/server/assets/stylesheets/date.sass +17 -0
  34. data/lib/watch_tower/server/assets/stylesheets/file_tree.sass +42 -0
  35. data/lib/watch_tower/server/assets/stylesheets/global.sass +7 -4
  36. data/lib/watch_tower/server/configurations/asset.rb +2 -0
  37. data/lib/watch_tower/server/configurations.rb +2 -0
  38. data/lib/watch_tower/server/database.rb +2 -0
  39. data/lib/watch_tower/server/db/migrate/001_create_projects.rb +2 -0
  40. data/lib/watch_tower/server/db/migrate/002_create_files.rb +2 -0
  41. data/lib/watch_tower/server/db/migrate/003_create_time_entries.rb +2 -0
  42. data/lib/watch_tower/server/db/migrate/004_create_durations.rb +2 -0
  43. data/lib/watch_tower/server/db/migrate/005_add_hash_to_time_entries.rb +2 -0
  44. data/lib/watch_tower/server/db/migrate/006_add_hash_to_files.rb +2 -0
  45. data/lib/watch_tower/server/db/migrate/007_add_editor_to_times_entries.rb +8 -0
  46. data/lib/watch_tower/server/db/migrate/008_rename_editor_to_editor_name_in_times_entries.rb +5 -0
  47. data/lib/watch_tower/server/db/migrate/009_remove_editor_index_from_time_entries.rb +7 -0
  48. data/lib/watch_tower/server/db/migrate/010_add_editor_version_to_times_entries.rb +7 -0
  49. data/lib/watch_tower/server/helpers/asset.rb +2 -0
  50. data/lib/watch_tower/server/helpers/improved_partials.rb +2 -0
  51. data/lib/watch_tower/server/helpers/presenters.rb +33 -0
  52. data/lib/watch_tower/server/helpers.rb +3 -0
  53. data/lib/watch_tower/server/models/duration.rb +9 -0
  54. data/lib/watch_tower/server/models/file.rb +17 -0
  55. data/lib/watch_tower/server/models/project.rb +30 -0
  56. data/lib/watch_tower/server/models/time_entry.rb +5 -0
  57. data/lib/watch_tower/server/presenters/application_presenter.rb +165 -0
  58. data/lib/watch_tower/server/presenters/file_presenter.rb +10 -0
  59. data/lib/watch_tower/server/presenters/project_presenter.rb +20 -0
  60. data/lib/watch_tower/server/presenters.rb +13 -0
  61. data/lib/watch_tower/server/public/assets/{WatchTower-4d6de11e1bd34165ad91ac46fb711bf3.jpg → WatchTower-58eff0713efffbc6054defddc879e0b1.jpg} +0 -0
  62. data/lib/watch_tower/server/public/assets/application-4e6971066e06aa53b0c8e52c764044d1.css +389 -0
  63. data/lib/watch_tower/server/public/assets/application-6a1be75d4fd6a545faceb638e47a2486.js +23778 -0
  64. data/lib/watch_tower/server/public/assets/calendar-379834cd6e6321a940b662ace47f3032.gif +0 -0
  65. data/lib/watch_tower/server/public/assets/calendar-blue-d6aa74feef7ee4287532761db99a6c0a.gif +0 -0
  66. data/lib/watch_tower/server/public/assets/calendar-green-3752fe2996091379c8d321f759039385.gif +0 -0
  67. data/lib/watch_tower/server/public/assets/jquery.datepick-9c8dfe3a4d40bcafc7b182e194c13836.css +227 -0
  68. data/lib/watch_tower/server/public/assets/{percentage-d8589e21a5fc85d32a445f531ff8ab95.png → percentage-d0176e99520c95e93eee63738ef5d487.png} +0 -0
  69. data/lib/watch_tower/server/vendor/assets/images/calendar-blue.gif +0 -0
  70. data/lib/watch_tower/server/vendor/assets/images/calendar-green.gif +0 -0
  71. data/lib/watch_tower/server/vendor/assets/images/calendar.gif +0 -0
  72. data/lib/watch_tower/server/vendor/assets/javascripts/jquery-datepick-ext.js +266 -0
  73. data/lib/watch_tower/server/vendor/assets/javascripts/jquery-datepick-validation.js +232 -0
  74. data/lib/watch_tower/server/vendor/assets/javascripts/jquery-datepick.js +2092 -0
  75. data/lib/watch_tower/server/vendor/assets/stylesheets/jquery.datepick.css +226 -0
  76. data/lib/watch_tower/server/views/_project.haml +10 -13
  77. data/lib/watch_tower/server/views/index.haml +9 -6
  78. data/lib/watch_tower/server/views/layout.haml +7 -4
  79. data/lib/watch_tower/server/views/project.haml +9 -11
  80. data/lib/watch_tower/server.rb +8 -1
  81. data/lib/watch_tower/templates/{watchtower.plist → watchtower.plist.erb} +5 -6
  82. data/lib/watch_tower/version.rb +12 -3
  83. data/lib/watch_tower.rb +20 -1
  84. data/spec/factories.rb +2 -0
  85. data/spec/watch_tower/appscript_spec.rb +36 -2
  86. data/spec/watch_tower/editor/base_appscript_spec.rb +83 -0
  87. data/spec/watch_tower/editor/textmate_spec.rb +37 -0
  88. data/spec/watch_tower/editor/xcode_spec.rb +6 -0
  89. data/spec/watch_tower/eye_spec.rb +21 -0
  90. data/spec/watch_tower/file_tree_spec.rb +156 -0
  91. data/spec/watch_tower/server/app_spec.rb +64 -20
  92. data/spec/watch_tower/server/models/file_spec.rb +93 -31
  93. data/spec/watch_tower/server/models/project_spec.rb +147 -18
  94. data/spec/watch_tower/server/models/time_entry_spec.rb +10 -0
  95. data/spec/watch_tower/server/{decorator/project_decorator_spec.rb → presenters/application_presenter_spec.rb} +24 -13
  96. data/spec/watch_tower/server/presenters/file_presenter_spec.rb +8 -0
  97. data/spec/watch_tower/server/presenters/project_presenter_spec.rb +130 -0
  98. data/watch_tower.gemspec +10 -4
  99. metadata +114 -74
  100. data/lib/watch_tower/server/decorator/application_decorator.rb +0 -91
  101. data/lib/watch_tower/server/decorator/file_decorator.rb +0 -38
  102. data/lib/watch_tower/server/decorator/project_decorator.rb +0 -51
  103. data/lib/watch_tower/server/decorator.rb +0 -21
  104. data/lib/watch_tower/server/public/assets/application-7829b53b5ece1a16d22dc3d00f329023.css +0 -107
  105. data/lib/watch_tower/server/public/assets/application-e0e6b7731aade460f680331e65cf0682.js +0 -9359
  106. data/lib/watch_tower/server/views/_file.haml +0 -9
@@ -0,0 +1,232 @@
1
+ /* http://keith-wood.name/datepick.html
2
+ Datepicker Validation extension for jQuery 4.0.6.
3
+ Requires Jörn Zaefferer's Validation plugin (http://plugins.jquery.com/project/validate).
4
+ Written by Keith Wood (kbwood{at}iinet.com.au).
5
+ Dual licensed under the GPL (http://dev.jquery.com/browser/trunk/jquery/GPL-LICENSE.txt) and
6
+ MIT (http://dev.jquery.com/browser/trunk/jquery/MIT-LICENSE.txt) licenses.
7
+ Please attribute the author if you use it. */
8
+
9
+ (function($) { // Hide the namespace
10
+
11
+ /* Add validation methods if validation plugin available. */
12
+ if ($.fn.validate) {
13
+
14
+ $.datepick.selectDateOrig = $.datepick.selectDate;
15
+
16
+ $.extend($.datepick.regional[''], {
17
+ validateDate: 'Please enter a valid date',
18
+ validateDateMin: 'Please enter a date on or after {0}',
19
+ validateDateMax: 'Please enter a date on or before {0}',
20
+ validateDateMinMax: 'Please enter a date between {0} and {1}',
21
+ validateDateCompare: 'Please enter a date {0} {1}',
22
+ validateDateToday: 'today',
23
+ validateDateOther: 'the other date',
24
+ validateDateEQ: 'equal to',
25
+ validateDateNE: 'not equal to',
26
+ validateDateLT: 'before',
27
+ validateDateGT: 'after',
28
+ validateDateLE: 'not after',
29
+ validateDateGE: 'not before'
30
+ });
31
+
32
+ $.extend($.datepick._defaults, $.datepick.regional['']);
33
+
34
+ $.extend($.datepick, {
35
+
36
+ /* Trigger a validation after updating the input field with the selected date.
37
+ @param target (element) the control to examine
38
+ @param elem (element) the selected datepicker element */
39
+ selectDate: function(target, elem) {
40
+ this.selectDateOrig(target, elem);
41
+ var inst = $.data(target, $.datepick.dataName);
42
+ if (!inst.inline && $.fn.validate) {
43
+ var validation = $(target).parents('form').validate();
44
+ if (validation) {
45
+ validation.element('#' + target.id);
46
+ }
47
+ }
48
+ },
49
+
50
+ /* Correct error placement for validation errors - after any trigger.
51
+ @param error (jQuery) the error message
52
+ @param element (jQuery) the field in error */
53
+ errorPlacement: function(error, element) {
54
+ var inst = $.data(element[0], $.datepick.dataName);
55
+ if (inst) {
56
+ error[inst.get('isRTL') ? 'insertBefore' : 'insertAfter'](
57
+ inst.trigger.length > 0 ? inst.trigger : element);
58
+ }
59
+ else {
60
+ error.insertAfter(element);
61
+ }
62
+ },
63
+
64
+ /* Format a validation error message involving dates.
65
+ @param source (string) the error message
66
+ @param params (Date[]) the dates
67
+ @return (string) the formatted message */
68
+ errorFormat: function(source, params) {
69
+ var format = ($.datepick.curInst ?
70
+ $.datepick.curInst.get('dateFormat') :
71
+ $.datepick._defaults.dateFormat);
72
+ $.each(params, function(index, value) {
73
+ source = source.replace(new RegExp('\\{' + index + '\\}', 'g'),
74
+ $.datepick.formatDate(format, value) || 'nothing');
75
+ });
76
+ return source;
77
+ }
78
+ });
79
+
80
+ var lastElement = null;
81
+
82
+ /* Validate date field. */
83
+ $.validator.addMethod('dpDate', function(value, element) {
84
+ lastElement = element;
85
+ return this.optional(element) || validateEach(value, element);
86
+ },
87
+ function(params) {
88
+ var inst = $.data(lastElement, $.datepick.dataName);
89
+ var minDate = inst.get('minDate');
90
+ var maxDate = inst.get('maxDate');
91
+ var messages = $.datepick._defaults;
92
+ return (minDate && maxDate ?
93
+ $.datepick.errorFormat(messages.validateDateMinMax, [minDate, maxDate]) :
94
+ (minDate ? $.datepick.errorFormat(messages.validateDateMin, [minDate]) :
95
+ (maxDate ? $.datepick.errorFormat(messages.validateDateMax, [maxDate]) :
96
+ messages.validateDate)));
97
+ });
98
+
99
+ /* Apply a validation test to each date provided.
100
+ @param value (string) the current field value
101
+ @param element (element) the field control
102
+ @return (boolean) true if OK, false if failed validation */
103
+ function validateEach(value, element) {
104
+ var inst = $.data(element, $.datepick.dataName);
105
+ var rangeSelect = inst.get('rangeSelect');
106
+ var multiSelect = inst.get('multiSelect');
107
+ var dates = (multiSelect ? value.split(inst.get('multiSeparator')) :
108
+ (rangeSelect ? value.split(inst.get('rangeSeparator')) : [value]));
109
+ var ok = (multiSelect && dates.length <= multiSelect) ||
110
+ (!multiSelect && rangeSelect && dates.length == 2) ||
111
+ (!multiSelect && !rangeSelect && dates.length == 1);
112
+ if (ok) {
113
+ try {
114
+ var dateFormat = inst.get('dateFormat');
115
+ var minDate = inst.get('minDate');
116
+ var maxDate = inst.get('maxDate');
117
+ var dp = $(element);
118
+ $.each(dates, function(i, v) {
119
+ dates[i] = $.datepick.parseDate(dateFormat, v);
120
+ ok = ok && (!dates[i] || (dp.datepick('isSelectable', dates[i]) &&
121
+ (!minDate || dates[i].getTime() >= minDate.getTime()) &&
122
+ (!maxDate || dates[i].getTime() <= maxDate.getTime())));
123
+ });
124
+ }
125
+ catch (e) {
126
+ ok = false;
127
+ }
128
+ }
129
+ if (ok && rangeSelect) {
130
+ ok = (dates[0].getTime() <= dates[1].getTime());
131
+ }
132
+ return ok;
133
+ }
134
+
135
+ /* And allow as a class rule. */
136
+ $.validator.addClassRules('dpDate', {dpDate: true});
137
+
138
+ var comparisons = {equal: 'eq', same: 'eq', notEqual: 'ne', notSame: 'ne',
139
+ lessThan: 'lt', before: 'lt', greaterThan: 'gt', after: 'gt',
140
+ notLessThan: 'ge', notBefore: 'ge', notGreaterThan: 'le', notAfter: 'le'};
141
+
142
+ /* Cross-validate date fields.
143
+ params should be an array with [0] comparison type eq/ne/lt/gt/le/ge or synonyms,
144
+ [1] 'today' or date string or Date or other field selector/element/jQuery OR
145
+ an object with one attribute with name eq/ne/lt/gt/le/ge or synonyms
146
+ and value 'today' or date string or Date or other field selector/element/jQuery OR
147
+ a string with eq/ne/lt/gt/le/ge or synonyms followed by 'today' or date string or jQuery selector */
148
+ $.validator.addMethod('dpCompareDate', function(value, element, params) {
149
+ if (this.optional(element)) {
150
+ return true;
151
+ }
152
+ params = normaliseParams(params);
153
+ var thisDate = $(element).datepick('getDate');
154
+ var thatDate = extractOtherDate(element, params[1]);
155
+ if (thisDate.length == 0 || thatDate.length == 0) {
156
+ return true;
157
+ }
158
+ lastElement = element;
159
+ var finalResult = true;
160
+ for (var i = 0; i < thisDate.length; i++) {
161
+ switch (comparisons[params[0]] || params[0]) {
162
+ case 'eq': finalResult = (thisDate[i].getTime() == thatDate[0].getTime()); break;
163
+ case 'ne': finalResult = (thisDate[i].getTime() != thatDate[0].getTime()); break;
164
+ case 'lt': finalResult = (thisDate[i].getTime() < thatDate[0].getTime()); break;
165
+ case 'gt': finalResult = (thisDate[i].getTime() > thatDate[0].getTime()); break;
166
+ case 'le': finalResult = (thisDate[i].getTime() <= thatDate[0].getTime()); break;
167
+ case 'ge': finalResult = (thisDate[i].getTime() >= thatDate[0].getTime()); break;
168
+ default: finalResult = true;
169
+ }
170
+ if (!finalResult) {
171
+ break;
172
+ }
173
+ }
174
+ return finalResult;
175
+ },
176
+ function(params) {
177
+ var messages = $.datepick._defaults;
178
+ var inst = $.data(lastElement, $.datepick.dataName);
179
+ params = normaliseParams(params);
180
+ var thatDate = extractOtherDate(lastElement, params[1], true);
181
+ thatDate = (params[1] == 'today' ? messages.validateDateToday : (thatDate.length ?
182
+ $.datepick.formatDate(inst.get('dateFormat'), thatDate[0], inst.getConfig()) :
183
+ messages.validateDateOther));
184
+ return messages.validateDateCompare.replace(/\{0\}/,
185
+ messages['validateDate' + (comparisons[params[0]] || params[0]).toUpperCase()]).
186
+ replace(/\{1\}/, thatDate);
187
+ });
188
+
189
+ /* Normalise the comparison parameters to an array.
190
+ @param params (array or object or string) the original parameters
191
+ @return (array) the normalised parameters */
192
+ function normaliseParams(params) {
193
+ if (typeof params == 'string') {
194
+ params = params.split(' ');
195
+ }
196
+ else if (!$.isArray(params)) {
197
+ var opts = [];
198
+ for (var name in params) {
199
+ opts[0] = name;
200
+ opts[1] = params[name];
201
+ }
202
+ params = opts;
203
+ }
204
+ return params;
205
+ }
206
+
207
+ /* Determine the comparison date.
208
+ @param element (element) the current datepicker element
209
+ @param source (string or Date or jQuery or element) the source of the other date
210
+ @param noOther (boolean) true to not get the date from another field
211
+ @return (Date[1]) the date for comparison */
212
+ function extractOtherDate(element, source, noOther) {
213
+ if (source.constructor == Date) {
214
+ return [source];
215
+ }
216
+ var inst = $.data(element, $.datepick.dataName);
217
+ var thatDate = null;
218
+ try {
219
+ if (typeof source == 'string' && source != 'today') {
220
+ thatDate = $.datepick.parseDate(inst.get('dateFormat'), source, inst.getConfig());
221
+ }
222
+ }
223
+ catch (e) {
224
+ // Ignore
225
+ }
226
+ thatDate = (thatDate ? [thatDate] : (source == 'today' ?
227
+ [$.datepick.today()] : (noOther ? [] : $(source).datepick('getDate'))));
228
+ return thatDate;
229
+ }
230
+ }
231
+
232
+ })(jQuery);