Commit ae9113ce authored by Marek Vavrusa's avatar Marek Vavrusa
Browse files

modules/http: reworked metrics interface

* the dygraphs are now leveraged for drawing as
  canvas based drawing is much faster than
  svg based rickshaw
* refreshed theme and layouts, code cleanup
parent 66fc8a09
...@@ -184,7 +184,7 @@ $(function() { ...@@ -184,7 +184,7 @@ $(function() {
const ws = new Socket(wsStats); const ws = new Socket(wsStats);
var lastRateUpdate = Date.now(); var lastRateUpdate = Date.now();
ws.onmessage = function(evt) { ws.onmessage = function(evt) {
var data = $.parseJSON(evt.data); var data = JSON.parse(evt.data);
/* Update heartbeat clock */ /* Update heartbeat clock */
var now = Date.now(); var now = Date.now();
var dt = now - lastRateUpdate; var dt = now - lastRateUpdate;
...@@ -201,7 +201,7 @@ $(function() { ...@@ -201,7 +201,7 @@ $(function() {
if (diff > 0) { if (diff > 0) {
/* Normalize difference to heartbeat (in msecs) */ /* Normalize difference to heartbeat (in msecs) */
const rate = Math.ceil((1000 * diff) / dt); const rate = Math.ceil((1000 * diff) / dt);
badge.text(Rickshaw.Fixtures.Number.formatKMBT(rate) + ' pps'); badge.text(rate + ' pps');
} }
} }
} }
......
...@@ -272,14 +272,12 @@ function M.config(conf) ...@@ -272,14 +272,12 @@ function M.config(conf)
-- Export snippet -- Export snippet
http.snippets['/daf'] = {'Application Firewall', [[ http.snippets['/daf'] = {'Application Firewall', [[
<script type="text/javascript" src="daf.js"></script> <script type="text/javascript" src="daf.js"></script>
<div class="row"> <div class="row" style="margin-bottom: 5px">
<form id="daf-builder-form"> <form id="daf-builder-form">
<div class="input-group"> <div class="col-md-11">
<input type="text" id="daf-builder" class="form-control" aria-label="..." /> <input type="text" id="daf-builder" class="form-control" aria-label="..." />
<div class="input-group-btn">
<button type="button" id="daf-add" class="btn btn-default" style="margin-top: -5px;">Add</button>
</div>
</div> </div>
<button type="button" id="daf-add" class="btn btn-default btn-sm">Add</button>
</form> </form>
</div> </div>
<div class="row"> <div class="row">
......
...@@ -46,16 +46,13 @@ local pages = { ...@@ -46,16 +46,13 @@ local pages = {
'd3.js', 'd3.js',
'topojson.js', 'topojson.js',
'datamaps.world.min.js', 'datamaps.world.min.js',
'rickshaw.min.js', 'dygraph-combined.js',
'rickshaw.min.css',
'selectize.min.js', 'selectize.min.js',
'selectize.min.css', 'selectize.min.css',
'selectize.bootstrap3.min.css', 'selectize.bootstrap3.min.css',
'bootstrap.min.js', 'bootstrap.min.js',
'bootstrap.min.css', 'bootstrap.min.css',
'bootstrap.min.css.map',
'bootstrap-theme.min.css', 'bootstrap-theme.min.css',
'bootstrap-theme.min.css.map',
'glyphicons-halflings-regular.woff2', 'glyphicons-halflings-regular.woff2',
} }
...@@ -120,11 +117,11 @@ local function serve(h, stream) ...@@ -120,11 +117,11 @@ local function serve(h, stream)
if type(data) == 'number' then return tostring(data), err end if type(data) == 'number' then return tostring(data), err end
-- Methods other than GET require handler to be closure -- Methods other than GET require handler to be closure
elseif h:get(':method') ~= 'GET' then elseif h:get(':method') ~= 'GET' then
return '501' return '501', ''
end end
if type(data) == 'table' then data = tojson(data) end if type(data) == 'table' then data = tojson(data) end
if not mime or type(data) ~= 'string' then if not mime or type(data) ~= 'string' then
return '404' return '404', ''
else else
-- Serve content type appropriately -- Serve content type appropriately
hsend:append(':status', '200') hsend:append(':status', '200')
...@@ -167,7 +164,9 @@ local function route(endpoints) ...@@ -167,7 +164,9 @@ local function route(endpoints)
else else
local ok, err, reason = pcall(serve, h, stream) local ok, err, reason = pcall(serve, h, stream)
if not ok or err then if not ok or err then
log('[http] %s %s: %s (%s)', m, path, err or '500', reason) if err ~= '404' then
log('[http] %s %s: %s (%s)', m, path, err or '500', reason)
end
-- Method is not supported -- Method is not supported
local hsend = headers.new() local hsend = headers.new()
hsend:append(':status', err or '500') hsend:append(':status', err or '500')
......
{"version":3,"sources":["less/theme.less","less/mixins/vendor-prefixes.less","less/mixins/gradients.less","less/mixins/reset-filter.less"],"names":[],"mappings":"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"}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This diff is collapsed.
This diff is collapsed.
...@@ -29,40 +29,3 @@ body { ...@@ -29,40 +29,3 @@ body {
border-color: #4cae4c !important; border-color: #4cae4c !important;
color: #fff !important; color: #fff !important;
} }
/*
* Graphs and maps.
*/
#stats { height: 350px; display: block; }
#chart {
display: inline-block;
left: 60px;
}
#legend {
background-color: white;
}
#legend .label {
color: #404040;
}
#legend .action {
color: black;
opacity: 0.5;
}
#legend ul {
padding: 0;
}
#legend_container h3 {
margin-top: 0;
}
#y_axis {
position: absolute;
width: 60px;
height: 350px;
}
#legend_container {
float: right;
width: 140px;
}
#chart_container {
float: left;
}
\ No newline at end of file
var colours = ['#ffffd9','#edf8b1','#c7e9b4','#7fcdbb','#41b6c4','#1d91c0','#225ea8','#253494','#081d58']; var colours = ["#081d58", "#253494", "#225ea8", "#1d91c0", "#41b6c4", "#7fcdbb", "#c7e9b4", "#edf8b1", "#edf8b1"];
var latency = ['1ms', '10ms', '50ms', '100ms', '250ms', '500ms', '1000ms', '1500ms', 'slow']; var latency = ["slow", "1500ms", "1000ms", "500ms", "250ms", "100ms", "50ms", "10ms", "1ms"];
var palette = new Rickshaw.Color.Palette( { scheme: 'colorwheel' } );
var Socket = "MozWebSocket" in window ? MozWebSocket : WebSocket; var Socket = "MozWebSocket" in window ? MozWebSocket : WebSocket;
$(function() { $(function() {
/* Helper functions */
function colorBracket(rtt) {
for (var i = latency.length - 1; i >= 0; i--) {
if (rtt <= parseInt(latency[i])) {
return 'q' + i;
}
}
return 'q8';
}
function toGeokey(lon, lat) {
return lon.toFixed(0)+'#'+lat.toFixed(0);
}
function updateVisibility(graph, metrics, id, toggle) {
/* Some labels are aggregates */
if (metrics[id] == null) {
for (var key in metrics) {
const m = metrics[key];
if (m.length > 3 && m[3] == id) {
graph.setVisibility(m[0], toggle);
}
}
} else {
graph.setVisibility(metrics[id][0], toggle);
}
}
/* Initialize snippets. */ /* Initialize snippets. */
$('section').each(function () { $('section').each(function () {
const heading = $(this).find('h2'); const heading = $(this).find('h2');
$('#modules-dropdown').append('<li><a href="#'+this.id+'">'+heading.text()+'</a></li>'); $('#modules-dropdown').append('<li><a href="#'+this.id+'">'+heading.text()+'</a></li>');
}); });
/* Latency has its own palette */
var series = []; /* Render other interesting metrics as lines (hidden by default) */
var data = []; var data = [];
function pushSeries(name, color) { var last_metric = 15;
data[name] = []; var metrics = {
var s = { 'answer.noerror': [0, 'NOERROR', null, 'By RCODE'],
name: name, 'answer.nodata': [1, 'NODATA', null, 'By RCODE'],
color: color, 'answer.nxdomain': [2, 'NXDOMAIN', null, 'By RCODE'],
data: data[name], 'answer.servfail': [3, 'SERVFAIL', null, 'By RCODE'],
stroke: true, 'answer.dnssec': [4, 'DNSSEC', null, 'By RCODE'],
preserve: true 'cache.hit': [5, 'Cache hit'],
} 'cache.miss': [6, 'Cache miss'],
series.push(s); 'cache.insert': [7, 'Cache insert'],
return s; 'cache.delete': [8, 'Cache delete'],
} 'worker.udp': [9, 'Outgoing UDP'],
'worker.tcp': [10, 'Outgoing TCP'],
'worker.ipv4': [11, 'Outgoing IPv4'],
'worker.ipv6': [12, 'Outgoing IPv6'],
'worker.concurrent': [13, 'Queries outstanding'],
'worker.queries': [14, 'Queries received/s'],
'worker.dropped': [15, 'Queries dropped'],
};
/* Render latency metrics as sort of a heatmap */ /* Render latency metrics as sort of a heatmap */
var series = {};
for (var i in latency) { for (var i in latency) {
var s = pushSeries('answer.'+latency[i], colours[colours.length - i - 1]); const name = 'RTT '+latency[i];
s.name = 'RTT '+latency[i]; const colour = colours[colours.length - i - 1];
s.renderer = 'bar'; last_metric = last_metric + 1;
metrics['answer.'+latency[i]] = [last_metric, name, colour, 'latency'];
series[name] = {fillGraph: true, color: colour, fillAlpha: 1.0};
} }
/* Render other interesting metrics as lines (hidden by default) */ var labels = ['x'];
var metrics = { var visibility = [];
'answer.noerror': 'NOERROR',
'answer.nodata': 'NODATA',
'answer.nxdomain': 'NXDOMAIN',
'answer.servfail': 'SERVFAIL',
'answer.dnssec': 'DNSSEC',
'cache.hit': 'Cache hit',
'cache.miss': 'Cache miss',
'worker.udp': 'Outgoing UDP',
'worker.tcp': 'Outgoing TCP',
'worker.ipv4': 'Outgoing IPv4',
'worker.ipv6': 'Outgoing IPv6',
};
for (var key in metrics) { for (var key in metrics) {
var s = pushSeries(key, palette.color()); labels.push(metrics[key][1]);
s.name = metrics[key]; visibility.push(false);
s.renderer = 'line';
s.disabled = true;
} }
/* Define how graph looks like. */ /* Define how graph looks like. */
var graphContainer = $('#stats'); const graphContainer = $('#stats');
var graph = new Rickshaw.Graph( { const graph = new Dygraph(
element: document.getElementById('chart'), document.getElementById("chart"),
height: 350, data, {
width: graphContainer.innerWidth() - 200, labels: labels,
renderer: 'multi', labelsUTC: true,
series: series, labelsShowZeroValues: false,
}); visibility: visibility,
var y_axis = new Rickshaw.Graph.Axis.Y( { axes: { y: {
graph: graph, axisLabelFormatter: function(d) {
orientation: 'left', return d + ' pps';
ticksTreatment: 'glow', },
tickFormat: function (y) { }},
return Rickshaw.Fixtures.Number.formatKMBT(y) + ' pps'; series: series,
}, strokeWidth: 1,
element: document.querySelector("#y_axis") highlightSeriesOpts: {
} ); strokeWidth: 3,
var graphHover = new Rickshaw.Graph.HoverDetail({graph: graph}); strokeBorderWidth: 1,
var legend = new Rickshaw.Graph.Legend({ highlightCircleSize: 5,
graph: graph, },
element: document.querySelector("#legend")
});
var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight( {
graph: graph,
legend: legend
} );
var shelving = new Rickshaw.Graph.Behavior.Series.Toggle( {
graph: graph,
legend: legend
} );
/* Somehow follow the responsive design. */
$(window).on('resize', function(){
graph.configure({
width: graphContainer.innerWidth() - 200,
}); });
graph.render(); /* Define metric selector */
}); const chartSelector = $('#chart-selector').selectize({
graph.render(); maxItems: null,
create: false,
onItemAdd: function (x) { updateVisibility(graph, metrics, x, true); },
onItemRemove: function (x) { updateVisibility(graph, metrics, x, false); }
})[0].selectize;
for (var key in metrics) {
const m = metrics[key];
const groupid = m.length > 3 ? m[3] : key.split('.')[0];
const group = m.length > 3 ? m[3] : m[1].split(' ')[0];
/* Latency has a special aggregated item */
if (group != 'latency') {
chartSelector.addOptionGroup(groupid, { label: group } );
chartSelector.addOption({ text: m[1], value: key, optgroup: groupid });
}
}
/* Add latency as default */
chartSelector.addOption({ text: 'Latency', value: 'latency', optgroup: 'Queries' });
chartSelector.addItem('latency');
/* Add stacked graph control */
$('#chart-stacked').on('change', function(e) {
graph.updateOptions({stackedGraph: this.checked});
}).click();
/* Data map */ /* Data map */
var fills = { defaultFill: '#F5F5F5' }; var fills = { defaultFill: '#F5F5F5' };
for (var i in colours) { for (var i in colours) {
fills['q' + i] = colours[colours.length - 1 - i]; fills['q' + i] = colours[i];
} }
var map = new Datamap({ const map = new Datamap({
element: document.getElementById('map'), element: document.getElementById('map'),
fills: fills, fills: fills,
data: {}, data: {},
...@@ -121,34 +151,22 @@ $(function() { ...@@ -121,34 +151,22 @@ $(function() {
} }
} }
}); });
function colorBracket(rtt) {
for (var i in latency) {
if (rtt <= parseInt(latency[i])) {
return 'q' + i;
}
}
return 'q8';
}
function togeokey(lon, lat) {
return lon.toFixed(0)+'#'+lat.toFixed(0);
}
/* Realtime updates over WebSockets */ /* Realtime updates over WebSockets */
function pushMetrics(resp, now, buffer) { function pushMetrics(resp, now, buffer) {
var line = new Array(last_metric + 1);
line[0] = new Date(now * 1000);
for (var lb in resp) { for (var lb in resp) {
var val = resp[lb];
/* Push new datapoints */ /* Push new datapoints */
if (lb in data) { const metric = metrics[lb];
data[lb].push({x: now, y:val}); if (metric) {
if (data[lb].length > 120) { line[metric[0] + 1] = resp[lb];
data[lb].shift();
}
} }
} }
/* Buffer graph changes. */ /* Buffer graph changes. */
data.push(line);
if (!buffer) { if (!buffer) {
graph.update(); graph.updateOptions( { 'file': data } );
} }
} }
...@@ -175,7 +193,7 @@ $(function() { ...@@ -175,7 +193,7 @@ $(function() {
} }
var sum = val.data.reduce(function(a, b) { return a + b; }); var sum = val.data.reduce(function(a, b) { return a + b; });
var avg = sum / val.data.length; var avg = sum / val.data.length;
var geokey = togeokey(val.location.longitude, val.location.latitude) var geokey = toGeokey(val.location.longitude, val.location.latitude)
var found = bubblemap[geokey]; var found = bubblemap[geokey];
if (!found) { if (!found) {
found = { found = {
...@@ -222,7 +240,7 @@ $(function() { ...@@ -222,7 +240,7 @@ $(function() {
for (var i in data) { for (var i in data) {
pushMetrics(data[i].stats, data[i].time, true); pushMetrics(data[i].stats, data[i].time, true);
} }
graph.update(); graph.updateOptions( { 'file': data } );
} else { } else {
pushMetrics(data.stats, data.time); pushMetrics(data.stats, data.time);
pushUpstreams(data.upstreams); pushUpstreams(data.upstreams);
......
...@@ -7,19 +7,16 @@ ...@@ -7,19 +7,16 @@
var secure = {{ secure }}; var secure = {{ secure }};
</script> </script>
<script src="jquery.js"></script> <script src="jquery.js"></script>
<script src="bootstrap.min.js"></script>
<script src="d3.js"></script> <script src="d3.js"></script>
<script src="rickshaw.min.js"></script> <script src="dygraph-combined.js"></script>
<script src="topojson.js"></script>
<script src="selectize.min.js"></script> <script src="selectize.min.js"></script>
<script src="bootstrap.min.js"></script> <script src="topojson.js"></script>
<script src="datamaps.world.min.js"></script> <script src="datamaps.world.min.js"></script>
<script src="kresd.js"></script> <script src="kresd.js"></script>
<link rel="icon" type="image/ico" href="favicon.ico"> <link rel="icon" type="image/ico" href="favicon.ico">
<link href="kresd.css" rel="stylesheet"> <link href="kresd.css" rel="stylesheet">
<link href="rickshaw.min.css" rel="stylesheet">
<link href="bootstrap.min.css" rel="stylesheet"> <link href="bootstrap.min.css" rel="stylesheet">
<link href="bootstrap-theme.min.css" rel="stylesheet">
<link href="selectize.min.css" rel="stylesheet">
<link href="selectize.bootstrap3.min.css" rel="stylesheet"> <link href="selectize.bootstrap3.min.css" rel="stylesheet">
<nav class="navbar navbar-inverse navbar-fixed-top"> <nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container"> <div class="container">
...@@ -47,13 +44,20 @@ ...@@ -47,13 +44,20 @@
<div class="main"> <div class="main">
<h2 class="sub-header">Metrics</h2> <h2 class="sub-header">Metrics</h2>
<div id="stats" class="row placeholders"> <div id="stats" class="row placeholders">
<div id="chart_container"> <div id="chart" style="width:100%"></div>
<div id="y_axis"></div> </div>
<div id="chart"></div> <div class="row">
<div class="col-md-12">
<h3><small>More metrics</small></h3>
<div class="col-md-11">
<select id="chart-selector" multiple></select>
</div>
<div class="col-md-1">
<div class="checkbox">
<label><input id="chart-stacked" type="checkbox">Stacked</label>
</div>
</div>
</div> </div>
<form id="legend_container">
<div id="legend"></div>
</form>
</div> </div>
<a name="worldmap"></a> <a name="worldmap"></a>
<h2 class="sub-header">Where do the queries go?</h2> <h2 class="sub-header">Where do the queries go?</h2>
......
.rickshaw_graph .detail{pointer-events:none;position:absolute;top:0;z-index:2;background:rgba(0,0,0,.1);bottom:0;width:1px;transition:opacity .25s linear;-moz-transition:opacity .25s linear;-o-transition:opacity .25s linear;-webkit-transition:opacity .25s linear}.rickshaw_graph .detail.inactive{opacity:0}.rickshaw_graph .detail .item.active{opacity:1}.rickshaw_graph .detail .x_label{font-family:Arial,sans-serif;border-radius:3px;padding:6px;opacity:.5;border:1px solid #e0e0e0;font-size:12px;position:absolute;background:#fff;white-space:nowrap}.rickshaw_graph .detail .x_label.left{left:0}.rickshaw_graph .detail .x_label.right{right:0}.rickshaw_graph .detail .item{position:absolute;z-index:2;border-radius:3px;padding:.25em;font-size:12px;font-family:Arial,sans-serif;opacity:0;background:rgba(0,0,0,.4);color:#fff;border:1px solid rgba(0,0,0,.4);margin-left:1em;margin-right:1em;margin-top:-1em;white-space:nowrap}.rickshaw_graph .detail .item.left{left:0}.rickshaw_graph .detail .item.right{right:0}.rickshaw_graph .detail .item.active{opacity:1;background:rgba(0,0,0,.8)}.rickshaw_graph .detail .item:after{position:absolute;display:block;width:0;height:0;content:"";border:5px solid transparent}.rickshaw_graph .detail .item.left:after{top:1em;left:-5px;margin-top:-5px;border-right-color:rgba(0,0,0,.8);border-left-width:0}.rickshaw_graph .detail .item.right:after{top:1em;right:-5px;margin-top:-5px;border-left-color:rgba(0,0,0,.8);border-right-width:0}.rickshaw_graph .detail .dot{width:4px;height:4px;margin-left:-3px;margin-top:-3.5px;border-radius:5px;position:absolute;box-shadow:0 0 2px rgba(0,0,0,.6);box-sizing:content-box;-moz-box-sizing:content-box;background:#fff;border-width:2px;border-style:solid;display:none;background-clip:padding-box}.rickshaw_graph .detail .dot.active{display:block}.rickshaw_graph{position:relative}.rickshaw_graph svg{display:block;overflow:hidden}.rickshaw_graph .x_tick{position:absolute;top:0;bottom:0;width:0;border-left:1px dotted rgba(0,0,0,.2);pointer-events:none}.rickshaw_graph .x_tick .title{position:absolute;font-size:12px;font-family:Arial,sans-serif;opacity:.5;white-space:nowrap;margin-left:3px;bottom:1px}.rickshaw_annotation_timeline{height:1px;border-top:1px solid #e0e0e0;margin-top:10px;position:relative}.rickshaw_annotation_timeline .annotation{position:absolute;height:6px;width:6px;margin-left:-2px;top:-3px;border-radius:5px;background-color:rgba(0,0,0,.25)}.rickshaw_graph .annotation_line{position:absolute;top:0;bottom:-6px;width:0;border-left:2px solid rgba(0,0,0,.3);display:none}.rickshaw_graph .annotation_line.active{display:block}.rickshaw_graph .annotation_range{background:rgba(0,0,0,.1);display:none;position:absolute;top:0;bottom:-6px}.rickshaw_graph .annotation_range.active{display:block}.rickshaw_graph .annotation_range.active.offscreen{display:none}.rickshaw_annotation_timeline .annotation .content{background:#fff;color:#000;opacity:.9;padding:5px;box-shadow:0 0 2px rgba(0,0,0,.8);border-radius:3px;position:relative;z-index:20;font-size:12px;padding:6px 8px 8px;top:18px;left:-11px;width:160px;display:none;cursor:pointer}.rickshaw_annotation_timeline .annotation .content:before{content:"\25b2";position:absolute;top:-11px;color:#fff;text-shadow:0 -1px 1px rgba(0,0,0,.8)}.rickshaw_annotation_timeline .annotation.active,.rickshaw_annotation_timeline .annotation:hover{background-color:rgba(0,0,0,.8);cursor:none}.rickshaw_annotation_timeline .annotation .content:hover{z-index:50}.rickshaw_annotation_timeline .annotation.active .content{display:block}.rickshaw_annotation_timeline .annotation:hover .content{display:block;z-index:50}.rickshaw_graph .y_axis,.rickshaw_graph .x_axis_d3{fill:none}.rickshaw_graph .y_ticks .tick line,.rickshaw_graph .x_ticks_d3 .tick{stroke:rgba(0,0,0,.16);stroke-width:2px;shape-rendering:crisp-edges;pointer-events:none}.rickshaw_graph .y_grid .tick,.rickshaw_graph .x_grid_d3 .tick{z-index:-1;stroke:rgba(0,0,0,.2);stroke-width:1px;stroke-dasharray:1 1}.rickshaw_graph .y_grid .tick[data-y-value="0"]{stroke-dasharray:1 0}.rickshaw_graph .y_grid path,.rickshaw_graph .x_grid_d3 path{fill:none;stroke:none}.rickshaw_graph .y_ticks path,.rickshaw_graph .x_ticks_d3 path{fill:none;stroke:gray}.rickshaw_graph .y_ticks text,.rickshaw_graph .x_ticks_d3 text{opacity:.5;font-size:12px;pointer-events:none}.rickshaw_graph .x_tick.glow .title,.rickshaw_graph .y_ticks.glow text{fill:#000;color:#000;text-shadow:-1px 1px 0 rgba(255,255,255,.1),1px -1px 0 rgba(255,255,255,.1),1px 1px 0 rgba(255,255,255,.1),0 1px 0 rgba(255,255,255,.1),0 -1px 0 rgba(255,255,255,.1),1px 0 0 rgba(255,255,255,.1),-1px 0 0 rgba(255,255,255,.1),-1px -1px 0 rgba(255,255,255,.1)}.rickshaw_graph .x_tick.inverse .title,.rickshaw_graph .y_ticks.inverse text{fill:#fff;color:#fff;text-shadow:-1px 1px 0 rgba(0,0,0,.8),1px -1px 0 rgba(0,0,0,.8),1px 1px 0 rgba(0,0,0,.8),0 1px 0 rgba(0,0,0,.8),0 -1px 0 rgba(0,0,0,.8),1px 0 0 rgba(0,0,0,.8),-1px 0 0 rgba(0,0,0,.8),-1px -1px 0 rgba(0,0,0,.8)}.rickshaw_legend{font-family:Arial;font-size:12px;color:#fff;background:#404040;display:inline-block;padding:12px 5px;border-radius:2px;position:relative}.rickshaw_legend:hover{z-index:10}.rickshaw_legend .swatch{width:10px;height:10px;border:1px solid rgba(0,0,0,.2)}.rickshaw_legend .line{clear:both;line-height:140%;padding-right:15px}.rickshaw_legend .line .swatch{display:inline-block;margin-right:3px;border-radius:2px}.rickshaw_legend .label{margin:0;white-space:nowrap;display:inline;font-size:inherit;background-color:transparent;color:inherit;font-weight:400;line-height:normal;padding:0;text-shadow:none}.rickshaw_legend .action:hover{opacity:.6}.rickshaw_legend .action{margin-right:.2em;font-size:10px;opacity:.2;cursor:pointer;font-size:14px}.rickshaw_legend .line.disabled{opacity:.4}.rickshaw_legend ul{list-style-type:none;margin:0;padding:0;margin:2px;cursor:pointer}.rickshaw_legend li{padding:0 0 0 2px;min-width:80px;white-space:nowrap}.rickshaw_legend li:hover{background:rgba(255,255,255,.08);border-radius:3px}.rickshaw_legend li:active{background:rgba(255,255,255,.2);border-radius:3px}
\ No newline at end of file
This diff is collapsed.
.selectize-control.plugin-drag_drop.multi>.selectize-input>div.ui-sortable-placeholder{visibility:visible !important;background:#f2f2f2 !important;background:rgba(0,0,0,0.06) !important;border:0 none !important;-webkit-box-shadow:inset 0 0 12px 4px #fff;box-shadow:inset 0 0 12px 4px #fff}.selectize-control.plugin-drag_drop .ui-sortable-placeholder::after{content:'!';visibility:hidden}.selectize-control.plugin-drag_drop .ui-sortable-helper{-webkit-box-shadow:0 2px 5px rgba(0,0,0,0.2);box-shadow:0 2px 5px rgba(0,0,0,0.2)}.selectize-dropdown-header{position:relative;padding:3px 12px;border-bottom:1px solid #d0d0d0;background:#f8f8f8;-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.selectize-dropdown-header-close{position:absolute;right:12px;top:50%;color:#333;opacity:.4;margin-top:-12px;line-height:20px;font-size:20px !important}.selectize-dropdown-header-close:hover{color:#000}.selectize-dropdown.plugin-optgroup_columns .optgroup{border-right:1px solid #f2f2f2;border-top:0 none;float:left;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.selectize-dropdown.plugin-optgroup_columns .optgroup:last-child{border-right:0 none}.selectize-dropdown.plugin-optgroup_columns .optgroup:before{display:none}.selectize-dropdown.plugin-optgroup_columns .optgroup-header{border-top:0 none}.selectize-control.plugin-remove_button [data-value]{position:relative;padding-right:24px !important}.selectize-control.plugin-remove_button [data-value] .remove{z-index:1;position:absolute;top:0;right:0;bottom:0;width:17px;text-align:center;font-weight:bold;font-size:12px;color:inherit;text-decoration:none;vertical-align:middle;display:inline-block;padding:1px 0 0 0;border-left:1px solid rgba(0,0,0,0);-webkit-border-radius:0 2px 2px 0;-moz-border-radius:0 2px 2px 0;border-radius:0 2px 2px 0;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.selectize-control.plugin-remove_button [data-value] .remove:hover{background:rgba(0,0,0,0.05)}.selectize-control.plugin-remove_button [data-value].active .remove{border-left-color:rgba(0,0,0,0)}.selectize-control.plugin-remove_button .disabled [data-value] .remove:hover{background:0}.selectize-control.plugin-remove_button .disabled [data-value] .remove{border-left-color:rgba(77,77,77,0)}.selectize-control{position:relative}.selectize-dropdown,.selectize-input,.selectize-input input{color:#333;font-family:inherit;font-size:inherit;line-height:20px;-webkit-font-smoothing:inherit}.selectize-input,.selectize-control.single .selectize-input.input-active{background:#fff;cursor:text;display:inline-block}.selectize-input{border:1px solid #ccc;padding:6px 12px;display:inline-block;width:100%;overflow:hidden;position:relative;z-index:1;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:none;box-shadow:none;-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.selectize-control.multi .selectize-input.has-items{padding:5px 12px 2px}.selectize-input.full{background-color:#fff}.selectize-input.disabled,.selectize-input.disabled *{cursor:default !important}.selectize-input.focus{-webkit-box-shadow:inset 0 1px 2px rgba(0,0,0,0.15);box-shadow:inset 0 1px 2px rgba(0,0,0,0.15)}.selectize-input.dropdown-active{-webkit-border-radius:4px 4px 0 0;-moz-border-radius:4px 4px 0 0;border-radius:4px 4px 0 0}.selectize-input>*{vertical-align:baseline;display:-moz-inline-stack;display:inline-block;zoom:1;*display:inline}.selectize-control.multi .selectize-input>div{cursor:pointer;margin:0 3px 3px 0;padding:1px 3px;background:#efefef;color:#333;border:0 solid rgba(0,0,0,0)}.selectize-control.multi .selectize-input>div.active{background:#428bca;color:#fff;border:0 solid rgba(0,0,0,0)}.selectize-control.multi .selectize-input.disabled>div,.selectize-control.multi .selectize-input.disabled>div.active{color:gray;background:#fff;border:0 solid rgba(77,77,77,0)}.selectize-input>input{display:inline-block !important;padding:0 !important;min-height:0 !important;max-height:none !important;max-width:100% !important;margin:0 !important;text-indent:0 !important;border:0 none !important;background:none !important;line-height:inherit !important;-webkit-user-select:auto !important;-webkit-box-shadow:none !important;box-shadow:none !important}.selectize-input>input::-ms-clear{display:none}.selectize-input>input:focus{outline:none !important}.selectize-input::after{content:' ';display:block;clear:left}.selectize-input.dropdown-active::before{content:' ';display:block;position:absolute;background:#fff;height:1px;bottom:0;left:0;right:0}.selectize-dropdown{position:absolute;z-index:10;border:1px solid #d0d0d0;background:#fff;margin:-1px 0 0 0;border-top:0 none;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-box-shadow:0 1px 3px rgba(0,0,0,0.1);box-shadow:0 1px 3px rgba(0,0,0,0.1);-webkit-border-radius:0 0 4px 4px;-moz-border-radius:0 0 4px 4px;border-radius:0 0 4px 4px}.selectize-dropdown [data-selectable]{cursor:pointer;overflow:hidden}.selectize-dropdown [data-selectable] .highlight{background:rgba(255,237,40,0.4);-webkit-border-radius:1px;-moz-border-radius:1px;border-radius:1px}.selectize-dropdown [data-selectable],.selectize-dropdown .optgroup-header{padding:3px 12px}.selectize-dropdown .optgroup:first-child .optgroup-header{border-top:0 none}.selectize-dropdown .optgroup-header{color:#777;background:#fff;cursor:default}.selectize-dropdown .active{background-color:#f5f5f5;color:#262626}.selectize-dropdown .active.create{color:#262626}.selectize-dropdown .create{color:rgba(51,51,51,0.5)}.selectize-dropdown-content{overflow-y:auto;overflow-x:hidden;max-height:200px}.selectize-control.single .selectize-input,.selectize-control.single .selectize-input input{cursor:pointer}.selectize-control.single .selectize-input.input-active,.selectize-control.single .selectize-input.input-active input{cursor:text}.selectize-control.single .selectize-input:after{content:' ';display:block;position:absolute;top:50%;right:17px;margin-top:-3px;width:0;height:0;border-style:solid;border-width:5px 5px 0 5px;border-color:#333 transparent transparent transparent}.selectize-control.single .selectize-input.dropdown-active:after{margin-top:-4px;border-width:0 5px 5px 5px;border-color:transparent transparent #333 transparent}.selectize-control.rtl.single .selectize-input:after{left:17px;right:auto}.selectize-control.rtl .selectize-input>input{margin:0 4px 0 -2px !important}.selectize-control .selectize-input.disabled{opacity:.5;background-color:#fff}.selectize-dropdown,.selectize-dropdown.form-control{height:auto;padding:0;margin:2px 0 0 0;z-index:1000;background:#fff;border:1px solid #ccc;border:1px solid rgba(0,0,0,0.15);-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,0.175);box-shadow:0 6px 12px rgba(0,0,0,0.175)}.selectize-dropdown .optgroup-header{font-size:12px;line-height:1.42857143}.selectize-dropdown .optgroup:first-child:before{display:none}.selectize-dropdown .optgroup:before{content:' ';display:block;height:1px;margin:9px 0;overflow:hidden;background-color:#e5e5e5;margin-left:-12px;margin-right:-12px}.selectize-dropdown-content{padding:5px 0}.selectize-dropdown-header{padding:6px 12px}.selectize-input{min-height:34px}.selectize-input.dropdown-active{-webkit-border-radius:4px;-moz-border-radius:4px;border-radius:4px}.selectize-input.dropdown-active::before{display:none}.selectize-input.focus{border-color:#66afe9;outline:0;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6);box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,0.6)}.has-error .selectize-input{border-color:#a94442;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075);box-shadow:inset 0 1px 1px rgba(0,0,0,0.075)}.has-error .selectize-input:focus{border-color:#843534;-webkit-box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 6px #ce8483}.selectize-control.multi .selectize-input.has-items{padding-left:9px;padding-right:9px}.selectize-control.multi .selectize-input>div{-webkit-border-radius:3px;-moz-border-radius:3px;border-radius:3px}.form-control.selectize-control{padding:0;height:auto;border:0;background:0;-webkit-box-shadow:none;box-shadow:none;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0}