Commit 1c80fe98e671b36c18993b67982116503ac34775

Authored by Stephen Crosby
2 parents 2b1f4c6d f75c2750
Exists in master and in 1 other branch production

Merge pull request #652 from brandedcrate/features/extract_issue_tracker-merge_master

Features/extract issue tracker merge master
Gemfile
... ... @@ -34,7 +34,6 @@ gem 'errbit_github_plugin',
34 34 :git => 'https://github.com/errbit/errbit_github_plugin.git'
35 35 # :path => 'vendor/gems/errbit_github_plugin'
36 36  
37   -
38 37 # Notification services
39 38 # ---------------------------------------
40 39 gem 'campy'
... ...
README.md
... ... @@ -299,6 +299,13 @@ heroku config:add GITHUB_SECRET=the_secret_provided_by_GitHub
299 299 heroku config:add GITHUB_ACCESS_SCOPE=repo,public_repo
300 300 ```
301 301  
  302 +* GITHUB_ORG_ID [*optional*] - If set, any user of the specified GitHub Organization can login. If it is their first time, an account will automatically be created for them.
  303 +
  304 +```bash
  305 +heroku config:add GITHUB_ORG_ID=1234567
  306 +```
  307 +
  308 +
302 309 __Note__: To avoid restarting your Heroku app 4 times you can set Heroku variables in a single command, i.e:
303 310  
304 311 ```bash
... ...
app/assets/javascripts/form.js
... ... @@ -81,7 +81,7 @@ function activateTypeSelector(field_class, section_class) {
81 81 $('div.'+field_class+' > div.'+section_class).not('.chosen').find('input')
82 82 .attr('disabled','disabled').val('');
83 83  
84   - $('div.'+field_class+' input[name*=type]').on('click', function(){
  84 + $('div.'+field_class).find('.choose input[name*=type]').on('click', function(){
85 85 // Look for section in 'data-section', and fall back to 'value'
86 86 var chosen = $(this).data("section") || $(this).val();
87 87 var wrapper = $(this).closest('.nested');
... ...
app/assets/stylesheets/errbit.css
... ... @@ -1,913 +0,0 @@
1   -html {
2   - margin: 0; padding: 0;
3   - color: #585858;
4   - background-color: #e6e6e6;
5   - font-size: 62.8%; font-family: Helvetica, "Lucida Grande","Lucida Sans",Arial,sans-serif;
6   -}
7   -body {
8   - margin: 0; padding: 0;
9   - font-size: 1.3em; line-height: 1.4em;
10   -}
11   -
12   -/* Convenience Classes */
13   -.float-left { float: left; }
14   -.float-right { float: right; }
15   -.clear { clear: both; }
16   -.clear-left { clear: left; }
17   -.clear-right { clear: right; }
18   -.nowrap { white-space: nowrap; }
19   -
20   -/* Headings */
21   -h1, h2, h3, h4, h5, h6 { padding: 0.2em 0; margin-bottom: 1em; border-bottom: 1px solid #dedede;}
22   -h1 { font-size: 2.0em; line-height: 1.2em; text-shadow: 1px 1px 0px #FFF; -webkit-text-shadow: 1px 1px 0px #FFF;}
23   -h2 { font-size: 1.7em; line-height: 1.2em; }
24   -h3 { font-size: 1.5em; line-height: 1.2em; }
25   -h4 { font-size: 1.3em; line-height: 1.2em; }
26   -h5 { font-size: 1.1em; line-height: 1.2em; }
27   -h6 { font-size: 0.9em; line-height: 1.2em; }
28   -
29   -/* General */
30   -p { margin-bottom: 1em; }
31   -
32   -/* Links */
33   -a { color: #0069cc; text-decoration: none;}
34   -a:visited { color: #0069cc;}
35   -a:hover { color: #0069cc; text-decoration: underline; }
36   -a.action { float: right; font-size: 0.9em;}
37   -
38   -#header > div, #content-wrapper, #footer {
39   - width: 930px;
40   - margin: 0 auto;
41   - position: relative;
42   -}
43   -
44   -/* Header */
45   -#header {
46   - margin-bottom: 24px;
47   - height: 71px;
48   - border-bottom: 1px solid #fff;
49   - position:relative;
50   - background: #000000;
51   -}
52   -#header > div {
53   - height: 71px;
54   -}
55   -#header #site-name {
56   - display: block;
57   - width: 88px;
58   - height: 31px;
59   - position: absolute;
60   - top: 22px;
61   - left: 2px;
62   - background: transparent url(images/logo.png) 0 0 no-repeat;
63   - text-indent: -5000em;
64   -}
65   -
66   -#header #session-links {
67   - position: absolute;
68   - top: 20px;
69   - right: 0;
70   - font-size: 0.9em;
71   -}
72   -#header #session-links li {
73   - float: right;
74   - margin-left: 10px;
75   - color: #ccc;
76   - background-color: #1e1e1e;
77   - border-radius: 30px;
78   - -moz-border-radius: 30px;
79   - -webkit-border-radius: 30px;
80   - border: 1px solid #484B4F;
81   - font-size: 14px;
82   -}
83   -#header #session-links li:hover {
84   - box-shadow: 0 0 3px #69c;
85   - -moz-box-shadow: 0 0 3px #69c;
86   - -webkit-box-shadow: 0 0 3px #69c;
87   -}
88   -#header #session-links li:hover a {
89   - color: white;
90   -}
91   -#header #session-links a {
92   - color: #ccc;
93   - padding: 0 14px;
94   - line-height: 30px;
95   -}
96   -#header #session-links #sign-out {
97   - background: transparent url(images/icons/bullet-red-sm.png) 12px 50% no-repeat;
98   - padding-left: 29px;
99   -}
100   -#header #session-links a:hover {
101   - text-decoration: none;
102   -}
103   -
104   -/* Navigation */
105   -#nav-bar {
106   - position: absolute;
107   - bottom: 0;
108   - left: 172px;
109   -}
110   -#nav-bar li {
111   - float: left;
112   - height: 34px;
113   - margin-right: 12px;
114   - color: #666;
115   - background-color: #d0d0d0;
116   - background-image: none;
117   - border-top-left-radius: 12px;
118   - border-top-right-radius: 12px;
119   - -moz-border-top-left-radius: 12px;
120   - -moz-border-top-right-radius: 12px;
121   - -webkit-border-top-left-radius: 12px;
122   - -webkit-border-top-right-radius: 12px;
123   - border: 1px solid #bbb;
124   -}
125   -#nav-bar li.active {
126   - border-color: #fff;
127   - background: #FFF url(images/button-bg.png) 0 -2px repeat-x;
128   - border-width:1px 1px 0;
129   - margin-bottom:-2px;
130   - height: 37px;
131   -}
132   -#nav-bar li.active a {
133   - color: #333;
134   -}
135   -
136   -#nav-bar li a {
137   - color: #666;
138   - display: block;
139   - padding: 0 20px 0 40px;
140   - font-size: 14px;
141   - font-weight: bold;
142   - line-height: 37px;
143   - text-decoration: none;
144   - text-shadow: 1px 1px 0px #FFF;
145   - -webkit-text-shadow: 1px 1px 0px #FFF;
146   - background: transparent 10px 6px no-repeat;
147   -}
148   -#nav-bar li a:hover { color: #666;}
149   -#nav-bar li.apps a { background-image: url(images/icons/briefcase.png); }
150   -#nav-bar li.errs a { background-image: url(images/icons/error.png); }
151   -#nav-bar li.users a { background-image: url(images/icons/user.png); }
152   -#nav-bar li:not(.active):hover {
153   - box-shadow: 0 0 3px #69c;
154   - -moz-box-shadow: 0 0 3px #69c;
155   - -webkit-box-shadow: 0 0 3px #69c;
156   -}
157   -
158   -/* Content Wrapper */
159   -#content-wrapper {
160   - border: 1px solid #C6C6C6;
161   -}
162   -
163   -/* Content Title and Comments */
164   -#content-title, #content-comments {
165   - padding: 30px 24px;
166   - border-top: 1px solid #FFF;
167   - border-bottom: 1px solid #FFF;
168   - background-color: #f2f2f2;
169   -}
170   -
171   -/* Make err title bar bigger to fit more buttons */
172   -#content-title.err_show {
173   - padding: 43px 24px 37px;
174   -}
175   -
176   -#content-comments {
177   - background-color: #ffffff;
178   -}
179   -#content-title h1, #content-comments h3 {
180   - padding: 0; margin: 0;
181   - width: 85%;
182   - border: none;
183   - color: #636363;
184   - font-size: 2em; line-height: 1em; font-weight: bold; font-family: arial, sans-serif;
185   - word-wrap: break-word;
186   -}
187   -#content-comments h3 {
188   - font-size: 1.5em;
189   - margin-bottom: 14px;
190   -}
191   -
192   -#content-title .meta { font-size: 0.9em; color: #787878; }
193   -
194   -/* Action Bar */
195   -#action-bar {
196   - position: absolute;
197   - text-align: right;
198   - top: 22px; right: 24px;
199   -}
200   -#action-bar span {
201   - display: inline-block;
202   - margin-left: 18px;
203   - margin-bottom: 16px;
204   - text-decoration: none;
205   - color: #666;
206   - background: #FFF url(images/button-bg.png) 0 bottom repeat-x;
207   - border-radius: 50px;
208   - -moz-border-radius: 50px;
209   - -webkit-border-radius: 50px;
210   - border: 1px solid #bbb;
211   -}
212   -#action-bar span a {
213   - color: #666;
214   - display: block;
215   - padding: 0 20px 0 40px;
216   - font-size: 14px; font-weight: bold; line-height: 39px; text-decoration: none;
217   - text-shadow: 1px 1px 0px #FFF; -webkit-text-shadow: 1px 1px 0px #FFF;
218   - background: transparent 10px 8px no-repeat;
219   -}
220   -#action-bar a:hover { text-decoration: none;}
221   -#action-bar span:hover {
222   - box-shadow: 0 0 3px #69c;
223   - -moz-box-shadow: 0 0 3px #69c;
224   - -webkit-box-shadow: 0 0 3px #69c;
225   -}
226   -#action-bar a.add {
227   - background-image: url(images/icons/add.png);
228   -}
229   -
230   -#action-bar .calendar_link {
231   - background: url(images/icons/ical.png) no-repeat scroll 12px 6px transparent;
232   - padding-left: 47px;
233   -}
234   -
235   -#action-bar span.github a { background: url(images/icons/github.png) no-repeat 6px 5px; }
236   -#action-bar span.unlink_github a { background: url(images/icons/unlink_github.png) no-repeat 6px 5px; }
237   -
238   -/* Content */
239   -#content {
240   - padding: 20px; border-top: 1px solid #C6C6C6;
241   - background-color: #FFF;
242   -}
243   -
244   -#content a.button {
245   - float: right;
246   - display: block;
247   - margin-bottom: 10px;
248   -}
249   -
250   -/* Footer */
251   -#footer {
252   - padding: 20px 0;
253   - font-size: 0.8em; text-align: center;
254   - color: #929292;
255   -}
256   -
257   -/* Flash Messages */
258   -#flash-messages li {
259   - padding: 13px 45px;
260   - margin-bottom:25px;
261   - border: 1px solid #C6C6C6;
262   - background-color: #F9F9F9;
263   - line-height: 1em;
264   -}
265   -#flash-messages li.notice {
266   - padding-left: 20px;
267   - background-color: #b5eeff;
268   - border: 1px solid #6cf;
269   -}
270   -#flash-messages li.success {
271   - background: #cfc url(images/icons/success.png) 16px 50% no-repeat;
272   - border: 1px solid #6c3;
273   -}
274   -#flash-messages li.error {
275   - background: #fcc url(images/icons/error.png) 16px 50% no-repeat;
276   - border: 1px solid #f99;
277   -}
278   -#flash-messages .alert {
279   - background: #ffc url(images/icons/warning.png) 10px 7px no-repeat;
280   - border-color: #e4bb69;
281   -}
282   -
283   -/* Forms */
284   -form#new_user,
285   -form.edit_user,
286   -form#new_app,
287   -form.edit_app {
288   - width: 620px;
289   -}
290   -form > div, form fieldset > div { margin: 1em 0;}
291   -form fieldset {
292   - padding: 0.8em; margin-bottom: 1em;
293   - background-color: #F0F0F0; border: 1px solid #C6C6C6; border-left: none; border-right: none;
294   -}
295   -form fieldset legend {
296   - font-size: 1.2em; font-weight: bold; text-transform: uppercase;
297   - color: #555;
298   -}
299   -form label {
300   - font-weight: bold; text-transform: uppercase; line-height: 1.6em;
301   - display: inline-block;
302   -}
303   -form label.inline { display: inline; }
304   -form .checkbox label { display: inline; }
305   -form .required label { padding-right: 20px; background: transparent url(images/icons/required.png) right 50% no-repeat; }
306   -form .field_with_errors label { color: #900; }
307   -form input[type=text], form input[type=password], form input[type=email] {
308   - width: 96%; padding: 0.8em;
309   - font-size: 1em;
310   - color: #787878; border: 1px solid #C6C6C6;
311   -}
312   -form textarea {
313   - width: 100%; padding: 0.8em;
314   - font-size: inherit; font-family: inherit;
315   - color: #787878; border: 1px solid #C6C6C6;
316   -}
317   -form textarea.short { height: 8em; }
318   -form textarea.supershort { height: 4em; }
319   -form input[type=text]:focus, form input[type=password]:focus, form input[type=email]:focus, form textarea:focus {
320   - box-shadow: 0px 0px 4px #69C;
321   - -moz-box-shadow: 0px 0px 4px #69C;
322   - -webkit-box-shadow: 0px 0px 4px #69C
323   -}
324   -form input[type=checkbox]:focus + label{
325   - color: #69C;
326   -}
327   -form input[type=submit] {
328   - display:block; width: auto; padding: 0.5em;
329   - font-size: 1.2em; line-height: 1em; text-transform: uppercase;
330   - border: none; color: #FFF; background-color: #387fc1;
331   -}
332   -form input[type=submit].button {
333   - font-size: 1em;
334   - text-transform: none;
335   -}
336   -form div.buttons {
337   - color: #666;
338   - background: #FFF url(images/button-bg.png) 0 bottom repeat-x;
339   - border-radius: 50px;
340   - -moz-border-radius: 50px;
341   - -webkit-border-radius: 50px;
342   - border: 1px solid #bbb;
343   - display: inline-block;
344   -}
345   -form div.buttons:hover {
346   - color: #666;
347   - box-shadow: 0 0 3px #69c;
348   - -moz-box-shadow: 0 0 3px #69c;
349   - -webkit-box-shadow: 0 0 3px #69c;
350   -}
351   -form div.buttons input, form div.buttons button {
352   - padding: 0 20px;
353   - color: #666;
354   - background: none;
355   - display: inline-block;
356   - height: 36px;
357   - font-size: 14px; font-weight: bold; line-height: 36px; text-decoration: none;
358   - text-shadow: 1px 1px 0px #FFF;
359   - -moz-text-shadow: 1px 1px 0px #FFF;
360   - -webkit-text-shadow: 1px 1px 0px #FFF;
361   - border: none;
362   -}
363   -form div.buttons button.sign_in {
364   - padding-left: 40px;
365   - background: transparent url(images/icons/right-arrow.png) 3px 3px no-repeat;
366   -}
367   -form strong.option {
368   - display: block;
369   - margin: 0.7em 0;
370   - color: #999;
371   -}
372   -
373   -form .nested {
374   - border-top: 1px dotted #BBB;
375   - margin-top: 1.5em;
376   - padding-top: 1.5em;
377   -}
378   -
379   -form legend + .nested {
380   - border: none;
381   - margin-top: 0;
382   - padding-top: 0;
383   -}
384   -
385   -form .error-messages {
386   - padding: 13px;
387   - background: #fcc;
388   - border: 1px solid #f99;
389   -}
390   -
391   -form .error-messages h2 {
392   - font-size: 1.2em;
393   - border-color: #F99;
394   -}
395   -form .error-messages ul {
396   - margin-left: 2em;
397   - list-style-type: square;
398   -}
399   -
400   -form .field-helpertext {
401   - display: inline;
402   -}
403   -
404   -form input#app_email_at_notices {
405   - width: 130px;
406   - margin: 0 5px;
407   -}
408   -
409   -
410   -/* Tables */
411   -table {
412   - width: 100%;
413   - border: 1px solid #C6C6C6;
414   - margin-bottom: 1.5em;
415   - border-collapse: separate;
416   -}
417   -table thead th {
418   - border-top: 1px solid #FFF;
419   - border-bottom: 1px solid #FFF;
420   -}
421   -table th, table td {
422   - border-top: 1px solid #C6C6C6;
423   - padding: 10px 8px;
424   - text-align: left;
425   -}
426   -table tbody tr:first-child th, table tbody tr:first-child td {
427   - border-top: none;
428   -}
429   -table thead + tbody tr:first-child td {
430   - border-top: 1px solid #C6C6C6;
431   -}
432   -table th { background-color: #ececec; font-weight: bold; text-transform: uppercase; white-space: nowrap; }
433   -table tbody tr:nth-child(odd) td { background-color: #F9F9F9; }
434   -table .main { width: 100%; }
435   -
436   -table.single_user {
437   - border-top: none;
438   -}
439   -
440   -.raw_data {
441   - width: 100%;
442   - color: #f0f0f0;
443   - background-color: #222;
444   - overflow: auto;
445   -}
446   -
447   -/* Code */
448   -pre {
449   - padding: 0.8em;
450   - margin-bottom: 1em;
451   - font-family: monaco, courier, monospace;
452   - font-size: 1.1em;
453   -}
454   -
455   -/* HTML Styling */
456   -.html { padding-left: 1em; border-left: 2px solid #C6C6C6;}
457   -.html h1, .html h2, .html h3, .html h4, .html h5, .html h6 {
458   - border: none;
459   -}
460   -.html ul, .html ol { margin-left: 2em; margin-bottom: 1em; }
461   -.html ul li { margin-bottom: 0.5em; list-style: disc; }
462   -.html ol li { margin-bottom: 0.5em; list-style: decimal; }
463   -
464   -/* Pagination */
465   -.pagination {
466   - margin: 0 0 25px;
467   - font-size: 17px;
468   - text-align: center;
469   -}
470   -.pagination em {
471   - font-style: normal;
472   - font-weight: bold;
473   -}
474   -
475   -
476   -/* Buttons */
477   -input[type="submit"].button,
478   -a.button {
479   - display: inline-block;
480   - padding: 0 0.8em;
481   - margin-left: 0.5em;
482   - color: #666;
483   - background-color: #dadada;
484   - border: 1px solid #BBB;
485   - border-radius: 30px;
486   - -moz-border-radius: 30px;
487   - -webkit-border-radius: 30px;
488   - line-height: 30px;
489   - min-width: 54px;
490   - text-align: center;
491   - text-shadow: 0 1px 0 #fff;
492   -}
493   -input[type="submit"]:hover.button,
494   -a:hover.button {
495   - box-shadow: 0px 0px 4px #bfbfbf;
496   - -moz-box-shadow: 0px 0px 4px #bfbfbf;
497   - -webkit-box-shadow: 0px 0px 4px #bfbfbf;
498   - text-decoration: none;
499   - background-color: #e5e5e5;
500   -}
501   -a.button.active {
502   - border-color: #fff;
503   - background-color: #CCC;
504   - background-image: none;
505   -}
506   -
507   -
508   -/* Tab Bar */
509   -.tab-bar {
510   - margin-top: 12px;
511   -}
512   -#content .tab-bar a.button {
513   - border-bottom:0;
514   - margin-bottom:0;
515   - border-top-left-radius:12px;
516   - border-top-right-radius:12px;
517   - border-bottom-left-radius:0;
518   - border-bottom-right-radius:0;
519   - height:30px;
520   -}
521   -#content .tab-bar a.button.active {
522   - background: #FFF;
523   - color: #444;
524   - border-color:#ccc;
525   - border-style:solid;
526   - border-width:1px 1px 0;
527   - margin-bottom:-1px;
528   - height:31px;
529   -}
530   -.tab-bar ul {
531   - padding: 9px 0 0;
532   - line-height:0;
533   -}
534   -.tab-bar li {
535   - display: inline-block;
536   -}
537   -
538   -/* Watchers / Issue Tracker / Notification Forms */
539   -div.watcher.nested .watcher_params, div.issue_tracker.nested .tracker_params, div.notification_service.nested .notification_params {
540   - display: none;
541   -}
542   -
543   -div.nested .chosen {
544   - display: block !important;
545   -}
546   -div.nested .choose {
547   - margin-bottom: 0.5em;
548   -}
549   -
550   -div.issue_tracker.nested .choose, div.notification_service.nested .choose {
551   - background-color: #ebebeb;
552   - border: 1px solid #dddddd;
553   - margin: 0 0 15px;
554   - padding: 12px;
555   -}
556   -div.issue_tracker.nested img, div.notification_service.nested img {
557   - vertical-align: middle;
558   -}
559   -
560   -/* Icons for Issue Tracker Radio Buttons */
561   -div.issue_tracker.nested label.label_radio, div.notification_service.nested label.label_radio {
562   - color: #929292;
563   - padding-left: 33px;
564   - margin-bottom: 6px;
565   - margin-right: 8px;
566   - line-height: 30px;
567   -}
568   -div.issue_tracker.nested .choose, div.notification_service.nested .choose {
569   - padding-bottom: 6px;
570   -}
571   -div.issue_tracker.nested label.label_radio:hover, div.notification_service.nested label.label_radio:hover {
572   - color: #696969;
573   -}
574   -div.issue_tracker.nested .label_radio input, div.notification_service.nested .label_radio input {
575   - position: absolute; left: -9999px;
576   -}
577   -
578   -div.issue_tracker.nested label.r_on, div.issue_tracker.nested label.r_on:hover, div.notification_service.nested label.r_on, div.notification_service.nested label.r_on:hover {
579   - color: #191919;
580   -}
581   -
582   -/* Icons need to be preloaded, otherwise it looks bad */
583   -.image_preloader { display: none; }
584   -
585   -/* Apps Table */
586   -table.apps tbody tr:hover td ,table.errs tbody tr:hover td { background-color: #F2F2F2;}
587   -
588   -table.apps td.name, table.errs td.message { width: 100%; }
589   -table.apps td { padding: 16px 20px; }
590   -table.apps th { padding: 10px 20px; }
591   -
592   -table.apps td.issue_tracker, table.apps td.count, table.apps td.deploy {
593   - text-align: center;
594   -}
595   -table.apps td.issue_tracker, table.apps td.count {
596   - padding: 10px 8px;
597   -}
598   -table.apps td.issue_tracker img { vertical-align: top; }
599   -
600   -td.message .line {
601   - display:inline-block;
602   - margin-left:1em;
603   -}
604   -td.deploy {
605   - white-space: nowrap;
606   -}
607   -td.latest {
608   - white-space: nowrap;
609   -}
610   -td.count, td.issue_link {
611   - text-align: center;
612   -}
613   -
614   -.count a {
615   - display: inline-block;
616   - padding: 0.1em 0.7em;
617   - margin-top: 3px;
618   - color: #fff;
619   - background: #cc0033 url(images/error-badge-bg.png) 0 bottom repeat-x;
620   - border: 1px solid #900;
621   - border-radius: 18px;
622   - -moz-border-radius: 18px;
623   - -webkit-border-radius: 18px;
624   - font-weight: bold;
625   - opacity: 0.8;
626   - -moz-opacity: 0.8;
627   - -webkit-opacity: 0.8
628   -}
629   -.count a.resolved {
630   - background: #05B81d url(images/resolved-badge-bg.png) 0 bottom repeat-x;
631   - border: 1px solid #080;
632   -}
633   -.count a:hover {
634   - text-decoration: none;
635   - opacity: 1;
636   - -moz-opacity: 1;
637   - -webkit-opacity: 1;
638   -}
639   -
640   -/* Err Tables */
641   -table.errs td.app {
642   - padding-right: 2em;
643   - width: 20%;
644   -}
645   -table.errs td.app .environment {
646   - font-size: 0.8em;
647   - color: #999;
648   -}
649   -table.errs td.message a {
650   - display: block;
651   - word-wrap: break-word;
652   - /* PjpG - configuration in WHAT & WHERE table's columns using ellipsis to avoid oversizing table's width */
653   - width: 300px;
654   - overflow: hidden;
655   - text-overflow: ellipsis;
656   - -o-text-overflow: ellipsis;
657   - /* ------ */
658   -}
659   -table.errs td.message em {
660   - color: #727272;
661   - font-size: 0.9em;
662   -}
663   -
664   -table.errs tr.resolved td > * {
665   - opacity: 0.5;
666   - -moz-opacity: 0.5;
667   - -webkit-opacity: 0.5;
668   -}
669   -
670   -/* Tally tables */
671   -table.tally {
672   - border:none;
673   -}
674   -table.tally td,
675   -table.tally th {
676   - border:none !important;
677   - background:none !important;
678   - padding:8px 0 0;
679   -}
680   -table.tally tbody tr:first-child td,
681   -table.tally tbody tr:first-child th {
682   - padding-top:0;
683   -}
684   -table.tally td.percent {
685   - padding-right: 10px;
686   -}
687   -table.tally th.value {
688   - width: 100%;
689   - text-transform: none;
690   -}
691   -
692   -/* Deploys table */
693   -table.deploys td.when {
694   - width: 102px;
695   -}
696   -
697   -/* Resolve Errs */
698   -#action-bar a.resolve {
699   - background: transparent url(images/icons/thumbs-up.png) 6px 5px no-repeat;
700   -}
701   -
702   -/* Go Up */
703   -#action-bar a.up {
704   - background: transparent url(images/icons/up.png) 6px 5px no-repeat;
705   -}
706   -
707   -/* Notices Pagination */
708   -.notice-pagination {
709   - float: left;
710   - margin-right: 10px;
711   -}
712   -
713   -.notice-pagination-loader {
714   - visibility: hidden;
715   - float: left;
716   - width: 16px;
717   - height: 16px;
718   - margin-right: 1em;
719   -}
720   -.notice-pagination-loader img {
721   - vertical-align: middle
722   -}
723   -
724   -
725   -/* Backtrace */
726   -.window {
727   - width: 100%;
728   - margin-bottom: 1em;
729   - overflow: auto;
730   - border:1px solid #ccc;
731   - padding:1px;
732   -}
733   -
734   -.window table {
735   - margin: 0;
736   -}
737   -
738   -table.backtrace {
739   - padding: 8px 0;
740   - background-color: #222;
741   -}
742   -
743   -table.backtrace td {
744   - width: 100%;
745   - padding: 0;
746   - margin: 0;
747   - color: #C7C7C7;
748   - background-color: #222;
749   -}
750   -
751   -table.backtrace td, table.backtrace th {
752   - border-top: none;
753   -}
754   -
755   -/* remove alternating color rules */
756   -table.backtrace tr:nth-child(2n+1) td { background-color: #222; }
757   -table.backtrace tr:first-child td { border-top: 0; }
758   -
759   -table.backtrace th.line-numbers {
760   - border-bottom: 1px solid #F0F0F0;
761   - font-size: 13px;
762   - text-align: right;
763   - vertical-align: top;
764   - padding: 1px 6px 1px 7px;
765   -}
766   -
767   -table.backtrace td.line {
768   - font-size: 13px;
769   - padding: 2px 8px;
770   - vertical-align: top;
771   - white-space: nowrap;
772   -}
773   -table.backtrace td.line .file {
774   - font-weight: bold;
775   -}
776   -table.backtrace td.line .method {
777   - color: #aaa;
778   - font-weight: bold;
779   -}
780   -
781   -table.backtrace td.line.in-app {
782   - color: #2adb2e;
783   - background-color: #2f2f2f;
784   -}
785   -table.backtrace td.line.in-app .path,
786   -table.backtrace td.line.in-app .number { color: #2ACB2E; }
787   -table.backtrace td.line.in-app .file { color: #3AFB3E; }
788   -table.backtrace td.line.in-app .method { color: #2ACB2E; }
789   -
790   -table.backtrace td.line.in-app a .path,
791   -table.backtrace td.line.in-app a .number,
792   -table.backtrace td.line.in-app a:hover { color: #21B4FF; }
793   -table.backtrace td.line.in-app a .file { color: #31C4FF; }
794   -
795   -/* External backtrace classes and separators */
796   -table.backtrace tr.hidden_external_backtrace {
797   - display: none;
798   -}
799   -table.backtrace td.backtrace_separator span {
800   - cursor: pointer;
801   - display: inline-block;
802   - font-size: 17px;
803   - font-weight: bold;
804   - padding: 0px 11px 5px;
805   - margin: 4px 0;
806   - background-color: #444444;
807   - border: 1px solid #555555;
808   -}
809   -table.backtrace td.backtrace_separator span:hover {
810   - background-color: #666666;
811   - border: 1px solid #777777;
812   -}
813   -
814   -
815   -
816   -/* Extra empty rows at top and bottom of table */
817   -table.backtrace tr.padding th, table.backtrace tr.padding td {
818   - height: 10px;
819   - margin: 0;
820   - padding: 0;
821   -}
822   -
823   -h3#watchers_toggle, h3#repository_toggle, h3#deploys_toggle {
824   - cursor: pointer;
825   -}
826   -
827   -span.click_span {
828   - font-size: 0.7em;
829   -}
830   -
831   -#deploys_div, #repository_div, #watchers_div {
832   - display: none;
833   -}
834   -
835   -/* Comments */
836   -#content-comments form p {
837   - margin: 30px 0 0 0;
838   - text-transform: uppercase;
839   -}
840   -table.comment tbody th {
841   - text-transform: none;
842   - font-weight: normal;
843   - height: 20px;
844   - line-height: 0.5em;
845   -}
846   -table.comment th span, table.comment th img {
847   - vertical-align: middle;
848   -}
849   -table.comment th span.comment-info {
850   - line-height: 21px;
851   - float: left;
852   -}
853   -table.comment img.gravatar {
854   - margin-right: 7px;
855   - float: left;
856   -}
857   -
858   -table.comment tbody td {
859   - background-color: #F9F9F9;
860   -}
861   -#content-comments a.destroy-comment {
862   - color: #EE0000;
863   - margin-right: 5px;
864   - margin-top: 2px;
865   - font-size: 21px;
866   - line-height: 1;
867   - float: right;
868   -}
869   -#content-comments a.destroy-comment:hover {
870   - text-decoration: none;
871   - color: #AA0000;
872   -}
873   -#content-comments #comment_submit {
874   - margin-top: 15px;
875   -}
876   -/* Inline comments in tables */
877   -table.errs tr td.message .inline_comment {
878   - display: inline-block;
879   - padding: 3px 7px;
880   - margin: 6px 0;
881   - background-color: #DAE5FF;
882   - border: 1px solid #E2E2E2;
883   - text-shadow: 0 1px 0 #FAFAFA;
884   - font-style: normal;
885   -}
886   -table.errs tr:hover td.message .inline_comment {
887   - background-color: #D5E0FA;
888   - border-color: #DBDBDB;
889   - text-shadow: 0 1px 0 #FFFFFF;
890   -}
891   -table.errs tr td.message .inline_comment em {
892   - color: #444;
893   -}
894   -table.errs tr td.message .inline_comment em.commenter {
895   - color: #777;
896   -}
897   -
898   -textarea#comment_body {
899   - width: 420px;
900   - height: 80px;
901   -}
902   -
903   -.current.asc:after { content: ' ↑'; }
904   -.current.desc:after { content: ' ↓'; }
905   -
906   -
907   -table.users td {
908   - vertical-align: middle;
909   -}
910   -table.users td img.gravatar {
911   - vertical-align: middle;
912   - margin-left: 3px;
913   -}
app/assets/stylesheets/errbit.css.erb 0 → 100644
... ... @@ -0,0 +1,918 @@
  1 +html {
  2 + margin: 0; padding: 0;
  3 + color: #585858;
  4 + background-color: #e6e6e6;
  5 + font-size: 62.8%; font-family: Helvetica, "Lucida Grande","Lucida Sans",Arial,sans-serif;
  6 +}
  7 +body {
  8 + margin: 0; padding: 0;
  9 + font-size: 1.3em; line-height: 1.4em;
  10 +}
  11 +
  12 +/* Convenience Classes */
  13 +.float-left { float: left; }
  14 +.float-right { float: right; }
  15 +.clear { clear: both; }
  16 +.clear-left { clear: left; }
  17 +.clear-right { clear: right; }
  18 +.nowrap { white-space: nowrap; }
  19 +
  20 +/* Headings */
  21 +h1, h2, h3, h4, h5, h6 { padding: 0.2em 0; margin-bottom: 1em; border-bottom: 1px solid #dedede;}
  22 +h1 { font-size: 2.0em; line-height: 1.2em; text-shadow: 1px 1px 0px #FFF; -webkit-text-shadow: 1px 1px 0px #FFF;}
  23 +h2 { font-size: 1.7em; line-height: 1.2em; }
  24 +h3 { font-size: 1.5em; line-height: 1.2em; }
  25 +h4 { font-size: 1.3em; line-height: 1.2em; }
  26 +h5 { font-size: 1.1em; line-height: 1.2em; }
  27 +h6 { font-size: 0.9em; line-height: 1.2em; }
  28 +
  29 +/* General */
  30 +p { margin-bottom: 1em; }
  31 +
  32 +/* Links */
  33 +a { color: #0069cc; text-decoration: none;}
  34 +a:visited { color: #0069cc;}
  35 +a:hover { color: #0069cc; text-decoration: underline; }
  36 +a.action { float: right; font-size: 0.9em;}
  37 +
  38 +#header > div, #content-wrapper, #footer {
  39 + width: 930px;
  40 + margin: 0 auto;
  41 + position: relative;
  42 +}
  43 +
  44 +/* Header */
  45 +#header {
  46 + margin-bottom: 24px;
  47 + height: 71px;
  48 + border-bottom: 1px solid #fff;
  49 + position:relative;
  50 + background: #000000;
  51 +}
  52 +#header > div {
  53 + height: 71px;
  54 +}
  55 +#header #site-name {
  56 + display: block;
  57 + width: 88px;
  58 + height: 31px;
  59 + position: absolute;
  60 + top: 22px;
  61 + left: 2px;
  62 + background: transparent url(<%= asset_path 'images/logo.png' %>) 0 0 no-repeat;
  63 + text-indent: -5000em;
  64 +}
  65 +
  66 +#header #session-links {
  67 + position: absolute;
  68 + top: 20px;
  69 + right: 0;
  70 + font-size: 0.9em;
  71 +}
  72 +#header #session-links li {
  73 + float: right;
  74 + margin-left: 10px;
  75 + color: #ccc;
  76 + background-color: #1e1e1e;
  77 + border-radius: 30px;
  78 + -moz-border-radius: 30px;
  79 + -webkit-border-radius: 30px;
  80 + border: 1px solid #484B4F;
  81 + font-size: 14px;
  82 +}
  83 +#header #session-links li:hover {
  84 + box-shadow: 0 0 3px #69c;
  85 + -moz-box-shadow: 0 0 3px #69c;
  86 + -webkit-box-shadow: 0 0 3px #69c;
  87 +}
  88 +#header #session-links li:hover a {
  89 + color: white;
  90 +}
  91 +#header #session-links a {
  92 + color: #ccc;
  93 + padding: 0 14px;
  94 + line-height: 30px;
  95 +}
  96 +#header #session-links #sign-out {
  97 + background: transparent url(<%= asset_path "images/icons/bullet-red-sm.png" %>) 12px 50% no-repeat;
  98 + padding-left: 29px;
  99 +}
  100 +#header #session-links a:hover {
  101 + text-decoration: none;
  102 +}
  103 +
  104 +/* Navigation */
  105 +#nav-bar {
  106 + position: absolute;
  107 + bottom: 0;
  108 + left: 172px;
  109 +}
  110 +#nav-bar li {
  111 + float: left;
  112 + height: 34px;
  113 + margin-right: 12px;
  114 + color: #666;
  115 + background-color: #d0d0d0;
  116 + background-image: none;
  117 + border-top-left-radius: 12px;
  118 + border-top-right-radius: 12px;
  119 + -moz-border-top-left-radius: 12px;
  120 + -moz-border-top-right-radius: 12px;
  121 + -webkit-border-top-left-radius: 12px;
  122 + -webkit-border-top-right-radius: 12px;
  123 + border: 1px solid #bbb;
  124 +}
  125 +#nav-bar li.active {
  126 + border-color: #fff;
  127 + background: #FFF url(<%= asset_path "images/button-bg.png" %>) 0 -2px repeat-x;
  128 + border-width:1px 1px 0;
  129 + margin-bottom:-2px;
  130 + height: 37px;
  131 +}
  132 +#nav-bar li.active a {
  133 + color: #333;
  134 +}
  135 +
  136 +#nav-bar li a {
  137 + color: #666;
  138 + display: block;
  139 + padding: 0 20px 0 40px;
  140 + font-size: 14px;
  141 + font-weight: bold;
  142 + line-height: 37px;
  143 + text-decoration: none;
  144 + text-shadow: 1px 1px 0px #FFF;
  145 + -webkit-text-shadow: 1px 1px 0px #FFF;
  146 + background: transparent 10px 6px no-repeat;
  147 +}
  148 +#nav-bar li a:hover { color: #666;}
  149 +#nav-bar li.apps a { background-image: url(<%= asset_path "images/icons/briefcase.png" %>); }
  150 +#nav-bar li.errs a { background-image: url(<%= asset_path "images/icons/error.png" %>); }
  151 +#nav-bar li.users a { background-image: url(<%= asset_path "images/icons/user.png" %>); }
  152 +#nav-bar li:not(.active):hover {
  153 + box-shadow: 0 0 3px #69c;
  154 + -moz-box-shadow: 0 0 3px #69c;
  155 + -webkit-box-shadow: 0 0 3px #69c;
  156 +}
  157 +
  158 +/* Content Wrapper */
  159 +#content-wrapper {
  160 + border: 1px solid #C6C6C6;
  161 +}
  162 +
  163 +/* Content Title and Comments */
  164 +#content-title, #content-comments {
  165 + padding: 30px 24px;
  166 + border-top: 1px solid #FFF;
  167 + border-bottom: 1px solid #FFF;
  168 + background-color: #f2f2f2;
  169 +}
  170 +
  171 +/* Make err title bar bigger to fit more buttons */
  172 +#content-title.err_show {
  173 + padding: 43px 24px 37px;
  174 +}
  175 +
  176 +#content-title.err_show.resolved{
  177 + background-color: #90EE90;
  178 +}
  179 +
  180 +#content-comments {
  181 + background-color: #ffffff;
  182 +}
  183 +#content-title h1, #content-comments h3 {
  184 + padding: 0; margin: 0;
  185 + width: 85%;
  186 + border: none;
  187 + color: #636363;
  188 + font-size: 2em; line-height: 1em; font-weight: bold; font-family: arial, sans-serif;
  189 + word-wrap: break-word;
  190 +}
  191 +#content-comments h3 {
  192 + font-size: 1.5em;
  193 + margin-bottom: 14px;
  194 +}
  195 +
  196 +#content-title .meta { font-size: 0.9em; color: #787878; }
  197 +
  198 +/* Action Bar */
  199 +#action-bar {
  200 + position: absolute;
  201 + text-align: right;
  202 + top: 22px; right: 24px;
  203 +}
  204 +#action-bar span {
  205 + display: inline-block;
  206 + margin-left: 18px;
  207 + margin-bottom: 16px;
  208 + text-decoration: none;
  209 + color: #666;
  210 + background: #FFF url(<%= asset_path "images/button-bg.png" %>) 0 bottom repeat-x;
  211 + border-radius: 50px;
  212 + -moz-border-radius: 50px;
  213 + -webkit-border-radius: 50px;
  214 + border: 1px solid #bbb;
  215 +}
  216 +#action-bar span a {
  217 + color: #666;
  218 + display: block;
  219 + padding: 0 20px 0 40px;
  220 + font-size: 14px; font-weight: bold; line-height: 39px; text-decoration: none;
  221 + text-shadow: 1px 1px 0px #FFF; -webkit-text-shadow: 1px 1px 0px #FFF;
  222 + background: transparent 10px 8px no-repeat;
  223 +}
  224 +#action-bar a:hover { text-decoration: none;}
  225 +#action-bar span:hover {
  226 + box-shadow: 0 0 3px #69c;
  227 + -moz-box-shadow: 0 0 3px #69c;
  228 + -webkit-box-shadow: 0 0 3px #69c;
  229 +}
  230 +#action-bar a.add {
  231 + background-image: url(<%= asset_path "images/icons/add.png" %>);
  232 +}
  233 +
  234 +#action-bar .calendar_link {
  235 + background: url(<%= asset_path "images/icons/ical.png" %>) no-repeat scroll 12px 6px transparent;
  236 + padding-left: 47px;
  237 +}
  238 +
  239 +#action-bar span.github a { background: url(<%= asset_path "images/icons/github.png" %>) no-repeat 6px 5px; }
  240 +#action-bar span.unlink_github a { background: url(<%= asset_path "images/icons/unlink_github.png" %>) no-repeat 6px 5px; }
  241 +
  242 +/* Content */
  243 +#content {
  244 + padding: 20px; border-top: 1px solid #C6C6C6;
  245 + background-color: #FFF;
  246 +}
  247 +
  248 +#content a.button {
  249 + float: right;
  250 + display: block;
  251 + margin-bottom: 10px;
  252 +}
  253 +
  254 +/* Footer */
  255 +#footer {
  256 + padding: 20px 0;
  257 + font-size: 0.8em; text-align: center;
  258 + color: #929292;
  259 +}
  260 +
  261 +/* Flash Messages */
  262 +#flash-messages li {
  263 + padding: 13px 45px;
  264 + margin-bottom:25px;
  265 + border: 1px solid #C6C6C6;
  266 + background-color: #F9F9F9;
  267 + line-height: 1em;
  268 +}
  269 +#flash-messages li.notice {
  270 + padding-left: 20px;
  271 + background-color: #b5eeff;
  272 + border: 1px solid #6cf;
  273 +}
  274 +#flash-messages li.success {
  275 + background: #cfc url(<%= asset_path "images/icons/success.png" %>) 16px 50% no-repeat;
  276 + border: 1px solid #6c3;
  277 +}
  278 +#flash-messages li.error {
  279 + background: #fcc url(<%= asset_path "images/icons/error.png" %>) 16px 50% no-repeat;
  280 + border: 1px solid #f99;
  281 +}
  282 +#flash-messages .alert {
  283 + background: #ffc url(<%= asset_path "images/icons/warning.png" %>) 10px 7px no-repeat;
  284 + border-color: #e4bb69;
  285 +}
  286 +
  287 +/* Forms */
  288 +form#new_user,
  289 +form.edit_user,
  290 +form#new_app,
  291 +form.edit_app {
  292 + width: 620px;
  293 +}
  294 +form > div, form fieldset > div { margin: 1em 0;}
  295 +form fieldset {
  296 + padding: 0.8em; margin-bottom: 1em;
  297 + background-color: #F0F0F0; border: 1px solid #C6C6C6; border-left: none; border-right: none;
  298 +}
  299 +form fieldset legend {
  300 + font-size: 1.2em; font-weight: bold; text-transform: uppercase;
  301 + color: #555;
  302 +}
  303 +form label {
  304 + font-weight: bold; text-transform: uppercase; line-height: 1.6em;
  305 + display: inline-block;
  306 +}
  307 +form label.inline { display: inline; }
  308 +form .checkbox label { display: inline; }
  309 +form .required label { padding-right: 20px; background: transparent url(<%= asset_path "images/icons/required.png" %>) right 50% no-repeat; }
  310 +form .field_with_errors label { color: #900; }
  311 +form input[type=text], form input[type=password], form input[type=email] {
  312 + width: 96%; padding: 0.8em;
  313 + font-size: 1em;
  314 + color: #787878; border: 1px solid #C6C6C6;
  315 +}
  316 +form textarea {
  317 + width: 100%; padding: 0.8em;
  318 + font-size: inherit; font-family: inherit;
  319 + color: #787878; border: 1px solid #C6C6C6;
  320 +}
  321 +form textarea.short { height: 8em; }
  322 +form textarea.supershort { height: 4em; }
  323 +form input[type=text]:focus, form input[type=password]:focus, form input[type=email]:focus, form textarea:focus {
  324 + box-shadow: 0px 0px 4px #69C;
  325 + -moz-box-shadow: 0px 0px 4px #69C;
  326 + -webkit-box-shadow: 0px 0px 4px #69C
  327 +}
  328 +form input[type=checkbox]:focus + label{
  329 + color: #69C;
  330 +}
  331 +form input[type=submit] {
  332 + display:block; width: auto; padding: 0.5em;
  333 + font-size: 1.2em; line-height: 1em; text-transform: uppercase;
  334 + border: none; color: #FFF; background-color: #387fc1;
  335 + cursor: pointer;
  336 +}
  337 +form input[type=submit].button {
  338 + font-size: 1em;
  339 + text-transform: none;
  340 +}
  341 +form div.buttons {
  342 + color: #666;
  343 + background: #FFF url(<%= asset_path "images/button-bg.png" %>) 0 bottom repeat-x;
  344 + border-radius: 50px;
  345 + -moz-border-radius: 50px;
  346 + -webkit-border-radius: 50px;
  347 + border: 1px solid #bbb;
  348 + display: inline-block;
  349 +}
  350 +form div.buttons:hover {
  351 + color: #666;
  352 + box-shadow: 0 0 3px #69c;
  353 + -moz-box-shadow: 0 0 3px #69c;
  354 + -webkit-box-shadow: 0 0 3px #69c;
  355 +}
  356 +form div.buttons input, form div.buttons button {
  357 + padding: 0 20px;
  358 + color: #666;
  359 + background: none;
  360 + display: inline-block;
  361 + height: 36px;
  362 + font-size: 14px; font-weight: bold; line-height: 36px; text-decoration: none;
  363 + text-shadow: 1px 1px 0px #FFF;
  364 + -moz-text-shadow: 1px 1px 0px #FFF;
  365 + -webkit-text-shadow: 1px 1px 0px #FFF;
  366 + border: none;
  367 +}
  368 +form div.buttons button.sign_in {
  369 + padding-left: 40px;
  370 + background: transparent url(<%= asset_path "images/icons/right-arrow.png" %>) 3px 3px no-repeat;
  371 +}
  372 +form strong.option {
  373 + display: block;
  374 + margin: 0.7em 0;
  375 + color: #999;
  376 +}
  377 +
  378 +form .nested {
  379 + border-top: 1px dotted #BBB;
  380 + margin-top: 1.5em;
  381 + padding-top: 1.5em;
  382 +}
  383 +
  384 +form legend + .nested {
  385 + border: none;
  386 + margin-top: 0;
  387 + padding-top: 0;
  388 +}
  389 +
  390 +form .error-messages {
  391 + padding: 13px;
  392 + background: #fcc;
  393 + border: 1px solid #f99;
  394 +}
  395 +
  396 +form .error-messages h2 {
  397 + font-size: 1.2em;
  398 + border-color: #F99;
  399 +}
  400 +form .error-messages ul {
  401 + margin-left: 2em;
  402 + list-style-type: square;
  403 +}
  404 +
  405 +form .field-helpertext {
  406 + display: inline;
  407 +}
  408 +
  409 +form input#app_email_at_notices {
  410 + width: 130px;
  411 + margin: 0 5px;
  412 +}
  413 +
  414 +
  415 +/* Tables */
  416 +table {
  417 + width: 100%;
  418 + border: 1px solid #C6C6C6;
  419 + margin-bottom: 1.5em;
  420 + border-collapse: separate;
  421 +}
  422 +table thead th {
  423 + border-top: 1px solid #FFF;
  424 + border-bottom: 1px solid #FFF;
  425 +}
  426 +table th, table td {
  427 + border-top: 1px solid #C6C6C6;
  428 + padding: 10px 8px;
  429 + text-align: left;
  430 +}
  431 +table tbody tr:first-child th, table tbody tr:first-child td {
  432 + border-top: none;
  433 +}
  434 +table thead + tbody tr:first-child td {
  435 + border-top: 1px solid #C6C6C6;
  436 +}
  437 +table th { background-color: #ececec; font-weight: bold; text-transform: uppercase; white-space: nowrap; }
  438 +table tbody tr:nth-child(odd) td { background-color: #F9F9F9; }
  439 +table .main { width: 100%; }
  440 +
  441 +table.single_user {
  442 + border-top: none;
  443 +}
  444 +
  445 +.raw_data {
  446 + width: 100%;
  447 + color: #f0f0f0;
  448 + background-color: #222;
  449 + overflow: auto;
  450 +}
  451 +
  452 +/* Code */
  453 +pre {
  454 + padding: 0.8em;
  455 + margin-bottom: 1em;
  456 + font-family: monaco, courier, monospace;
  457 + font-size: 1.1em;
  458 +}
  459 +
  460 +/* HTML Styling */
  461 +.html { padding-left: 1em; border-left: 2px solid #C6C6C6;}
  462 +.html h1, .html h2, .html h3, .html h4, .html h5, .html h6 {
  463 + border: none;
  464 +}
  465 +.html ul, .html ol { margin-left: 2em; margin-bottom: 1em; }
  466 +.html ul li { margin-bottom: 0.5em; list-style: disc; }
  467 +.html ol li { margin-bottom: 0.5em; list-style: decimal; }
  468 +
  469 +/* Pagination */
  470 +.pagination {
  471 + margin: 0 0 25px;
  472 + font-size: 17px;
  473 + text-align: center;
  474 +}
  475 +.pagination em {
  476 + font-style: normal;
  477 + font-weight: bold;
  478 +}
  479 +
  480 +
  481 +/* Buttons */
  482 +input[type="submit"].button,
  483 +a.button {
  484 + display: inline-block;
  485 + padding: 0 0.8em;
  486 + margin-left: 0.5em;
  487 + color: #666;
  488 + background-color: #dadada;
  489 + border: 1px solid #BBB;
  490 + border-radius: 30px;
  491 + -moz-border-radius: 30px;
  492 + -webkit-border-radius: 30px;
  493 + line-height: 30px;
  494 + min-width: 54px;
  495 + text-align: center;
  496 + text-shadow: 0 1px 0 #fff;
  497 +}
  498 +input[type="submit"]:hover.button,
  499 +a:hover.button {
  500 + box-shadow: 0px 0px 4px #bfbfbf;
  501 + -moz-box-shadow: 0px 0px 4px #bfbfbf;
  502 + -webkit-box-shadow: 0px 0px 4px #bfbfbf;
  503 + text-decoration: none;
  504 + background-color: #e5e5e5;
  505 +}
  506 +a.button.active {
  507 + border-color: #fff;
  508 + background-color: #CCC;
  509 + background-image: none;
  510 +}
  511 +
  512 +
  513 +/* Tab Bar */
  514 +.tab-bar {
  515 + margin-top: 12px;
  516 +}
  517 +#content .tab-bar a.button {
  518 + border-bottom:0;
  519 + margin-bottom:0;
  520 + border-top-left-radius:12px;
  521 + border-top-right-radius:12px;
  522 + border-bottom-left-radius:0;
  523 + border-bottom-right-radius:0;
  524 + height:30px;
  525 +}
  526 +#content .tab-bar a.button.active {
  527 + background: #FFF;
  528 + color: #444;
  529 + border-color:#ccc;
  530 + border-style:solid;
  531 + border-width:1px 1px 0;
  532 + margin-bottom:-1px;
  533 + height:31px;
  534 +}
  535 +.tab-bar ul {
  536 + padding: 9px 0 0;
  537 + line-height:0;
  538 +}
  539 +.tab-bar li {
  540 + display: inline-block;
  541 +}
  542 +
  543 +/* Watchers / Issue Tracker / Notification Forms */
  544 +div.watcher.nested .watcher_params, div.issue_tracker.nested .tracker_params, div.notification_service.nested .notification_params {
  545 + display: none;
  546 +}
  547 +
  548 +div.nested .chosen {
  549 + display: block !important;
  550 +}
  551 +div.nested .choose {
  552 + margin-bottom: 0.5em;
  553 +}
  554 +
  555 +div.issue_tracker.nested .choose, div.notification_service.nested .choose {
  556 + background-color: #ebebeb;
  557 + border: 1px solid #dddddd;
  558 + margin: 0 0 15px;
  559 + padding: 12px;
  560 +}
  561 +div.issue_tracker.nested img, div.notification_service.nested img {
  562 + vertical-align: middle;
  563 +}
  564 +
  565 +/* Icons for Issue Tracker Radio Buttons */
  566 +div.issue_tracker.nested label.label_radio, div.notification_service.nested label.label_radio {
  567 + color: #929292;
  568 + padding-left: 33px;
  569 + margin-bottom: 6px;
  570 + margin-right: 8px;
  571 + line-height: 30px;
  572 +}
  573 +div.issue_tracker.nested .choose, div.notification_service.nested .choose {
  574 + padding-bottom: 6px;
  575 +}
  576 +div.issue_tracker.nested label.label_radio:hover, div.notification_service.nested label.label_radio:hover {
  577 + color: #696969;
  578 +}
  579 +div.issue_tracker.nested .label_radio input, div.notification_service.nested .label_radio input {
  580 + position: absolute; left: -9999px;
  581 +}
  582 +
  583 +div.issue_tracker.nested label.r_on, div.issue_tracker.nested label.r_on:hover, div.notification_service.nested label.r_on, div.notification_service.nested label.r_on:hover {
  584 + color: #191919;
  585 +}
  586 +
  587 +/* Icons need to be preloaded, otherwise it looks bad */
  588 +.image_preloader { display: none; }
  589 +
  590 +/* Apps Table */
  591 +table.apps tbody tr:hover td ,table.errs tbody tr:hover td { background-color: #F2F2F2;}
  592 +
  593 +table.apps td.name, table.errs td.message { width: 100%; }
  594 +table.apps td { padding: 16px 20px; }
  595 +table.apps th { padding: 10px 20px; }
  596 +
  597 +table.apps td.issue_tracker, table.apps td.count, table.apps td.deploy {
  598 + text-align: center;
  599 +}
  600 +table.apps td.issue_tracker, table.apps td.count {
  601 + padding: 10px 8px;
  602 +}
  603 +table.apps td.issue_tracker img { vertical-align: top; }
  604 +
  605 +td.message .line {
  606 + display:inline-block;
  607 + margin-left:1em;
  608 +}
  609 +td.deploy {
  610 + white-space: nowrap;
  611 +}
  612 +td.latest {
  613 + white-space: nowrap;
  614 +}
  615 +td.count, td.issue_link {
  616 + text-align: center;
  617 +}
  618 +
  619 +.count a {
  620 + display: inline-block;
  621 + padding: 0.1em 0.7em;
  622 + margin-top: 3px;
  623 + color: #fff;
  624 + background: #cc0033 url(<%= asset_path "images/error-badge-bg.png" %>) 0 bottom repeat-x;
  625 + border: 1px solid #900;
  626 + border-radius: 18px;
  627 + -moz-border-radius: 18px;
  628 + -webkit-border-radius: 18px;
  629 + font-weight: bold;
  630 + opacity: 0.8;
  631 + -moz-opacity: 0.8;
  632 + -webkit-opacity: 0.8
  633 +}
  634 +.count a.resolved {
  635 + background: #05B81d url(<%= asset_path "images/resolved-badge-bg.png" %>) 0 bottom repeat-x;
  636 + border: 1px solid #080;
  637 +}
  638 +.count a:hover {
  639 + text-decoration: none;
  640 + opacity: 1;
  641 + -moz-opacity: 1;
  642 + -webkit-opacity: 1;
  643 +}
  644 +
  645 +/* Err Tables */
  646 +table.errs td.app {
  647 + padding-right: 2em;
  648 + width: 20%;
  649 +}
  650 +table.errs td.app .environment {
  651 + font-size: 0.8em;
  652 + color: #999;
  653 +}
  654 +table.errs td.message a {
  655 + display: block;
  656 + word-wrap: break-word;
  657 + /* PjpG - configuration in WHAT & WHERE table's columns using ellipsis to avoid oversizing table's width */
  658 + width: 300px;
  659 + overflow: hidden;
  660 + text-overflow: ellipsis;
  661 + -o-text-overflow: ellipsis;
  662 + /* ------ */
  663 +}
  664 +table.errs td.message em {
  665 + color: #727272;
  666 + font-size: 0.9em;
  667 +}
  668 +
  669 +table.errs tr.resolved td > * {
  670 + opacity: 0.5;
  671 + -moz-opacity: 0.5;
  672 + -webkit-opacity: 0.5;
  673 +}
  674 +
  675 +/* Tally tables */
  676 +table.tally {
  677 + border:none;
  678 +}
  679 +table.tally td,
  680 +table.tally th {
  681 + border:none !important;
  682 + background:none !important;
  683 + padding:8px 0 0;
  684 +}
  685 +table.tally tbody tr:first-child td,
  686 +table.tally tbody tr:first-child th {
  687 + padding-top:0;
  688 +}
  689 +table.tally td.percent {
  690 + padding-right: 10px;
  691 +}
  692 +table.tally th.value {
  693 + width: 100%;
  694 + text-transform: none;
  695 +}
  696 +
  697 +/* Deploys table */
  698 +table.deploys td.when {
  699 + width: 102px;
  700 +}
  701 +
  702 +/* Resolve Errs */
  703 +#action-bar a.resolve {
  704 + background: transparent url(<%= asset_path "images/icons/thumbs-up.png" %>) 6px 5px no-repeat;
  705 +}
  706 +
  707 +/* Go Up */
  708 +#action-bar a.up {
  709 + background: transparent url(<%= asset_path "images/icons/up.png" %>) 6px 5px no-repeat;
  710 +}
  711 +
  712 +/* Notices Pagination */
  713 +.notice-pagination {
  714 + float: left;
  715 + margin-right: 10px;
  716 +}
  717 +
  718 +.notice-pagination-loader {
  719 + visibility: hidden;
  720 + float: left;
  721 + width: 16px;
  722 + height: 16px;
  723 + margin-right: 1em;
  724 +}
  725 +.notice-pagination-loader img {
  726 + vertical-align: middle
  727 +}
  728 +
  729 +
  730 +/* Backtrace */
  731 +.window {
  732 + width: 100%;
  733 + margin-bottom: 1em;
  734 + overflow: auto;
  735 + border:1px solid #ccc;
  736 + padding:1px;
  737 +}
  738 +
  739 +.window table {
  740 + margin: 0;
  741 +}
  742 +
  743 +table.backtrace {
  744 + padding: 8px 0;
  745 + background-color: #222;
  746 +}
  747 +
  748 +table.backtrace td {
  749 + width: 100%;
  750 + padding: 0;
  751 + margin: 0;
  752 + color: #C7C7C7;
  753 + background-color: #222;
  754 +}
  755 +
  756 +table.backtrace td, table.backtrace th {
  757 + border-top: none;
  758 +}
  759 +
  760 +/* remove alternating color rules */
  761 +table.backtrace tr:nth-child(2n+1) td { background-color: #222; }
  762 +table.backtrace tr:first-child td { border-top: 0; }
  763 +
  764 +table.backtrace th.line-numbers {
  765 + border-bottom: 1px solid #F0F0F0;
  766 + font-size: 13px;
  767 + text-align: right;
  768 + vertical-align: top;
  769 + padding: 1px 6px 1px 7px;
  770 +}
  771 +
  772 +table.backtrace td.line {
  773 + font-size: 13px;
  774 + padding: 2px 8px;
  775 + vertical-align: top;
  776 + white-space: nowrap;
  777 +}
  778 +table.backtrace td.line .file {
  779 + font-weight: bold;
  780 +}
  781 +table.backtrace td.line .method {
  782 + color: #aaa;
  783 + font-weight: bold;
  784 +}
  785 +
  786 +table.backtrace td.line.in-app {
  787 + color: #2adb2e;
  788 + background-color: #2f2f2f;
  789 +}
  790 +table.backtrace td.line.in-app .path,
  791 +table.backtrace td.line.in-app .number { color: #2ACB2E; }
  792 +table.backtrace td.line.in-app .file { color: #3AFB3E; }
  793 +table.backtrace td.line.in-app .method { color: #2ACB2E; }
  794 +
  795 +table.backtrace td.line.in-app a .path,
  796 +table.backtrace td.line.in-app a .number,
  797 +table.backtrace td.line.in-app a:hover { color: #21B4FF; }
  798 +table.backtrace td.line.in-app a .file { color: #31C4FF; }
  799 +
  800 +/* External backtrace classes and separators */
  801 +table.backtrace tr.hidden_external_backtrace {
  802 + display: none;
  803 +}
  804 +table.backtrace td.backtrace_separator span {
  805 + cursor: pointer;
  806 + display: inline-block;
  807 + font-size: 17px;
  808 + font-weight: bold;
  809 + padding: 0px 11px 5px;
  810 + margin: 4px 0;
  811 + background-color: #444444;
  812 + border: 1px solid #555555;
  813 +}
  814 +table.backtrace td.backtrace_separator span:hover {
  815 + background-color: #666666;
  816 + border: 1px solid #777777;
  817 +}
  818 +
  819 +
  820 +
  821 +/* Extra empty rows at top and bottom of table */
  822 +table.backtrace tr.padding th, table.backtrace tr.padding td {
  823 + height: 10px;
  824 + margin: 0;
  825 + padding: 0;
  826 +}
  827 +
  828 +h3#watchers_toggle, h3#repository_toggle, h3#deploys_toggle {
  829 + cursor: pointer;
  830 +}
  831 +
  832 +span.click_span {
  833 + font-size: 0.7em;
  834 +}
  835 +
  836 +#deploys_div, #repository_div, #watchers_div {
  837 + display: none;
  838 +}
  839 +
  840 +/* Comments */
  841 +#content-comments form p {
  842 + margin: 30px 0 0 0;
  843 + text-transform: uppercase;
  844 +}
  845 +table.comment tbody th {
  846 + text-transform: none;
  847 + font-weight: normal;
  848 + height: 20px;
  849 + line-height: 0.5em;
  850 +}
  851 +table.comment th span, table.comment th img {
  852 + vertical-align: middle;
  853 +}
  854 +table.comment th span.comment-info {
  855 + line-height: 21px;
  856 + float: left;
  857 +}
  858 +table.comment img.gravatar {
  859 + margin-right: 7px;
  860 + float: left;
  861 +}
  862 +
  863 +table.comment tbody td {
  864 + background-color: #F9F9F9;
  865 +}
  866 +#content-comments a.destroy-comment {
  867 + color: #EE0000;
  868 + margin-right: 5px;
  869 + margin-top: 2px;
  870 + font-size: 21px;
  871 + line-height: 1;
  872 + float: right;
  873 +}
  874 +#content-comments a.destroy-comment:hover {
  875 + text-decoration: none;
  876 + color: #AA0000;
  877 +}
  878 +#content-comments #comment_submit {
  879 + margin-top: 15px;
  880 +}
  881 +/* Inline comments in tables */
  882 +table.errs tr td.message .inline_comment {
  883 + display: inline-block;
  884 + padding: 3px 7px;
  885 + margin: 6px 0;
  886 + background-color: #DAE5FF;
  887 + border: 1px solid #E2E2E2;
  888 + text-shadow: 0 1px 0 #FAFAFA;
  889 + font-style: normal;
  890 +}
  891 +table.errs tr:hover td.message .inline_comment {
  892 + background-color: #D5E0FA;
  893 + border-color: #DBDBDB;
  894 + text-shadow: 0 1px 0 #FFFFFF;
  895 +}
  896 +table.errs tr td.message .inline_comment em {
  897 + color: #444;
  898 +}
  899 +table.errs tr td.message .inline_comment em.commenter {
  900 + color: #777;
  901 +}
  902 +
  903 +textarea#comment_body {
  904 + width: 420px;
  905 + height: 80px;
  906 +}
  907 +
  908 +.current.asc:after { content: ' ↑'; }
  909 +.current.desc:after { content: ' ↓'; }
  910 +
  911 +
  912 +table.users td {
  913 + vertical-align: middle;
  914 +}
  915 +table.users td img.gravatar {
  916 + vertical-align: middle;
  917 + margin-left: 3px;
  918 +}
... ...
app/assets/stylesheets/issue_tracker_icons.css.erb
... ... @@ -3,16 +3,16 @@
3 3  
4 4 <% trackers.each do |tracker| %>
5 5 div.issue_tracker.nested label.<%= tracker %> {
6   - background: url(<%= tracker %>_inactive.png) no-repeat;
  6 + background: url(<%= asset_path "#{ tracker }_inactive.png" %>) no-repeat;
7 7 }
8 8 div.issue_tracker.nested label.r_on.<%= tracker %> {
9   - background: url(<%= tracker %>_create.png) no-repeat;
  9 + background: url(<%= asset_path "#{ tracker }_create.png" %>) no-repeat;
10 10 }
11 11 #action-bar a.<%= tracker %>_create {
12   - background: transparent url(<%= tracker %>_create.png) 6px 5px no-repeat;
  12 + background: transparent url(<%= asset_path "#{ tracker }_create.png" %>) 6px 5px no-repeat;
13 13 }
14 14 #action-bar a.<%= tracker %>_goto {
15   - background: transparent url(<%= tracker %>_goto.png) 6px 5px no-repeat;
  15 + background: transparent url(<%= asset_path "#{ tracker }_goto.png" %>) 6px 5px no-repeat;
16 16 }
17 17 <% end %>
18 18  
... ...
app/assets/stylesheets/jquery.alerts.css
... ... @@ -1,57 +0,0 @@
1   -#popup_container {
2   - font-family: Arial, sans-serif;
3   - font-size: 12px;
4   - min-width: 300px; /* Dialog will be no smaller than this */
5   - max-width: 600px; /* Dialog will wrap after this width */
6   - background: #FFF;
7   - border: solid 5px #999;
8   - color: #000;
9   - -moz-border-radius: 5px;
10   - -webkit-border-radius: 5px;
11   - border-radius: 5px;
12   -}
13   -
14   -#popup_title {
15   - font-size: 14px;
16   - font-weight: bold;
17   - text-align: center;
18   - line-height: 1.75em;
19   - color: #666;
20   - background: #CCC url(alerts/title.gif) top repeat-x;
21   - border: solid 1px #FFF;
22   - border-bottom: solid 1px #999;
23   - cursor: default;
24   - padding: 0em;
25   - margin: 0em;
26   -}
27   -
28   -#popup_content {
29   - background: 16px 16px no-repeat url(alerts/info.gif);
30   - padding: 1em 1.75em;
31   - margin: 0em;
32   -}
33   -
34   -#popup_content.alert {
35   - background-image: url(alerts/info.gif);
36   -}
37   -
38   -#popup_content.confirm {
39   - background-image: url(alerts/important.gif);
40   -}
41   -
42   -#popup_content.prompt {
43   - background-image: url(alerts/help.gif);
44   -}
45   -
46   -#popup_message {
47   - padding-left: 48px;
48   -}
49   -
50   -#popup_panel {
51   - text-align: center;
52   - margin: 1em 0em 0em 1em;
53   -}
54   -
55   -#popup_prompt {
56   - margin: .5em 0em;
57   -}
58 0 \ No newline at end of file
app/assets/stylesheets/jquery.alerts.css.erb 0 → 100644
... ... @@ -0,0 +1,57 @@
  1 +#popup_container {
  2 + font-family: Arial, sans-serif;
  3 + font-size: 12px;
  4 + min-width: 300px; /* Dialog will be no smaller than this */
  5 + max-width: 600px; /* Dialog will wrap after this width */
  6 + background: #FFF;
  7 + border: solid 5px #999;
  8 + color: #000;
  9 + -moz-border-radius: 5px;
  10 + -webkit-border-radius: 5px;
  11 + border-radius: 5px;
  12 +}
  13 +
  14 +#popup_title {
  15 + font-size: 14px;
  16 + font-weight: bold;
  17 + text-align: center;
  18 + line-height: 1.75em;
  19 + color: #666;
  20 + background: #CCC url(<%= asset_path "alerts/title.gif" %>) top repeat-x;
  21 + border: solid 1px #FFF;
  22 + border-bottom: solid 1px #999;
  23 + cursor: default;
  24 + padding: 0em;
  25 + margin: 0em;
  26 +}
  27 +
  28 +#popup_content {
  29 + background: 16px 16px no-repeat url(<%= asset_path "alerts/info.gif" %>);
  30 + padding: 1em 1.75em;
  31 + margin: 0em;
  32 +}
  33 +
  34 +#popup_content.alert {
  35 + background-image: url(<%= asset_path "alerts/info.gif" %>);
  36 +}
  37 +
  38 +#popup_content.confirm {
  39 + background-image: url(<%= asset_path "alerts/important.gif" %>);
  40 +}
  41 +
  42 +#popup_content.prompt {
  43 + background-image: url(<%= asset_path "alerts/help.gif" %>);
  44 +}
  45 +
  46 +#popup_message {
  47 + padding-left: 48px;
  48 +}
  49 +
  50 +#popup_panel {
  51 + text-align: center;
  52 + margin: 1em 0em 0em 1em;
  53 +}
  54 +
  55 +#popup_prompt {
  56 + margin: .5em 0em;
  57 +}
... ...
app/assets/stylesheets/notification_service_icons.css.erb
... ... @@ -3,16 +3,16 @@
3 3  
4 4 <% notification_services.each do |notification_service| %>
5 5 div.notification_service.nested label.<%= notification_service %> {
6   - background: url(<%= notification_service %>_inactive.png) no-repeat;
  6 + background: url(<%= asset_path "#{ notification_service }_inactive.png" %>) no-repeat;
7 7 }
8 8 div.notification_service.nested label.r_on.<%= notification_service %> {
9   - background: url(<%= notification_service %>_create.png) no-repeat;
  9 + background: url(<%= asset_path "#{ notification_service }_create.png" %>) no-repeat;
10 10 }
11 11 #action-bar a.<%= notification_service %>_create {
12   - background: transparent url(<%= notification_service %>_create.png) 6px 5px no-repeat;
  12 + background: transparent url(<%= asset_path "#{ notification_service }_create.png" %>) 6px 5px no-repeat;
13 13 }
14 14 #action-bar a.<%= notification_service %>_goto {
15   - background: transparent url(<%= notification_service %>_goto.png) 6px 5px no-repeat;
  15 + background: transparent url(<%= asset_path "#{ notification_service }_goto.png" %>) 6px 5px no-repeat;
16 16 }
17 17 <% end %>
18 18  
... ...
app/controllers/notices_controller.rb
... ... @@ -11,11 +11,15 @@ class NoticesController &lt; ApplicationController
11 11 report = ErrorReport.new(notice_params)
12 12  
13 13 if report.valid?
14   - report.generate_notice!
15   - api_xml = report.notice.to_xml(:only => false, :methods => [:id]) do |xml|
16   - xml.url locate_url(report.notice.id, :host => Errbit::Config.host)
  14 + if report.should_keep?
  15 + report.generate_notice!
  16 + api_xml = report.notice.to_xml(:only => false, :methods => [:id]) do |xml|
  17 + xml.url locate_url(report.notice.id, :host => Errbit::Config.host)
  18 + end
  19 + render :xml => api_xml
  20 + else
  21 + render :text => "Notice for old app version ignored"
17 22 end
18   - render :xml => api_xml
19 23 else
20 24 render :text => "Your API key is unknown", :status => 422
21 25 end
... ...
app/controllers/users/omniauth_callbacks_controller.rb
... ... @@ -4,6 +4,16 @@ class Users::OmniauthCallbacksController &lt; Devise::OmniauthCallbacksController
4 4 github_token = env["omniauth.auth"].credentials.token
5 5 github_user = User.where(:github_login => github_login).first
6 6  
  7 + if github_user.nil? && github_org_id = Errbit::Config.github_org_id
  8 + # See if they are a member of the organization that we have access for
  9 + # If they are, automatically create an account
  10 + client = Octokit::Client.new(access_token: github_token)
  11 + org_ids = client.organizations.map { |org| org.id.to_s }
  12 + if org_ids.include?(github_org_id)
  13 + github_user = User.create(name: env["omniauth.auth"].extra.raw_info.name, email: env["omniauth.auth"].extra.raw_info.email)
  14 + end
  15 + end
  16 +
7 17 # If user is already signed in, link github details to their account
8 18 if current_user
9 19 # ... unless a user is already registered with same github login
... ...
app/models/app.rb
... ... @@ -9,6 +9,7 @@ class App
9 9 field :bitbucket_repo
10 10 field :asset_host
11 11 field :repository_branch
  12 + field :current_app_version
12 13 field :resolve_errs_on_deploy, :type => Boolean, :default => false
13 14 field :notify_all_users, :type => Boolean, :default => false
14 15 field :notify_on_errs, :type => Boolean, :default => true
... ... @@ -98,7 +99,7 @@ class App
98 99 end
99 100  
100 101 def github_url
101   - "https://github.com/#{github_repo}" if github_repo?
  102 + "#{Errbit::Config.github_url}/#{github_repo}" if github_repo?
102 103 end
103 104  
104 105 def github_url_to_file(file)
... ... @@ -202,8 +203,10 @@ class App
202 203  
203 204 def normalize_github_repo
204 205 return if github_repo.blank?
  206 + github_host = URI.parse(Errbit::Config.github_url).host
  207 + github_host = Regexp.escape(github_host)
205 208 github_repo.strip!
206   - github_repo.sub!(/(git@|https?:\/\/)github\.com(\/|:)/, '')
  209 + github_repo.sub!(/(git@|https?:\/\/)#{github_host}(\/|:)/, '')
207 210 github_repo.sub!(/\.git$/, '')
208 211 end
209 212  
... ...
app/models/error_report.rb
... ... @@ -72,6 +72,15 @@ class ErrorReport
72 72 !!app
73 73 end
74 74  
  75 + def should_keep?
  76 + app_version = server_environment['app-version'] || ''
  77 + if self.app.current_app_version.present? && ( app_version.length <= 0 || Gem::Version.new(app_version) < Gem::Version.new(self.app.current_app_version) )
  78 + false
  79 + else
  80 + true
  81 + end
  82 + end
  83 +
75 84 private
76 85  
77 86 def fingerprint
... ...
app/models/issue_tracker.rb
... ... @@ -5,6 +5,7 @@ class IssueTracker
5 5 include Rails.application.routes.url_helpers
6 6  
7 7 default_url_options[:host] = ActionMailer::Base.default_url_options[:host]
  8 + default_url_options[:port] = ActionMailer::Base.default_url_options[:port]
8 9  
9 10 embedded_in :app, :inverse_of => :issue_tracker
10 11  
... ...
app/models/notification_service.rb
... ... @@ -3,6 +3,7 @@ class NotificationService
3 3  
4 4 include Rails.application.routes.url_helpers
5 5 default_url_options[:host] = ActionMailer::Base.default_url_options[:host]
  6 + default_url_options[:port] = ActionMailer::Base.default_url_options[:port]
6 7  
7 8 field :room_id, :type => String
8 9 field :user_id, :type => String
... ...
app/views/apps/_fields.html.haml
... ... @@ -22,7 +22,10 @@
22 22 = f.label :asset_host
23 23 %em Used to generate links for JavaScript errors
24 24 = f.text_field :asset_host, :placeholder => "e.g. https://assets.example.com"
25   -
  25 +%div
  26 + = f.label :current_app_version, 'Latest App Version'
  27 + %em Mobile apps can set this to ignore any error below this version. ie: 1.4.3
  28 + = f.text_field :current_app_version, :placeholder => "e.g. 2.0.1 from the Bundle Identifier on an iOS app"
26 29 %fieldset
27 30 %legend Notifications
28 31 %div.checkbox
... ...
app/views/apps/show.html.haml
... ... @@ -2,6 +2,9 @@
2 2 - content_for :head do
3 3 = auto_discovery_link_tag :atom, app_path(app, User.token_authentication_key => current_user.authentication_token, :format => "atom"), :title => t('.atom_title', :name => app.name, :host => request.host)
4 4 - content_for :meta do
  5 + - if app.current_app_version.present?
  6 + %strong="Latest App Version:"
  7 + = app.current_app_version
5 8 %strong=t('.errors_caught')
6 9 = app.problems.count
7 10 %strong=t('.deploy_count')
... ...
app/views/mailer/err_notification.html.haml
... ... @@ -32,6 +32,11 @@
32 32 = link_to_source_file(line) do
33 33 = line.to_s
34 34 %br
  35 + - if @notice.app_version.present?
  36 + %p.heading APP VERSION:
  37 + %p.monospace
  38 + = @notice.app_version
  39 + %br
35 40 %p.heading URL:
36 41 %p.monospace
37 42 - if @notice.request['url'].present?
... ...
app/views/mailer/err_notification.text.erb
... ... @@ -18,6 +18,11 @@ WHERE:
18 18 <%= line %>
19 19 <% end %>
20 20  
  21 +<%- if @notice.app_version.present? %>
  22 +APP VERSION:
  23 +
  24 +<%= @notice.app_version %>
  25 +<%- end %>
21 26  
22 27 URL:
23 28  
... ...
app/views/problems/show.html.haml
1 1 - content_for :page_title, problem.message
2   -- content_for :title_css_class, 'err_show'
  2 +- content_for :title_css_class, "err_show #{'resolved' if problem.resolved?}"
3 3 - content_for :title, problem.error_class || truncate(problem.message, :length => 32)
4 4 - content_for :meta do
5 5 %strong App:
... ...
config/config.example.yml
... ... @@ -11,6 +11,14 @@
11 11 # The host of your errbit server
12 12 host: errbit.example.com
13 13  
  14 +# The port for your errbit server.
  15 +# Only set this if it isn't the default for the protocol (i.e.. 80 for HTTP, 443 for HTTPS)
  16 +# port: 8080
  17 +
  18 +# The protocol for your errbit server.
  19 +# Only set if not running default HTTP
  20 +# protocol: https
  21 +
14 22 # Enforce SSL connections
15 23 enforce_ssl: false
16 24  
... ... @@ -65,7 +73,7 @@ deployment:
65 73 web: errbit.example.com
66 74 app: errbit.example.com
67 75 db: errbit.example.com
68   - repository: http://github.com/errbit/errbit.git
  76 + repository: https://github.com/errbit/errbit.git
69 77 branch: master
70 78 user: deploy
71 79 deploy_to: /var/www/apps/errbit
... ... @@ -90,6 +98,10 @@ github_secret: &#39;GITHUB_SECRET&#39;
90 98 # [] - No permission to create issues on any repos.
91 99 github_access_scope: ['repo']
92 100  
  101 +# Change this to point to the URL of your GitHub Enterprise installation, if
  102 +# you want to link local repositories.
  103 +github_url: https://github.com
  104 +
93 105 # Configure SMTP settings. If you are running Errbit on Heroku,
94 106 # sendgrid will be configured by default.
95 107 # ------------------------------------------------------------------------
... ...
config/initializers/_load_config.rb
... ... @@ -9,6 +9,7 @@ unless defined?(Errbit::Config)
9 9 # If Errbit is running on Heroku, config can be set from environment variables.
10 10 if use_env
11 11 Errbit::Config.host = ENV['ERRBIT_HOST']
  12 + Errbit::Config.port = ENV['ERRBIT_PORT']
12 13 Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM']
13 14 # Not really easy to use like an env because need an array and ENV return a string :(
14 15 # Errbit::Config.email_at_notices = ENV['ERRBIT_EMAIL_AT_NOTICES']
... ... @@ -20,9 +21,11 @@ unless defined?(Errbit::Config)
20 21 Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR']
21 22 Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT']
22 23  
  24 + Errbit::Config.github_url = ENV['GITHUB_URL']
23 25 Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION']
24 26 Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID']
25 27 Errbit::Config.github_secret = ENV['GITHUB_SECRET']
  28 + Errbit::Config.github_org_id = ENV['GITHUB_ORG_ID'] if ENV['GITHUB_ORG_ID']
26 29 Errbit::Config.github_access_scope = ENV['GITHUB_ACCESS_SCOPE'].split(',').map(&:strip) if ENV['GITHUB_ACCESS_SCOPE']
27 30  
28 31 Errbit::Config.smtp_settings = {
... ... @@ -62,6 +65,10 @@ default_config.each do |k,v|
62 65 Errbit::Config.send("#{k}=", v) if Errbit::Config.send(k) === nil
63 66 end
64 67  
  68 +# Make sure the GitHub link doesn't end with a slash, so we don't have to deal
  69 +# with it later on in the code.
  70 +Errbit::Config.github_url.gsub!(/\/*\z/, '')
  71 +
65 72 # Disable GitHub oauth if gem is missing
66 73 Errbit::Config.github_authentication = false unless defined?(OmniAuth::Strategies::GitHub)
67 74  
... ... @@ -78,7 +85,13 @@ end
78 85  
79 86 # Set config specific values
80 87 (ActionMailer::Base.default_url_options ||= {}).tap do |default|
81   - default.merge! :host => Errbit::Config.host if default[:host].blank?
  88 + options_from_config = {
  89 + host: Errbit::Config.host,
  90 + port: Errbit::Config.port,
  91 + protocol: Errbit::Config.protocol
  92 + }.select { |k, v| v }
  93 +
  94 + default.reverse_merge!(options_from_config)
82 95 end
83 96  
84 97 if Rails.env.production?
... ...
config/locales/en.yml
... ... @@ -35,13 +35,13 @@ en:
35 35 flash:
36 36 create:
37 37 success: "Your app was successfully created."
38   - error: "You app was successfully destroyed."
  38 + error: "Your app could not be created."
39 39 update:
40   - success: "You app was successfully updated."
41   - error: "You app was not updated"
  40 + success: "Your app was successfully updated."
  41 + error: "Your app could not be updated."
42 42 destroy:
43   - success: "You app was successfully destroyed."
44   - error: "You app could not be destroyed."
  43 + success: "Your app was successfully destroyed."
  44 + error: "Your app could not be destroyed."
45 45  
46 46 users:
47 47 flash:
... ...
db/migrate/20131206152837_add_min_app_version_to_apps.rb 0 → 100644
... ... @@ -0,0 +1,5 @@
  1 +class AddMinAppVersionToApps < Mongoid::Migration
  2 + def change
  3 + add_column :apps, :current_app_version, :string
  4 + end
  5 +end
0 6 \ No newline at end of file
... ...
public/javascripts/notifier.js
... ... @@ -556,11 +556,11 @@ printStackTrace.implementation.prototype = {
556 556  
557 557 "userId": "{user_id}",
558 558 "userName": "{user_name}",
559   - "userEmail": "{user_email}",
  559 + "userEmail": "{user_email}"
560 560 },
561 561 "environment": {},
562 562 //"session": "",
563   - "params": {},
  563 + "params": {}
564 564 };
565 565  
566 566 Util = {
... ...
spec/controllers/notices_controller_spec.rb
... ... @@ -6,7 +6,7 @@ describe NoticesController do
6 6 let(:notice) { Fabricate(:notice) }
7 7 let(:xml) { Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read }
8 8 let(:app) { Fabricate(:app) }
9   - let(:error_report) { double(:valid? => true, :generate_notice! => true, :notice => notice) }
  9 + let(:error_report) { double(:valid? => true, :generate_notice! => true, :notice => notice, :should_keep? => true) }
10 10  
11 11 context 'notices API' do
12 12 context "with all params" do
... ...
spec/models/error_report_spec.rb
... ... @@ -230,5 +230,35 @@ describe ErrorReport do
230 230 end
231 231 end
232 232  
  233 + describe "#should_keep?" do
  234 + context "with current app version not set" do
  235 + before do
  236 + error_report.app.current_app_version = nil
  237 + error_report.server_environment['app-version'] = '1.0'
  238 + end
  239 +
  240 + it "return true" do
  241 + expect(error_report.should_keep?).to be true
  242 + end
  243 + end
  244 +
  245 + context "with current app version set" do
  246 + before do
  247 + error_report.app.current_app_version = '1.0'
  248 + end
  249 +
  250 + it "return true if current or newer" do
  251 + error_report.server_environment['app-version'] = '1.0'
  252 + expect(error_report.should_keep?).to be true
  253 + end
  254 +
  255 + it "return false if older" do
  256 + error_report.server_environment['app-version'] = '0.9'
  257 + expect(error_report.should_keep?).to be false
  258 + end
  259 + end
  260 +
  261 + end
  262 +
233 263 end
234 264 end
... ...