rocketjob_mission_control 0.9.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +7 -0
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +26 -0
  4. data/app/assets/javascripts/rocket_job_mission_control/application.js +18 -0
  5. data/app/assets/javascripts/rocket_job_mission_control/base.js.coffee +24 -0
  6. data/app/assets/javascripts/rocket_job_mission_control/jobs.js.coffee +11 -0
  7. data/app/assets/stylesheets/rocket_job_mission_control/application.scss +18 -0
  8. data/app/assets/stylesheets/rocket_job_mission_control/base.scss +468 -0
  9. data/app/assets/stylesheets/rocket_job_mission_control/bootstrap_and_overrides.scss +6 -0
  10. data/app/assets/stylesheets/rocket_job_mission_control/callout.scss +40 -0
  11. data/app/assets/stylesheets/rocket_job_mission_control/jobs.scss +16 -0
  12. data/app/assets/stylesheets/rocket_job_mission_control/jquery.bootstrap-touchspin.scss +45 -0
  13. data/app/controllers/rocket_job_mission_control/application_controller.rb +15 -0
  14. data/app/controllers/rocket_job_mission_control/jobs/inputs_controller.rb +9 -0
  15. data/app/controllers/rocket_job_mission_control/jobs/slices_controller.rb +10 -0
  16. data/app/controllers/rocket_job_mission_control/jobs_controller.rb +97 -0
  17. data/app/controllers/rocket_job_mission_control/workers_controller.rb +79 -0
  18. data/app/helpers/rocket_job_mission_control/application_helper.rb +16 -0
  19. data/app/helpers/rocket_job_mission_control/jobs_helper.rb +57 -0
  20. data/app/helpers/rocket_job_mission_control/workers_helper.rb +14 -0
  21. data/app/views/layouts/rocket_job_mission_control/application.html.haml +43 -0
  22. data/app/views/layouts/rocket_job_mission_control/partials/_header.html.haml +16 -0
  23. data/app/views/layouts/rocket_job_mission_control/partials/_sidebar.html.haml +20 -0
  24. data/app/views/rocket_job_mission_control/jobs/_list.html.haml +33 -0
  25. data/app/views/rocket_job_mission_control/jobs/_status.html.haml +39 -0
  26. data/app/views/rocket_job_mission_control/jobs/index.html.haml +8 -0
  27. data/app/views/rocket_job_mission_control/jobs/running.html.haml +37 -0
  28. data/app/views/rocket_job_mission_control/jobs/show.html.haml +50 -0
  29. data/app/views/rocket_job_mission_control/workers/_actions.html.haml +9 -0
  30. data/app/views/rocket_job_mission_control/workers/index.html.haml +51 -0
  31. data/config/locales/en.yml +57 -0
  32. data/config/routes.rb +28 -0
  33. data/lib/rocket_job_mission_control/engine.rb +15 -0
  34. data/lib/rocket_job_mission_control/version.rb +3 -0
  35. data/lib/rocketjob_mission_control.rb +4 -0
  36. data/lib/tasks/rocket_job_mission_control_tasks.rake +4 -0
  37. data/spec/controllers/application_controller_spec.rb +47 -0
  38. data/spec/controllers/jobs_controller_spec.rb +217 -0
  39. data/spec/controllers/workers_controller_spec.rb +125 -0
  40. data/spec/dummy/README.rdoc +28 -0
  41. data/spec/dummy/Rakefile +6 -0
  42. data/spec/dummy/app/assets/javascripts/application.js +13 -0
  43. data/spec/dummy/app/assets/stylesheets/application.css +15 -0
  44. data/spec/dummy/app/controllers/application_controller.rb +5 -0
  45. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  46. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  47. data/spec/dummy/bin/bundle +3 -0
  48. data/spec/dummy/bin/rails +4 -0
  49. data/spec/dummy/bin/rake +4 -0
  50. data/spec/dummy/config.ru +4 -0
  51. data/spec/dummy/config/application.rb +25 -0
  52. data/spec/dummy/config/boot.rb +5 -0
  53. data/spec/dummy/config/database.yml +25 -0
  54. data/spec/dummy/config/environment.rb +5 -0
  55. data/spec/dummy/config/environments/development.rb +34 -0
  56. data/spec/dummy/config/environments/test.rb +39 -0
  57. data/spec/dummy/config/initializers/assets.rb +8 -0
  58. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  59. data/spec/dummy/config/initializers/cookies_serializer.rb +3 -0
  60. data/spec/dummy/config/initializers/filter_parameter_logging.rb +4 -0
  61. data/spec/dummy/config/initializers/inflections.rb +16 -0
  62. data/spec/dummy/config/initializers/mime_types.rb +4 -0
  63. data/spec/dummy/config/initializers/session_store.rb +3 -0
  64. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  65. data/spec/dummy/config/locales/en.yml +23 -0
  66. data/spec/dummy/config/routes.rb +4 -0
  67. data/spec/dummy/config/secrets.yml +22 -0
  68. data/spec/dummy/log/test.log +2459 -0
  69. data/spec/dummy/public/404.html +67 -0
  70. data/spec/dummy/public/422.html +67 -0
  71. data/spec/dummy/public/500.html +66 -0
  72. data/spec/dummy/public/favicon.ico +0 -0
  73. data/spec/helpers/jobs_helper_spec.rb +100 -0
  74. data/spec/rails_helper.rb +47 -0
  75. data/spec/spec_helper.rb +81 -0
  76. data/spec/views/workers/index.html.haml_spec.rb +17 -0
  77. data/vendor/assets/javascripts/jquery.bootstrap-touchspin.js +686 -0
  78. data/vendor/assets/javascripts/prism.js +6 -0
  79. data/vendor/assets/stylesheets/jquery.bootstrap-touchspin.css +45 -0
  80. data/vendor/assets/stylesheets/prism.scss +160 -0
  81. metadata +319 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a0f6fa5b68e946e2b5653fdd70982fac66cefaaa
4
+ data.tar.gz: 474bc74f3068e1cc1ecd64e8c7b9e4881783fea9
5
+ SHA512:
6
+ metadata.gz: e79f7aea29c373ab555ca462ab420d41530312ca832471f5eb67a6057cbc9e65f25ee4a653c0a00ef3d125f25de5c125ff0e10b3850eaff5ea542ac8b744cf59
7
+ data.tar.gz: ba14bdc4682789d88fa5ea73aa355100051b349f02bed156847c6dbd695d4a3e7447ab02ab008d793a078aea8cf713ba8a25fc0ef09dfbbab22047a508a09416
@@ -0,0 +1,20 @@
1
+ Copyright 2015 YOURNAME
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,26 @@
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 = 'RocketJobMissionControl'
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("../spec/dummy/Rakefile", __FILE__)
18
+ load 'rails/tasks/engine.rake'
19
+
20
+ Bundler::GemHelper.install_tasks
21
+
22
+ require 'rspec/core'
23
+ require 'rspec/core/rake_task'
24
+
25
+ task spec: 'app:spec'
26
+ task default: :spec
@@ -0,0 +1,18 @@
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
+ // compiled file.
9
+ //
10
+ // Read Sprockets README (https://github.com/sstephenson/sprockets#sprockets-directives) for details
11
+ // about supported directives.
12
+ //
13
+ //= require jquery
14
+ //= require jquery_ujs
15
+ //= require jquery.bootstrap-touchspin
16
+ //= require bootstrap-sprockets
17
+ //= require prism
18
+ //= require_tree .
@@ -0,0 +1,24 @@
1
+ $(document).load ->
2
+ readyMenuToggle()
3
+ registerJobPriority()
4
+
5
+ $(document).on 'ready page:change', ->
6
+ readyMenuToggle()
7
+ registerJobPriority()
8
+
9
+ readyMenuToggle = ->
10
+ $('#menu-toggle').click (e) ->
11
+ e.preventDefault()
12
+ $('#wrapper').toggleClass 'toggled'
13
+
14
+ $('#menu-close').click (e) ->
15
+ e.preventDefault()
16
+ $('#wrapper').toggleClass 'toggled'
17
+
18
+
19
+ registerJobPriority = ->
20
+ $('#increase_priority').on 'click', ->
21
+ $('#job_priority').val(parseInt($('#job_priority').val(), 10) + 1)
22
+
23
+ $('#decrease_priority').on 'click', ->
24
+ $('#job_priority').val(parseInt($('#job_priority').val(), 10) - 1)
@@ -0,0 +1,11 @@
1
+ $(document).on 'ready', ->
2
+ $('.filter .state-toggle').on 'change', ->
3
+ active_states = $('.filter :checked')
4
+ param_string = "?"
5
+ active_states.each (_, state) ->
6
+ param_string += "states[]=" + $(state).attr('id') + "&"
7
+ window.location.href = window.location.href.replace( /[\?#].*|$/, param_string );
8
+
9
+ $('.panel a').on 'click', ->
10
+ $('i', this).toggleClass('fa-plus-square-o')
11
+ $('i', this).toggleClass('fa-minus-square-o')
@@ -0,0 +1,18 @@
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 bottom of the
9
+ * compiled file so the styles you add here take precedence over styles defined in any styles
10
+ * defined in the other CSS/SCSS files in this directory. It is generally better to create a new
11
+ * file per style scope.
12
+ *
13
+ *= require_self
14
+ *= require_tree .
15
+ */
16
+
17
+ @import "bootstrap-sprockets";
18
+ @import "bootstrap";
@@ -0,0 +1,468 @@
1
+ #wrapper {
2
+ height: 100%;
3
+ overflow: hidden;
4
+ }
5
+
6
+ body.rocket_job {
7
+ padding: 0;
8
+
9
+ #queue { height: 100%; }
10
+
11
+ .job-list {
12
+ height: 100%;
13
+ border-right: 1px solid #ddd;
14
+ padding: 0;
15
+ }
16
+
17
+ .job-status {
18
+ padding: 0 3em;
19
+ height: 100%;
20
+ background-color: #fff;
21
+ overflow: scroll;
22
+ padding-bottom: 100px;
23
+
24
+ .lead {
25
+ color: #50555b;
26
+ float: left;
27
+ margin-top: 1em;
28
+ vertical-align: middle;
29
+ }
30
+
31
+ p {
32
+ font-size: 14px;
33
+ color: #666;
34
+ }
35
+
36
+ .welcome_screen {
37
+ text-align: center;
38
+ margin-top: 20%;
39
+
40
+ h1 { margin-bottom: 50px; }
41
+ p { font-size: 16px; }
42
+ }
43
+
44
+ .job-retry {
45
+ float: left;
46
+ margin-top: 23px;
47
+ margin-left: 20px;
48
+
49
+ .btn { padding: 2px 6px; }
50
+ }
51
+
52
+ .job-state {
53
+ margin-left: 20px;
54
+ padding: 0;
55
+ font-size: 12px;
56
+ margin-top: 25px;
57
+ vertical-align: middle;
58
+ float: left;
59
+
60
+ .left {
61
+ float: left;
62
+ text-shadow: 0 2px 3px #000;
63
+ background-color: #404650;
64
+ color: #fff;
65
+ padding: 2px 6px;
66
+ border-top-left-radius: 3px;
67
+ border-bottom-left-radius: 3px;
68
+ }
69
+
70
+ .right {
71
+ float: left;
72
+ color: #fff;
73
+ padding: 2px 6px;
74
+ border-top-right-radius: 3px;
75
+ border-bottom-right-radius: 3px;
76
+ }
77
+
78
+ .success { background-color: green; }
79
+ .danger { background-color: red; }
80
+ .warning { background-color: orange; }
81
+ .primary { background-color: #337ab7; }
82
+ }
83
+
84
+ .priority {
85
+ display: inline-block;
86
+ vertical-align: middle;
87
+ float: right;
88
+ margin-top: 20px;
89
+
90
+ .form-control {
91
+ width: 47px;
92
+ height: 34px;
93
+ }
94
+ }
95
+
96
+ .priority-set {
97
+ float: right;
98
+ padding: 7px 14px;
99
+ font-weight: bold;
100
+ border-top-left-radius: 0;
101
+ border-bottom-left-radius: 0;
102
+ }
103
+ }
104
+
105
+ /* Header Styles */
106
+
107
+ #header {
108
+ padding: 15px;
109
+ background-color: #262C37;//#526A95;
110
+ border-bottom: 1px solid #ddd;
111
+
112
+ .first { left: 15px; }
113
+ .last { right: 15px; }
114
+
115
+ .btn {
116
+ color: #fff;
117
+ position: absolute;
118
+ z-index: 2;
119
+ }
120
+
121
+ .brand {
122
+ font-size: 18px;
123
+ text-align: center;
124
+
125
+ a { color: #fff; }
126
+
127
+ .color {
128
+ display: inline-block;
129
+ position: relative;
130
+ left: -3px;
131
+ color: #83ADFA;
132
+ }
133
+ }
134
+ }
135
+
136
+ /* Toggle Styles */
137
+
138
+ #wrapper {
139
+ padding-left: 0;
140
+ -webkit-transition: all 0.5s ease;
141
+ -moz-transition: all 0.5s ease;
142
+ -o-transition: all 0.5s ease;
143
+ transition: all 0.5s ease;
144
+ }
145
+
146
+ #wrapper.toggled { padding-left: 250px; }
147
+
148
+ #sidebar-wrapper {
149
+ z-index: 1000;
150
+ position: fixed;
151
+ left: 215px;
152
+ width: 0;
153
+ height: 100%;
154
+ margin-left: -215px;
155
+ overflow-y: auto;
156
+ background: #4D628A;
157
+ -webkit-transition: all 0.5s ease;
158
+ -moz-transition: all 0.5s ease;
159
+ -o-transition: all 0.5s ease;
160
+ transition: all 0.5s ease;
161
+ border-right: 1px solid #fff;
162
+
163
+ .active {
164
+ background-color: rgba(255, 255, 255, 0.2);
165
+ }
166
+ }
167
+
168
+ #wrapper.toggled #sidebar-wrapper {
169
+ width: 250px;
170
+ border: 0;
171
+ }
172
+
173
+ #page-content-wrapper {
174
+ width: 100%;
175
+ height: 100%;
176
+ position: absolute;
177
+ overflow: auto;
178
+ }
179
+
180
+ #wrapper.toggled #page-content-wrapper {
181
+ position: absolute;
182
+ margin-right: -215px;
183
+ }
184
+
185
+ /* Sidebar Styles */
186
+
187
+ .sidebar-nav {
188
+ position: absolute;
189
+ top: 0;
190
+ width: 215px;
191
+ margin: 0;
192
+ padding: 0;
193
+ list-style: none;
194
+
195
+ li {
196
+ text-indent: 20px;
197
+ line-height: 40px;
198
+
199
+ a {
200
+ display: block;
201
+ text-decoration: none;
202
+ color: #C3D3E3;
203
+
204
+ &:hover {
205
+ text-decoration: none;
206
+ color: #fff;
207
+ background: rgba(255,255,255,0.2);
208
+ }
209
+
210
+ &:active, &:focus { text-decoration: none; }
211
+ }
212
+ }
213
+
214
+ .sidebar-brand {
215
+ height: 65px;
216
+ font-size: 18px;
217
+ line-height: 60px;
218
+ }
219
+ }
220
+
221
+ .sidebar-nav > .sidebar-brand a {
222
+ color: #fff;
223
+
224
+ &:hover {
225
+ color: #fff;
226
+ background: none;
227
+ }
228
+ }
229
+
230
+ .panel-footer {
231
+ background-color: #fff;
232
+ border-top: 1px solid #eee;
233
+ }
234
+
235
+ .pagination { margin: 0; }
236
+
237
+ @media(min-width:768px) {
238
+ #wrapper { padding-left: 215px; }
239
+
240
+ #wrapper.toggled { padding-left: 0; }
241
+
242
+ #sidebar-wrapper { width: 215px; }
243
+
244
+ #wrapper.toggled #sidebar-wrapper { width: 0; }
245
+
246
+ #page-content-wrapper { position: relative; }
247
+
248
+ #wrapper.toggled #page-content-wrapper {
249
+ position: relative;
250
+ margin-right: 0;
251
+ }
252
+ }
253
+
254
+ .btn-blank {
255
+ background: none;
256
+ border: none;
257
+ }
258
+
259
+ .menu-close {
260
+ position: absolute;
261
+ right: 20px;
262
+ color: #C3D3E3 !important;
263
+
264
+ &:hover { color: #fff !important; }
265
+ }
266
+
267
+ // List View
268
+
269
+ .job-search-box { padding: 20px 100px; }
270
+
271
+ .list {
272
+ a { display: block; }
273
+
274
+ .card:nth-child(1) { border-top: 1px solid #ddd; }
275
+ .card:nth-child(odd) { background-color: #fff; }
276
+
277
+ .card {
278
+ border-bottom: 1px solid #ddd;
279
+ height: 7.5em;
280
+
281
+ &:hover {
282
+ cursor: pointer;
283
+ background-color: #E7F4FF;
284
+ }
285
+
286
+ .inner {
287
+ padding: 0.5em;
288
+ position: relative;
289
+ margin: 0 0 0 10px;
290
+
291
+ .title {
292
+ display: inline-block;
293
+ vertical-align: middle;
294
+
295
+ i.success { color: green; }
296
+ i.danger { color: red; }
297
+ i.warning { color: orange; }
298
+ i.primary { color: #337ab7; }
299
+
300
+ h3 {
301
+ font-weight: bold;
302
+ margin: 0;
303
+ font-size: 16px;
304
+ }
305
+ }
306
+
307
+ .lead {
308
+ margin-bottom: 5px;
309
+ }
310
+
311
+ .duration, .description {
312
+ color: #7C735C;
313
+ }
314
+
315
+ .batch {
316
+ position: absolute;
317
+ right: -10px;
318
+ top: -10px;
319
+ background-color: #444;
320
+ border-radius: 30px;
321
+ padding: 4px 10px;
322
+ color: #fff;
323
+ z-index: 2;
324
+ }
325
+ }
326
+ }
327
+ }
328
+
329
+ // Grid View
330
+
331
+ .grid {
332
+ padding: 1em;
333
+ font-size: .85em;
334
+
335
+ .card {
336
+ padding: 1em;
337
+
338
+ .inner {
339
+ padding: 1em;
340
+ border-radius: 3px;
341
+ display: inline-block;
342
+ background: #fff;
343
+ width: 100%;
344
+ min-height: 250px;
345
+ box-sizing: border-box;
346
+ -moz-box-sizing: border-box;
347
+ -webkit-box-sizing: border-box;
348
+ box-shadow: 0px 1px 2px 0 #ccc;
349
+ position: relative;
350
+ text-align: center;
351
+
352
+ .icon {
353
+ color: #83ADFA;
354
+ text-align: center;
355
+ font-size: 50px;
356
+ }
357
+
358
+ .title, .state, .threads, .time { margin-bottom: 10px; }
359
+
360
+ .actions {
361
+ padding: 10px 0;
362
+ background: #f5f5f5;
363
+ border: 1px solid #eee;
364
+ border-radius: 2px;
365
+ }
366
+
367
+ .title {
368
+ text-align: center;
369
+
370
+ h3 {
371
+ font-weight: bold;
372
+ margin: 0;
373
+ font-size: 16px;
374
+ }
375
+ }
376
+ }
377
+ }
378
+ }
379
+
380
+ .spinner {
381
+ width: 67px;
382
+ margin: 0 auto;
383
+
384
+ input { text-align: right; }
385
+
386
+ .input-group-btn-vertical {
387
+ position: relative;
388
+ white-space: nowrap;
389
+ width: 1%;
390
+ vertical-align: middle;
391
+ display: table-cell;
392
+ }
393
+
394
+ .input-group-btn-vertical > .btn {
395
+ display: block;
396
+ float: none;
397
+ width: 100%;
398
+ max-width: 100%;
399
+ padding: 8px;
400
+ margin-left: -1px;
401
+ position: relative;
402
+ border-radius: 0;
403
+ }
404
+
405
+ .input-group-btn-vertical > .btn:first-child {
406
+ border-right: 0;
407
+ }
408
+
409
+ .input-group-btn-vertical > .btn:last-child {
410
+ margin-top: -2px;
411
+ border-right: 0;
412
+ }
413
+
414
+ .input-group-btn-vertical i{
415
+ position: absolute;
416
+ top: 0;
417
+ left: 4px;
418
+ }
419
+ }
420
+
421
+ .green.signal {
422
+ -webkit-animation: greenPulse 2s infinite;
423
+ -moz-animation: greenPulse 2s infinite;
424
+ -o-animation: greenPulse 2s infinite;
425
+ animation: greenPulse 2s infinite;
426
+ margin: 0 5px 0 10px;
427
+ }
428
+
429
+ .code-block { margin-top: 25px; }
430
+
431
+ .status {
432
+ padding: 1em;
433
+ }
434
+
435
+ // Warnings & Notifications
436
+
437
+ .no-servers {
438
+ text-align: center;
439
+ font-size: 23px;
440
+ padding-top: 50px;
441
+ color: #777;
442
+ }
443
+ }
444
+
445
+ // Rocket Job Animations
446
+ @-webkit-keyframes greenPulse {
447
+ 0% { color: #91bd09; -webkit-box-shadow: 0 0 9px #91bd09; border-radius: 30px; }
448
+ 50% { color: rgb(107, 240, 123); -webkit-box-shadow: 0 0 18px rgb(107, 240, 123); border-radius: 30px; }
449
+ 100% { color: #91bd09; -webkit-box-shadow: 0 0 9px #91bd09; border-radius: 30px; }
450
+ }
451
+
452
+ @-moz-keyframes greenPulse {
453
+ 0% { background-color: #749a02; -moz-box-shadow: 0 0 9px #333; }
454
+ 50% { background-color: lime; -moz-box-shadow: 0 0 18px #91bd09; }
455
+ 100% { background-color: #749a02; -moz-box-shadow: 0 0 9px #333; }
456
+ }
457
+
458
+ @-o-keyframes greenPulse {
459
+ 0% { background-color: #749a02; box-shadow: 0 0 9px #749a02; }
460
+ 50% { background-color: #91bd09; box-shadow: 0 0 18px #91bd09; }
461
+ 100% { background-color: #749a02; box-shadow: 0 0 9px #749a02; }
462
+ }
463
+
464
+ @keyframes greenPulse {
465
+ 0% { background-color: #749a02; box-shadow: 0 0 9px #333; }
466
+ 50% { background-color: #91bd09; box-shadow: 0 0 18px #91bd09; }
467
+ 100% { background-color: #749a02; box-shadow: 0 0 9px #333; }
468
+ }