Commit f75c27502c8b2b7e2e556b08367917d5a4602484

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

Merge remote-tracking branch 'errbit/master' into features/extract_issue_tracker-merge_master

Conflicts:
	Gemfile
	Gemfile.lock
	app/models/issue_trackers/github_issues_tracker.rb
	app/models/issue_trackers/redmine_tracker.rb
	spec/models/issue_trackers/redmine_tracker_spec.rb
@@ -34,7 +34,6 @@ gem 'errbit_github_plugin', @@ -34,7 +34,6 @@ gem 'errbit_github_plugin',
34 :git => 'https://github.com/errbit/errbit_github_plugin.git' 34 :git => 'https://github.com/errbit/errbit_github_plugin.git'
35 # :path => 'vendor/gems/errbit_github_plugin' 35 # :path => 'vendor/gems/errbit_github_plugin'
36 36
37 -  
38 # Notification services 37 # Notification services
39 # --------------------------------------- 38 # ---------------------------------------
40 gem 'campy' 39 gem 'campy'
@@ -299,6 +299,13 @@ heroku config:add GITHUB_SECRET=the_secret_provided_by_GitHub @@ -299,6 +299,13 @@ heroku config:add GITHUB_SECRET=the_secret_provided_by_GitHub
299 heroku config:add GITHUB_ACCESS_SCOPE=repo,public_repo 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 __Note__: To avoid restarting your Heroku app 4 times you can set Heroku variables in a single command, i.e: 309 __Note__: To avoid restarting your Heroku app 4 times you can set Heroku variables in a single command, i.e:
303 310
304 ```bash 311 ```bash
app/assets/javascripts/form.js
@@ -81,7 +81,7 @@ function activateTypeSelector(field_class, section_class) { @@ -81,7 +81,7 @@ function activateTypeSelector(field_class, section_class) {
81 $('div.'+field_class+' > div.'+section_class).not('.chosen').find('input') 81 $('div.'+field_class+' > div.'+section_class).not('.chosen').find('input')
82 .attr('disabled','disabled').val(''); 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 // Look for section in 'data-section', and fall back to 'value' 85 // Look for section in 'data-section', and fall back to 'value'
86 var chosen = $(this).data("section") || $(this).val(); 86 var chosen = $(this).data("section") || $(this).val();
87 var wrapper = $(this).closest('.nested'); 87 var wrapper = $(this).closest('.nested');
app/assets/stylesheets/errbit.css
@@ -1,913 +0,0 @@ @@ -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 @@ @@ -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,16 +3,16 @@
3 3
4 <% trackers.each do |tracker| %> 4 <% trackers.each do |tracker| %>
5 div.issue_tracker.nested label.<%= tracker %> { 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 div.issue_tracker.nested label.r_on.<%= tracker %> { 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 #action-bar a.<%= tracker %>_create { 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 #action-bar a.<%= tracker %>_goto { 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 <% end %> 17 <% end %>
18 18
app/assets/stylesheets/jquery.alerts.css
@@ -1,57 +0,0 @@ @@ -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 \ No newline at end of file 0 \ No newline at end of file
app/assets/stylesheets/jquery.alerts.css.erb 0 → 100644
@@ -0,0 +1,57 @@ @@ -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,16 +3,16 @@
3 3
4 <% notification_services.each do |notification_service| %> 4 <% notification_services.each do |notification_service| %>
5 div.notification_service.nested label.<%= notification_service %> { 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 div.notification_service.nested label.r_on.<%= notification_service %> { 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 #action-bar a.<%= notification_service %>_create { 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 #action-bar a.<%= notification_service %>_goto { 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 <% end %> 17 <% end %>
18 18
app/controllers/notices_controller.rb
@@ -11,11 +11,15 @@ class NoticesController &lt; ApplicationController @@ -11,11 +11,15 @@ class NoticesController &lt; ApplicationController
11 report = ErrorReport.new(notice_params) 11 report = ErrorReport.new(notice_params)
12 12
13 if report.valid? 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 end 22 end
18 - render :xml => api_xml  
19 else 23 else
20 render :text => "Your API key is unknown", :status => 422 24 render :text => "Your API key is unknown", :status => 422
21 end 25 end
app/controllers/users/omniauth_callbacks_controller.rb
@@ -4,6 +4,16 @@ class Users::OmniauthCallbacksController &lt; Devise::OmniauthCallbacksController @@ -4,6 +4,16 @@ class Users::OmniauthCallbacksController &lt; Devise::OmniauthCallbacksController
4 github_token = env["omniauth.auth"].credentials.token 4 github_token = env["omniauth.auth"].credentials.token
5 github_user = User.where(:github_login => github_login).first 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 # If user is already signed in, link github details to their account 17 # If user is already signed in, link github details to their account
8 if current_user 18 if current_user
9 # ... unless a user is already registered with same github login 19 # ... unless a user is already registered with same github login
app/models/app.rb
@@ -9,6 +9,7 @@ class App @@ -9,6 +9,7 @@ class App
9 field :bitbucket_repo 9 field :bitbucket_repo
10 field :asset_host 10 field :asset_host
11 field :repository_branch 11 field :repository_branch
  12 + field :current_app_version
12 field :resolve_errs_on_deploy, :type => Boolean, :default => false 13 field :resolve_errs_on_deploy, :type => Boolean, :default => false
13 field :notify_all_users, :type => Boolean, :default => false 14 field :notify_all_users, :type => Boolean, :default => false
14 field :notify_on_errs, :type => Boolean, :default => true 15 field :notify_on_errs, :type => Boolean, :default => true
@@ -98,7 +99,7 @@ class App @@ -98,7 +99,7 @@ class App
98 end 99 end
99 100
100 def github_url 101 def github_url
101 - "https://github.com/#{github_repo}" if github_repo? 102 + "#{Errbit::Config.github_url}/#{github_repo}" if github_repo?
102 end 103 end
103 104
104 def github_url_to_file(file) 105 def github_url_to_file(file)
@@ -202,8 +203,10 @@ class App @@ -202,8 +203,10 @@ class App
202 203
203 def normalize_github_repo 204 def normalize_github_repo
204 return if github_repo.blank? 205 return if github_repo.blank?
  206 + github_host = URI.parse(Errbit::Config.github_url).host
  207 + github_host = Regexp.escape(github_host)
205 github_repo.strip! 208 github_repo.strip!
206 - github_repo.sub!(/(git@|https?:\/\/)github\.com(\/|:)/, '') 209 + github_repo.sub!(/(git@|https?:\/\/)#{github_host}(\/|:)/, '')
207 github_repo.sub!(/\.git$/, '') 210 github_repo.sub!(/\.git$/, '')
208 end 211 end
209 212
app/models/error_report.rb
@@ -72,6 +72,15 @@ class ErrorReport @@ -72,6 +72,15 @@ class ErrorReport
72 !!app 72 !!app
73 end 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 private 84 private
76 85
77 def fingerprint 86 def fingerprint
app/models/issue_tracker.rb
@@ -5,6 +5,7 @@ class IssueTracker @@ -5,6 +5,7 @@ class IssueTracker
5 include Rails.application.routes.url_helpers 5 include Rails.application.routes.url_helpers
6 6
7 default_url_options[:host] = ActionMailer::Base.default_url_options[:host] 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 embedded_in :app, :inverse_of => :issue_tracker 10 embedded_in :app, :inverse_of => :issue_tracker
10 11
app/models/notification_service.rb
@@ -3,6 +3,7 @@ class NotificationService @@ -3,6 +3,7 @@ class NotificationService
3 3
4 include Rails.application.routes.url_helpers 4 include Rails.application.routes.url_helpers
5 default_url_options[:host] = ActionMailer::Base.default_url_options[:host] 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 field :room_id, :type => String 8 field :room_id, :type => String
8 field :user_id, :type => String 9 field :user_id, :type => String
app/views/apps/_fields.html.haml
@@ -22,7 +22,10 @@ @@ -22,7 +22,10 @@
22 = f.label :asset_host 22 = f.label :asset_host
23 %em Used to generate links for JavaScript errors 23 %em Used to generate links for JavaScript errors
24 = f.text_field :asset_host, :placeholder => "e.g. https://assets.example.com" 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 %fieldset 29 %fieldset
27 %legend Notifications 30 %legend Notifications
28 %div.checkbox 31 %div.checkbox
app/views/apps/show.html.haml
@@ -2,6 +2,9 @@ @@ -2,6 +2,9 @@
2 - content_for :head do 2 - content_for :head do
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) 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 - content_for :meta do 4 - content_for :meta do
  5 + - if app.current_app_version.present?
  6 + %strong="Latest App Version:"
  7 + = app.current_app_version
5 %strong=t('.errors_caught') 8 %strong=t('.errors_caught')
6 = app.problems.count 9 = app.problems.count
7 %strong=t('.deploy_count') 10 %strong=t('.deploy_count')
app/views/mailer/err_notification.html.haml
@@ -32,6 +32,11 @@ @@ -32,6 +32,11 @@
32 = link_to_source_file(line) do 32 = link_to_source_file(line) do
33 = line.to_s 33 = line.to_s
34 %br 34 %br
  35 + - if @notice.app_version.present?
  36 + %p.heading APP VERSION:
  37 + %p.monospace
  38 + = @notice.app_version
  39 + %br
35 %p.heading URL: 40 %p.heading URL:
36 %p.monospace 41 %p.monospace
37 - if @notice.request['url'].present? 42 - if @notice.request['url'].present?
app/views/mailer/err_notification.text.erb
@@ -18,6 +18,11 @@ WHERE: @@ -18,6 +18,11 @@ WHERE:
18 <%= line %> 18 <%= line %>
19 <% end %> 19 <% end %>
20 20
  21 +<%- if @notice.app_version.present? %>
  22 +APP VERSION:
  23 +
  24 +<%= @notice.app_version %>
  25 +<%- end %>
21 26
22 URL: 27 URL:
23 28
app/views/problems/show.html.haml
1 - content_for :page_title, problem.message 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 - content_for :title, problem.error_class || truncate(problem.message, :length => 32) 3 - content_for :title, problem.error_class || truncate(problem.message, :length => 32)
4 - content_for :meta do 4 - content_for :meta do
5 %strong App: 5 %strong App:
config/config.example.yml
@@ -11,6 +11,14 @@ @@ -11,6 +11,14 @@
11 # The host of your errbit server 11 # The host of your errbit server
12 host: errbit.example.com 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 # Enforce SSL connections 22 # Enforce SSL connections
15 enforce_ssl: false 23 enforce_ssl: false
16 24
@@ -65,7 +73,7 @@ deployment: @@ -65,7 +73,7 @@ deployment:
65 web: errbit.example.com 73 web: errbit.example.com
66 app: errbit.example.com 74 app: errbit.example.com
67 db: errbit.example.com 75 db: errbit.example.com
68 - repository: http://github.com/errbit/errbit.git 76 + repository: https://github.com/errbit/errbit.git
69 branch: master 77 branch: master
70 user: deploy 78 user: deploy
71 deploy_to: /var/www/apps/errbit 79 deploy_to: /var/www/apps/errbit
@@ -90,6 +98,10 @@ github_secret: &#39;GITHUB_SECRET&#39; @@ -90,6 +98,10 @@ github_secret: &#39;GITHUB_SECRET&#39;
90 # [] - No permission to create issues on any repos. 98 # [] - No permission to create issues on any repos.
91 github_access_scope: ['repo'] 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 # Configure SMTP settings. If you are running Errbit on Heroku, 105 # Configure SMTP settings. If you are running Errbit on Heroku,
94 # sendgrid will be configured by default. 106 # sendgrid will be configured by default.
95 # ------------------------------------------------------------------------ 107 # ------------------------------------------------------------------------
config/initializers/_load_config.rb
@@ -9,6 +9,7 @@ unless defined?(Errbit::Config) @@ -9,6 +9,7 @@ unless defined?(Errbit::Config)
9 # If Errbit is running on Heroku, config can be set from environment variables. 9 # If Errbit is running on Heroku, config can be set from environment variables.
10 if use_env 10 if use_env
11 Errbit::Config.host = ENV['ERRBIT_HOST'] 11 Errbit::Config.host = ENV['ERRBIT_HOST']
  12 + Errbit::Config.port = ENV['ERRBIT_PORT']
12 Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM'] 13 Errbit::Config.email_from = ENV['ERRBIT_EMAIL_FROM']
13 # Not really easy to use like an env because need an array and ENV return a string :( 14 # Not really easy to use like an env because need an array and ENV return a string :(
14 # Errbit::Config.email_at_notices = ENV['ERRBIT_EMAIL_AT_NOTICES'] 15 # Errbit::Config.email_at_notices = ENV['ERRBIT_EMAIL_AT_NOTICES']
@@ -20,9 +21,11 @@ unless defined?(Errbit::Config) @@ -20,9 +21,11 @@ unless defined?(Errbit::Config)
20 Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR'] 21 Errbit::Config.use_gravatar = ENV['ERRBIT_USE_GRAVATAR']
21 Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT'] 22 Errbit::Config.gravatar_default = ENV['ERRBIT_GRAVATAR_DEFAULT']
22 23
  24 + Errbit::Config.github_url = ENV['GITHUB_URL']
23 Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION'] 25 Errbit::Config.github_authentication = ENV['GITHUB_AUTHENTICATION']
24 Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID'] 26 Errbit::Config.github_client_id = ENV['GITHUB_CLIENT_ID']
25 Errbit::Config.github_secret = ENV['GITHUB_SECRET'] 27 Errbit::Config.github_secret = ENV['GITHUB_SECRET']
  28 + Errbit::Config.github_org_id = ENV['GITHUB_ORG_ID'] if ENV['GITHUB_ORG_ID']
26 Errbit::Config.github_access_scope = ENV['GITHUB_ACCESS_SCOPE'].split(',').map(&:strip) if ENV['GITHUB_ACCESS_SCOPE'] 29 Errbit::Config.github_access_scope = ENV['GITHUB_ACCESS_SCOPE'].split(',').map(&:strip) if ENV['GITHUB_ACCESS_SCOPE']
27 30
28 Errbit::Config.smtp_settings = { 31 Errbit::Config.smtp_settings = {
@@ -62,6 +65,10 @@ default_config.each do |k,v| @@ -62,6 +65,10 @@ default_config.each do |k,v|
62 Errbit::Config.send("#{k}=", v) if Errbit::Config.send(k) === nil 65 Errbit::Config.send("#{k}=", v) if Errbit::Config.send(k) === nil
63 end 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 # Disable GitHub oauth if gem is missing 72 # Disable GitHub oauth if gem is missing
66 Errbit::Config.github_authentication = false unless defined?(OmniAuth::Strategies::GitHub) 73 Errbit::Config.github_authentication = false unless defined?(OmniAuth::Strategies::GitHub)
67 74
@@ -78,7 +85,13 @@ end @@ -78,7 +85,13 @@ end
78 85
79 # Set config specific values 86 # Set config specific values
80 (ActionMailer::Base.default_url_options ||= {}).tap do |default| 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 end 95 end
83 96
84 if Rails.env.production? 97 if Rails.env.production?
config/locales/en.yml
@@ -35,13 +35,13 @@ en: @@ -35,13 +35,13 @@ en:
35 flash: 35 flash:
36 create: 36 create:
37 success: "Your app was successfully created." 37 success: "Your app was successfully created."
38 - error: "You app was successfully destroyed." 38 + error: "Your app could not be created."
39 update: 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 destroy: 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 users: 46 users:
47 flash: 47 flash:
db/migrate/20131206152837_add_min_app_version_to_apps.rb 0 → 100644
@@ -0,0 +1,5 @@ @@ -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 \ No newline at end of file 6 \ No newline at end of file
public/javascripts/notifier.js
@@ -556,11 +556,11 @@ printStackTrace.implementation.prototype = { @@ -556,11 +556,11 @@ printStackTrace.implementation.prototype = {
556 556
557 "userId": "{user_id}", 557 "userId": "{user_id}",
558 "userName": "{user_name}", 558 "userName": "{user_name}",
559 - "userEmail": "{user_email}", 559 + "userEmail": "{user_email}"
560 }, 560 },
561 "environment": {}, 561 "environment": {},
562 //"session": "", 562 //"session": "",
563 - "params": {}, 563 + "params": {}
564 }; 564 };
565 565
566 Util = { 566 Util = {
spec/controllers/notices_controller_spec.rb
@@ -6,7 +6,7 @@ describe NoticesController do @@ -6,7 +6,7 @@ describe NoticesController do
6 let(:notice) { Fabricate(:notice) } 6 let(:notice) { Fabricate(:notice) }
7 let(:xml) { Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read } 7 let(:xml) { Rails.root.join('spec','fixtures','hoptoad_test_notice.xml').read }
8 let(:app) { Fabricate(:app) } 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 context 'notices API' do 11 context 'notices API' do
12 context "with all params" do 12 context "with all params" do
spec/models/error_report_spec.rb
@@ -230,5 +230,35 @@ describe ErrorReport do @@ -230,5 +230,35 @@ describe ErrorReport do
230 end 230 end
231 end 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 end 263 end
234 end 264 end