resque-web-edge 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +96 -0
  3. data/Rakefile +34 -0
  4. data/app/assets/images/resque_web/idle.png +0 -0
  5. data/app/assets/images/resque_web/lifebuoy.png +0 -0
  6. data/app/assets/images/resque_web/poll.png +0 -0
  7. data/app/assets/images/resque_web/rails.png +0 -0
  8. data/app/assets/images/resque_web/working.png +0 -0
  9. data/app/assets/javascripts/resque_web/application.js +16 -0
  10. data/app/assets/javascripts/resque_web/bootstrap.js.coffee +4 -0
  11. data/app/assets/javascripts/resque_web/failure.js.coffee +7 -0
  12. data/app/assets/javascripts/resque_web/jquery.relative-date.js +47 -0
  13. data/app/assets/javascripts/resque_web/polling.js.coffee +25 -0
  14. data/app/assets/javascripts/resque_web/relative_date.js.coffee +27 -0
  15. data/app/assets/stylesheets/resque_web/application.css +13 -0
  16. data/app/assets/stylesheets/resque_web/bootstrap_and_overrides.css.scss.erb +146 -0
  17. data/app/controllers/resque_web/application_controller.rb +26 -0
  18. data/app/controllers/resque_web/failures_controller.rb +62 -0
  19. data/app/controllers/resque_web/jobs_controller.rb +12 -0
  20. data/app/controllers/resque_web/overview_controller.rb +7 -0
  21. data/app/controllers/resque_web/queues_controller.rb +22 -0
  22. data/app/controllers/resque_web/stats_controller.rb +36 -0
  23. data/app/controllers/resque_web/workers_controller.rb +23 -0
  24. data/app/controllers/resque_web/working_controller.rb +8 -0
  25. data/app/helpers/resque_web/application_helper.rb +69 -0
  26. data/app/helpers/resque_web/failures_helper.rb +58 -0
  27. data/app/helpers/resque_web/overview_helper.rb +6 -0
  28. data/app/helpers/resque_web/queues_helper.rb +72 -0
  29. data/app/helpers/resque_web/stats_helper.rb +54 -0
  30. data/app/helpers/resque_web/workers_helper.rb +16 -0
  31. data/app/helpers/resque_web/working_helper.rb +19 -0
  32. data/app/views/layouts/resque_web/application.html.erb +75 -0
  33. data/app/views/resque_web/failures/_failed_job.html.erb +53 -0
  34. data/app/views/resque_web/failures/_overview.html.erb +24 -0
  35. data/app/views/resque_web/failures/index.html.erb +32 -0
  36. data/app/views/resque_web/failures/show.html.erb +20 -0
  37. data/app/views/resque_web/overview/show.html.erb +4 -0
  38. data/app/views/resque_web/queues/_queues.html.erb +4 -0
  39. data/app/views/resque_web/queues/_queues_advanced.html.erb +14 -0
  40. data/app/views/resque_web/queues/_queues_basic.html.erb +17 -0
  41. data/app/views/resque_web/queues/index.html.erb +1 -0
  42. data/app/views/resque_web/queues/show.html.erb +39 -0
  43. data/app/views/resque_web/stats/key.html.erb +26 -0
  44. data/app/views/resque_web/stats/keys.html.erb +17 -0
  45. data/app/views/resque_web/stats/redis.html.erb +14 -0
  46. data/app/views/resque_web/stats/resque.html.erb +14 -0
  47. data/app/views/resque_web/workers/index.html.erb +19 -0
  48. data/app/views/resque_web/workers/show.html.erb +38 -0
  49. data/app/views/resque_web/working/_working.html.erb +34 -0
  50. data/app/views/resque_web/working/index.html.erb +1 -0
  51. data/config/initializers/resque_config.rb +13 -0
  52. data/config/routes.rb +35 -0
  53. data/lib/resque_web.rb +4 -0
  54. data/lib/resque_web/engine.rb +13 -0
  55. data/lib/resque_web/version.rb +3 -0
  56. data/test/dummy/Rakefile +6 -0
  57. data/test/dummy/app/assets/javascripts/application.js +13 -0
  58. data/test/dummy/app/assets/stylesheets/application.css +13 -0
  59. data/test/dummy/app/controllers/application_controller.rb +5 -0
  60. data/test/dummy/app/helpers/application_helper.rb +2 -0
  61. data/test/dummy/app/views/layouts/application.html.erb +14 -0
  62. data/test/dummy/bin/bundle +3 -0
  63. data/test/dummy/bin/rails +4 -0
  64. data/test/dummy/bin/rake +4 -0
  65. data/test/dummy/config.ru +4 -0
  66. data/test/dummy/config/application.rb +23 -0
  67. data/test/dummy/config/boot.rb +5 -0
  68. data/test/dummy/config/database.yml +25 -0
  69. data/test/dummy/config/environment.rb +5 -0
  70. data/test/dummy/config/environments/development.rb +29 -0
  71. data/test/dummy/config/environments/production.rb +80 -0
  72. data/test/dummy/config/environments/test.rb +36 -0
  73. data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
  74. data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  75. data/test/dummy/config/initializers/inflections.rb +16 -0
  76. data/test/dummy/config/initializers/mime_types.rb +5 -0
  77. data/test/dummy/config/initializers/secret_token.rb +12 -0
  78. data/test/dummy/config/initializers/session_store.rb +3 -0
  79. data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
  80. data/test/dummy/config/locales/en.yml +23 -0
  81. data/test/dummy/config/routes.rb +4 -0
  82. data/test/dummy/db/schema.rb +16 -0
  83. data/test/dummy/public/404.html +58 -0
  84. data/test/dummy/public/422.html +58 -0
  85. data/test/dummy/public/500.html +57 -0
  86. data/test/dummy/public/favicon.ico +0 -0
  87. data/test/functional/failures_controller_test.rb +74 -0
  88. data/test/functional/jobs_controller_test.rb +45 -0
  89. data/test/functional/overview_controller_test.rb +37 -0
  90. data/test/functional/queues_controller_test.rb +58 -0
  91. data/test/functional/stats_controller_test.rb +70 -0
  92. data/test/functional/workers_controller_test.rb +26 -0
  93. data/test/functional/working_controller_test.rb +19 -0
  94. data/test/integration/plugin_integration_test.rb +72 -0
  95. data/test/support/controller_test_helpers.rb +22 -0
  96. data/test/test_helper.rb +26 -0
  97. data/test/unit/helpers/failures_helper_test.rb +15 -0
  98. data/test/unit/helpers/jobs_helper_test.rb +4 -0
  99. data/test/unit/helpers/overview_helper_test.rb +4 -0
  100. data/test/unit/helpers/queues_helper_test.rb +4 -0
  101. data/test/unit/helpers/retry_controller_helper_test.rb +4 -0
  102. data/test/unit/helpers/stats_helper_test.rb +4 -0
  103. data/test/unit/helpers/workers_helper_test.rb +4 -0
  104. data/test/unit/helpers/working_helper_test.rb +4 -0
  105. metadata +267 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c7fa3ed90c437f67015a11983b634b6f763d325f
4
+ data.tar.gz: 236c1cfddcb2b2b5bfcb34c7c78b4202282e1d6b
5
+ SHA512:
6
+ metadata.gz: 9e00ccb08e1c165fa1f35bd2d302212cee331b9f92691b632515f7219da85ef73c73e33a5ff0f05fe89efe751a0496bd1de4ad4656e92625fb2b54dc0e681565
7
+ data.tar.gz: 010c55743bb9b040345517318e419a591d5c4d5e3f2ccde657513bad35f2ef4f4ac73f23640be10ebb458f12a691507bcf4e590398103efa6355be3df8739785
@@ -0,0 +1,96 @@
1
+ resque-web
2
+ ==========
3
+ [![Gem Version](http://img.shields.io/gem/v/resque-web.svg)](https://rubygems.org/gems/resque-web)
4
+ [![Build Status](https://img.shields.io/travis/resque/resque-web.svg)](https://travis-ci.org/resque/resque-web)
5
+ [![Dependency Status](https://img.shields.io/gemnasium/resque/resque-web.svg)](https://gemnasium.com/resque/resque-web)
6
+ [![Code Climate](https://img.shields.io/codeclimate/github/resque/resque-web.svg)](https://codeclimate.com/github/resque/resque-web)
7
+ [![Coverage Status](https://img.shields.io/coveralls/resque/resque-web/master.svg)](https://coveralls.io/r/resque/resque-web)
8
+
9
+ A Rails-based frontend to the [Resque](https://github.com/resque/resque) job
10
+ queue system. This provides a similar interface to the existing Sinatra
11
+ application that comes bundled with Resque, but deploys like a Rails application
12
+ and leverages Rails conventions for factoring things like controllers, helpers,
13
+ and views.
14
+
15
+ # NOTICE
16
+ Note this is NOT the old sinatra interface that comes with Resque 1-x. This is
17
+ a new project based on rails. If you have any issues with old web server,
18
+ please file an issue on the [resque](https://github.com/resque/resque) project.
19
+ Note that the sinatra web interface will be gone in Resque 2.0 and this is
20
+ meant to be the replacement.
21
+
22
+ More documentation coming soon!
23
+
24
+ ## Starting
25
+ Resque web is built as a rails engine.
26
+
27
+ Add it to your gemfile.
28
+
29
+ ```Ruby
30
+ gem 'resque-web', require: 'resque_web'
31
+ ```
32
+
33
+ Mount it in your config/routes.rb.
34
+
35
+ ```Ruby
36
+ require "resque_web"
37
+
38
+ MyApp::Application.routes.draw do
39
+ mount ResqueWeb::Engine => "/resque_web"
40
+ end
41
+ ```
42
+
43
+ If you need a non-default resque server, use this environment variable.
44
+
45
+ ```
46
+ RAILS_RESQUE_REDIS=123.x.0.456:6712
47
+ ```
48
+
49
+ If you need to set a password for your redis server, use this env variable.
50
+
51
+ ```
52
+ RAILS_RESQUE_REDIS_PASSWORD=verys3cureP@ss
53
+ ```
54
+
55
+ ## Security
56
+
57
+ You almost certainly want to limit access when using resque-web in production. Using [routes constraints](http://guides.rubyonrails.org/routing.html#request-based-constraints) is one way to achieve this:
58
+
59
+ ```ruby
60
+ # config/routes.rb
61
+
62
+ resque_web_constraint = lambda { |request| request.remote_ip == '127.0.0.1' }
63
+ constraints resque_web_constraint do
64
+ mount ResqueWeb::Engine => "/resque_web"
65
+ end
66
+
67
+ ```
68
+
69
+ Another example of a route constraint using the current user when using Devise or another warden based authentication system:
70
+
71
+ ```ruby
72
+ # config/routes.rb
73
+ resque_web_constraint = lambda do |request|
74
+ current_user = request.env['warden'].user
75
+ current_user.present? && current_user.respond_to?(:is_admin?) && current_user.is_admin?
76
+ end
77
+
78
+ constraints resque_web_constraint do
79
+ mount ResqueWeb::Engine => "/resque_web"
80
+ end
81
+
82
+ ```
83
+
84
+ ### HTTP Basic Authentication
85
+
86
+ HTTP Basic Authentication is supported out of the box. Simply set the environment variables `RESQUE_WEB_HTTP_BASIC_AUTH_USER` and `RESQUE_WEB_HTTP_BASIC_AUTH_PASSWORD` to turn it on. If you're using Resque with Heroku run `heroku config:set RESQUE_WEB_HTTP_BASIC_AUTH_USER=user RESQUE_WEB_HTTP_BASIC_AUTH_PASSWORD=secret` to get ResqueWeb secured.
87
+
88
+ ## Plugins
89
+
90
+ In the past with the sinatra app it was fairly simple to just monkey-patch the
91
+ server to add more functionality/tabs. With this rails version you have to write
92
+ an engine under a specific namespace. Read more in PLUGINS.md.
93
+
94
+ ## Screenshot
95
+
96
+ ![Screenshot](http://i.imgur.com/LkNgl.png)
@@ -0,0 +1,34 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'ResqueWeb'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.rdoc')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+ APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+
21
+
22
+ Bundler::GemHelper.install_tasks
23
+
24
+ require 'rake/testtask'
25
+
26
+ Rake::TestTask.new(:test) do |t|
27
+ t.libs << 'lib'
28
+ t.libs << 'test'
29
+ t.pattern = 'test/**/*_test.rb'
30
+ t.verbose = false
31
+ end
32
+
33
+
34
+ task :default => :test
@@ -0,0 +1,16 @@
1
+ // This is a manifest file that'll be compiled into application.js, which will include all the files
2
+ // listed below.
3
+ //
4
+ // Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
5
+ // or vendor/assets/javascripts of plugins, if any, can be referenced here using a relative path.
6
+ //
7
+ // It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
8
+ // the compiled file.
9
+ //
10
+ // WARNING: THE FIRST BLANK LINE MARKS THE END OF WHAT'S TO BE PROCESSED, ANY BLANK LINE SHOULD
11
+ // GO AFTER THE REQUIRES BELOW.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require twitter/bootstrap
16
+ //= require_tree .
@@ -0,0 +1,4 @@
1
+ jQuery ->
2
+ $("a[rel=popover]").popover()
3
+ $(".tooltip").tooltip()
4
+ $("a[rel=tooltip]").tooltip()
@@ -0,0 +1,7 @@
1
+ jQuery ->
2
+ $(".backtrace").click (e) ->
3
+ e.preventDefault()
4
+ $(this).next().toggle()
5
+
6
+ $("ul.failed li").hover ->
7
+ $(this).toggleClass "hover"
@@ -0,0 +1,47 @@
1
+ /**
2
+ * jQ plugin adapted from 37s' relative date tool
3
+ * Takes the format of "Jan 15, 2007 15:45:00 GMT" and converts it to a relative time
4
+ * @see http://37signals.com/svn/posts/1557-javascript-makes-relative-times-compatible-with-caching
5
+ */
6
+ (function($, window, undefined){
7
+
8
+ $.fn.relativeDate = function(opts){
9
+ var defaults = {
10
+ dateGetter: function(el){
11
+ return $(el).text();
12
+ }
13
+ },
14
+ options = $.extend({}, defaults, opts),
15
+ time_ago_in_words_with_parsing = function(from) {
16
+ var date = new Date;
17
+ date.setTime(Date.parse(from));
18
+ return time_ago_in_words(date);
19
+ },
20
+ time_ago_in_words = function(from) {
21
+ return distance_of_time_in_words(new Date, from);
22
+ },
23
+ distance_of_time_in_words = function(to, from) {
24
+ var distance_in_seconds = ((to - from) / 1000);
25
+ var distance_in_minutes = Math.floor(distance_in_seconds / 60);
26
+
27
+ if (distance_in_minutes == 0) { return 'less than a minute ago'; }
28
+ if (distance_in_minutes == 1) { return 'a minute ago'; }
29
+ if (distance_in_minutes < 45) { return distance_in_minutes + ' minutes ago'; }
30
+ if (distance_in_minutes < 90) { return 'about 1 hour ago'; }
31
+ if (distance_in_minutes < 1440) { return 'about ' + Math.round(distance_in_minutes / 60) + ' hours ago'; }
32
+ if (distance_in_minutes < 2880) { return '1 day ago'; }
33
+ if (distance_in_minutes < 43200) { return Math.floor(distance_in_minutes / 1440) + ' days ago'; }
34
+ if (distance_in_minutes < 86400) { return 'about 1 month ago'; }
35
+ if (distance_in_minutes < 525960) { return Math.floor(distance_in_minutes / 43200) + ' months ago'; }
36
+ if (distance_in_minutes < 1051199) { return 'about 1 year ago'; }
37
+
38
+ return 'over ' + Math.floor(distance_in_minutes / 525960) + ' years ago';
39
+ }
40
+
41
+ return $(this).each(function(){
42
+ date_str = options.dateGetter(this);
43
+ $(this).html(time_ago_in_words_with_parsing(date_str));
44
+ });
45
+ };
46
+
47
+ })(jQuery, window);
@@ -0,0 +1,25 @@
1
+ jQuery ->
2
+ poll_interval = 2
3
+
4
+ poll_start = (el) ->
5
+ href = el.attr("href")
6
+ el.parent().text "Starting..."
7
+ $("#main").addClass "polling"
8
+ setInterval (->
9
+ $.ajax
10
+ dataType: "text"
11
+ type: "get"
12
+ url: href
13
+ success: (data) ->
14
+ $("#main").html data
15
+ $("#main .time").relativeDate()
16
+ ), poll_interval * 1000
17
+ location.hash = "#poll"
18
+
19
+ # auto start if hash is poll
20
+ poll_start $("a[rel=poll]") if location.hash == "#poll"
21
+
22
+ # start when click on link
23
+ $("a[rel=poll]").click (e) ->
24
+ e.preventDefault()
25
+ poll_start $(this)
@@ -0,0 +1,27 @@
1
+ jQuery ->
2
+ relatizer = ->
3
+ dt = $(this).text()
4
+ $(this).relativeDate()
5
+ relatized = $(this).text()
6
+ if $(this).parents("a").size() > 0 || $(this).is("a")
7
+ $(this).relativeDate()
8
+ $(this).attr("title", dt) unless $(this).attr("title")
9
+ else
10
+ $(this).html """
11
+ <a href='#'' class='toggle_format' title='#{dt}'>
12
+ <span class='date_time'>#{dt}</span>
13
+ <span class='relatized_time'>#{relatized}</span>
14
+ </a>
15
+ """
16
+
17
+ format_toggler = (e) ->
18
+ e.preventDefault()
19
+ $(".time a.toggle_format span").toggle()
20
+ $(this).attr "title", $("span:hidden", this).text()
21
+
22
+ # changed html when doom is ready
23
+ $(".time").each relatizer
24
+ $(".time a.toggle_format .date_time").hide()
25
+
26
+ # add event on click in relative time to show date_time
27
+ $(".time").on "click", "a.toggle_format", format_toggler
@@ -0,0 +1,13 @@
1
+ /*
2
+ * This is a manifest file that'll be compiled into application.css, which will include all the files
3
+ * listed below.
4
+ *
5
+ * Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
6
+ * or vendor/assets/stylesheets of plugins, if any, can be referenced here using a relative path.
7
+ *
8
+ * You're free to add application-wide styles to this file and they'll appear at the top of the
9
+ * compiled file, but it's generally better to create a new file per style scope.
10
+ *
11
+ *= require_self
12
+ *= require_tree .
13
+ */
@@ -0,0 +1,146 @@
1
+ /*
2
+ =require twitter-bootstrap-static/bootstrap
3
+
4
+ Use Font Awesome icons (default)
5
+ To use Glyphicons sprites instead of Font Awesome, replace with "require twitter-bootstrap-static/sprites"
6
+ =require twitter-bootstrap-static/fontawesome
7
+ */
8
+
9
+ html {
10
+ background: #efefef;
11
+ }
12
+
13
+ body {
14
+ padding-top: 40px;
15
+ }
16
+
17
+ .navbar {
18
+ border-bottom: 5px solid #ce1212;
19
+ }
20
+
21
+ .navbar .brand, .navbar .navbar-brand {
22
+ color: white;
23
+ }
24
+
25
+ .navbar-fixed-top .navbar-inner, .navbar-static-top .navbar-inner {
26
+ border-width: 0;
27
+ }
28
+
29
+ .navbar-inverse .nav>.active {
30
+ background: #fa2424; /* Old browsers */
31
+ background: -moz-linear-gradient(top, #fa2424 0%, #ce1212 100%); /* FF3.6+ */
32
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#fa2424), color-stop(100%,#ce1212)); /* Chrome,Safari4+ */
33
+ background: -webkit-linear-gradient(top, #fa2424 0%,#ce1212 100%); /* Chrome10+,Safari5.1+ */
34
+ background: -o-linear-gradient(top, #fa2424 0%,#ce1212 100%); /* Opera 11.10+ */
35
+ background: -ms-linear-gradient(top, #fa2424 0%,#ce1212 100%); /* IE10+ */
36
+ background: linear-gradient(to bottom, #fa2424 0%,#ce1212 100%); /* W3C */
37
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#fa2424', endColorstr='#ce1212',GradientType=0 ); /* IE6-8 */
38
+ }
39
+
40
+ .navbar .nav>.active>a,.navbar .nav>.active>a:hover,.navbar .nav>.active>a:focus {
41
+ background: none;
42
+ }
43
+
44
+ .container h1 { color:#ce1212; font-size: 24px; }
45
+
46
+ .label-info[href], .badge-info[href] {
47
+ background-color: #3A87AD;
48
+ }
49
+
50
+ .logo {
51
+ float: left;
52
+ margin: 2px 5px;
53
+ width: 36px;
54
+ height: 36px;
55
+ }
56
+
57
+ /* The remaining CSS rules come from the legacy Resque application */
58
+ .subnav { padding: 8px 10px 7px 10px; background:#ce1212; font-size:90%;}
59
+ .subnav li { display:inline; line-height: 16px; }
60
+ .subnav li a { color:#fff; text-decoration:none; margin:3px; display:inline-block; background:#dd5b5b; padding:5px; -webkit-border-radius:3px; -moz-border-radius:3px;}
61
+ .subnav li.current a { background:#fff; font-weight:bold; color:#ce1212;}
62
+ .subnav li a:active { background:#b00909;}
63
+
64
+ .container span.hl { background:#efefef; padding:2px;}
65
+ .container h2 { margin:10px 0; font-size:130%;}
66
+ .container table tr th { background:#efefef; color:#888; font-size:15px; font-weight:bold; min-width: 16px; }
67
+ .container table tr td.no-data { text-align:center; padding:40px 0; color:#999; font-style:italic; font-size:130%;}
68
+ .container p { margin:5px 0;}
69
+ .container p.intro { margin-bottom:15px; font-size:85%; color:#999; margin-top:0; line-height:1.3;}
70
+ .container h1.wi { margin-bottom:5px;}
71
+ .container p.sub { font-size:95%; color:#999;}
72
+
73
+ .container table.queues { width:40%;}
74
+ .container table.queues td.queue { font-weight:bold; width:50%;}
75
+ .container table.queues tr.failure td { background:#ffecec; color:#d37474;}
76
+ .container table.queues tr.failure td a{ color:#d37474;}
77
+ .container table.queues td.failure .badge a { color: white; }
78
+ .container table.queues tr.first_failure td { border-top:2px solid #d37474; }
79
+
80
+ .container table.jobs td.class { font-family:Monaco, "Courier New", monospace; font-size:90%; width:50%;}
81
+ .container table.jobs td.args{ width:50%;}
82
+
83
+ .container table.workers td.icon {width:1%; background:#efefef;text-align:center;}
84
+ .container table.workers td.icon img { height: 16px; width: 16px; }
85
+ .container table.workers td.where { width:25%;}
86
+ .container table.workers td.queues { width:35%;}
87
+ .container table.workers td.queues.queue { width:10%;}
88
+ .container table.workers td.process { width:35%;}
89
+ .container table.workers td.process span.waiting { color:#999; font-size:90%;}
90
+ .container table.workers td.process small { font-size:80%; margin-left:5px;}
91
+ .container table.workers td.process code { font-family:Monaco, "Courier New", monospace; font-size:90%;}
92
+ .container table.workers td.process small a { color:#999;}
93
+ .container.polling table.workers tr.working td { background:#f4ffe4; color:#7ac312;}
94
+ .container.polling table.workers tr.working td.where a { color:#7ac312;}
95
+ .container.polling table.workers tr.working td.process code { font-weight:bold;}
96
+
97
+
98
+ .container table.stats th { font-size:100%; width:40%; color:#000;}
99
+ .container hr { border:0; border-top:5px solid #efefef; margin:15px 0;}
100
+
101
+ #footer { padding:10px 5%; background:#efefef; color:#999; font-size:85%; line-height:1.5; border-top:5px solid #ccc; padding-top:10px;}
102
+ #footer p a { color:#999;}
103
+
104
+ .container p.poll { background:url('<%= asset_path('resque_web/poll.png') %>') no-repeat 0 2px; padding:3px 0; padding-left:23px; float:right; font-size:85%; }
105
+
106
+ .container ul.failed {margin-top: 20px;}
107
+ .container ul.failed li {
108
+ background: #efefef; /* Old browsers */
109
+ background: -moz-linear-gradient(top, #efefef 0%, #fff 100%); /* FF3.6+ */
110
+ background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,#efefef), color-stop(100%,#fff)); /* Chrome,Safari4+ */
111
+ background: -webkit-linear-gradient(top, #efefef 0%,#fff 100%); /* Chrome10+,Safari5.1+ */
112
+ background: -o-linear-gradient(top, #efefef 0%,#fff 100%); /* Opera 11.10+ */
113
+ background: -ms-linear-gradient(top, #efefef 0%,#fff 100%); /* IE10+ */
114
+ background: linear-gradient(to bottom, #efefef 0%,#fff 100%); /* W3C */
115
+ filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#efefef', endColorstr='#fff',GradientType=0 ); /* IE6-8 */
116
+
117
+ margin-top:10px;
118
+ padding:10px;
119
+ overflow:hidden;
120
+ border:1px solid #ccc;
121
+ -webkit-border-radius:5px;
122
+ -moz-border-radius:5px;
123
+ border-radius:5px;
124
+ }
125
+ .container ul.failed li dl dt {font-size:80%; color:#999; width:60px; float:left; padding-top:1px; text-align:right;}
126
+ .container ul.failed li dl dd {margin-bottom:10px; margin-left:70px;}
127
+ .container ul.failed li dl dd .retried { float:right; text-align: right; }
128
+ .container ul.failed li dl dd .retried .remove { display:none; margin-top: 8px; }
129
+ .container ul.failed li.hover dl dd .retried .remove { display:block; }
130
+ .container ul.failed li dl dd .controls { display:none; float:right; }
131
+ .container ul.failed li.hover dl dd .controls { display:block; }
132
+ .container ul.failed li dl dd code, .container ul.failed li dl dd pre { font-family:Monaco, "Courier New", monospace; font-size:90%; white-space: pre-wrap;}
133
+ .container ul.failed li dl dd.error a {font-family:Monaco, "Courier New", monospace; font-size:90%; }
134
+ .container ul.failed li dl dd.error pre { margin-top:3px; line-height:1.3;}
135
+
136
+ .container p.pagination { background:#efefef; padding:10px; overflow:hidden;}
137
+ .container p.pagination a.less { float:left;}
138
+ .container p.pagination a.more { float:right;}
139
+
140
+ .container form {float:right; margin-top:-10px;margin-left:10px;}
141
+
142
+ .container .time a.toggle_format {text-decoration:none;}
143
+
144
+ #failed tr.total td {background-color: #FFECEC; color: #D37474; font-size: 15px; font-weight: bold;}
145
+ #failed .center {text-align: center;}
146
+ #failed .failed_class { padding-left: 20px; font-size:12px; }