mirror of https://github.com/Aidaho12/haproxy-wi
v3.5.1
parent
30432686ed
commit
4a1a4008b5
|
@ -24,7 +24,7 @@ template = template.render(h2 = 1, title = "Metrics",
|
||||||
autorefresh = 1,
|
autorefresh = 1,
|
||||||
role = sql.get_user_role_by_uuid(user_id.value),
|
role = sql.get_user_role_by_uuid(user_id.value),
|
||||||
user = user,
|
user = user,
|
||||||
servers = sql.get_dick_permit(),
|
servers = sql.select_servers_metrics(user_id.value),
|
||||||
versions = funct.versions(),
|
versions = funct.versions(),
|
||||||
token = token)
|
token = token)
|
||||||
print(template)
|
print(template)
|
180
app/options.py
180
app/options.py
|
@ -10,7 +10,7 @@ form = cgi.FieldStorage()
|
||||||
serv = form.getvalue('serv')
|
serv = form.getvalue('serv')
|
||||||
act = form.getvalue('act')
|
act = form.getvalue('act')
|
||||||
|
|
||||||
if form.getvalue('new_metrics'):
|
if form.getvalue('new_metrics') or form.getvalue('new_waf_metrics'):
|
||||||
print('Content-type: application/json\n')
|
print('Content-type: application/json\n')
|
||||||
else:
|
else:
|
||||||
print('Content-type: text/html\n')
|
print('Content-type: text/html\n')
|
||||||
|
@ -442,19 +442,7 @@ if form.getvalue('table_metrics'):
|
||||||
|
|
||||||
|
|
||||||
if form.getvalue('new_metrics'):
|
if form.getvalue('new_metrics'):
|
||||||
from datetime import timedelta
|
|
||||||
import http.cookies
|
|
||||||
|
|
||||||
# cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
|
|
||||||
# user_id = cookie.get('uuid')
|
|
||||||
# servers = sql.select_servers_metrics(user_id.value)
|
|
||||||
# servers = sorted(servers)
|
|
||||||
serv = form.getvalue('server')
|
serv = form.getvalue('server')
|
||||||
|
|
||||||
# p = {}
|
|
||||||
# for serv in servers:
|
|
||||||
# serv = serv[0]
|
|
||||||
# p[serv] = {}
|
|
||||||
metric = sql.select_metrics(serv)
|
metric = sql.select_metrics(serv)
|
||||||
metrics = {}
|
metrics = {}
|
||||||
metrics['chartData'] = {}
|
metrics['chartData'] = {}
|
||||||
|
@ -463,175 +451,43 @@ if form.getvalue('new_metrics'):
|
||||||
curr_con = ''
|
curr_con = ''
|
||||||
curr_ssl_con = ''
|
curr_ssl_con = ''
|
||||||
sess_rate = ''
|
sess_rate = ''
|
||||||
max_sess_rate = ''
|
|
||||||
for i in metric:
|
for i in metric:
|
||||||
labels += str(i[5].split(' ')[1])+','
|
labels += str(i[5].split(' ')[1])+','
|
||||||
curr_con += str(i[1])+','
|
curr_con += str(i[1])+','
|
||||||
curr_ssl_con += str(i[2])+','
|
curr_ssl_con += str(i[2])+','
|
||||||
sess_rate += str(i[3])+','
|
sess_rate += str(i[3])+','
|
||||||
max_sess_rate += str(i[4])+','
|
|
||||||
server = str(i[0])
|
server = str(i[0])
|
||||||
|
|
||||||
metrics['chartData']['labels'] = labels
|
metrics['chartData']['labels'] = labels
|
||||||
|
|
||||||
# metrics[rep_date]['server'] = str(i[0])
|
|
||||||
metrics['chartData']['curr_con'] = curr_con
|
metrics['chartData']['curr_con'] = curr_con
|
||||||
metrics['chartData']['curr_ssl_con'] = curr_ssl_con
|
metrics['chartData']['curr_ssl_con'] = curr_ssl_con
|
||||||
metrics['chartData']['sess_rate'] = sess_rate
|
metrics['chartData']['sess_rate'] = sess_rate
|
||||||
metrics['chartData']['max_sess_rate'] = max_sess_rate
|
|
||||||
metrics['chartData']['server'] = server
|
metrics['chartData']['server'] = server
|
||||||
import json
|
import json
|
||||||
|
|
||||||
print(json.dumps(metrics))
|
print(json.dumps(metrics))
|
||||||
|
|
||||||
|
|
||||||
if form.getvalue('metrics'):
|
if form.getvalue('new_waf_metrics'):
|
||||||
from datetime import timedelta
|
serv = form.getvalue('server')
|
||||||
from bokeh.plotting import figure, output_file, show
|
metric = sql.select_waf_metrics(serv)
|
||||||
from bokeh.models import ColumnDataSource, HoverTool, DatetimeTickFormatter, DatePicker
|
metrics = {}
|
||||||
from bokeh.layouts import widgetbox, gridplot
|
metrics['chartData'] = {}
|
||||||
from bokeh.models.widgets import Button, RadioButtonGroup, Select
|
metrics['chartData']['labels'] = {}
|
||||||
import pandas as pd
|
labels = ''
|
||||||
import http.cookies
|
curr_con = ''
|
||||||
|
|
||||||
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
|
|
||||||
user_id = cookie.get('uuid')
|
|
||||||
servers = sql.select_servers_metrics(user_id.value)
|
|
||||||
servers = sorted(servers)
|
|
||||||
|
|
||||||
p = {}
|
|
||||||
for serv in servers:
|
|
||||||
serv = serv[0]
|
|
||||||
p[serv] = {}
|
|
||||||
metric = sql.select_metrics(serv)
|
|
||||||
metrics = {}
|
|
||||||
|
|
||||||
for i in metric:
|
|
||||||
rep_date = str(i[5])
|
|
||||||
metrics[rep_date] = {}
|
|
||||||
metrics[rep_date]['server'] = str(i[0])
|
|
||||||
metrics[rep_date]['curr_con'] = str(i[1])
|
|
||||||
metrics[rep_date]['curr_ssl_con'] = str(i[2])
|
|
||||||
metrics[rep_date]['sess_rate'] = str(i[3])
|
|
||||||
metrics[rep_date]['max_sess_rate'] = str(i[4])
|
|
||||||
|
|
||||||
df = pd.DataFrame.from_dict(metrics, orient="index")
|
for i in metric:
|
||||||
df = df.fillna(0)
|
labels += str(i[2].split(' ')[1])+','
|
||||||
df.index = pd.to_datetime(df.index)
|
curr_con += str(i[1])+','
|
||||||
df.index.name = 'Date'
|
|
||||||
df.sort_index(inplace=True)
|
|
||||||
source = ColumnDataSource(df)
|
|
||||||
|
|
||||||
output_file("templates/metrics_out.html", mode='inline')
|
|
||||||
|
|
||||||
x_min = df.index.min() - pd.Timedelta(hours=1)
|
|
||||||
x_max = df.index.max() + pd.Timedelta(minutes=1)
|
|
||||||
|
|
||||||
p[serv] = figure(
|
|
||||||
tools="pan,box_zoom,reset,xwheel_zoom",
|
|
||||||
title=metric[0][0],
|
|
||||||
x_axis_type="datetime", y_axis_label='Connections',
|
|
||||||
x_range = (x_max.timestamp()*1000-60*100000, x_max.timestamp()*1000)
|
|
||||||
)
|
|
||||||
|
|
||||||
hover = HoverTool(
|
metrics['chartData']['labels'] = labels
|
||||||
tooltips=[
|
metrics['chartData']['curr_con'] = curr_con
|
||||||
("Connections", "@curr_con"),
|
metrics['chartData']['server'] = serv
|
||||||
("SSL connections", "@curr_ssl_con"),
|
import json
|
||||||
("Sessions rate", "@sess_rate")
|
print(json.dumps(metrics))
|
||||||
],
|
|
||||||
mode='mouse'
|
|
||||||
)
|
|
||||||
|
|
||||||
p[serv].ygrid.band_fill_color = "#f3f8fb"
|
|
||||||
p[serv].ygrid.band_fill_alpha = 0.9
|
|
||||||
p[serv].y_range.start = 0
|
|
||||||
p[serv].y_range.end = int(df['curr_con'].max()) + 150
|
|
||||||
p[serv].add_tools(hover)
|
|
||||||
p[serv].title.text_font_size = "20px"
|
|
||||||
p[serv].line("Date", "curr_con", source=source, alpha=0.5, color='#5cb85c', line_width=2, legend="Conn")
|
|
||||||
p[serv].line("Date", "curr_ssl_con", source=source, alpha=0.5, color="#5d9ceb", line_width=2, legend="SSL con")
|
|
||||||
p[serv].line("Date", "sess_rate", source=source, alpha=0.5, color="#33414e", line_width=2, legend="Sessions")
|
|
||||||
p[serv].legend.orientation = "horizontal"
|
|
||||||
p[serv].legend.location = "top_left"
|
|
||||||
p[serv].legend.padding = 5
|
|
||||||
|
|
||||||
plots = []
|
|
||||||
for key, value in p.items():
|
|
||||||
plots.append(value)
|
|
||||||
|
|
||||||
grid = gridplot(plots, ncols=2, plot_width=800, plot_height=250, toolbar_location = "left", toolbar_options=dict(logo=None))
|
|
||||||
show(grid)
|
|
||||||
|
|
||||||
if form.getvalue('waf_metrics'):
|
|
||||||
from datetime import timedelta
|
|
||||||
from bokeh.plotting import figure, output_file, show
|
|
||||||
from bokeh.models import ColumnDataSource, HoverTool, DatetimeTickFormatter, DatePicker
|
|
||||||
from bokeh.layouts import widgetbox, gridplot
|
|
||||||
from bokeh.models.widgets import Button, RadioButtonGroup, Select
|
|
||||||
import pandas as pd
|
|
||||||
import http.cookies
|
|
||||||
|
|
||||||
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
|
|
||||||
user_id = cookie.get('uuid')
|
|
||||||
servers = sql.select_waf_servers_metrics(user_id.value)
|
|
||||||
servers = sorted(servers)
|
|
||||||
|
|
||||||
p = {}
|
|
||||||
for serv in servers:
|
|
||||||
serv = serv[0]
|
|
||||||
p[serv] = {}
|
|
||||||
metric = sql.select_waf_metrics(serv)
|
|
||||||
metrics = {}
|
|
||||||
|
|
||||||
for i in metric:
|
|
||||||
rep_date = str(i[2])
|
|
||||||
metrics[rep_date] = {}
|
|
||||||
metrics[rep_date]['conn'] = str(i[1])
|
|
||||||
|
|
||||||
df = pd.DataFrame.from_dict(metrics, orient="index")
|
|
||||||
df = df.fillna(0)
|
|
||||||
df.index = pd.to_datetime(df.index)
|
|
||||||
df.index.name = 'Date'
|
|
||||||
df.sort_index(inplace=True)
|
|
||||||
source = ColumnDataSource(df)
|
|
||||||
|
|
||||||
output_file("templates/metrics_waf_out.html", mode='inline')
|
|
||||||
|
|
||||||
x_min = df.index.min() - pd.Timedelta(hours=1)
|
|
||||||
x_max = df.index.max() + pd.Timedelta(minutes=1)
|
|
||||||
|
|
||||||
p[serv] = figure(
|
|
||||||
tools="pan,box_zoom,reset,xwheel_zoom",
|
|
||||||
title=metric[0][0],
|
|
||||||
x_axis_type="datetime", y_axis_label='Connections',
|
|
||||||
x_range = (x_max.timestamp()*1000-60*100000, x_max.timestamp()*1000)
|
|
||||||
)
|
|
||||||
|
|
||||||
hover = HoverTool(
|
|
||||||
tooltips=[
|
|
||||||
("Connections", "@conn"),
|
|
||||||
],
|
|
||||||
mode='mouse'
|
|
||||||
)
|
|
||||||
|
|
||||||
p[serv].ygrid.band_fill_color = "#f3f8fb"
|
|
||||||
p[serv].ygrid.band_fill_alpha = 0.9
|
|
||||||
p[serv].y_range.start = 0
|
|
||||||
p[serv].y_range.end = int(df['conn'].max()) + 150
|
|
||||||
p[serv].add_tools(hover)
|
|
||||||
p[serv].title.text_font_size = "20px"
|
|
||||||
p[serv].line("Date", "conn", source=source, alpha=0.5, color='#5cb85c', line_width=2, legend="Conn")
|
|
||||||
p[serv].legend.orientation = "horizontal"
|
|
||||||
p[serv].legend.location = "top_left"
|
|
||||||
p[serv].legend.padding = 5
|
|
||||||
|
|
||||||
plots = []
|
|
||||||
for key, value in p.items():
|
|
||||||
plots.append(value)
|
|
||||||
|
|
||||||
grid = gridplot(plots, ncols=2, plot_width=800, plot_height=250, toolbar_location = "left", toolbar_options=dict(logo=None))
|
|
||||||
show(grid)
|
|
||||||
|
|
||||||
if form.getvalue('get_hap_v'):
|
if form.getvalue('get_hap_v'):
|
||||||
output = funct.check_haproxy_version(serv)
|
output = funct.check_haproxy_version(serv)
|
||||||
|
|
|
@ -14,17 +14,17 @@ th, tr, td {
|
||||||
width: 6%;
|
width: 6%;
|
||||||
padding: 10px;
|
padding: 10px;
|
||||||
}
|
}
|
||||||
.metrics1 {
|
|
||||||
width: 400px;
|
|
||||||
height: 100px;}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
<link href="/inc/chart.min.css" rel="stylesheet">
|
||||||
<script src="/inc/metrics.js"></script>
|
<script src="/inc/metrics.js"></script>
|
||||||
|
<script src="/inc/chart.min.js"></script>
|
||||||
<div id="table_metrics"></div>
|
<div id="table_metrics"></div>
|
||||||
{% for s in servers %}
|
{% for s in servers %}
|
||||||
<canvas id="{{s.2}}" width="100" height="20" class="metrics1" role="img"></canvas>
|
<div class="chart-container" style="">
|
||||||
|
<canvas id="{{s.0}}" role="img"></canvas>
|
||||||
|
</div>
|
||||||
<script>
|
<script>
|
||||||
getChartData('{{s.2}}')
|
getChartData('{{s.0}}')
|
||||||
</script>
|
</script>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
|
|
|
@ -24,31 +24,21 @@
|
||||||
<tbody id="ajaxwafstatus"></tbody>
|
<tbody id="ajaxwafstatus"></tbody>
|
||||||
</table>
|
</table>
|
||||||
<div id="ajax"></div>
|
<div id="ajax"></div>
|
||||||
<style>
|
|
||||||
iframe {
|
|
||||||
border: none;
|
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id="metrics_iframe"></div>
|
<link href="/inc/chart.min.css" rel="stylesheet">
|
||||||
|
<script src="/inc/metrics.js"></script>
|
||||||
|
<script src="/inc/chart.min.js"></script>
|
||||||
|
|
||||||
|
{% for s in servers %}
|
||||||
|
<div class="chart-container" style="">
|
||||||
|
<canvas id="{{s.0}}" role="img"></canvas>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
getWafChartData('{{s.0}}')
|
||||||
|
</script>
|
||||||
|
{% endfor %}
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
showOverviewWaf()
|
showOverviewWaf()
|
||||||
function callIframe(url, callback) {
|
|
||||||
$('#metrics_iframe').html('<iframe id="metrics" style="width:100%;height:100%;" />');
|
|
||||||
$('iframe#metrics').attr('src', url);
|
|
||||||
$('iframe#metrics').load(function() {
|
|
||||||
callback(this);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
function loadMetrics() {
|
|
||||||
callIframe('templates/metrics_waf_out.html', function(){
|
|
||||||
$.get( "options.py?waf_metrics=1&token="+$('#token').val(), function( data ) {
|
|
||||||
$( ".result" ).html( data );
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
loadMetrics()
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -25,7 +25,7 @@ template = template.render(h2 = 1, title = "Web application firewall",
|
||||||
autorefresh = 1,
|
autorefresh = 1,
|
||||||
role = sql.get_user_role_by_uuid(user_id.value),
|
role = sql.get_user_role_by_uuid(user_id.value),
|
||||||
user = user,
|
user = user,
|
||||||
table_stat = sql.select_table_metrics(user_id.value),
|
servers = sql.select_waf_servers_metrics(user_id.value),
|
||||||
versions = funct.versions(),
|
versions = funct.versions(),
|
||||||
token = token)
|
token = token)
|
||||||
print(template)
|
print(template)
|
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -14,14 +14,10 @@ function getChartData(server) {
|
||||||
data.push(result.chartData.curr_con);
|
data.push(result.chartData.curr_con);
|
||||||
data.push(result.chartData.curr_ssl_con);
|
data.push(result.chartData.curr_ssl_con);
|
||||||
data.push(result.chartData.sess_rate);
|
data.push(result.chartData.sess_rate);
|
||||||
data.push(result.chartData.max_sess_rate);
|
|
||||||
data.push(result.chartData.server);
|
data.push(result.chartData.server);
|
||||||
|
|
||||||
var labels = result.chartData.labels;
|
var labels = result.chartData.labels;
|
||||||
renderChart(data, labels, server);
|
renderChart(data, labels, server);
|
||||||
},
|
|
||||||
error: function (err) {
|
|
||||||
$("#loadingMessage").html("Error");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -49,19 +45,13 @@ function renderChart(data, labels, server) {
|
||||||
data: data[2].split(','),
|
data: data[2].split(','),
|
||||||
borderColor: 'rgba(255, 206, 86, 1)',
|
borderColor: 'rgba(255, 206, 86, 1)',
|
||||||
backgroundColor: 'rgba(255, 206, 86, 0.2)',
|
backgroundColor: 'rgba(255, 206, 86, 0.2)',
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'max_sess_rate',
|
|
||||||
data: data[3].split(','),
|
|
||||||
borderColor: 'rgba(192, 192, 192, 1)',
|
|
||||||
backgroundColor: 'rgba(192, 192, 192, 0.2)',
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
options: {
|
options: {
|
||||||
title: {
|
title: {
|
||||||
display: true,
|
display: true,
|
||||||
text: data[4],
|
text: data[3],
|
||||||
fontSize: 20,
|
fontSize: 20,
|
||||||
padding: 0,
|
padding: 0,
|
||||||
},
|
},
|
||||||
|
@ -81,6 +71,66 @@ function renderChart(data, labels, server) {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getWafChartData(server) {
|
||||||
|
$.ajax({
|
||||||
|
url: "options.py",
|
||||||
|
data: {
|
||||||
|
new_waf_metrics: '1',
|
||||||
|
server: server,
|
||||||
|
token: $('#token').val()
|
||||||
|
},
|
||||||
|
type: "GET",
|
||||||
|
success: function (result) {
|
||||||
|
|
||||||
|
var data = [];
|
||||||
|
|
||||||
|
data.push(result.chartData.curr_con);
|
||||||
|
data.push(result.chartData.server);
|
||||||
|
var labels = result.chartData.labels;
|
||||||
|
renderWafChart(data, labels, server);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
function renderWafChart(data, labels, server) {
|
||||||
|
var ctx = document.getElementById(server)
|
||||||
|
var myChart = new Chart(ctx, {
|
||||||
|
type: 'line',
|
||||||
|
data: {
|
||||||
|
labels: labels.split(','),
|
||||||
|
datasets: [
|
||||||
|
{
|
||||||
|
label: 'curr_con',
|
||||||
|
data: data[0].split(','),
|
||||||
|
borderColor: 'rgba(75, 192, 192, 1)',
|
||||||
|
backgroundColor: 'rgba(75, 192, 192, 0.2)',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
title: {
|
||||||
|
display: true,
|
||||||
|
text: data[1],
|
||||||
|
fontSize: 20,
|
||||||
|
padding: 0,
|
||||||
|
},
|
||||||
|
scales: {
|
||||||
|
yAxes: [{
|
||||||
|
ticks: {
|
||||||
|
beginAtZero: true,
|
||||||
|
}
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
display: true,
|
||||||
|
labels: {
|
||||||
|
fontColor: 'rgb(255, 99, 132)'
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
$("#secIntervals").css("display", "none");
|
$("#secIntervals").css("display", "none");
|
||||||
function callIframe(url, callback) {
|
function callIframe(url, callback) {
|
||||||
$('#metrics_iframe').html('<iframe id="metrics" style="width:100%;height:100%;" />');
|
$('#metrics_iframe').html('<iframe id="metrics" style="width:100%;height:100%;" />');
|
||||||
|
|
|
@ -148,7 +148,7 @@ pre {
|
||||||
float: right;
|
float: right;
|
||||||
margin-top: 5px;
|
margin-top: 5px;
|
||||||
margin-left: 14px;
|
margin-left: 14px;
|
||||||
margin-right: 15px;
|
margin-right: 20px;
|
||||||
color: #fff !important;
|
color: #fff !important;
|
||||||
font-size: 15px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
@ -328,14 +328,14 @@ pre {
|
||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
.tooltip {
|
/* .tooltip { */
|
||||||
font-size: 12px;
|
/* font-size: 12px; */
|
||||||
padding-bottom: 10px;
|
/* padding-bottom: 10px; */
|
||||||
}
|
/* } */
|
||||||
.tooltipTop {
|
/* .tooltipTop { */
|
||||||
margin-bottom: -20px;
|
/* margin-bottom: -20px; */
|
||||||
padding-top: 10px;
|
/* padding-top: 10px; */
|
||||||
}
|
/* } */
|
||||||
.overview {
|
.overview {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
/* margin-top: 1.5em; */
|
/* margin-top: 1.5em; */
|
||||||
|
@ -565,12 +565,15 @@ ul{
|
||||||
border: none !important;
|
border: none !important;
|
||||||
border-color: #5D9CEB !important;
|
border-color: #5D9CEB !important;
|
||||||
}
|
}
|
||||||
.ui-tooltip, .arrow:after {
|
/* .ui-tooltip, .arrow:after { */
|
||||||
background: #33414E !important;
|
/* background: #33414E !important; */
|
||||||
border: 1px solid #33414E !important;
|
/* border: 1px solid #33414E !important; */
|
||||||
border-radius: 5px !important;
|
/* border-radius: 5px !important; */
|
||||||
color: #fff !important;
|
/* color: #fff !important; */
|
||||||
}
|
/* font-size: 10px !important; */
|
||||||
|
/* padding: 2px !important; */
|
||||||
|
/* margin-bottom: -20px !important; */
|
||||||
|
/* } */
|
||||||
.ui-tabs-nav {
|
.ui-tabs-nav {
|
||||||
border-radius: 0 !important;
|
border-radius: 0 !important;
|
||||||
padding-left: 25px !important;
|
padding-left: 25px !important;
|
||||||
|
@ -804,6 +807,14 @@ label {
|
||||||
margin-bottom: -40px;
|
margin-bottom: -40px;
|
||||||
padding-left: 70px;
|
padding-left: 70px;
|
||||||
}
|
}
|
||||||
|
.chart-container {
|
||||||
|
position: relative;
|
||||||
|
height: 310px;
|
||||||
|
width: 49%;
|
||||||
|
float: left;
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-left: 10px;
|
||||||
|
}
|
||||||
@media (max-width: 1920px) {
|
@media (max-width: 1920px) {
|
||||||
#logo_span {
|
#logo_span {
|
||||||
margin-left: 17%;
|
margin-left: 17%;
|
||||||
|
|
|
@ -11,6 +11,4 @@ matplotlib==2.1.2
|
||||||
future==0.13.1
|
future==0.13.1
|
||||||
mysql-connector-python==8.0.11
|
mysql-connector-python==8.0.11
|
||||||
Jinja2>=2.10.1
|
Jinja2>=2.10.1
|
||||||
pandas==0.22.0
|
|
||||||
bokeh==0.13.0
|
|
||||||
python-ldap>=3.1.0
|
python-ldap>=3.1.0
|
||||||
|
|
Loading…
Reference in New Issue