mirror of
https://github.com/mperham/sidekiq.git
synced 2022-11-09 13:52:34 -05:00
Persist live poll status in browser localStorage (#4976)
* Persist live poll status in browser localStorage * Prefix localStorage variables with 'sidekiq' * Minor fix for default handling in localStorage timeInterval parsing
This commit is contained in:
parent
8e36432662
commit
84dd20d397
8 changed files with 80 additions and 58 deletions
|
@ -70,17 +70,6 @@ module Sidekiq
|
||||||
@head_html.join if defined?(@head_html)
|
@head_html.join if defined?(@head_html)
|
||||||
end
|
end
|
||||||
|
|
||||||
def poll_path
|
|
||||||
if current_path != "" && params["poll"]
|
|
||||||
path = root_path + current_path
|
|
||||||
query_string = to_query_string(params.slice(*params.keys - %w[page poll]))
|
|
||||||
path += "?#{query_string}" unless query_string.empty?
|
|
||||||
path
|
|
||||||
else
|
|
||||||
""
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def text_direction
|
def text_direction
|
||||||
get_locale["TextDirection"] || "ltr"
|
get_locale["TextDirection"] || "ltr"
|
||||||
end
|
end
|
||||||
|
@ -203,7 +192,7 @@ module Sidekiq
|
||||||
[score.to_f, jid]
|
[score.to_f, jid]
|
||||||
end
|
end
|
||||||
|
|
||||||
SAFE_QPARAMS = %w[page poll direction]
|
SAFE_QPARAMS = %w[page direction]
|
||||||
|
|
||||||
# Merge options with current params, filter safe params, and stringify to query string
|
# Merge options with current params, filter safe params, and stringify to query string
|
||||||
def qparams(options)
|
def qparams(options)
|
||||||
|
|
|
@ -428,12 +428,6 @@ describe Sidekiq::Web do
|
||||||
assert_match(/#{msg['args'][2]}/, last_response.body)
|
assert_match(/#{msg['args'][2]}/, last_response.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calls updatePage() once when polling' do
|
|
||||||
get '/busy?poll=true'
|
|
||||||
assert_equal 200, last_response.status
|
|
||||||
assert_equal 1, last_response.body.scan('data-poll-path="/busy').count
|
|
||||||
end
|
|
||||||
|
|
||||||
it 'escape job args and error messages' do
|
it 'escape job args and error messages' do
|
||||||
# on /retries page
|
# on /retries page
|
||||||
params = add_xss_retry
|
params = add_xss_retry
|
||||||
|
@ -647,12 +641,6 @@ describe Sidekiq::Web do
|
||||||
assert_equal 200, last_response.status
|
assert_equal 200, last_response.status
|
||||||
assert_match(/#{params.first['args'][2]}/, last_response.body)
|
assert_match(/#{params.first['args'][2]}/, last_response.body)
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'handles bad query input' do
|
|
||||||
get '/queues/foo?page=B<H'
|
|
||||||
assert_equal 200, last_response.status
|
|
||||||
assert_match(/B%3CH/, last_response.body)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_scheduled
|
def add_scheduled
|
||||||
|
|
|
@ -109,4 +109,19 @@ class TestWebHelpers < Minitest::Test
|
||||||
s = o.display_args(nil)
|
s = o.display_args(nil)
|
||||||
assert_equal "Invalid job payload, args is nil", s
|
assert_equal "Invalid job payload, args is nil", s
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_to_query_string_escapes_bad_query_input
|
||||||
|
obj = Helpers.new
|
||||||
|
assert_equal "page=B%3CH", obj.to_query_string("page" => "B<H")
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_qparams_string_escapes_bad_query_input
|
||||||
|
obj = Helpers.new
|
||||||
|
obj.instance_eval do
|
||||||
|
def params
|
||||||
|
{ "direction" => "H>B" }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
assert_equal "direction=H%3EB&page=B%3CH", obj.qparams("page" => "B<H")
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,13 +16,9 @@
|
||||||
|
|
||||||
Sidekiq = {};
|
Sidekiq = {};
|
||||||
|
|
||||||
$(function() {
|
var livePollTimer = null;
|
||||||
var pollpath = $('body').data('poll-path');
|
|
||||||
if (pollpath != "") {
|
|
||||||
var ti = parseInt(localStorage.timeInterval) || 2000;
|
|
||||||
setTimeout(function(){updatePage(pollpath)}, ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
$(function() {
|
||||||
$(document).on('click', '.check_all', function() {
|
$(document).on('click', '.check_all', function() {
|
||||||
$('input[type=checkbox]', $(this).closest('table')).prop('checked', this.checked);
|
$('input[type=checkbox]', $(this).closest('table')).prop('checked', this.checked);
|
||||||
});
|
});
|
||||||
|
@ -36,6 +32,26 @@ $(function() {
|
||||||
});
|
});
|
||||||
|
|
||||||
updateFuzzyTimes($('body').data('locale'));
|
updateFuzzyTimes($('body').data('locale'));
|
||||||
|
|
||||||
|
if ($(".live-poll").length > 0) { // set up live poll only when button is present
|
||||||
|
$(document).on("click", ".live-poll", function() {
|
||||||
|
if (localStorage.sidekiqLivePoll == "enabled") {
|
||||||
|
localStorage.sidekiqLivePoll = "disabled";
|
||||||
|
clearTimeout(livePollTimer);
|
||||||
|
livePollTimer = null;
|
||||||
|
} else {
|
||||||
|
localStorage.sidekiqLivePoll = "enabled";
|
||||||
|
livePollCallback();
|
||||||
|
}
|
||||||
|
|
||||||
|
updateLivePollButton();
|
||||||
|
});
|
||||||
|
|
||||||
|
updateLivePollButton();
|
||||||
|
if (localStorage.sidekiqLivePoll == "enabled") {
|
||||||
|
scheduleLivePoll();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
function updateFuzzyTimes(locale) {
|
function updateFuzzyTimes(locale) {
|
||||||
|
@ -50,11 +66,35 @@ function updateFuzzyTimes(locale) {
|
||||||
t.cancel();
|
t.cancel();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updatePage(url) {
|
function updateLivePollButton() {
|
||||||
|
if (localStorage.sidekiqLivePoll == "enabled") {
|
||||||
|
$('.live-poll-stop').show();
|
||||||
|
$('.live-poll-start').hide();
|
||||||
|
} else {
|
||||||
|
$('.live-poll-start').show();
|
||||||
|
$('.live-poll-stop').hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function livePollCallback() {
|
||||||
|
clearTimeout(livePollTimer);
|
||||||
|
|
||||||
$.ajax({
|
$.ajax({
|
||||||
url: url,
|
url: document.url,
|
||||||
dataType: 'html'
|
dataType: 'html'
|
||||||
}).done(function(data) {
|
}).done(
|
||||||
|
replacePage
|
||||||
|
).complete(
|
||||||
|
scheduleLivePoll
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
function scheduleLivePoll() {
|
||||||
|
let ti = parseInt(localStorage.sidekiqTimeInterval) || 5000;
|
||||||
|
livePollTimer = setTimeout(livePollCallback, ti);
|
||||||
|
}
|
||||||
|
|
||||||
|
function replacePage(data) {
|
||||||
$data = $(data)
|
$data = $(data)
|
||||||
|
|
||||||
var $page = $data.filter('#page')
|
var $page = $data.filter('#page')
|
||||||
|
@ -64,13 +104,6 @@ function updatePage(url) {
|
||||||
$('.status').replaceWith($header_status)
|
$('.status').replaceWith($header_status)
|
||||||
|
|
||||||
updateFuzzyTimes($('body').data('locale'));
|
updateFuzzyTimes($('body').data('locale'));
|
||||||
|
|
||||||
var ti = parseInt(localStorage.timeInterval) || 2000;
|
|
||||||
setTimeout(function(){updatePage(url)}, ti)
|
|
||||||
}).fail(function() {
|
|
||||||
var ti = parseInt(localStorage.timeInterval) || 2000;
|
|
||||||
setTimeout(function(){updatePage(url)}, ti)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$(function() {
|
$(function() {
|
||||||
|
|
|
@ -17,7 +17,7 @@ var nodes=vis.selectAll("path").data(series.stack.filter(function(d){return d.y!
|
||||||
|
|
||||||
var poller;
|
var poller;
|
||||||
var realtimeGraph = function(updatePath) {
|
var realtimeGraph = function(updatePath) {
|
||||||
var timeInterval = parseInt(localStorage.timeInterval || '5000');
|
var timeInterval = parseInt(localStorage.sidekiqTimeInterval) || 5000;
|
||||||
var graphElement = document.getElementById("realtime");
|
var graphElement = document.getElementById("realtime");
|
||||||
|
|
||||||
var graph = new Rickshaw.Graph( {
|
var graph = new Rickshaw.Graph( {
|
||||||
|
@ -246,14 +246,14 @@ var setSliderLabel = function(val) {
|
||||||
$(function(){
|
$(function(){
|
||||||
renderGraphs();
|
renderGraphs();
|
||||||
|
|
||||||
if (typeof localStorage.timeInterval !== 'undefined'){
|
if (typeof localStorage.sidekiqTimeInterval !== 'undefined'){
|
||||||
$('div.interval-slider input').val(localStorage.timeInterval);
|
$('div.interval-slider input').val(localStorage.sidekiqTimeInterval);
|
||||||
setSliderLabel(localStorage.timeInterval);
|
setSliderLabel(localStorage.sidekiqTimeInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
$(document).on('change', 'div.interval-slider input', function(){
|
$(document).on('change', 'div.interval-slider input', function(){
|
||||||
clearInterval(poller);
|
clearInterval(poller);
|
||||||
localStorage.timeInterval = $(this).val();
|
localStorage.sidekiqTimeInterval = $(this).val();
|
||||||
setSliderLabel($(this).val());
|
setSliderLabel($(this).val());
|
||||||
resetGraphs();
|
resetGraphs();
|
||||||
renderGraphs();
|
renderGraphs();
|
||||||
|
|
|
@ -98,10 +98,10 @@ header.row .pagination {
|
||||||
.poll-wrapper {
|
.poll-wrapper {
|
||||||
margin: 9px;
|
margin: 9px;
|
||||||
}
|
}
|
||||||
#live-poll.active {
|
.live-poll.active {
|
||||||
background-color: #009300;
|
background-color: #009300;
|
||||||
}
|
}
|
||||||
#live-poll.active:hover {
|
.live-poll.active:hover {
|
||||||
background-color: #777;
|
background-color: #777;
|
||||||
}
|
}
|
||||||
.summary_bar ul {
|
.summary_bar ul {
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
<% if current_path != '' %>
|
<% if current_path != '' %>
|
||||||
<% if params[:poll] %>
|
<a class="live-poll-start live-poll btn btn-primary"><%= t('LivePoll') %></a>
|
||||||
<a id="live-poll" class="btn btn-primary active" href="<%= root_path + current_path %>"><%= t('StopPolling') %></a>
|
<a class="live-poll-stop live-poll btn btn-primary active"><%= t('StopPolling') %></a>
|
||||||
<% else %>
|
|
||||||
<a id="live-poll" class="btn btn-primary" href="<%= root_path + current_path %>?<%= qparams(poll: true) %>"><%= t('LivePoll') %></a>
|
|
||||||
<% end %>
|
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
<meta name="google" content="notranslate" />
|
<meta name="google" content="notranslate" />
|
||||||
<%= display_custom_head %>
|
<%= display_custom_head %>
|
||||||
</head>
|
</head>
|
||||||
<body class="admin" data-poll-path="<%= poll_path %>" data-locale="<%= locale %>">
|
<body class="admin" data-locale="<%= locale %>">
|
||||||
<%= erb :_nav %>
|
<%= erb :_nav %>
|
||||||
<div id="page">
|
<div id="page">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
|
|
Loading…
Add table
Reference in a new issue