sidekiq 7.3.10 → 8.0.9
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.
- checksums.yaml +4 -4
- data/Changes.md +125 -4
- data/README.md +16 -13
- data/bin/sidekiqload +10 -10
- data/bin/webload +69 -0
- data/lib/active_job/queue_adapters/sidekiq_adapter.rb +104 -58
- data/lib/generators/sidekiq/templates/job.rb.erb +1 -1
- data/lib/sidekiq/api.rb +142 -44
- data/lib/sidekiq/capsule.rb +10 -6
- data/lib/sidekiq/cli.rb +15 -19
- data/lib/sidekiq/client.rb +28 -17
- data/lib/sidekiq/component.rb +42 -3
- data/lib/sidekiq/config.rb +31 -22
- data/lib/sidekiq/embedded.rb +2 -1
- data/lib/sidekiq/iterable_job.rb +1 -0
- data/lib/sidekiq/job/iterable.rb +46 -18
- data/lib/sidekiq/job.rb +2 -2
- data/lib/sidekiq/job_logger.rb +8 -6
- data/lib/sidekiq/job_retry.rb +33 -10
- data/lib/sidekiq/job_util.rb +5 -1
- data/lib/sidekiq/launcher.rb +16 -6
- data/lib/sidekiq/loader.rb +57 -0
- data/lib/sidekiq/logger.rb +25 -69
- data/lib/sidekiq/manager.rb +0 -1
- data/lib/sidekiq/metrics/query.rb +71 -45
- data/lib/sidekiq/metrics/shared.rb +8 -5
- data/lib/sidekiq/metrics/tracking.rb +12 -7
- data/lib/sidekiq/middleware/current_attributes.rb +11 -19
- data/lib/sidekiq/monitor.rb +4 -8
- data/lib/sidekiq/paginator.rb +8 -1
- data/lib/sidekiq/processor.rb +21 -14
- data/lib/sidekiq/profiler.rb +73 -0
- data/lib/sidekiq/rails.rb +46 -67
- data/lib/sidekiq/redis_client_adapter.rb +0 -1
- data/lib/sidekiq/testing.rb +3 -3
- data/lib/sidekiq/version.rb +2 -2
- data/lib/sidekiq/web/action.rb +146 -83
- data/lib/sidekiq/web/application.rb +361 -330
- data/lib/sidekiq/web/config.rb +120 -0
- data/lib/sidekiq/web/helpers.rb +56 -34
- data/lib/sidekiq/web/router.rb +60 -76
- data/lib/sidekiq/web.rb +51 -156
- data/lib/sidekiq.rb +6 -1
- data/sidekiq.gemspec +6 -6
- data/web/assets/images/logo.png +0 -0
- data/web/assets/images/status.png +0 -0
- data/web/assets/javascripts/application.js +42 -26
- data/web/assets/javascripts/base-charts.js +30 -16
- data/web/assets/javascripts/chartjs-adapter-date-fns.min.js +7 -0
- data/web/assets/javascripts/dashboard.js +1 -1
- data/web/assets/javascripts/metrics.js +16 -34
- data/web/assets/stylesheets/style.css +776 -0
- data/web/locales/ar.yml +2 -0
- data/web/locales/cs.yml +2 -0
- data/web/locales/da.yml +2 -0
- data/web/locales/de.yml +2 -0
- data/web/locales/el.yml +2 -0
- data/web/locales/en.yml +7 -0
- data/web/locales/es.yml +25 -2
- data/web/locales/fa.yml +2 -0
- data/web/locales/fr.yml +2 -0
- data/web/locales/gd.yml +2 -0
- data/web/locales/he.yml +2 -0
- data/web/locales/hi.yml +2 -0
- data/web/locales/it.yml +9 -0
- data/web/locales/ja.yml +2 -0
- data/web/locales/ko.yml +2 -0
- data/web/locales/lt.yml +2 -0
- data/web/locales/nb.yml +2 -0
- data/web/locales/nl.yml +2 -0
- data/web/locales/pl.yml +2 -0
- data/web/locales/{pt-br.yml → pt-BR.yml} +3 -1
- data/web/locales/pt.yml +2 -0
- data/web/locales/ru.yml +2 -0
- data/web/locales/sv.yml +2 -0
- data/web/locales/ta.yml +2 -0
- data/web/locales/tr.yml +2 -0
- data/web/locales/uk.yml +7 -5
- data/web/locales/ur.yml +2 -0
- data/web/locales/vi.yml +2 -0
- data/web/locales/{zh-cn.yml → zh-CN.yml} +86 -73
- data/web/locales/{zh-tw.yml → zh-TW.yml} +3 -1
- data/web/views/_footer.erb +31 -33
- data/web/views/_job_info.erb +91 -89
- data/web/views/_metrics_period_select.erb +13 -10
- data/web/views/_nav.erb +14 -21
- data/web/views/_paging.erb +22 -21
- data/web/views/_poll_link.erb +2 -2
- data/web/views/_summary.erb +16 -16
- data/web/views/busy.erb +123 -125
- data/web/views/dashboard.erb +62 -66
- data/web/views/dead.erb +31 -27
- data/web/views/filtering.erb +3 -3
- data/web/views/layout.erb +12 -28
- data/web/views/metrics.erb +76 -82
- data/web/views/metrics_for_job.erb +45 -46
- data/web/views/morgue.erb +65 -70
- data/web/views/profiles.erb +43 -0
- data/web/views/queue.erb +54 -52
- data/web/views/queues.erb +43 -41
- data/web/views/retries.erb +70 -75
- data/web/views/retry.erb +32 -27
- data/web/views/scheduled.erb +63 -55
- data/web/views/scheduled_job_info.erb +3 -3
- metadata +24 -41
- data/web/assets/stylesheets/application-dark.css +0 -147
- data/web/assets/stylesheets/application-rtl.css +0 -163
- data/web/assets/stylesheets/application.css +0 -759
- data/web/assets/stylesheets/bootstrap-rtl.min.css +0 -9
- data/web/assets/stylesheets/bootstrap.css +0 -5
- data/web/views/_status.erb +0 -4
data/lib/sidekiq/web.rb
CHANGED
|
@@ -2,20 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
require "erb"
|
|
4
4
|
require "securerandom"
|
|
5
|
-
|
|
6
|
-
require "sidekiq"
|
|
7
|
-
require "sidekiq/api"
|
|
8
|
-
require "sidekiq/paginator"
|
|
9
|
-
require "sidekiq/web/helpers"
|
|
10
|
-
|
|
11
|
-
require "sidekiq/web/router"
|
|
12
|
-
require "sidekiq/web/action"
|
|
13
|
-
require "sidekiq/web/application"
|
|
14
|
-
require "sidekiq/web/csrf_protection"
|
|
15
|
-
|
|
16
|
-
require "rack/content_length"
|
|
17
5
|
require "rack/builder"
|
|
18
6
|
require "rack/static"
|
|
7
|
+
require "sidekiq"
|
|
8
|
+
require "sidekiq/api"
|
|
9
|
+
require "sidekiq/web/config"
|
|
19
10
|
|
|
20
11
|
module Sidekiq
|
|
21
12
|
class Web
|
|
@@ -32,176 +23,85 @@ module Sidekiq
|
|
|
32
23
|
"Retries" => "retries",
|
|
33
24
|
"Scheduled" => "scheduled",
|
|
34
25
|
"Dead" => "morgue",
|
|
35
|
-
"Metrics" => "metrics"
|
|
26
|
+
"Metrics" => "metrics",
|
|
27
|
+
"Profiles" => "profiles"
|
|
36
28
|
}
|
|
37
29
|
|
|
38
|
-
|
|
39
|
-
CONTENT_LANGUAGE = "Content-Language"
|
|
40
|
-
CONTENT_SECURITY_POLICY = "Content-Security-Policy"
|
|
41
|
-
LOCATION = "Location"
|
|
42
|
-
X_CASCADE = "X-Cascade"
|
|
43
|
-
X_CONTENT_TYPE_OPTIONS = "X-Content-Type-Options"
|
|
44
|
-
else
|
|
45
|
-
CONTENT_LANGUAGE = "content-language"
|
|
46
|
-
CONTENT_SECURITY_POLICY = "content-security-policy"
|
|
47
|
-
LOCATION = "location"
|
|
48
|
-
X_CASCADE = "x-cascade"
|
|
49
|
-
X_CONTENT_TYPE_OPTIONS = "x-content-type-options"
|
|
50
|
-
end
|
|
30
|
+
@@config = Sidekiq::Web::Config.new
|
|
51
31
|
|
|
52
32
|
class << self
|
|
53
|
-
# Forward compatibility with 8.0
|
|
54
33
|
def configure
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
34
|
+
if block_given?
|
|
35
|
+
yield @@config
|
|
36
|
+
else
|
|
37
|
+
@@config
|
|
38
|
+
end
|
|
60
39
|
end
|
|
61
40
|
|
|
62
|
-
def
|
|
63
|
-
|
|
41
|
+
def app_url=(url)
|
|
42
|
+
@@config.app_url = url
|
|
64
43
|
end
|
|
65
44
|
|
|
66
|
-
def
|
|
67
|
-
@custom_tabs ||= {}
|
|
68
|
-
end
|
|
69
|
-
alias_method :tabs, :custom_tabs
|
|
45
|
+
def tabs = @@config.tabs
|
|
70
46
|
|
|
71
|
-
def
|
|
72
|
-
@custom_job_info_rows ||= []
|
|
73
|
-
end
|
|
47
|
+
def locales = @@config.locales
|
|
74
48
|
|
|
75
|
-
def
|
|
76
|
-
@locales ||= LOCALES
|
|
77
|
-
end
|
|
49
|
+
def views = @@config.views
|
|
78
50
|
|
|
79
|
-
def
|
|
80
|
-
@views ||= VIEWS
|
|
81
|
-
end
|
|
51
|
+
def custom_job_info_rows = @@config.custom_job_info_rows
|
|
82
52
|
|
|
83
|
-
def
|
|
84
|
-
|
|
53
|
+
def redis_pool
|
|
54
|
+
@pool || Sidekiq.default_configuration.redis_pool
|
|
85
55
|
end
|
|
86
56
|
|
|
87
|
-
def
|
|
88
|
-
|
|
57
|
+
def redis_pool=(pool)
|
|
58
|
+
@pool = pool
|
|
89
59
|
end
|
|
90
60
|
|
|
91
|
-
def middlewares
|
|
92
|
-
@middlewares ||= []
|
|
93
|
-
end
|
|
61
|
+
def middlewares = @@config.middlewares
|
|
94
62
|
|
|
95
|
-
def use(*args, &block)
|
|
96
|
-
middlewares << [args, block]
|
|
97
|
-
end
|
|
63
|
+
def use(*args, &block) = @@config.middlewares << [args, block]
|
|
98
64
|
|
|
99
|
-
def
|
|
100
|
-
|
|
65
|
+
def register(*args, **kw, &block)
|
|
66
|
+
Sidekiq.logger.warn { "`Sidekiq::Web.register` is deprecated, use `Sidekiq::Web.configure {|cfg| cfg.register(...) }`" }
|
|
67
|
+
@@config.register(*args, **kw, &block)
|
|
101
68
|
end
|
|
102
|
-
|
|
103
|
-
attr_accessor :app_url, :redis_pool
|
|
104
|
-
attr_writer :locales, :views
|
|
105
|
-
end
|
|
106
|
-
|
|
107
|
-
def self.inherited(child)
|
|
108
|
-
child.app_url = app_url
|
|
109
|
-
child.redis_pool = redis_pool
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
def settings
|
|
113
|
-
self.class.settings
|
|
114
69
|
end
|
|
115
70
|
|
|
116
|
-
|
|
117
|
-
|
|
71
|
+
# Allow user to say
|
|
72
|
+
# run Sidekiq::Web
|
|
73
|
+
# rather than:
|
|
74
|
+
# run Sidekiq::Web.new
|
|
75
|
+
def self.call(env)
|
|
76
|
+
@inst ||= new
|
|
77
|
+
@inst.call(env)
|
|
118
78
|
end
|
|
119
79
|
|
|
120
|
-
|
|
121
|
-
|
|
80
|
+
# testing, internal use only
|
|
81
|
+
def self.reset!
|
|
82
|
+
@@config.reset!
|
|
83
|
+
@inst = nil
|
|
122
84
|
end
|
|
123
85
|
|
|
124
86
|
def call(env)
|
|
125
|
-
env[:
|
|
87
|
+
env[:web_config] = Sidekiq::Web.configure
|
|
88
|
+
env[:csp_nonce] = SecureRandom.hex(8)
|
|
89
|
+
env[:redis_pool] = self.class.redis_pool
|
|
126
90
|
app.call(env)
|
|
127
91
|
end
|
|
128
92
|
|
|
129
|
-
def self.call(env)
|
|
130
|
-
@app ||= new
|
|
131
|
-
@app.call(env)
|
|
132
|
-
end
|
|
133
|
-
|
|
134
93
|
def app
|
|
135
|
-
@app ||= build
|
|
136
|
-
end
|
|
137
|
-
|
|
138
|
-
def enable(*opts)
|
|
139
|
-
opts.each { |key| set(key, true) }
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def disable(*opts)
|
|
143
|
-
opts.each { |key| set(key, false) }
|
|
144
|
-
end
|
|
145
|
-
|
|
146
|
-
def set(attribute, value)
|
|
147
|
-
send(:"#{attribute}=", value)
|
|
148
|
-
end
|
|
149
|
-
|
|
150
|
-
# Register a class as a Sidekiq Web UI extension. The class should
|
|
151
|
-
# provide one or more tabs which map to an index route. Options:
|
|
152
|
-
#
|
|
153
|
-
# @param extension [Class] Class which contains the HTTP actions, required
|
|
154
|
-
# @param name [String] the name of the extension, used to namespace assets
|
|
155
|
-
# @param tab [String | Array] labels(s) of the UI tabs
|
|
156
|
-
# @param index [String | Array] index route(s) for each tab
|
|
157
|
-
# @param root_dir [String] directory location to find assets, locales and views, typically `web/` within the gemfile
|
|
158
|
-
# @param asset_paths [Array] one or more directories under {root}/assets/{name} to be publicly served, e.g. ["js", "css", "img"]
|
|
159
|
-
# @param cache_for [Integer] amount of time to cache assets, default one day
|
|
160
|
-
#
|
|
161
|
-
# TODO name, tab and index will be mandatory in 8.0
|
|
162
|
-
#
|
|
163
|
-
# Web extensions will have a root `web/` directory with `locales/`, `assets/`
|
|
164
|
-
# and `views/` subdirectories.
|
|
165
|
-
def self.register(extension, name: nil, tab: nil, index: nil, root_dir: nil, cache_for: 86400, asset_paths: nil)
|
|
166
|
-
tab = Array(tab)
|
|
167
|
-
index = Array(index)
|
|
168
|
-
tab.zip(index).each do |tab, index|
|
|
169
|
-
tabs[tab] = index
|
|
170
|
-
end
|
|
171
|
-
if root_dir
|
|
172
|
-
locdir = File.join(root_dir, "locales")
|
|
173
|
-
locales << locdir if File.directory?(locdir)
|
|
174
|
-
|
|
175
|
-
if asset_paths && name
|
|
176
|
-
# if you have {root}/assets/{name}/js/scripts.js
|
|
177
|
-
# and {root}/assets/{name}/css/styles.css
|
|
178
|
-
# you would pass in:
|
|
179
|
-
# asset_paths: ["js", "css"]
|
|
180
|
-
# See script_tag and style_tag in web/helpers.rb
|
|
181
|
-
assdir = File.join(root_dir, "assets")
|
|
182
|
-
assurls = Array(asset_paths).map { |x| "/#{name}/#{x}" }
|
|
183
|
-
assetprops = {
|
|
184
|
-
urls: assurls,
|
|
185
|
-
root: assdir,
|
|
186
|
-
cascade: true
|
|
187
|
-
}
|
|
188
|
-
assetprops[:header_rules] = [[:all, {Rack::CACHE_CONTROL => "private, max-age=#{cache_for.to_i}"}]] if cache_for
|
|
189
|
-
middlewares << [[Rack::Static, assetprops], nil]
|
|
190
|
-
end
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
yield self if block_given?
|
|
194
|
-
extension.registered(WebApplication)
|
|
94
|
+
@app ||= build(@@config)
|
|
195
95
|
end
|
|
196
96
|
|
|
197
97
|
private
|
|
198
98
|
|
|
199
|
-
def build
|
|
200
|
-
|
|
201
|
-
m = middlewares
|
|
99
|
+
def build(cfg)
|
|
100
|
+
cfg.freeze
|
|
101
|
+
m = cfg.middlewares
|
|
202
102
|
|
|
203
103
|
rules = []
|
|
204
|
-
rules = [[:all, {
|
|
104
|
+
rules = [[:all, {"cache-control" => "private, max-age=86400"}]] unless ENV["SIDEKIQ_WEB_TESTING"]
|
|
205
105
|
|
|
206
106
|
::Rack::Builder.new do
|
|
207
107
|
use Rack::Static, urls: ["/stylesheets", "/images", "/javascripts"],
|
|
@@ -209,18 +109,13 @@ module Sidekiq
|
|
|
209
109
|
cascade: true,
|
|
210
110
|
header_rules: rules
|
|
211
111
|
m.each { |middleware, block| use(*middleware, &block) }
|
|
212
|
-
use
|
|
213
|
-
run
|
|
112
|
+
use CsrfProtection if cfg[:csrf]
|
|
113
|
+
run Sidekiq::Web::Application.new(self.class)
|
|
214
114
|
end
|
|
215
115
|
end
|
|
216
116
|
end
|
|
217
|
-
|
|
218
|
-
Sidekiq::WebApplication.helpers WebHelpers
|
|
219
|
-
Sidekiq::WebApplication.helpers Sidekiq::Paginator
|
|
220
|
-
|
|
221
|
-
Sidekiq::WebAction.class_eval <<-RUBY, Web::LAYOUT, -1 # standard:disable Style/EvalWithLocation
|
|
222
|
-
def _render
|
|
223
|
-
#{ERB.new(File.read(Web::LAYOUT)).src}
|
|
224
|
-
end
|
|
225
|
-
RUBY
|
|
226
117
|
end
|
|
118
|
+
|
|
119
|
+
require "sidekiq/web/router"
|
|
120
|
+
require "sidekiq/web/action"
|
|
121
|
+
require "sidekiq/web/application"
|
data/lib/sidekiq.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require "sidekiq/version"
|
|
4
|
-
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 2.
|
|
4
|
+
fail "Sidekiq #{Sidekiq::VERSION} does not support Ruby versions below 3.2.0." if RUBY_PLATFORM != "java" && Gem::Version.new(RUBY_VERSION) < Gem::Version.new("3.2.0")
|
|
5
5
|
|
|
6
6
|
begin
|
|
7
7
|
require "sidekiq-ent/version"
|
|
@@ -29,6 +29,7 @@ end
|
|
|
29
29
|
|
|
30
30
|
require "sidekiq/config"
|
|
31
31
|
require "sidekiq/logger"
|
|
32
|
+
require "sidekiq/loader"
|
|
32
33
|
require "sidekiq/client"
|
|
33
34
|
require "sidekiq/transaction_aware_client"
|
|
34
35
|
require "sidekiq/job"
|
|
@@ -94,6 +95,10 @@ module Sidekiq
|
|
|
94
95
|
default_configuration.logger
|
|
95
96
|
end
|
|
96
97
|
|
|
98
|
+
def self.loader
|
|
99
|
+
@loader ||= Loader.new
|
|
100
|
+
end
|
|
101
|
+
|
|
97
102
|
def self.configure_server(&block)
|
|
98
103
|
(@config_blocks ||= []) << block
|
|
99
104
|
yield default_configuration if server?
|
data/sidekiq.gemspec
CHANGED
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |gem|
|
|
|
12
12
|
gem.files = %w[sidekiq.gemspec README.md Changes.md LICENSE.txt] + `git ls-files | grep -E '^(bin|lib|web)'`.split("\n")
|
|
13
13
|
gem.name = "sidekiq"
|
|
14
14
|
gem.version = Sidekiq::VERSION
|
|
15
|
-
gem.required_ruby_version = ">= 2.
|
|
15
|
+
gem.required_ruby_version = ">= 3.2.0"
|
|
16
16
|
|
|
17
17
|
gem.metadata = {
|
|
18
18
|
"homepage_uri" => "https://sidekiq.org",
|
|
@@ -23,9 +23,9 @@ Gem::Specification.new do |gem|
|
|
|
23
23
|
"rubygems_mfa_required" => "true"
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
gem.add_dependency "redis-client", ">= 0.23.
|
|
27
|
-
gem.add_dependency "connection_pool", ">= 2.
|
|
28
|
-
gem.add_dependency "rack", ">=
|
|
29
|
-
gem.add_dependency "
|
|
30
|
-
gem.add_dependency "
|
|
26
|
+
gem.add_dependency "redis-client", ">= 0.23.2"
|
|
27
|
+
gem.add_dependency "connection_pool", ">= 2.5.0"
|
|
28
|
+
gem.add_dependency "rack", ">= 3.1.0"
|
|
29
|
+
gem.add_dependency "json", ">= 2.9.0"
|
|
30
|
+
gem.add_dependency "logger", ">= 1.6.2"
|
|
31
31
|
end
|
data/web/assets/images/logo.png
CHANGED
|
File without changes
|
|
File without changes
|
|
@@ -18,20 +18,12 @@ function addListeners() {
|
|
|
18
18
|
})
|
|
19
19
|
});
|
|
20
20
|
|
|
21
|
-
document.querySelectorAll("input[data-confirm]").forEach(node => {
|
|
22
|
-
node.addEventListener("click", event => {
|
|
23
|
-
if (!window.confirm(node.getAttribute("data-confirm"))) {
|
|
24
|
-
event.preventDefault();
|
|
25
|
-
event.stopPropagation();
|
|
26
|
-
}
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
21
|
document.querySelectorAll("[data-toggle]").forEach(node => {
|
|
31
22
|
node.addEventListener("click", addDataToggleListeners)
|
|
32
23
|
})
|
|
33
24
|
|
|
34
|
-
|
|
25
|
+
initializeBulkToggle();
|
|
26
|
+
addShiftClickListeners();
|
|
35
27
|
updateFuzzyTimes();
|
|
36
28
|
updateNumbers();
|
|
37
29
|
updateProgressBars();
|
|
@@ -67,13 +59,24 @@ function addPollingListeners(_event) {
|
|
|
67
59
|
|
|
68
60
|
function addDataToggleListeners(event) {
|
|
69
61
|
var source = event.target || event.srcElement;
|
|
70
|
-
var targName = source.
|
|
62
|
+
var targName = source.dataset.toggle;
|
|
71
63
|
var full = document.getElementById(targName);
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
64
|
+
full.classList.toggle("is-open");
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function toggleBulkButtons() {
|
|
68
|
+
const checkboxes = document.querySelectorAll('.select-item-checkbox, .check-all-items');
|
|
69
|
+
const anyChecked = Array.from(checkboxes).some(cb => cb.checked);
|
|
70
|
+
const buttons = document.querySelectorAll('.bulk-action-buttons');
|
|
71
|
+
buttons.forEach(btn => {
|
|
72
|
+
btn.style.display = anyChecked ? 'none' : 'block';
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function initializeBulkToggle(){
|
|
77
|
+
document.querySelectorAll('.check-all-items, .select-item-checkbox').forEach(cb => {
|
|
78
|
+
cb.addEventListener('change', toggleBulkButtons);
|
|
79
|
+
});
|
|
77
80
|
}
|
|
78
81
|
|
|
79
82
|
function addShiftClickListeners() {
|
|
@@ -94,7 +97,7 @@ function addShiftClickListeners() {
|
|
|
94
97
|
}
|
|
95
98
|
|
|
96
99
|
function updateFuzzyTimes() {
|
|
97
|
-
var locale = document.body.
|
|
100
|
+
var locale = document.body.dataset.locale;
|
|
98
101
|
var parts = locale.split('-');
|
|
99
102
|
if (typeof parts[1] !== 'undefined') {
|
|
100
103
|
parts[1] = parts[1].toUpperCase();
|
|
@@ -109,7 +112,7 @@ function updateFuzzyTimes() {
|
|
|
109
112
|
function updateNumbers() {
|
|
110
113
|
document.querySelectorAll("[data-nwp]").forEach(node => {
|
|
111
114
|
let number = parseFloat(node.textContent);
|
|
112
|
-
let precision = parseInt(node.dataset
|
|
115
|
+
let precision = parseInt(node.dataset.nwp || 0);
|
|
113
116
|
if (typeof number === "number") {
|
|
114
117
|
let formatted = number.toLocaleString(undefined, {
|
|
115
118
|
minimumFractionDigits: precision,
|
|
@@ -130,11 +133,11 @@ function setLivePollFromUrl() {
|
|
|
130
133
|
|
|
131
134
|
function updateLivePollButton() {
|
|
132
135
|
if (localStorage.sidekiqLivePoll == "enabled") {
|
|
133
|
-
document.querySelectorAll('.live-poll-stop').forEach(box => { box.
|
|
134
|
-
document.querySelectorAll('.live-poll-start').forEach(box => { box.
|
|
136
|
+
document.querySelectorAll('.live-poll-stop').forEach(box => { box.classList.add("active") })
|
|
137
|
+
document.querySelectorAll('.live-poll-start').forEach(box => { box.classList.remove("active") })
|
|
135
138
|
} else {
|
|
136
|
-
document.querySelectorAll('.live-poll-start').forEach(box => { box.
|
|
137
|
-
document.querySelectorAll('.live-poll-stop').forEach(box => { box.
|
|
139
|
+
document.querySelectorAll('.live-poll-start').forEach(box => { box.classList.add("active") })
|
|
140
|
+
document.querySelectorAll('.live-poll-stop').forEach(box => { box.classList.remove("active") })
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
143
|
|
|
@@ -169,9 +172,6 @@ function replacePage(text) {
|
|
|
169
172
|
var page = doc.querySelector('#page')
|
|
170
173
|
document.querySelector("#page").replaceWith(page)
|
|
171
174
|
|
|
172
|
-
var header_status = doc.querySelector('.status')
|
|
173
|
-
document.querySelector('.status').replaceWith(header_status)
|
|
174
|
-
|
|
175
175
|
addListeners();
|
|
176
176
|
}
|
|
177
177
|
|
|
@@ -185,4 +185,20 @@ function updateLocale(event) {
|
|
|
185
185
|
|
|
186
186
|
function updateProgressBars() {
|
|
187
187
|
document.querySelectorAll('.progress-bar').forEach(bar => { bar.style.width = bar.dataset.width + "%"})
|
|
188
|
-
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
function handleConfirmDialog (event) {
|
|
191
|
+
const target = event.target
|
|
192
|
+
|
|
193
|
+
if (target.localName !== "input") { return }
|
|
194
|
+
const confirmMessage = target.dataset.confirm
|
|
195
|
+
|
|
196
|
+
if (confirmMessage === undefined) { return }
|
|
197
|
+
|
|
198
|
+
if (!window.confirm(confirmMessage)) {
|
|
199
|
+
event.preventDefault()
|
|
200
|
+
event.stopPropagation()
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
document.addEventListener("click", handleConfirmDialog)
|
|
@@ -1,27 +1,35 @@
|
|
|
1
1
|
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
2
2
|
Chart.defaults.borderColor = "#333";
|
|
3
3
|
Chart.defaults.color = "#aaa";
|
|
4
|
+
// Chart.defaults.borderColor = "oklch(22% 0.01 256)";
|
|
5
|
+
// Chart.defaults.color = "oklch(65% 0.01 256)";
|
|
4
6
|
}
|
|
5
7
|
|
|
6
8
|
class Colors {
|
|
7
9
|
constructor() {
|
|
8
10
|
this.assignments = {};
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
12
|
+
this.light = "65%";
|
|
13
|
+
this.chroma = "0.15";
|
|
14
|
+
} else {
|
|
15
|
+
this.light = "48%";
|
|
16
|
+
this.chroma = "0.2";
|
|
17
|
+
}
|
|
18
|
+
this.success = "oklch(" + this.light + " " + this.chroma + " 179)";
|
|
19
|
+
this.failure = "oklch(" + this.light + " " + this.chroma + " 29)";
|
|
20
|
+
this.fallback = "oklch(" + this.light + " 0.02 269)";
|
|
21
|
+
this.primary = "oklch(" + this.light + " " + this.chroma + " 269)";
|
|
13
22
|
this.available = [
|
|
14
|
-
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
"
|
|
18
|
-
"
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
24
|
-
"#991b1b",
|
|
23
|
+
"oklch(" + this.light + " " + this.chroma + " 256)",
|
|
24
|
+
"oklch(" + this.light + " " + this.chroma + " 196)",
|
|
25
|
+
"oklch(" + this.light + " " + this.chroma + " 46)",
|
|
26
|
+
"oklch(" + this.light + " " + this.chroma + " 316)",
|
|
27
|
+
"oklch(" + this.light + " " + this.chroma + " 106)",
|
|
28
|
+
"oklch(" + this.light + " " + this.chroma + " 226)",
|
|
29
|
+
"oklch(" + this.light + " " + this.chroma + " 136)",
|
|
30
|
+
"oklch(" + this.light + " 0.02 269)",
|
|
31
|
+
"oklch(" + this.light + " " + this.chroma + " 286)",
|
|
32
|
+
"oklch(" + this.light + " " + this.chroma + " 16)",
|
|
25
33
|
];
|
|
26
34
|
}
|
|
27
35
|
|
|
@@ -90,12 +98,18 @@ class BaseChart {
|
|
|
90
98
|
};
|
|
91
99
|
|
|
92
100
|
if (this.options.marks) {
|
|
101
|
+
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
|
|
102
|
+
this.Borderlight = "30%";
|
|
103
|
+
} else {
|
|
104
|
+
this.Borderlight = "65%";
|
|
105
|
+
}
|
|
106
|
+
|
|
93
107
|
this.options.marks.forEach(([bucket, label], i) => {
|
|
94
108
|
chartOptions.plugins.annotation.annotations[`deploy-${i}`] = {
|
|
95
109
|
type: "line",
|
|
96
110
|
xMin: bucket,
|
|
97
111
|
xMax: bucket,
|
|
98
|
-
borderColor: "
|
|
112
|
+
borderColor: "oklch(" + this.Borderlight + " 0.01 256)",
|
|
99
113
|
borderWidth: 2,
|
|
100
114
|
};
|
|
101
115
|
});
|