sidekiq 3.3.3 → 3.3.4
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.
- checksums.yaml +4 -4
- data/Changes.md +13 -0
- data/Pro-Changes.md +12 -0
- data/lib/sidekiq.rb +6 -1
- data/lib/sidekiq/api.rb +16 -10
- data/lib/sidekiq/client.rb +15 -11
- data/lib/sidekiq/fetch.rb +1 -1
- data/lib/sidekiq/middleware/server/logging.rb +6 -2
- data/lib/sidekiq/middleware/server/retry_jobs.rb +6 -2
- data/lib/sidekiq/paginator.rb +5 -3
- data/lib/sidekiq/redis_connection.rb +1 -4
- data/lib/sidekiq/version.rb +1 -1
- data/lib/sidekiq/web_helpers.rb +56 -9
- data/lib/sidekiq/worker.rb +1 -1
- data/test/test_retry.rb +40 -0
- data/test/test_web.rb +13 -0
- data/test/test_web_helpers.rb +46 -0
- data/web/assets/javascripts/application.js +37 -0
- data/web/assets/stylesheets/application.css +60 -15
- data/web/locales/en.yml +1 -0
- data/web/locales/hi.yml +75 -0
- data/web/locales/ru.yml +2 -1
- data/web/locales/ta.yml +75 -0
- data/web/views/_nav.erb +59 -26
- data/web/views/_poll.erb +3 -3
- data/web/views/dashboard.erb +2 -2
- data/web/views/layout.erb +1 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a6ca011daf81025502d9f9abfdf4e38fafd05d83
|
4
|
+
data.tar.gz: 3687865623e0ad65b98fcd7e5e576f540d80df23
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 87bf6bf803ce2c24d2c424348fe83681c77dafda7206300c13ebda6c9aca5d36d1551642c68a0d2f37558540a64e8bd5aa5cfb6d95baaa7ce1fd08d62000ffdb
|
7
|
+
data.tar.gz: ddf4ccef0e503b5e59b874d8ec14ecb6d94721cf674f19385cb0a6e3d180c3605da63b03bb4752fd11c4da60be2d41f63f08c2f2a413e623d15bd929bc9210ff
|
data/Changes.md
CHANGED
@@ -1,3 +1,16 @@
|
|
1
|
+
3.3.4
|
2
|
+
-----------
|
3
|
+
|
4
|
+
- **Improved ActiveJob integration** - Web UI now shows ActiveJobs in a
|
5
|
+
nicer format and job logging shows the actual class name, requires
|
6
|
+
Rails 4.2.2+ [#2248, #2259]
|
7
|
+
- Add Sidekiq::Process#dump\_threads API to trigger TTIN output [#2247]
|
8
|
+
- Web UI polling now uses Ajax to avoid page reload [#2266, davydovanton]
|
9
|
+
- Several Web UI styling improvements [davydovanton]
|
10
|
+
- Add Tamil, Hindi translations for Web UI [ferdinandrosario, tejasbubane]
|
11
|
+
- Fix Web UI to work with country-specific locales [#2243]
|
12
|
+
- Handle circular error causes [#2285, eugenk]
|
13
|
+
|
1
14
|
3.3.3
|
2
15
|
-----------
|
3
16
|
|
data/Pro-Changes.md
CHANGED
@@ -3,6 +3,18 @@ Sidekiq Pro Changelog
|
|
3
3
|
|
4
4
|
Please see [http://sidekiq.org/pro](http://sidekiq.org/pro) for more details and how to buy.
|
5
5
|
|
6
|
+
2.0.2
|
7
|
+
-----------
|
8
|
+
|
9
|
+
- Multiple Web UIs can now run in the same process. [#2267] If you have
|
10
|
+
multiple Redis shards, you can mount UIs for all in the same process:
|
11
|
+
```ruby
|
12
|
+
POOL1 = ConnectionPool.new { Redis.new(:url => "redis://localhost:6379/0") }
|
13
|
+
POOL2 = ConnectionPool.new { Redis.new(:url => "redis://localhost:6378/0") }
|
14
|
+
|
15
|
+
mount Sidekiq::Pro::Web.with(redis_pool: POOL1) => '/sidekiq1'
|
16
|
+
mount Sidekiq::Pro::Web.with(redis_pool: POOL2) => '/sidekiq2'
|
17
|
+
```
|
6
18
|
|
7
19
|
2.0.1
|
8
20
|
-----------
|
data/lib/sidekiq.rb
CHANGED
@@ -30,6 +30,11 @@ module Sidekiq
|
|
30
30
|
dead_timeout_in_seconds: 180 * 24 * 60 * 60 # 6 months
|
31
31
|
}
|
32
32
|
|
33
|
+
DEFAULT_WORKER_OPTIONS = {
|
34
|
+
'retry' => true,
|
35
|
+
'queue' => 'default'
|
36
|
+
}
|
37
|
+
|
33
38
|
def self.❨╯°□°❩╯︵┻━┻
|
34
39
|
puts "Calm down, bro"
|
35
40
|
end
|
@@ -103,7 +108,7 @@ module Sidekiq
|
|
103
108
|
end
|
104
109
|
|
105
110
|
def self.default_worker_options
|
106
|
-
defined?(@default_worker_options) ? @default_worker_options :
|
111
|
+
defined?(@default_worker_options) ? @default_worker_options : DEFAULT_WORKER_OPTIONS
|
107
112
|
end
|
108
113
|
|
109
114
|
def self.load_json(string)
|
data/lib/sidekiq/api.rb
CHANGED
@@ -283,7 +283,7 @@ module Sidekiq
|
|
283
283
|
"#{target}.#{method}"
|
284
284
|
end
|
285
285
|
when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
286
|
-
args[0]
|
286
|
+
@item['wrapped'] || args[0]
|
287
287
|
else
|
288
288
|
klass
|
289
289
|
end
|
@@ -297,7 +297,7 @@ module Sidekiq
|
|
297
297
|
arg
|
298
298
|
end
|
299
299
|
when "ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper"
|
300
|
-
args[
|
300
|
+
@item['wrapped'] ? args[0]["arguments"] : []
|
301
301
|
else
|
302
302
|
args
|
303
303
|
end
|
@@ -384,7 +384,7 @@ module Sidekiq
|
|
384
384
|
raise "Retry not available on jobs which have not failed" unless item["failed_at"]
|
385
385
|
remove_job do |message|
|
386
386
|
msg = Sidekiq.load_json(message)
|
387
|
-
msg['retry_count']
|
387
|
+
msg['retry_count'] -= 1
|
388
388
|
Sidekiq::Client.push(msg)
|
389
389
|
end
|
390
390
|
end
|
@@ -721,6 +721,10 @@ module Sidekiq
|
|
721
721
|
signal('TERM')
|
722
722
|
end
|
723
723
|
|
724
|
+
def dump_threads
|
725
|
+
signal('TTIN')
|
726
|
+
end
|
727
|
+
|
724
728
|
private
|
725
729
|
|
726
730
|
def signal(sig)
|
@@ -785,13 +789,15 @@ module Sidekiq
|
|
785
789
|
def size
|
786
790
|
Sidekiq.redis do |conn|
|
787
791
|
procs = conn.smembers('processes')
|
788
|
-
|
789
|
-
|
790
|
-
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
792
|
+
if procs.empty?
|
793
|
+
0
|
794
|
+
else
|
795
|
+
conn.pipelined do
|
796
|
+
procs.each do |key|
|
797
|
+
conn.hget(key, 'busy')
|
798
|
+
end
|
799
|
+
end.map(&:to_i).inject(:+)
|
800
|
+
end
|
795
801
|
end
|
796
802
|
end
|
797
803
|
end
|
data/lib/sidekiq/client.rb
CHANGED
@@ -211,19 +211,23 @@ module Sidekiq
|
|
211
211
|
raise(ArgumentError, "Message args must be an Array") unless item['args'].is_a?(Array)
|
212
212
|
raise(ArgumentError, "Message class must be either a Class or String representation of the class name") unless item['class'].is_a?(Class) || item['class'].is_a?(String)
|
213
213
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
214
|
+
normalized_hash(item['class'.freeze])
|
215
|
+
.each{ |key, value| item[key] = value if item[key].nil? }
|
216
|
+
|
217
|
+
item['class'.freeze] = item['class'.freeze].to_s
|
218
|
+
item['queue'.freeze] = item['queue'.freeze].to_s
|
219
|
+
item['jid'.freeze] ||= SecureRandom.hex(12)
|
220
|
+
item['enqueued_at'.freeze] ||= Time.now.to_f
|
221
|
+
item
|
222
|
+
end
|
223
|
+
|
224
|
+
def normalized_hash(item_class)
|
225
|
+
if item_class.is_a?(Class)
|
226
|
+
raise(ArgumentError, "Message must include a Sidekiq::Worker class, not class name: #{item_class.ancestors.inspect}") if !item_class.respond_to?('get_sidekiq_options'.freeze)
|
227
|
+
item_class.get_sidekiq_options
|
218
228
|
else
|
219
|
-
|
229
|
+
Sidekiq.default_worker_options
|
220
230
|
end
|
221
|
-
|
222
|
-
normalized_item['queue'] = normalized_item['queue'].to_s
|
223
|
-
normalized_item['jid'] ||= SecureRandom.hex(12)
|
224
|
-
normalized_item['enqueued_at'] ||= Time.now.to_f
|
225
|
-
normalized_item
|
226
231
|
end
|
227
|
-
|
228
232
|
end
|
229
233
|
end
|
data/lib/sidekiq/fetch.rb
CHANGED
@@ -35,7 +35,7 @@ module Sidekiq
|
|
35
35
|
|
36
36
|
begin
|
37
37
|
work = @strategy.retrieve_work
|
38
|
-
::Sidekiq.logger.info("Redis is online, #{Time.now
|
38
|
+
::Sidekiq.logger.info("Redis is online, #{Time.now - @down} sec downtime") if @down
|
39
39
|
@down = nil
|
40
40
|
|
41
41
|
if work
|
@@ -4,7 +4,11 @@ module Sidekiq
|
|
4
4
|
class Logging
|
5
5
|
|
6
6
|
def call(worker, item, queue)
|
7
|
-
|
7
|
+
# If we're using a wrapper class, like ActiveJob, use the "wrapped"
|
8
|
+
# attribute to expose the underlying thing.
|
9
|
+
klass = item['wrapped'] || worker.class.to_s
|
10
|
+
|
11
|
+
Sidekiq::Logging.with_context("#{klass} JID-#{item['jid']}#{" BID-#{item['bid']}" if item['bid']}") do
|
8
12
|
begin
|
9
13
|
start = Time.now
|
10
14
|
logger.info { "start" }
|
@@ -18,7 +22,7 @@ module Sidekiq
|
|
18
22
|
end
|
19
23
|
|
20
24
|
def elapsed(start)
|
21
|
-
(Time.now - start).
|
25
|
+
(Time.now - start).round(3)
|
22
26
|
end
|
23
27
|
|
24
28
|
def logger
|
@@ -188,12 +188,16 @@ module Sidekiq
|
|
188
188
|
end
|
189
189
|
end
|
190
190
|
|
191
|
-
def exception_caused_by_shutdown?(e)
|
191
|
+
def exception_caused_by_shutdown?(e, checked_causes = [])
|
192
192
|
# In Ruby 2.1.0 only, check if exception is a result of shutdown.
|
193
193
|
return false unless defined?(e.cause)
|
194
194
|
|
195
|
+
# Handle circular causes
|
196
|
+
checked_causes << e.object_id
|
197
|
+
return false if checked_causes.include?(e.cause.object_id)
|
198
|
+
|
195
199
|
e.cause.instance_of?(Sidekiq::Shutdown) ||
|
196
|
-
exception_caused_by_shutdown?(e.cause)
|
200
|
+
exception_caused_by_shutdown?(e.cause, checked_causes)
|
197
201
|
end
|
198
202
|
|
199
203
|
end
|
data/lib/sidekiq/paginator.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Sidekiq
|
2
2
|
module Paginator
|
3
|
+
|
3
4
|
def page(key, pageidx=1, page_size=25, opts=nil)
|
4
5
|
current_page = pageidx.to_i < 1 ? 1 : pageidx.to_i
|
5
6
|
pageidx = current_page - 1
|
@@ -22,19 +23,20 @@ module Sidekiq
|
|
22
23
|
conn.zrange(key, starting, ending, :with_scores => true)
|
23
24
|
end
|
24
25
|
end
|
26
|
+
[current_page, total_size, items]
|
25
27
|
when 'list'
|
26
28
|
total_size, items = conn.multi do
|
27
29
|
conn.llen(key)
|
28
30
|
conn.lrange(key, starting, ending)
|
29
31
|
end
|
32
|
+
[current_page, total_size, items]
|
30
33
|
when 'none'
|
31
|
-
|
34
|
+
[1, 0, []]
|
32
35
|
else
|
33
36
|
raise "can't page a #{type}"
|
34
37
|
end
|
35
38
|
end
|
36
|
-
|
37
|
-
[current_page, total_size, items]
|
38
39
|
end
|
40
|
+
|
39
41
|
end
|
40
42
|
end
|
@@ -7,10 +7,7 @@ module Sidekiq
|
|
7
7
|
class << self
|
8
8
|
|
9
9
|
def create(options={})
|
10
|
-
|
11
|
-
if url
|
12
|
-
options[:url] = url
|
13
|
-
end
|
10
|
+
options[:url] ||= determine_redis_provider
|
14
11
|
|
15
12
|
# need a connection for Fetcher and Retry
|
16
13
|
size = options[:size] || (Sidekiq.server? ? (Sidekiq.options[:concurrency] + 2) : 5)
|
data/lib/sidekiq/version.rb
CHANGED
data/lib/sidekiq/web_helpers.rb
CHANGED
@@ -3,30 +3,77 @@ require 'uri'
|
|
3
3
|
module Sidekiq
|
4
4
|
# This is not a public API
|
5
5
|
module WebHelpers
|
6
|
-
def strings
|
7
|
-
@@strings ||=
|
6
|
+
def strings(lang)
|
7
|
+
@@strings ||= {}
|
8
|
+
@@strings[lang] ||= begin
|
8
9
|
# Allow sidekiq-web extensions to add locale paths
|
9
10
|
# so extensions can be localized
|
10
|
-
settings.locales.each_with_object({}) do |path,global|
|
11
|
-
|
11
|
+
settings.locales.each_with_object({}) do |path, global|
|
12
|
+
find_locale_files(lang).each do |file|
|
12
13
|
strs = YAML.load(File.open(file))
|
13
|
-
|
14
|
+
global.deep_merge!(strs[lang])
|
14
15
|
end
|
15
16
|
end
|
16
17
|
end
|
17
18
|
end
|
18
19
|
|
20
|
+
def locale_files
|
21
|
+
@@locale_files = settings.locales.flat_map do |path|
|
22
|
+
Dir["#{path}/*.yml"]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def find_locale_files(lang)
|
27
|
+
locale_files.select { |file| file =~ /\/#{lang}\.yml$/ }
|
28
|
+
end
|
29
|
+
|
19
30
|
# This is a hook for a Sidekiq Pro feature. Please don't touch.
|
20
31
|
def filtering(*)
|
21
32
|
end
|
22
33
|
|
34
|
+
# This view helper provide ability display you html code in
|
35
|
+
# to head of page. Example:
|
36
|
+
#
|
37
|
+
# <% add_to_head do %>
|
38
|
+
# <link rel="stylesheet" .../>
|
39
|
+
# <meta .../>
|
40
|
+
# <% end %>
|
41
|
+
#
|
42
|
+
def add_to_head(&block)
|
43
|
+
@head_html ||= []
|
44
|
+
@head_html << block if block_given?
|
45
|
+
end
|
46
|
+
|
47
|
+
def display_custom_head
|
48
|
+
return unless @head_html
|
49
|
+
@head_html.map { |block| capture(&block) }.join
|
50
|
+
end
|
51
|
+
|
52
|
+
# Simple capture method for erb templates. The origin was
|
53
|
+
# capture method from sinatra-contrib library.
|
54
|
+
def capture(&block)
|
55
|
+
block.call
|
56
|
+
eval('', block.binding)
|
57
|
+
end
|
58
|
+
|
59
|
+
# Given a browser request Accept-Language header like
|
60
|
+
# "fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2", this function
|
61
|
+
# will return "fr" since that's the first code with a matching
|
62
|
+
# locale in web/locales
|
23
63
|
def locale
|
24
|
-
|
25
|
-
|
64
|
+
@locale ||= begin
|
65
|
+
locale = 'en'.freeze
|
66
|
+
languages = request.env['HTTP_ACCEPT_LANGUAGE'.freeze] || 'en'.freeze
|
67
|
+
languages.downcase.split(','.freeze).each do |lang|
|
68
|
+
lang = lang.split(';'.freeze)[0]
|
69
|
+
break locale = lang if find_locale_files(lang).any?
|
70
|
+
end
|
71
|
+
locale
|
72
|
+
end
|
26
73
|
end
|
27
74
|
|
28
75
|
def get_locale
|
29
|
-
strings
|
76
|
+
strings(locale)
|
30
77
|
end
|
31
78
|
|
32
79
|
def t(msg, options={})
|
@@ -129,7 +176,7 @@ module Sidekiq
|
|
129
176
|
RETRY_JOB_KEYS = Set.new(%w(
|
130
177
|
queue class args retry_count retried_at failed_at
|
131
178
|
jid error_message error_class backtrace
|
132
|
-
error_backtrace enqueued_at retry
|
179
|
+
error_backtrace enqueued_at retry wrapped
|
133
180
|
))
|
134
181
|
|
135
182
|
def retry_extra_items(retry_job)
|
data/lib/sidekiq/worker.rb
CHANGED
@@ -64,7 +64,7 @@ module Sidekiq
|
|
64
64
|
# can be true, false or an integer number of lines to save, default *false*
|
65
65
|
# :pool - use the given Redis connection pool to push this type of job to a given shard.
|
66
66
|
def sidekiq_options(opts={})
|
67
|
-
self.sidekiq_options_hash = get_sidekiq_options.merge(
|
67
|
+
self.sidekiq_options_hash = get_sidekiq_options.merge(opts.stringify_keys)
|
68
68
|
end
|
69
69
|
|
70
70
|
def sidekiq_retry_in(&block)
|
data/test/test_retry.rb
CHANGED
@@ -328,6 +328,46 @@ class TestRetry < Sidekiq::Test
|
|
328
328
|
File.read(@tmp_log_path), 'Log entry missing for sidekiq_retry_in')
|
329
329
|
end
|
330
330
|
end
|
331
|
+
|
332
|
+
describe 'handles errors withouth cause' do
|
333
|
+
before do
|
334
|
+
@error = nil
|
335
|
+
begin
|
336
|
+
raise ::StandardError, 'Error'
|
337
|
+
rescue ::StandardError => e
|
338
|
+
@error = e
|
339
|
+
end
|
340
|
+
end
|
341
|
+
|
342
|
+
it "does not recurse infinitely checking if it's a shutdown" do
|
343
|
+
assert(!Sidekiq::Middleware::Server::RetryJobs.new.send(
|
344
|
+
:exception_caused_by_shutdown?, @error))
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
describe 'handles errors with circular causes' do
|
349
|
+
before do
|
350
|
+
@error = nil
|
351
|
+
begin
|
352
|
+
begin
|
353
|
+
raise ::StandardError, 'Error 1'
|
354
|
+
rescue ::StandardError => e1
|
355
|
+
begin
|
356
|
+
raise ::StandardError, 'Error 2'
|
357
|
+
rescue ::StandardError => e2
|
358
|
+
raise e1
|
359
|
+
end
|
360
|
+
end
|
361
|
+
rescue ::StandardError => e
|
362
|
+
@error = e
|
363
|
+
end
|
364
|
+
end
|
365
|
+
|
366
|
+
it "does not recurse infinitely checking if it's a shutdown" do
|
367
|
+
assert(!Sidekiq::Middleware::Server::RetryJobs.new.send(
|
368
|
+
:exception_caused_by_shutdown?, @error))
|
369
|
+
end
|
370
|
+
end
|
331
371
|
end
|
332
372
|
|
333
373
|
end
|
data/test/test_web.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
# encoding: utf-8
|
1
2
|
require_relative 'helper'
|
2
3
|
require 'sidekiq'
|
3
4
|
require 'sidekiq/web'
|
@@ -29,6 +30,18 @@ class TestWeb < Sidekiq::Test
|
|
29
30
|
end
|
30
31
|
end
|
31
32
|
|
33
|
+
it 'can show text with any locales' do
|
34
|
+
rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'ru,en'}
|
35
|
+
get '/', {}, rackenv
|
36
|
+
assert_match(/Панель управления/, last_response.body)
|
37
|
+
rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'es,en'}
|
38
|
+
get '/', {}, rackenv
|
39
|
+
assert_match(/Panel de Control/, last_response.body)
|
40
|
+
rackenv = {'HTTP_ACCEPT_LANGUAGE' => 'en-us'}
|
41
|
+
get '/', {}, rackenv
|
42
|
+
assert_match(/Dashboard/, last_response.body)
|
43
|
+
end
|
44
|
+
|
32
45
|
describe 'busy' do
|
33
46
|
|
34
47
|
it 'can display workers' do
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require_relative 'helper'
|
2
|
+
require 'sidekiq'
|
3
|
+
require 'sidekiq/web_helpers'
|
4
|
+
|
5
|
+
class TestWebHelpers < Sidekiq::Test
|
6
|
+
|
7
|
+
class Helpers
|
8
|
+
include Sidekiq::WebHelpers
|
9
|
+
|
10
|
+
def initialize(params={})
|
11
|
+
@thehash = default.merge(params)
|
12
|
+
end
|
13
|
+
|
14
|
+
def request
|
15
|
+
self
|
16
|
+
end
|
17
|
+
|
18
|
+
def settings
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
def locales
|
23
|
+
['web/locales']
|
24
|
+
end
|
25
|
+
|
26
|
+
def env
|
27
|
+
@thehash
|
28
|
+
end
|
29
|
+
|
30
|
+
def default
|
31
|
+
{
|
32
|
+
}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_locale_determination
|
37
|
+
obj = Helpers.new
|
38
|
+
assert_equal 'en', obj.locale
|
39
|
+
|
40
|
+
obj = Helpers.new('HTTP_ACCEPT_LANGUAGE' => 'fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2')
|
41
|
+
assert_equal 'fr', obj.locale
|
42
|
+
|
43
|
+
obj = Helpers.new('HTTP_ACCEPT_LANGUAGE' => 'zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4,ru;q=0.2')
|
44
|
+
assert_equal 'zh-cn', obj.locale
|
45
|
+
end
|
46
|
+
end
|
@@ -18,6 +18,15 @@
|
|
18
18
|
*/
|
19
19
|
(function(e){function n(){var t=r(this);if(!isNaN(t.datetime)){e(this).text(i(t.datetime))}return this}function r(n){n=e(n);if(!n.data("timeago")){n.data("timeago",{datetime:t.datetime(n)});var r=e.trim(n.text());if(r.length>0&&!(t.isTime(n)&&n.attr("title"))){n.attr("title",r)}}return n.data("timeago")}function i(e){return t.inWords(s(e))}function s(e){return(new Date).getTime()-e.getTime()}e.timeago=function(t){if(t instanceof Date){return i(t)}else if(typeof t==="string"){return i(e.timeago.parse(t))}else if(typeof t==="number"){return i(new Date(t))}else{return i(e.timeago.datetime(t))}};var t=e.timeago;e.extend(e.timeago,{settings:{refreshMillis:6e4,allowFuture:false,strings:{prefixAgo:null,prefixFromNow:null,suffixAgo:"ago",suffixFromNow:"from now",seconds:"less than a minute",minute:"about a minute",minutes:"%d minutes",hour:"about an hour",hours:"about %d hours",day:"a day",days:"%d days",month:"about a month",months:"%d months",year:"about a year",years:"%d years",wordSeparator:" ",numbers:[]}},inWords:function(t){function l(r,i){var s=e.isFunction(r)?r(i,t):r;var o=n.numbers&&n.numbers[i]||i;return s.replace(/%d/i,o)}var n=this.settings.strings;var r=n.prefixAgo;var i=n.suffixAgo;if(this.settings.allowFuture){if(t<0){r=n.prefixFromNow;i=n.suffixFromNow}}var s=Math.abs(t)/1e3;var o=s/60;var u=o/60;var a=u/24;var f=a/365;var c=s<45&&l(n.seconds,Math.round(s))||s<90&&l(n.minute,1)||o<45&&l(n.minutes,Math.round(o))||o<90&&l(n.hour,1)||u<24&&l(n.hours,Math.round(u))||u<42&&l(n.day,1)||a<30&&l(n.days,Math.round(a))||a<45&&l(n.month,1)||a<365&&l(n.months,Math.round(a/30))||f<1.5&&l(n.year,1)||l(n.years,Math.round(f));var h=n.wordSeparator===undefined?" ":n.wordSeparator;return e.trim([r,c,i].join(h))},parse:function(t){var n=e.trim(t);n=n.replace(/\.\d+/,"");n=n.replace(/-/,"/").replace(/-/,"/");n=n.replace(/T/," ").replace(/Z/," UTC");n=n.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2");return new Date(n)},datetime:function(n){var r=t.isTime(n)?e(n).attr("datetime"):e(n).attr("title");return t.parse(r)},isTime:function(t){return e(t).get(0).tagName.toLowerCase()==="time"}});e.fn.timeago=function(){var e=this;e.each(n);var r=t.settings;if(r.refreshMillis>0){setInterval(function(){e.each(n)},r.refreshMillis)}return e};document.createElement("abbr");document.createElement("time")})(jQuery)
|
20
20
|
|
21
|
+
/* ========================================================================
|
22
|
+
* Bootstrap: dropdown.js v3.3.4
|
23
|
+
* http://getbootstrap.com/javascript/#dropdowns
|
24
|
+
* ========================================================================
|
25
|
+
* Copyright 2011-2015 Twitter, Inc.
|
26
|
+
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
|
27
|
+
* ======================================================================== */
|
28
|
+
+function(a){"use strict";function e(d){d&&3===d.which||(a(b).remove(),a(c).each(function(){var b=a(this),c=f(b),e={relatedTarget:this};c.hasClass("open")&&(d&&"click"==d.type&&/input|textarea/i.test(d.target.tagName)&&a.contains(c[0],d.target)||(c.trigger(d=a.Event("hide.bs.dropdown",e)),d.isDefaultPrevented()||(b.attr("aria-expanded","false"),c.removeClass("open").trigger("hidden.bs.dropdown",e))))}))}function f(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#[A-Za-z]/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}function g(b){return this.each(function(){var c=a(this),e=c.data("bs.dropdown");e||c.data("bs.dropdown",e=new d(this)),"string"==typeof b&&e[b].call(c)})}var b=".dropdown-backdrop",c='[data-toggle="dropdown"]',d=function(b){a(b).on("click.bs.dropdown",this.toggle)};d.VERSION="3.3.4",d.prototype.toggle=function(b){var c=a(this);if(!c.is(".disabled, :disabled")){var d=f(c),g=d.hasClass("open");if(e(),!g){"ontouchstart"in document.documentElement&&!d.closest(".navbar-nav").length&&a(document.createElement("div")).addClass("dropdown-backdrop").insertAfter(a(this)).on("click",e);var h={relatedTarget:this};if(d.trigger(b=a.Event("show.bs.dropdown",h)),b.isDefaultPrevented())return;c.trigger("focus").attr("aria-expanded","true"),d.toggleClass("open").trigger("shown.bs.dropdown",h)}return!1}},d.prototype.keydown=function(b){if(/(38|40|27|32)/.test(b.which)&&!/input|textarea/i.test(b.target.tagName)){var d=a(this);if(b.preventDefault(),b.stopPropagation(),!d.is(".disabled, :disabled")){var e=f(d),g=e.hasClass("open");if(!g&&27!=b.which||g&&27==b.which)return 27==b.which&&e.find(c).trigger("focus"),d.trigger("click");var h=" li:not(.disabled):visible a",i=e.find('[role="menu"]'+h+', [role="listbox"]'+h);if(i.length){var j=i.index(b.target);38==b.which&&j>0&&j--,40==b.which&&j<i.length-1&&j++,~j||(j=0),i.eq(j).trigger("focus")}}}};var h=a.fn.dropdown;a.fn.dropdown=g,a.fn.dropdown.Constructor=d,a.fn.dropdown.noConflict=function(){return a.fn.dropdown=h,this},a(document).on("click.bs.dropdown.data-api",e).on("click.bs.dropdown.data-api",".dropdown form",function(a){a.stopPropagation()}).on("click.bs.dropdown.data-api",c,d.prototype.toggle).on("keydown.bs.dropdown.data-api",c,d.prototype.keydown).on("keydown.bs.dropdown.data-api",'[role="menu"]',d.prototype.keydown).on("keydown.bs.dropdown.data-api",'[role="listbox"]',d.prototype.keydown)}(jQuery);
|
29
|
+
|
21
30
|
Sidekiq = {};
|
22
31
|
|
23
32
|
$(function() {
|
@@ -42,3 +51,31 @@ $(function() {
|
|
42
51
|
$($(this).attr('data-target')).toggle();
|
43
52
|
});
|
44
53
|
});
|
54
|
+
|
55
|
+
function updatePage(url) {
|
56
|
+
setInterval(function () {
|
57
|
+
$.ajax({
|
58
|
+
url: url,
|
59
|
+
dataType: 'html'
|
60
|
+
}).done(function (data) {
|
61
|
+
var $page = $(data).filter('#page')
|
62
|
+
$('#page').replaceWith($page)
|
63
|
+
})
|
64
|
+
}, parseInt(localStorage.timeInterval) || 2000);
|
65
|
+
}
|
66
|
+
|
67
|
+
$(function() {
|
68
|
+
'use strict';
|
69
|
+
|
70
|
+
var $navbar = $('.navbar-default')
|
71
|
+
, staticContentWidth = 0
|
72
|
+
|
73
|
+
$('[data-navbar="static"]').each(function () {
|
74
|
+
staticContentWidth += $(this).width()
|
75
|
+
});
|
76
|
+
|
77
|
+
if ($navbar.width() < staticContentWidth) {
|
78
|
+
$('[data-navbar="custom-tab"]').hide()
|
79
|
+
$('[data-navbar="dropdown"]').show()
|
80
|
+
}
|
81
|
+
});
|
@@ -101,11 +101,6 @@ header.row .pagination {
|
|
101
101
|
.poll-wrapper {
|
102
102
|
margin: 9px;
|
103
103
|
}
|
104
|
-
.nav #live-poll {
|
105
|
-
height: 25px;
|
106
|
-
line-height: 25px;
|
107
|
-
width: 195px;
|
108
|
-
}
|
109
104
|
#live-poll.active {
|
110
105
|
background-color: #009300;
|
111
106
|
}
|
@@ -208,6 +203,53 @@ table .table-checkbox label {
|
|
208
203
|
color: #585454;
|
209
204
|
}
|
210
205
|
|
206
|
+
@media (max-width: 768px) {
|
207
|
+
.navbar .navbar-header .navbar-livereload {
|
208
|
+
border: none;
|
209
|
+
margin: 9px 10px 0;
|
210
|
+
padding: 0;
|
211
|
+
}
|
212
|
+
|
213
|
+
.navbar .navbar-collapse {
|
214
|
+
max-height: 400px;
|
215
|
+
}
|
216
|
+
|
217
|
+
.navbar .navbar-collapse .navbar-livereload {
|
218
|
+
display: none;
|
219
|
+
}
|
220
|
+
|
221
|
+
.navbar.navbar-fixed-top ul {
|
222
|
+
margin-right: -15px!important;
|
223
|
+
}
|
224
|
+
|
225
|
+
.navbar .nav a {
|
226
|
+
text-align: center;
|
227
|
+
}
|
228
|
+
}
|
229
|
+
|
230
|
+
@media (width: 768px) {
|
231
|
+
.navbar .navbar-collapse .navbar-livereload {
|
232
|
+
display: block;
|
233
|
+
margin-top: 5px;
|
234
|
+
}
|
235
|
+
|
236
|
+
.navbar .poll-wrapper {
|
237
|
+
margin: 4px 4px 0 0;
|
238
|
+
}
|
239
|
+
|
240
|
+
.navbar .dropdown-menu {
|
241
|
+
min-width: 120px;
|
242
|
+
}
|
243
|
+
|
244
|
+
.navbar .dropdown-menu a {
|
245
|
+
text-align: left;
|
246
|
+
}
|
247
|
+
}
|
248
|
+
|
249
|
+
.nav .dropdown {
|
250
|
+
display: none;
|
251
|
+
}
|
252
|
+
|
211
253
|
.navbar-footer .navbar ul.nav {
|
212
254
|
text-align: center;
|
213
255
|
float: none;
|
@@ -581,6 +623,10 @@ div.interval-slider input {
|
|
581
623
|
}
|
582
624
|
}
|
583
625
|
|
626
|
+
.chart {
|
627
|
+
margin: 0;
|
628
|
+
}
|
629
|
+
|
584
630
|
.history-heading {
|
585
631
|
padding-right: 15px;
|
586
632
|
}
|
@@ -600,24 +646,17 @@ div.interval-slider input {
|
|
600
646
|
text-decoration: none;
|
601
647
|
}
|
602
648
|
|
603
|
-
@media (max-width:
|
649
|
+
@media (max-width: 767px) {
|
604
650
|
.navbar .navbar-brand {
|
605
651
|
float: none;
|
606
652
|
display: block;
|
607
653
|
}
|
608
654
|
|
609
|
-
.navbar ul.nav li a {
|
610
|
-
padding-left: 8px;
|
611
|
-
padding-right: 8px;
|
612
|
-
}
|
613
|
-
|
614
655
|
.navbar.navbar-fixed-top ul {
|
615
|
-
float: none;
|
616
656
|
margin-right: 0;
|
617
657
|
}
|
618
658
|
|
619
659
|
.navbar.navbar-fixed-top li {
|
620
|
-
float: none;
|
621
660
|
margin-right: 0;
|
622
661
|
}
|
623
662
|
|
@@ -644,14 +683,20 @@ div.interval-slider input {
|
|
644
683
|
.navbar-text {
|
645
684
|
float:none;
|
646
685
|
line-height: 30px;
|
686
|
+
margin: 15px auto;
|
647
687
|
}
|
648
688
|
}
|
649
689
|
|
650
|
-
@media (max-width:
|
690
|
+
@media (max-width: 767px) {
|
651
691
|
.navbar-fixed-top, .navbar-fixed-bottom {
|
652
692
|
margin: 0 -20px;
|
653
693
|
}
|
654
694
|
|
695
|
+
.navbar ul.nav li a {
|
696
|
+
padding-left: 8px;
|
697
|
+
padding-right: 8px;
|
698
|
+
}
|
699
|
+
|
655
700
|
.admin #page {
|
656
701
|
padding-top: 10px;
|
657
702
|
}
|
@@ -686,7 +731,7 @@ div.interval-slider input {
|
|
686
731
|
.container {
|
687
732
|
padding: 0;
|
688
733
|
}
|
689
|
-
@media (max-width:
|
734
|
+
@media (max-width: 767px) {
|
690
735
|
.navbar-fixed-top, .navbar-fixed-bottom {
|
691
736
|
position: relative;
|
692
737
|
top: auto;
|
data/web/locales/en.yml
CHANGED
data/web/locales/hi.yml
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# elements like %{queue} are variables and should not be translated
|
2
|
+
hi:
|
3
|
+
Dashboard: डैशबोर्ड
|
4
|
+
Status: स्थिती
|
5
|
+
Time: समय
|
6
|
+
Namespace: नामस्थान
|
7
|
+
Realtime: रिअल टाईम
|
8
|
+
History: वृत्तान्त
|
9
|
+
Busy: व्यस्थ
|
10
|
+
Processed: कार्रवाई कृत
|
11
|
+
Failed: असफल
|
12
|
+
Scheduled: परिगणित
|
13
|
+
Retries: पुनर्प्रयास
|
14
|
+
Enqueued: कतारबद्ध
|
15
|
+
Worker: वर्कर
|
16
|
+
LivePoll: लाईव सर्वेक्षण
|
17
|
+
StopPolling: सर्वेक्षण रोको
|
18
|
+
Queue: कतार
|
19
|
+
Class: क्लास
|
20
|
+
Job: कार्य
|
21
|
+
Arguments: अर्गुमेन्ट्स्
|
22
|
+
Extras: अतिरिक्त
|
23
|
+
Started: शुरु हुआ
|
24
|
+
ShowAll: सब दिखाएं
|
25
|
+
CurrentMessagesInQueue: <span class='title'>%{queue}</span> कतार मे वर्तमान कार्य
|
26
|
+
Delete: हटाओ
|
27
|
+
AddToQueue: कतार मे जोड़ें
|
28
|
+
AreYouSureDeleteJob: क्या आप इस कार्य को हटाना चाहते है?
|
29
|
+
AreYouSureDeleteQueue: क्या आप %{queue} कतार को हटाना चाहते है?
|
30
|
+
Queues: कतारे
|
31
|
+
Size: आकार
|
32
|
+
Actions: कार्रवाई
|
33
|
+
NextRetry: अगला पुन:प्रयास
|
34
|
+
RetryCount: पुन:प्रयास संख्या
|
35
|
+
RetryNow: पुन:प्रयास करे
|
36
|
+
Kill: नष्ट करे
|
37
|
+
LastRetry: अंतिम पुन:प्रयास
|
38
|
+
OriginallyFailed: पहिले से विफल
|
39
|
+
AreYouSure: क्या आपको यकीन है?
|
40
|
+
DeleteAll: सब हटाओ
|
41
|
+
RetryAll: सब पुन:प्रयास करे
|
42
|
+
NoRetriesFound: कोई पुनर्प्रयास नही पाए गए
|
43
|
+
Error: एरर
|
44
|
+
ErrorClass: एरर क्लास
|
45
|
+
ErrorMessage: एरर संदेश
|
46
|
+
ErrorBacktrace: एरर बैकट्रेस
|
47
|
+
GoBack: ← पीछे
|
48
|
+
NoScheduledFound: कोई परिगणित कार्य नही पाए गए
|
49
|
+
When: कब
|
50
|
+
ScheduledJobs: परिगणित कार्य
|
51
|
+
idle: निष्क्रिय
|
52
|
+
active: सक्रिय
|
53
|
+
Version: वर्जन
|
54
|
+
Connections: कनेक्श्न
|
55
|
+
MemoryUsage: मेमरी उपयोग
|
56
|
+
PeakMemoryUsage: अधिकतम मेमरी उपयोग
|
57
|
+
Uptime: उपरिकाल (दिवस)
|
58
|
+
OneWeek: १ सप्ताह
|
59
|
+
OneMonth: १ महीना
|
60
|
+
ThreeMonths: ३ महीने
|
61
|
+
SixMonths: ६ महीने
|
62
|
+
Failures: असफलता
|
63
|
+
DeadJobs: निष्प्राण कार्य
|
64
|
+
NoDeadJobsFound: कोई निष्प्राण कार्य नही पाए गए
|
65
|
+
Dead: निष्प्राण
|
66
|
+
Processes: प्रोसेसेस्
|
67
|
+
Thread: थ्रेड
|
68
|
+
Threads: थ्रेड्स्
|
69
|
+
Jobs: कार्य
|
70
|
+
Paused: थमे हुए
|
71
|
+
Stop: रोको
|
72
|
+
Quiet: शांत करो
|
73
|
+
StopAll: सब रोको
|
74
|
+
QuietAll: सब शांत करो
|
75
|
+
PollingInterval: सर्वेक्षण अंतराल
|
data/web/locales/ru.yml
CHANGED
@@ -2,7 +2,7 @@ ru:
|
|
2
2
|
Dashboard: Панель управления
|
3
3
|
Status: Статус
|
4
4
|
Time: Время
|
5
|
-
Namespace:
|
5
|
+
Namespace: Пространство имен
|
6
6
|
Realtime: Сейчас
|
7
7
|
History: История
|
8
8
|
Busy: Занят
|
@@ -72,3 +72,4 @@ ru:
|
|
72
72
|
StopAll: Остановить все
|
73
73
|
QuietAll: Отдыхать всем
|
74
74
|
PollingInterval: Интервал опроса
|
75
|
+
Plugins: Плагины
|
data/web/locales/ta.yml
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
# elements like %{queue} are variables and should not be translated
|
2
|
+
ta: # <---- change this to your locale code
|
3
|
+
Dashboard: டாஷ்போர்டு
|
4
|
+
Status: நிலைமை
|
5
|
+
Time: நேரம்
|
6
|
+
Namespace: பெயர்வெளி
|
7
|
+
Realtime: நேரலை
|
8
|
+
History: வரலாறு
|
9
|
+
Busy: பணிமிகுதி
|
10
|
+
Processed: நிறையுற்றது
|
11
|
+
Failed: தோல்வி
|
12
|
+
Scheduled: திட்டமிடப்பட்ட
|
13
|
+
Retries: மீண்டும் முயற்சிக்க,
|
14
|
+
Enqueued: வரிசைப்படுத்தப்பட்டவை
|
15
|
+
Worker: பணியாளர்
|
16
|
+
LivePoll: நேரடி கணிப்பு
|
17
|
+
StopPolling: நிறுத்து வாக்குப்பதிவு
|
18
|
+
Queue: வரிசை
|
19
|
+
Class: வகுப்பு
|
20
|
+
Job: வேலை
|
21
|
+
Arguments: வாதங்கள்,
|
22
|
+
Extras: உபரி
|
23
|
+
Started: தொடங்குதல்
|
24
|
+
ShowAll: அனைத்து காட்டு
|
25
|
+
CurrentMessagesInQueue: தற்போதைய வேலைகள் <span class='title'>%{queue}</span>
|
26
|
+
Delete: நீக்கு
|
27
|
+
AddToQueue: வரிசையில் சேர்
|
28
|
+
AreYouSureDeleteJob: நீ இந்த வேலையை நீக்க வேண்டும் என்று உறுதியாக இருக்கிறீர்களா?
|
29
|
+
AreYouSureDeleteQueue: நீங்கள் %{queue} வரிசையில் நீக்க வேண்டும் என்பதில் உறுதியாக இருக்கிறீர்களா?
|
30
|
+
Queues: வரிசை
|
31
|
+
Size: அளவு
|
32
|
+
Actions: செயல்கள்
|
33
|
+
NextRetry: அடுத்த, மீண்டும் முயற்சிக்கவும்
|
34
|
+
RetryCount: கணிப்பீடு, மீண்டும் முயற்சிக்கவும்
|
35
|
+
RetryNow: இப்போது மீண்டும் முயற்சி செய்க
|
36
|
+
Kill: கொல்
|
37
|
+
LastRetry: கடைசியாக, மீண்டும் முயற்சிக்கவும்
|
38
|
+
OriginallyFailed: முதலில் தோல்வி
|
39
|
+
AreYouSure: நீங்கள் உறுதியாக இருக்கிறீர்களா?
|
40
|
+
DeleteAll: அனைத்து நீக்கு
|
41
|
+
RetryAll: அனைத்து, மீண்டும் முயற்சிக்கவும்
|
42
|
+
NoRetriesFound: இல்லை மீண்டும் காணப்படவில்லை
|
43
|
+
Error: பிழை
|
44
|
+
ErrorClass: பிழை வகுப்பு
|
45
|
+
ErrorMessage: பிழை செய்தி
|
46
|
+
ErrorBacktrace: பிழை பின்தேடுலை
|
47
|
+
GoBack: பின்புறம்
|
48
|
+
NoScheduledFound: திட்டமிட்ட வேலைகள் காணப்படவில்லை
|
49
|
+
When: எப்பொழுது?
|
50
|
+
ScheduledJobs: திட்டமிட்ட வேலைகள்
|
51
|
+
idle: முடங்கு நேரம்
|
52
|
+
active: செயலில்
|
53
|
+
Version: பதிப்பு
|
54
|
+
Connections: இணைப்புகள்
|
55
|
+
MemoryUsage: நினைவக பயன்பாடு
|
56
|
+
PeakMemoryUsage: உச்ச நினைவக பயன்பாடு
|
57
|
+
Uptime: இயக்க நேரம் (நாட்கள்)
|
58
|
+
OneWeek: 1 வாரம்
|
59
|
+
OneMonth: 1 மாதம்
|
60
|
+
ThreeMonths: 3 மாதங்கள்
|
61
|
+
SixMonths: 6 மாதங்கள்
|
62
|
+
Failures: தோல்விகள்
|
63
|
+
DeadJobs: டெட் வேலைகள்
|
64
|
+
NoDeadJobsFound: இறந்த வேலை எதுவும் இல்லை
|
65
|
+
Dead: இறந்துபோன
|
66
|
+
Processes: செயல்முறைகள்
|
67
|
+
Thread: நூல்
|
68
|
+
Threads: நூல்கள்
|
69
|
+
Jobs: வேலை வாய்ப்புகள்
|
70
|
+
Paused: தற்காலிக பணிநிறுத்தம்
|
71
|
+
Stop: நிறுத்து
|
72
|
+
Quiet: அமைதியான
|
73
|
+
StopAll: நிறுத்து அனைத்து
|
74
|
+
QuietAll: அமைதியான அனைத்து
|
75
|
+
PollingInterval: வாக்குப்பதிவு இடைவெளி
|
data/web/views/_nav.erb
CHANGED
@@ -1,34 +1,67 @@
|
|
1
1
|
<div class="navbar navbar-default navbar-fixed-top">
|
2
|
-
<div class="
|
3
|
-
<div class="
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
2
|
+
<div class="container-fluid">
|
3
|
+
<div class="navbar-header" data-navbar="static">
|
4
|
+
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar-menu">
|
5
|
+
<span class="icon-bar"></span>
|
6
|
+
<span class="icon-bar"></span>
|
7
|
+
<span class="icon-bar"></span>
|
8
|
+
</button>
|
9
|
+
<div class="navbar-toggle collapsed navbar-livereload">
|
10
|
+
<%= erb :_poll %>
|
11
|
+
<% if Sidekiq::Web.app_url %>
|
12
|
+
<a class="btn btn-inverse" href="<%= Sidekiq::Web.app_url %>">Back to App</a>
|
13
|
+
<% end %>
|
14
|
+
</div>
|
15
|
+
<a class="navbar-brand" href="<%= root_path %>">
|
16
|
+
<%= Sidekiq::NAME %>
|
17
|
+
<%= erb :_status %>
|
18
|
+
</a>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<div class="collapse navbar-collapse" id="navbar-menu">
|
22
|
+
<ul class="nav navbar-nav" data-navbar="static">
|
23
|
+
<% Sidekiq::Web.default_tabs.each do |title, url| %>
|
24
|
+
<% if url == '' %>
|
25
|
+
<li class="<%= current_path == url ? 'active' : '' %>">
|
26
|
+
<a href="<%= root_path %><%= url %>"><%= t(title) %></a>
|
27
|
+
</li>
|
28
|
+
<% else %>
|
29
|
+
<li class="<%= current_path.start_with?(url) ? 'active' : '' %>">
|
30
|
+
<a href="<%= root_path %><%= url %>"><%= t(title) %></a>
|
31
|
+
</li>
|
19
32
|
<% end %>
|
20
|
-
|
21
|
-
|
33
|
+
<% end %>
|
34
|
+
|
35
|
+
<li class="dropdown" data-navbar="dropdown">
|
36
|
+
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">
|
37
|
+
<%= t('Plugins') %> <span class="caret"></span>
|
38
|
+
</a>
|
39
|
+
<ul class="dropdown-menu" role="menu">
|
40
|
+
<% Sidekiq::Web.custom_tabs.each do |title, url| %>
|
41
|
+
<li>
|
22
42
|
<a href="<%= root_path %><%= url %>"><%= t(title) %></a>
|
23
43
|
</li>
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
<a
|
44
|
+
<% end %>
|
45
|
+
</ul>
|
46
|
+
</li>
|
47
|
+
|
48
|
+
<% Sidekiq::Web.custom_tabs.each do |title, url| %>
|
49
|
+
<li class="<%= current_path.start_with?(url) ? 'active' : '' %>" data-navbar="custom-tab">
|
50
|
+
<a href="<%= root_path %><%= url %>"><%= t(title) %></a>
|
51
|
+
</li>
|
31
52
|
<% end %>
|
53
|
+
</ul>
|
54
|
+
<ul class="nav navbar-nav navbar-right navbar-livereload" data-navbar="static">
|
55
|
+
<li>
|
56
|
+
<div class="poll-wrapper pull-right">
|
57
|
+
<%= erb :_poll %>
|
58
|
+
<% if Sidekiq::Web.app_url %>
|
59
|
+
<a class="btn btn-inverse" href="<%= Sidekiq::Web.app_url %>">Back to App</a>
|
60
|
+
<% end %>
|
61
|
+
</div>
|
62
|
+
</li>
|
63
|
+
</ul>
|
32
64
|
</div>
|
33
65
|
</div>
|
34
66
|
</div>
|
67
|
+
</div>
|
data/web/views/_poll.erb
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
<% if current_path != '' %>
|
2
2
|
<% if params[:poll] %>
|
3
3
|
<script>
|
4
|
-
|
4
|
+
updatePage('<%= root_path + current_path %>')
|
5
5
|
</script>
|
6
|
-
<a id="live-poll" class="btn btn-primary active" href="<%= root_path
|
6
|
+
<a id="live-poll" class="btn btn-primary active" href="<%= root_path + current_path %>"><%= t('StopPolling') %></a>
|
7
7
|
<% else %>
|
8
|
-
<a id="live-poll" class="btn btn-primary" href="<%= root_path
|
8
|
+
<a id="live-poll" class="btn btn-primary" href="<%= root_path + current_path %>?<%= qparams(poll: true) %>"><%= t('LivePoll') %></a>
|
9
9
|
<% end %>
|
10
10
|
<% end %>
|
data/web/views/dashboard.erb
CHANGED
@@ -15,12 +15,12 @@
|
|
15
15
|
</div>
|
16
16
|
</div>
|
17
17
|
|
18
|
-
<div class="row">
|
18
|
+
<div class="row chart">
|
19
19
|
<div id="realtime" data-processed-label="<%= t('Processed') %>" data-failed-label="<%= t('Failed') %>"></div>
|
20
20
|
<div id="realtime-legend"></div>
|
21
21
|
</div>
|
22
22
|
|
23
|
-
<div class="row">
|
23
|
+
<div class="row chart">
|
24
24
|
<h5>
|
25
25
|
<span class="history-heading"><%= t('History') %></span>
|
26
26
|
<a href="<%= root_path %>?days=7" class="history-graph <%= "active" if params[:days] == "7" %>"><%= t('OneWeek') %></a>
|
data/web/views/layout.erb
CHANGED
@@ -8,6 +8,7 @@
|
|
8
8
|
<script type="text/javascript" src="<%= root_path %>javascripts/application.js"></script>
|
9
9
|
<script type="text/javascript" src="<%= root_path %>javascripts/locales/jquery.timeago.<%= locale %>.js"></script>
|
10
10
|
<meta name="google" content="notranslate" />
|
11
|
+
<%= display_custom_head %>
|
11
12
|
</head>
|
12
13
|
<body class="admin">
|
13
14
|
<%= erb :_nav %>
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sidekiq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.3.
|
4
|
+
version: 3.3.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Perham
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-
|
11
|
+
date: 2015-04-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: redis
|
@@ -234,6 +234,7 @@ files:
|
|
234
234
|
- test/test_testing_fake.rb
|
235
235
|
- test/test_testing_inline.rb
|
236
236
|
- test/test_web.rb
|
237
|
+
- test/test_web_helpers.rb
|
237
238
|
- test/test_worker_generator.rb
|
238
239
|
- web/assets/images/bootstrap/glyphicons-halflings-white.png
|
239
240
|
- web/assets/images/bootstrap/glyphicons-halflings.png
|
@@ -297,6 +298,7 @@ files:
|
|
297
298
|
- web/locales/en.yml
|
298
299
|
- web/locales/es.yml
|
299
300
|
- web/locales/fr.yml
|
301
|
+
- web/locales/hi.yml
|
300
302
|
- web/locales/it.yml
|
301
303
|
- web/locales/ja.yml
|
302
304
|
- web/locales/ko.yml
|
@@ -307,6 +309,7 @@ files:
|
|
307
309
|
- web/locales/pt.yml
|
308
310
|
- web/locales/ru.yml
|
309
311
|
- web/locales/sv.yml
|
312
|
+
- web/locales/ta.yml
|
310
313
|
- web/locales/zh-cn.yml
|
311
314
|
- web/locales/zh-tw.yml
|
312
315
|
- web/views/_footer.erb
|
@@ -376,4 +379,5 @@ test_files:
|
|
376
379
|
- test/test_testing_fake.rb
|
377
380
|
- test/test_testing_inline.rb
|
378
381
|
- test/test_web.rb
|
382
|
+
- test/test_web_helpers.rb
|
379
383
|
- test/test_worker_generator.rb
|