watch_tower 0.0.0.1 → 0.0.1.beta1

Sign up to get free protection for your applications and to get access to all the features.
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);