sidekiq 2.14.1 → 2.15.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of sidekiq might be problematic. Click here for more details.
- data/Changes.md +24 -0
- data/README.md +6 -3
- data/lib/sidekiq.rb +8 -0
- data/lib/sidekiq/api.rb +1 -1
- data/lib/sidekiq/cli.rb +1 -1
- data/lib/sidekiq/client.rb +24 -2
- data/lib/sidekiq/exception_handler.rb +2 -2
- data/lib/sidekiq/launcher.rb +38 -9
- data/lib/sidekiq/manager.rb +0 -3
- data/lib/sidekiq/testing.rb +65 -4
- data/lib/sidekiq/testing/inline.rb +27 -40
- data/lib/sidekiq/util.rb +1 -0
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web.rb +16 -3
- data/lib/sidekiq/worker.rb +6 -8
- data/sidekiq.gemspec +4 -4
- data/test/helper.rb +8 -0
- data/test/test_api.rb +1 -1
- data/test/test_cli.rb +1 -1
- data/test/test_client.rb +23 -2
- data/test/test_exception_handler.rb +1 -1
- data/test/test_extensions.rb +1 -1
- data/test/test_fetch.rb +1 -1
- data/test/test_manager.rb +11 -18
- data/test/test_middleware.rb +1 -1
- data/test/test_processor.rb +1 -1
- data/test/test_redis_connection.rb +3 -3
- data/test/test_retry.rb +1 -1
- data/test/test_scheduled.rb +1 -1
- data/test/test_scheduling.rb +10 -2
- data/test/test_sidekiq.rb +2 -2
- data/test/test_testing.rb +43 -230
- data/test/test_testing_fake.rb +265 -0
- data/test/test_testing_inline.rb +4 -7
- data/test/test_util.rb +1 -1
- data/test/test_web.rb +1 -1
- data/web/assets/javascripts/dashboard.js +3 -1
- data/web/assets/stylesheets/application.css +84 -21
- data/web/assets/stylesheets/bootstrap.css +4 -15
- data/web/views/_nav.erb +12 -2
- data/web/views/_poll.erb +14 -0
- data/web/views/_status.erb +1 -1
- data/web/views/_summary.erb +23 -15
- data/web/views/_workers.erb +1 -1
- data/web/views/dashboard.erb +37 -34
- data/web/views/index.erb +2 -2
- data/web/views/layout.erb +3 -23
- data/web/views/queue.erb +4 -4
- data/web/views/queues.erb +1 -1
- data/web/views/retries.erb +10 -6
- data/web/views/retry.erb +1 -1
- data/web/views/scheduled.erb +2 -2
- data/web/views/scheduled_job_info.erb +1 -1
- metadata +13 -10
@@ -0,0 +1,265 @@
|
|
1
|
+
require 'helper'
|
2
|
+
require 'sidekiq'
|
3
|
+
require 'sidekiq/worker'
|
4
|
+
require 'active_record'
|
5
|
+
require 'action_mailer'
|
6
|
+
require 'sidekiq/rails'
|
7
|
+
require 'sidekiq/extensions/action_mailer'
|
8
|
+
require 'sidekiq/extensions/active_record'
|
9
|
+
|
10
|
+
Sidekiq.hook_rails!
|
11
|
+
|
12
|
+
class TestTesting < Sidekiq::Test
|
13
|
+
describe 'sidekiq testing' do
|
14
|
+
class PerformError < RuntimeError; end
|
15
|
+
|
16
|
+
class DirectWorker
|
17
|
+
include Sidekiq::Worker
|
18
|
+
def perform(a, b)
|
19
|
+
a + b
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class EnqueuedWorker
|
24
|
+
include Sidekiq::Worker
|
25
|
+
def perform(a, b)
|
26
|
+
a + b
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class StoredWorker
|
31
|
+
include Sidekiq::Worker
|
32
|
+
def perform(error)
|
33
|
+
raise PerformError if error
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
class FooMailer < ActionMailer::Base
|
38
|
+
def bar(str)
|
39
|
+
str
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
class FooModel < ActiveRecord::Base
|
44
|
+
def bar(str)
|
45
|
+
str
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
before do
|
50
|
+
require 'sidekiq/testing.rb'
|
51
|
+
Sidekiq::Testing.fake!
|
52
|
+
EnqueuedWorker.jobs.clear
|
53
|
+
DirectWorker.jobs.clear
|
54
|
+
end
|
55
|
+
|
56
|
+
after do
|
57
|
+
Sidekiq::Testing.disable!
|
58
|
+
end
|
59
|
+
|
60
|
+
it 'stubs the async call' do
|
61
|
+
assert_equal 0, DirectWorker.jobs.size
|
62
|
+
assert DirectWorker.perform_async(1, 2)
|
63
|
+
assert_equal 1, DirectWorker.jobs.size
|
64
|
+
assert DirectWorker.perform_in(10, 1, 2)
|
65
|
+
assert_equal 2, DirectWorker.jobs.size
|
66
|
+
assert DirectWorker.perform_at(10, 1, 2)
|
67
|
+
assert_equal 3, DirectWorker.jobs.size
|
68
|
+
assert_in_delta 10.seconds.from_now.to_f, DirectWorker.jobs.last['at'], 0.01
|
69
|
+
end
|
70
|
+
|
71
|
+
it 'stubs the delay call on mailers' do
|
72
|
+
assert_equal 0, Sidekiq::Extensions::DelayedMailer.jobs.size
|
73
|
+
FooMailer.delay.bar('hello!')
|
74
|
+
assert_equal 1, Sidekiq::Extensions::DelayedMailer.jobs.size
|
75
|
+
end
|
76
|
+
|
77
|
+
class Something
|
78
|
+
def self.foo(x)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'stubs the delay call on models' do
|
83
|
+
assert_equal 0, Sidekiq::Extensions::DelayedClass.jobs.size
|
84
|
+
Something.delay.foo(Date.today)
|
85
|
+
assert_equal 1, Sidekiq::Extensions::DelayedClass.jobs.size
|
86
|
+
end
|
87
|
+
|
88
|
+
it 'stubs the enqueue call' do
|
89
|
+
assert_equal 0, EnqueuedWorker.jobs.size
|
90
|
+
assert Sidekiq::Client.enqueue(EnqueuedWorker, 1, 2)
|
91
|
+
assert_equal 1, EnqueuedWorker.jobs.size
|
92
|
+
end
|
93
|
+
|
94
|
+
it 'stubs the enqueue_to call' do
|
95
|
+
assert_equal 0, EnqueuedWorker.jobs.size
|
96
|
+
assert Sidekiq::Client.enqueue_to('someq', EnqueuedWorker, 1, 2)
|
97
|
+
assert_equal 1, EnqueuedWorker.jobs.size
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'executes all stored jobs' do
|
101
|
+
assert StoredWorker.perform_async(false)
|
102
|
+
assert StoredWorker.perform_async(true)
|
103
|
+
|
104
|
+
assert_equal 2, StoredWorker.jobs.size
|
105
|
+
assert_raises PerformError do
|
106
|
+
StoredWorker.drain
|
107
|
+
end
|
108
|
+
assert_equal 0, StoredWorker.jobs.size
|
109
|
+
|
110
|
+
end
|
111
|
+
|
112
|
+
class SpecificJidWorker
|
113
|
+
include Sidekiq::Worker
|
114
|
+
class_attribute :count
|
115
|
+
self.count = 0
|
116
|
+
def perform(worker_jid)
|
117
|
+
return unless worker_jid == self.jid
|
118
|
+
self.class.count += 1
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'execute only jobs with assigned JID' do
|
123
|
+
4.times do |i|
|
124
|
+
jid = SpecificJidWorker.perform_async(nil)
|
125
|
+
if i % 2 == 0
|
126
|
+
SpecificJidWorker.jobs[-1]["args"] = ["wrong_jid"]
|
127
|
+
else
|
128
|
+
SpecificJidWorker.jobs[-1]["args"] = [jid]
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
SpecificJidWorker.perform_one
|
133
|
+
assert_equal 0, SpecificJidWorker.count
|
134
|
+
|
135
|
+
SpecificJidWorker.perform_one
|
136
|
+
assert_equal 1, SpecificJidWorker.count
|
137
|
+
|
138
|
+
SpecificJidWorker.drain
|
139
|
+
assert_equal 2, SpecificJidWorker.count
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'round trip serializes the job arguments' do
|
143
|
+
assert StoredWorker.perform_async(:mike)
|
144
|
+
job = StoredWorker.jobs.first
|
145
|
+
assert_equal "mike", job['args'].first
|
146
|
+
StoredWorker.clear
|
147
|
+
end
|
148
|
+
|
149
|
+
it 'perform_one runs only one job' do
|
150
|
+
DirectWorker.perform_async(1, 2)
|
151
|
+
DirectWorker.perform_async(3, 4)
|
152
|
+
assert_equal 2, DirectWorker.jobs.size
|
153
|
+
|
154
|
+
DirectWorker.perform_one
|
155
|
+
assert_equal 1, DirectWorker.jobs.size
|
156
|
+
|
157
|
+
DirectWorker.clear
|
158
|
+
end
|
159
|
+
|
160
|
+
it 'perform_one raise error upon empty queue' do
|
161
|
+
DirectWorker.clear
|
162
|
+
assert_raises Sidekiq::EmptyQueueError do
|
163
|
+
DirectWorker.perform_one
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
class FirstWorker
|
168
|
+
include Sidekiq::Worker
|
169
|
+
class_attribute :count
|
170
|
+
self.count = 0
|
171
|
+
def perform
|
172
|
+
self.class.count += 1
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
class SecondWorker
|
177
|
+
include Sidekiq::Worker
|
178
|
+
class_attribute :count
|
179
|
+
self.count = 0
|
180
|
+
def perform
|
181
|
+
self.class.count += 1
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class ThirdWorker
|
186
|
+
include Sidekiq::Worker
|
187
|
+
class_attribute :count
|
188
|
+
def perform
|
189
|
+
FirstWorker.perform_async
|
190
|
+
SecondWorker.perform_async
|
191
|
+
end
|
192
|
+
end
|
193
|
+
|
194
|
+
it 'clears jobs across all workers' do
|
195
|
+
Sidekiq::Worker.jobs.clear
|
196
|
+
FirstWorker.count = 0
|
197
|
+
SecondWorker.count = 0
|
198
|
+
|
199
|
+
assert_equal 0, FirstWorker.jobs.size
|
200
|
+
assert_equal 0, SecondWorker.jobs.size
|
201
|
+
|
202
|
+
FirstWorker.perform_async
|
203
|
+
SecondWorker.perform_async
|
204
|
+
|
205
|
+
assert_equal 1, FirstWorker.jobs.size
|
206
|
+
assert_equal 1, SecondWorker.jobs.size
|
207
|
+
|
208
|
+
Sidekiq::Worker.clear_all
|
209
|
+
|
210
|
+
assert_equal 0, FirstWorker.jobs.size
|
211
|
+
assert_equal 0, SecondWorker.jobs.size
|
212
|
+
|
213
|
+
assert_equal 0, FirstWorker.count
|
214
|
+
assert_equal 0, SecondWorker.count
|
215
|
+
end
|
216
|
+
|
217
|
+
it 'drains jobs across all workers' do
|
218
|
+
Sidekiq::Worker.jobs.clear
|
219
|
+
FirstWorker.count = 0
|
220
|
+
SecondWorker.count = 0
|
221
|
+
|
222
|
+
assert_equal 0, FirstWorker.jobs.size
|
223
|
+
assert_equal 0, SecondWorker.jobs.size
|
224
|
+
|
225
|
+
assert_equal 0, FirstWorker.count
|
226
|
+
assert_equal 0, SecondWorker.count
|
227
|
+
|
228
|
+
FirstWorker.perform_async
|
229
|
+
SecondWorker.perform_async
|
230
|
+
|
231
|
+
assert_equal 1, FirstWorker.jobs.size
|
232
|
+
assert_equal 1, SecondWorker.jobs.size
|
233
|
+
|
234
|
+
Sidekiq::Worker.drain_all
|
235
|
+
|
236
|
+
assert_equal 0, FirstWorker.jobs.size
|
237
|
+
assert_equal 0, SecondWorker.jobs.size
|
238
|
+
|
239
|
+
assert_equal 1, FirstWorker.count
|
240
|
+
assert_equal 1, SecondWorker.count
|
241
|
+
end
|
242
|
+
|
243
|
+
it 'drains jobs across all workers even when workers create new jobs' do
|
244
|
+
Sidekiq::Worker.jobs.clear
|
245
|
+
FirstWorker.count = 0
|
246
|
+
SecondWorker.count = 0
|
247
|
+
|
248
|
+
assert_equal 0, ThirdWorker.jobs.size
|
249
|
+
|
250
|
+
assert_equal 0, FirstWorker.count
|
251
|
+
assert_equal 0, SecondWorker.count
|
252
|
+
|
253
|
+
ThirdWorker.perform_async
|
254
|
+
|
255
|
+
assert_equal 1, ThirdWorker.jobs.size
|
256
|
+
|
257
|
+
Sidekiq::Worker.drain_all
|
258
|
+
|
259
|
+
assert_equal 0, ThirdWorker.jobs.size
|
260
|
+
|
261
|
+
assert_equal 1, FirstWorker.count
|
262
|
+
assert_equal 1, SecondWorker.count
|
263
|
+
end
|
264
|
+
end
|
265
|
+
end
|
data/test/test_testing_inline.rb
CHANGED
@@ -9,7 +9,7 @@ require 'sidekiq/extensions/active_record'
|
|
9
9
|
|
10
10
|
Sidekiq.hook_rails!
|
11
11
|
|
12
|
-
class TestInline <
|
12
|
+
class TestInline < Sidekiq::Test
|
13
13
|
describe 'sidekiq inline testing' do
|
14
14
|
class InlineError < RuntimeError; end
|
15
15
|
class ParameterIsNotString < RuntimeError; end
|
@@ -41,15 +41,12 @@ class TestInline < Minitest::Test
|
|
41
41
|
end
|
42
42
|
|
43
43
|
before do
|
44
|
-
|
44
|
+
require 'sidekiq/testing/inline.rb'
|
45
|
+
Sidekiq::Testing.inline!
|
45
46
|
end
|
46
47
|
|
47
48
|
after do
|
48
|
-
Sidekiq::
|
49
|
-
remove_method :raw_push
|
50
|
-
alias_method :raw_push, :raw_push_old
|
51
|
-
remove_method :raw_push_old
|
52
|
-
end
|
49
|
+
Sidekiq::Testing.disable!
|
53
50
|
end
|
54
51
|
|
55
52
|
it 'stubs the async call when in testing mode' do
|
data/test/test_util.rb
CHANGED
data/test/test_web.rb
CHANGED
@@ -6,7 +6,9 @@ n){return arguments.length?(t=+n,e):t},e.translate=function(t){return arguments.
|
|
6
6
|
|
7
7
|
// Match width of graphs with summary bar
|
8
8
|
var responsiveWidth = function() {
|
9
|
-
|
9
|
+
//Bootstrap now uses padding instead of margin for gutters. 30px (15 on each side)
|
10
|
+
//http://getbootstrap.com/css/#grid
|
11
|
+
return document.getElementsByClassName('summary_bar')[0].clientWidth - 30;
|
10
12
|
};
|
11
13
|
|
12
14
|
// Richshaw
|
@@ -32,7 +32,7 @@ h1, h2, h3, h4, h5, h6, strong {
|
|
32
32
|
font-weight: 700;
|
33
33
|
}
|
34
34
|
|
35
|
-
.brand, .navbar .brand, h5, h4, h3, h2, h1 {
|
35
|
+
.navbar-brand, .navbar .navbar-brand, h5, h4, h3, h2, h1 {
|
36
36
|
font-family: Armata;
|
37
37
|
font-weight: 400;
|
38
38
|
}
|
@@ -79,7 +79,7 @@ h3 {
|
|
79
79
|
}
|
80
80
|
|
81
81
|
.admin #page {
|
82
|
-
padding: 60px 0
|
82
|
+
padding: 60px 0;
|
83
83
|
}
|
84
84
|
|
85
85
|
.row.header .actions {
|
@@ -113,10 +113,15 @@ header.row .pagination {
|
|
113
113
|
margin-bottom: 10px;
|
114
114
|
border-width: 0px;
|
115
115
|
}
|
116
|
-
.
|
117
|
-
|
116
|
+
.poll-wrapper {
|
117
|
+
padding: 9px 0 0 0;
|
118
118
|
}
|
119
|
-
.
|
119
|
+
.nav #live-poll {
|
120
|
+
height: 25px;
|
121
|
+
line-height: 25px;
|
122
|
+
width: 195px;
|
123
|
+
}
|
124
|
+
#live-poll.active {
|
120
125
|
background-color: #009300;
|
121
126
|
}
|
122
127
|
.summary_bar ul {
|
@@ -144,21 +149,21 @@ header.row .pagination {
|
|
144
149
|
}
|
145
150
|
}
|
146
151
|
@media (max-width: 979px) and (min-width: 768px) {
|
147
|
-
.summary_bar ul li.
|
152
|
+
.summary_bar ul li.col-sm-2 {
|
148
153
|
margin: 0px 10px;
|
149
154
|
width: 96px !important;
|
150
155
|
}
|
151
156
|
}
|
152
|
-
|
153
|
-
.summary_bar ul li.
|
157
|
+
/*@media (max-width: 1199px) and (min-width: 980px) {
|
158
|
+
.summary_bar ul li.col-sm-2 {
|
154
159
|
width: 130px !important;
|
155
160
|
}
|
156
161
|
}
|
157
162
|
@media (min-width: 1200px) {
|
158
|
-
.summary_bar ul li.
|
163
|
+
.summary_bar ul li.col-sm-2 {
|
159
164
|
width: 154px !important;
|
160
165
|
}
|
161
|
-
}
|
166
|
+
}*/
|
162
167
|
.summary_bar ul .desc {
|
163
168
|
display: block;
|
164
169
|
font-size: 1em;
|
@@ -191,11 +196,16 @@ td form {
|
|
191
196
|
margin-bottom: 0;
|
192
197
|
}
|
193
198
|
|
194
|
-
.navbar .brand {
|
199
|
+
.navbar .navbar-brand {
|
195
200
|
color: #b1003e;
|
201
|
+
padding: 13px;
|
196
202
|
text-shadow: none;
|
197
203
|
}
|
198
204
|
|
205
|
+
.navbar .navbar-brand .status {
|
206
|
+
color: #585454;
|
207
|
+
}
|
208
|
+
|
199
209
|
.navbar-footer .navbar ul.nav {
|
200
210
|
text-align: center;
|
201
211
|
float: none;
|
@@ -206,7 +216,7 @@ td form {
|
|
206
216
|
padding: 15px;
|
207
217
|
}
|
208
218
|
|
209
|
-
.navbar-footer .navbar ul.nav a.brand {
|
219
|
+
.navbar-footer .navbar ul.nav a.navbar-brand {
|
210
220
|
font-weight: 400;
|
211
221
|
padding: 0 15px 0 0;
|
212
222
|
}
|
@@ -232,16 +242,17 @@ img.smallogo {
|
|
232
242
|
|
233
243
|
.status-sprite {
|
234
244
|
background-image: url(../images/status-sd8051fd480.png);
|
235
|
-
height:
|
236
|
-
width:
|
245
|
+
height: 19px;
|
246
|
+
width: 20px;
|
237
247
|
display: inline-block;
|
248
|
+
background-size: 20px;
|
238
249
|
}
|
239
250
|
.status-active {
|
240
251
|
background-position: 0 0;
|
241
252
|
}
|
242
253
|
|
243
254
|
.status-idle {
|
244
|
-
background-position: 0 -
|
255
|
+
background-position: 0 -54px;
|
245
256
|
}
|
246
257
|
|
247
258
|
.btn {
|
@@ -291,6 +302,15 @@ img.smallogo {
|
|
291
302
|
padding: 10px 0;
|
292
303
|
}
|
293
304
|
|
305
|
+
.redis-wrapper {
|
306
|
+
width: 100%;
|
307
|
+
text-align: center;
|
308
|
+
}
|
309
|
+
|
310
|
+
.stats-container {
|
311
|
+
display: inline-block;
|
312
|
+
}
|
313
|
+
|
294
314
|
.stat {
|
295
315
|
float: left;
|
296
316
|
text-align: center;
|
@@ -301,10 +321,33 @@ img.smallogo {
|
|
301
321
|
margin-bottom: 20px;
|
302
322
|
}
|
303
323
|
|
324
|
+
.stat:last-child {
|
325
|
+
margin-right: 0;
|
326
|
+
}
|
327
|
+
|
304
328
|
.stat p {
|
305
329
|
font-size: 0.9em;
|
306
330
|
}
|
307
|
-
|
331
|
+
@media (max-width: 767px) {
|
332
|
+
.stats-container {
|
333
|
+
display: block;
|
334
|
+
}
|
335
|
+
.stat {
|
336
|
+
float: left;
|
337
|
+
margin-right: 10px;
|
338
|
+
width: 100%;
|
339
|
+
text-align: left;
|
340
|
+
line-height: 45px;
|
341
|
+
}
|
342
|
+
.stat h3{
|
343
|
+
float: right;
|
344
|
+
margin: 5px 10px 5px 5px;
|
345
|
+
}
|
346
|
+
.stat p{
|
347
|
+
font-size: normal;
|
348
|
+
margin: 5px 5px 5px 10px;
|
349
|
+
}
|
350
|
+
}
|
308
351
|
.beacon {
|
309
352
|
position: relative;
|
310
353
|
height: 20px;
|
@@ -482,13 +525,14 @@ img.smallogo {
|
|
482
525
|
text-decoration: none;
|
483
526
|
}
|
484
527
|
|
485
|
-
@media (max-width:
|
528
|
+
@media (max-width: 768px) {
|
486
529
|
.navbar .container {
|
487
530
|
text-align: center
|
488
531
|
}
|
489
532
|
|
490
|
-
.navbar .brand {
|
533
|
+
.navbar .navbar-brand {
|
491
534
|
float: none;
|
535
|
+
display: block;
|
492
536
|
}
|
493
537
|
|
494
538
|
.navbar ul.nav li a {
|
@@ -506,6 +550,11 @@ img.smallogo {
|
|
506
550
|
margin-right: 0;
|
507
551
|
}
|
508
552
|
|
553
|
+
.poll-wrapper {
|
554
|
+
padding: 0px 20px 5px 0px;
|
555
|
+
width: 20%;
|
556
|
+
}
|
557
|
+
|
509
558
|
.navbar.navbar-fixed-bottom ul {
|
510
559
|
float: none;
|
511
560
|
margin-right: 0;
|
@@ -517,6 +566,7 @@ img.smallogo {
|
|
517
566
|
}
|
518
567
|
|
519
568
|
.navbar-text {
|
569
|
+
float:none;
|
520
570
|
line-height: 30px;
|
521
571
|
}
|
522
572
|
}
|
@@ -532,7 +582,7 @@ img.smallogo {
|
|
532
582
|
}
|
533
583
|
|
534
584
|
@media (max-width: 500px) {
|
535
|
-
.navbar-footer .navbar ul.nav a.brand {
|
585
|
+
.navbar-footer .navbar ul.nav a.navbar-brand {
|
536
586
|
padding-right: 5px;
|
537
587
|
}
|
538
588
|
}
|
@@ -846,10 +896,23 @@ img.smallogo {
|
|
846
896
|
border-radius: 3px;
|
847
897
|
}
|
848
898
|
.args {
|
849
|
-
overflow: scroll;
|
899
|
+
overflow-y: scroll;
|
850
900
|
max-height: 100px;
|
851
901
|
}
|
852
902
|
.args-extended {
|
853
|
-
overflow: scroll;
|
903
|
+
overflow-y: scroll;
|
854
904
|
max-height: 500px;
|
855
905
|
}
|
906
|
+
|
907
|
+
|
908
|
+
/* BOOTSTRAP 3 FIXES */
|
909
|
+
/* @grid-float-breakpoint -1 */
|
910
|
+
.container {
|
911
|
+
padding: 0;
|
912
|
+
}
|
913
|
+
@media (max-width: 979px) {
|
914
|
+
.navbar-fixed-top, .navbar-fixed-bottom {
|
915
|
+
position: relative;
|
916
|
+
top: auto;
|
917
|
+
}
|
918
|
+
}
|