v1.10.2.3

Afax, bugs, design
pull/19/head
Aidaho12 2018-04-11 09:30:46 +06:00
parent 541bfb2b2f
commit 23f45cb30e
10 changed files with 196 additions and 197 deletions

View File

@ -42,7 +42,7 @@ print('<option value="show">Show</option>'
'</td><td>' '</td><td>'
'<input type="checkbox" name="save" id="save" value="123" title="Save changes after restart">' '<input type="checkbox" name="save" id="save" value="123" title="Save changes after restart">'
'</td><td>' '</td><td>'
'<a class="ui-button ui-widget ui-corner-all" id="show" title="Show stats" onclick="showRuntime()">Show</a>' '<a class="ui-button ui-widget ui-corner-all" id="show" title="Enter" onclick="showRuntime()">Enter</a>'
'</td></form>' '</td></form>'
'</tr></table>' '</tr></table>'
'<div id="ajax">' '<div id="ajax">'

View File

@ -160,7 +160,7 @@ def head(title):
def links(): def links():
print('<nav class="menu">' print('<nav class="menu">'
'<ul>' '<ul>'
'<li><a title="Statistics, monitoring and logs" class="stats">Stats</a>' '<li><span style="color: #fff" title="Statistics, monitoring and logs" class="stats">Stats</span>'
'<ul>' '<ul>'
'<li><a href=/cgi-bin/overview.py title="Server and service status" class="overview-link">Overview</a> </li>' '<li><a href=/cgi-bin/overview.py title="Server and service status" class="overview-link">Overview</a> </li>'
'<li><a href=/cgi-bin/viewsttats.py title="View Stats" class="stats">Stats</a> </li>' '<li><a href=/cgi-bin/viewsttats.py title="View Stats" class="stats">Stats</a> </li>'
@ -169,7 +169,7 @@ def links():
'</ul>' '</ul>'
'</li>' '</li>'
'<li><a href=/cgi-bin/edit.py title="Runtime API" class="runtime">Runtime API</a> </li>' '<li><a href=/cgi-bin/edit.py title="Runtime API" class="runtime">Runtime API</a> </li>'
'<li><a class="config-show">Configs</a>' '<li><span style="color: #fff" title="Actions with configs" class="config-show">Configs</span>'
'<ul>' '<ul>'
'<li><a href=/cgi-bin/configshow.py title="Show Config" class="config-show">Show</a></li> ' '<li><a href=/cgi-bin/configshow.py title="Show Config" class="config-show">Show</a></li> '
'<li><a href=/cgi-bin/diff.py title="Compare Configs" class="compare">Compare</a></li>') '<li><a href=/cgi-bin/diff.py title="Compare Configs" class="compare">Compare</a></li>')
@ -180,7 +180,7 @@ def links():
'<li><a href=/cgi-bin/config.py title="Edit Config" class="edit">Edit</a> </li>') '<li><a href=/cgi-bin/config.py title="Edit Config" class="edit">Edit</a> </li>')
print('</ul></li>') print('</ul></li>')
if is_admin(level = 1): if is_admin(level = 1):
print('<li><a class="version">Versions</a>' print('<li><span style="color: #fff" title="Actions with configs" class="version">Versions</span>'
'<ul>' '<ul>'
'<li><a href=/cgi-bin/configver.py title="Upload old versions configs" class="upload">Upload</a></li>') '<li><a href=/cgi-bin/configver.py title="Upload old versions configs" class="upload">Upload</a></li>')
if is_admin(): if is_admin():
@ -191,7 +191,7 @@ def links():
show_login_links() show_login_links()
print('</ul>' print('</ul>'
'</nav>' '</nav>'
'<div class="copyright-menu">HAproxy-WI v1.10.2.2</div>') '<div class="copyright-menu">HAproxy-WI v1.10.2.3</div>')
def show_login_links(): def show_login_links():
cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE")) cookie = http.cookies.SimpleCookie(os.environ.get("HTTP_COOKIE"))
@ -214,10 +214,10 @@ def get_auto_refresh(h2):
print('<h2>') print('<h2>')
print('<span>%s</span>' % h2) print('<span>%s</span>' % h2)
print('<span class="auto-refresh">' print('<span class="auto-refresh">'
'<a id="0"><img style="margin-top: 10px; margin-left: -23px; position: fixed;" src=/image/pic/update.png alt="restart" class="icon"> Auto-refresh</a>' '<a id="0"><img style="margin-top: 3px; margin-left: -23px; position: fixed;" src=/image/pic/update.png alt="restart" class="icon"> Auto-refresh</a>'
'<a id="1" style="display: none;"><img style="margin-top: 10px; margin-left: -23px; position: fixed;" src=/image/pic/update.png alt="restart" class="icon"> Auto-refresh</a>' '<a id="1" style="display: none;"><img style="margin-top: 3px; margin-left: -23px; position: fixed;" src=/image/pic/update.png alt="restart" class="icon"> Auto-refresh</a>'
'<a onclick="pauseAutoRefresh()" title="Pause auto-refresh" class="auto-refresh-pause" style="display: none;"></a>' '<a onclick="pauseAutoRefresh()" title="Pause auto-refresh" class="auto-refresh-pause" style="display: none; margin-top: 4px;"></a>'
'<a onclick="pauseAutoResume()" title="Resume auto-refresh" class="auto-refresh-resume" style="display: none;"></a>' '<a onclick="pauseAutoResume()" title="Resume auto-refresh" class="auto-refresh-resume" style="display: none; margin-top: 4px;"></a>'
'</span></h2>' '</span></h2>'
'<div class="auto-refresh-div">' '<div class="auto-refresh-div">'
'<div class="auto-refresh-head">' '<div class="auto-refresh-head">'

View File

@ -28,7 +28,7 @@ print('<table class="overview">'
'<td class="padding10">' '<td class="padding10">'
'<form action="logs.py" method="get">' '<form action="logs.py" method="get">'
'<select autofocus required name="serv" id="serv">' '<select autofocus required name="serv" id="serv">'
'<option disabled>Choose server</option>') '<option disabled selected>Choose server</option>')
funct.choose_only_select(serv) funct.choose_only_select(serv)

View File

@ -3,6 +3,7 @@ import html
import cgi import cgi
import os import os
import funct import funct
import ovw
import configparser import configparser
from datetime import datetime from datetime import datetime
from pytz import timezone from pytz import timezone
@ -13,117 +14,15 @@ import matplotlib.pyplot as plt
form = cgi.FieldStorage() form = cgi.FieldStorage()
serv = form.getvalue('serv') serv = form.getvalue('serv')
servNew = form.getvalue('serNew')
funct.head("Show HAproxy config") funct.head("Show HAproxy config")
funct.check_config() funct.check_config()
funct.check_login() funct.check_login()
funct.chooseServer("map.py", "Show HAproxy map", "n", onclick="showMap()")
path_config = "haproxy-webintarface.config" print('<div id="ajax">')
config = configparser.ConfigParser() if form.getvalue('serv') is not None:
config.read(path_config) ovw.get_map(serv)
time_zone = config.get('main', 'time_zone') print('</div>')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
haproxy_config_path = config.get('haproxy', 'haproxy_config_path')
stats_port= config.get('haproxy', 'stats_port')
fullpath = config.get('main', 'fullpath')
if serv is not None:
fmt = "%Y-%m-%d.%H:%M:%S"
now_utc = datetime.now(timezone(time_zone))
cfg = hap_configs_dir + serv + "-" + now_utc.strftime(fmt) + ".cfg"
funct.chooseServer("map.py", "Show HAproxy map", "n")
def is_neighbors(G, neighbor):
for line in nx.generate_edgelist(G, data=False):
if neighbor in line:
return True
break
if form.getvalue('serv') is not None and form.getvalue('open') is not None :
print('<a name="map"></a>')
print("<h3>Map from %s</h3><br />" % serv)
G = nx.DiGraph()
funct.get_config(serv, cfg)
conf = open(cfg, "r")
node = ""
line_new2 = [1,""]
i = 1200
k = 1200
j = 0
m = 0
for line in conf:
if "listen" in line or "frontend" in line:
if "stats" not in line:
node = line
i = i - 500
if line.find("backend") == 0:
node = line
i = i - 500
G.add_node(node,pos=(k,i),label_pos=(k,i+150))
if "bind" in line:
bind = line.split(":")
if stats_port not in bind[1]:
bind[1] = bind[1].strip(' ')
bind = bind[1].split("crt")
node = node.strip(' \t\n\r')
node = node + ":" + bind[0]
G.add_node(node,pos=(k,i),label_pos=(k,i+150))
if "server " in line or "use_backend" in line or "default_backend" in line and "stats" not in line:
if "timeout" not in line and "default-server" not in line and "#use_backend" not in line and "stats" not in line:
i = i - 300
j = j + 1
if "check" in line:
line_new = line.split("check")
else:
line_new = line.split("if ")
if "server" in line:
line_new1 = line_new[0].split("server")
line_new[0] = line_new1[1]
line_new2 = line_new[0].split(":")
line_new[0] = line_new2[0]
line_new[0] = line_new[0].strip(' \t\n\r')
line_new2[1] = line_new2[1].strip(' \t\n\r')
if j % 2 == 0:
G.add_node(line_new[0],pos=(k+250,i-350),label_pos=(k+225,i-100))
else:
G.add_node(line_new[0],pos=(k-250,i-50),label_pos=(k-225,i+180))
if line_new2[1] != "":
G.add_edge(node, line_new[0], port=line_new2[1])
else:
G.add_edge(node,line_new[0])
os.system("/bin/rm -f " + cfg)
os.chdir("%s/cgi-bin/" % fullpath)
pos=nx.get_node_attributes(G,'pos')
pos_label=nx.get_node_attributes(G,'label_pos')
edge_labels = nx.get_edge_attributes(G,'port')
try:
plt.figure(10,figsize=(9.5,15))
nx.draw(G, pos, with_labels=False, font_weight='bold', width=3, alpha=0.1,linewidths=5)
nx.draw_networkx_nodes(G,pos, node_color="skyblue", node_size=100, alpha=0.8, node_shape="p")
nx.draw_networkx_labels(G,pos=pos_label, alpha=1, font_color="green", font_size=10)
nx.draw_networkx_edges(G,pos, width=0.5,alpha=0.5, edge_color="#5D9CEB",arrows=False)
nx.draw_networkx_edge_labels(G, pos,label_pos=0.5,font_color="blue", labels=edge_labels, font_size=8)
plt.savefig("map.png")
plt.show()
except Exception as e:
print("!!! There was an issue, " + str(e))
commands = [ "mv %s/cgi-bin/map.png %s" % (fullpath, fullpath)]
funct.ssh_command("localhost", commands)
print('<img src="/map.png" alt="map">')
funct.footer() funct.footer()

View File

@ -4,6 +4,7 @@ import cgi
import json import json
import subprocess import subprocess
import funct import funct
import ovw
import configparser import configparser
options = [ "acl", "http-request", "http-response", "set-uri", "set-url", "set-header", "add-header", "del-header", "replace-header", "path_beg", "url_beg()", "urlp_sub()", "tcpka", "tcplog", "forwardfor", "option" ] options = [ "acl", "http-request", "http-response", "set-uri", "set-url", "set-header", "add-header", "del-header", "replace-header", "path_beg", "url_beg()", "urlp_sub()", "tcpka", "tcplog", "forwardfor", "option" ]
@ -71,27 +72,8 @@ if form.getvalue('action') is not None and serv is not None:
else: else:
print("Bad config, check please") print("Bad config, check please")
if serv is not None and form.getvalue('rows') is not None: if form.getvalue('act') == "overview":
rows = form.getvalue('rows') ovw.get_overview()
grep = form.getvalue('grep')
if grep is not None:
grep_act = '|grep'
else:
grep_act = ''
grep = ''
syslog_server_enable = config.get('logs', 'syslog_server_enable')
if syslog_server_enable is None or syslog_server_enable == "0":
local_path_logs = config.get('logs', 'local_path_logs')
syslog_server = serv
commands = [ 'sudo tail -%s %s %s %s' % (rows, local_path_logs, grep_act, grep) ]
else:
commands = [ 'sudo tail -%s /var/log/%s/syslog.log %s %s' % (rows, serv, grep_act, grep) ]
syslog_server = config.get('logs', 'syslog_server')
print('<div id"logs">')
funct.ssh_command(syslog_server, commands, show_log="1")
print('</div>')
if serv is not None and form.getvalue('act') == "stats": if serv is not None and form.getvalue('act') == "stats":
import requests import requests
@ -119,9 +101,30 @@ if serv is not None and form.getvalue('act') == "stats":
data = response.content data = response.content
print(data.decode('utf-8')) print(data.decode('utf-8'))
if form.getvalue('act') == "overview": if serv is not None and form.getvalue('rows') is not None:
import ovw rows = form.getvalue('rows')
ovw.get_overview() grep = form.getvalue('grep')
if grep is not None:
grep_act = '|grep'
else:
grep_act = ''
grep = ''
syslog_server_enable = config.get('logs', 'syslog_server_enable')
if syslog_server_enable is None or syslog_server_enable == "0":
local_path_logs = config.get('logs', 'local_path_logs')
syslog_server = serv
commands = [ 'sudo tail -%s %s %s %s' % (rows, local_path_logs, grep_act, grep) ]
else:
commands = [ 'sudo tail -%s /var/log/%s/syslog.log %s %s' % (rows, serv, grep_act, grep) ]
syslog_server = config.get('logs', 'syslog_server')
print('<div id"logs">')
funct.ssh_command(syslog_server, commands, show_log="1")
print('</div>')
if serv is not None and form.getvalue('act') == "showMap":
ovw.get_map(serv)
if form.getvalue('servaction') is not None: if form.getvalue('servaction') is not None:
server_state_file = config.get('haproxy', 'server_state_file') server_state_file = config.get('haproxy', 'server_state_file')

View File

@ -2,9 +2,6 @@
import html import html
import cgi import cgi
import funct import funct
import configparser
import json
import listserv as listhap
import ovw import ovw
funct.head("Overview") funct.head("Overview")

View File

@ -2,13 +2,19 @@ import funct
import configparser import configparser
import json import json
path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser()
config.read(path_config)
time_zone = config.get('main', 'time_zone')
cgi_path = config.get('main', 'cgi_path')
fullpath = config.get('main', 'fullpath')
stats_port= config.get('haproxy', 'stats_port')
haproxy_config_path = config.get('haproxy', 'haproxy_config_path')
status_command = config.get('haproxy', 'status_command')
hap_configs_dir = config.get('configs', 'haproxy_save_configs_dir')
def get_overview(): def get_overview():
path_config = "haproxy-webintarface.config"
config = configparser.ConfigParser()
config.read(path_config)
haproxy_config_path = config.get('haproxy', 'haproxy_config_path')
status_command = config.get('haproxy', 'status_command')
cgi_path = config.get('main', 'cgi_path')
USERS = cgi_path + '/users' USERS = cgi_path + '/users'
try: try:
@ -106,3 +112,102 @@ def get_overview():
print('</pre></td></tr>') print('</pre></td></tr>')
print('<tr></table>') print('<tr></table>')
def get_map(serv):
import os
from datetime import datetime
from pytz import timezone
import networkx as nx
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
fmt = "%Y-%m-%d.%H:%M:%S"
now_utc = datetime.now(timezone(time_zone))
cfg = hap_configs_dir + serv + "-" + now_utc.strftime(fmt) + ".cfg"
print('<center>')
print("<h3>Map from %s</h3><br />" % serv)
G = nx.DiGraph()
funct.get_config(serv, cfg)
conf = open(cfg, "r")
node = ""
line_new2 = [1,""]
i = 1200
k = 1200
j = 0
m = 0
for line in conf:
if "listen" in line or "frontend" in line:
if "stats" not in line:
node = line
i = i - 500
if line.find("backend") == 0:
node = line
i = i - 500
G.add_node(node,pos=(k,i),label_pos=(k,i+150))
if "bind" in line:
bind = line.split(":")
if stats_port not in bind[1]:
bind[1] = bind[1].strip(' ')
bind = bind[1].split("crt")
node = node.strip(' \t\n\r')
node = node + ":" + bind[0]
G.add_node(node,pos=(k,i),label_pos=(k,i+150))
if "server " in line or "use_backend" in line or "default_backend" in line and "stats" not in line:
if "timeout" not in line and "default-server" not in line and "#use_backend" not in line and "stats" not in line:
i = i - 300
j = j + 1
if "check" in line:
line_new = line.split("check")
else:
line_new = line.split("if ")
if "server" in line:
line_new1 = line_new[0].split("server")
line_new[0] = line_new1[1]
line_new2 = line_new[0].split(":")
line_new[0] = line_new2[0]
line_new[0] = line_new[0].strip(' \t\n\r')
line_new2[1] = line_new2[1].strip(' \t\n\r')
if j % 2 == 0:
G.add_node(line_new[0],pos=(k+250,i-350),label_pos=(k+225,i-100))
else:
G.add_node(line_new[0],pos=(k-250,i-50),label_pos=(k-225,i+180))
if line_new2[1] != "":
G.add_edge(node, line_new[0], port=line_new2[1])
else:
G.add_edge(node,line_new[0])
os.system("/bin/rm -f " + cfg)
os.chdir(cgi_path)
pos=nx.get_node_attributes(G,'pos')
pos_label=nx.get_node_attributes(G,'label_pos')
edge_labels = nx.get_edge_attributes(G,'port')
try:
plt.figure(10,figsize=(9.5,15))
nx.draw(G, pos, with_labels=False, font_weight='bold', width=3, alpha=0.1,linewidths=5)
nx.draw_networkx_nodes(G,pos, node_color="skyblue", node_size=100, alpha=0.8, node_shape="p")
nx.draw_networkx_labels(G,pos=pos_label, alpha=1, font_color="green", font_size=10)
nx.draw_networkx_edges(G,pos, width=0.5,alpha=0.5, edge_color="#5D9CEB",arrows=False)
nx.draw_networkx_edge_labels(G, pos,label_pos=0.5,font_color="blue", labels=edge_labels, font_size=8)
plt.savefig("map.png")
plt.show()
except Exception as e:
print("!!! There was an issue, " + str(e))
commands = [ "rm -f "+fullpath+"/map*.png", "mv %s/map.png %s/map%s.png" % (cgi_path, fullpath, now_utc.strftime(fmt)) ]
funct.ssh_command("localhost", commands)
print('<img src="/map%s.png" alt="map">' % now_utc.strftime(fmt))
#commands = [ "rm -f %s/map%s.png" % (fullpath, now_utc.strftime(fmt))]
#funct.ssh_command("localhost", commands)

View File

@ -30,7 +30,7 @@
position: fixed; position: fixed;
z-index: 1031; z-index: 1031;
top: 15px; top: 15px;
right: 55px; right: 175px;
} }
#nprogress .spinner-icon { #nprogress .spinner-icon {
width: 18px; width: 18px;

View File

@ -28,7 +28,7 @@ function setRefreshInterval(interval) {
if (interval == "0") { if (interval == "0") {
Cookies.remove('auto-refresh'); Cookies.remove('auto-refresh');
pauseAutoRefresh(); pauseAutoRefresh();
$('.auto-refresh').append('<img style="margin-top: 10px; margin-left: -110px; position: fixed;" src=/image/pic/update.png alt="restart" class="icon">'); $('.auto-refresh').append('<img style="margin-top: 3px; margin-left: -110px; position: fixed;" src=/image/pic/update.png alt="restart" class="icon">');
$('#1').text('Auto-refresh'); $('#1').text('Auto-refresh');
$('#0').text('Auto-refresh'); $('#0').text('Auto-refresh');
$('.auto-refresh-pause').css('display', 'none'); $('.auto-refresh-pause').css('display', 'none');
@ -80,6 +80,12 @@ function hideAutoRefreshDiv() {
$('#0').css("display", "inline"); $('#0').css("display", "inline");
}); });
} }
$( document ).ajaxSend(function( event, request, settings ) {
NProgress.start();
});
$( document ).ajaxComplete(function( event, request, settings ) {
NProgress.done();
});
function showOverview() { function showOverview() {
$.ajax( { $.ajax( {
url: "options.py", url: "options.py",
@ -87,12 +93,6 @@ function showOverview() {
act: "overview", act: "overview",
}, },
type: "GET", type: "GET",
beforeSend: function () {
NProgress.start();
},
complete: function () {
NProgress.done();
},
success: function( data ) { success: function( data ) {
var form = $("#ajax").html(); var form = $("#ajax").html();
$("#ajax").html(data); $("#ajax").html(data);
@ -108,12 +108,6 @@ function showStats() {
serv: $("#serv").val() serv: $("#serv").val()
}, },
type: "GET", type: "GET",
beforeSend: function () {
NProgress.start();
},
complete: function () {
NProgress.done();
},
success: function( data ) { success: function( data ) {
var form = $("#ajax").html(); var form = $("#ajax").html();
$("#ajax").html(data); $("#ajax").html(data);
@ -130,18 +124,29 @@ function showLog() {
grep: $("#grep").val(), grep: $("#grep").val(),
}, },
type: "GET", type: "GET",
beforeSend: function () {
NProgress.start();
},
complete: function () {
NProgress.done();
},
success: function( data ) { success: function( data ) {
var form = $("#ajax").html(); var form = $("#ajax").html();
$("#ajax").html(data); $("#ajax").html(data);
} }
} ); } );
} }
function showMap() {
var unique = $.now();
$.ajax( {
url: "options.py",
data: {
serv: $("#serv").val(),
act: "showMap"
},
type: "GET",
success: function( data ) {
var form = $("#ajax").html();
$("#ajax").html(data);
window.history.pushState("Map", "Map", cur_url[0]+"?serv="+$("#serv").val());
}
} );
}
function showRuntime() { function showRuntime() {
if($('#save').prop('checked')) { if($('#save').prop('checked')) {
saveCheck = "on"; saveCheck = "on";
@ -157,12 +162,6 @@ function showRuntime() {
save: saveCheck save: saveCheck
}, },
type: "GET", type: "GET",
beforeSend: function () {
NProgress.start();
},
complete: function () {
NProgress.done();
},
success: function( data ) { success: function( data ) {
var form = $("#ajax").html(); var form = $("#ajax").html();
$("#ajax").html(data); $("#ajax").html(data);
@ -178,12 +177,6 @@ function showCompare() {
right: $("#right").val() right: $("#right").val()
}, },
type: "GET", type: "GET",
beforeSend: function () {
NProgress.start();
},
complete: function () {
NProgress.done();
},
success: function( data ) { success: function( data ) {
var form = $("#ajax").html(); var form = $("#ajax").html();
$("#ajax").html(data); $("#ajax").html(data);
@ -199,12 +192,6 @@ function showConfig() {
act: "configShow" act: "configShow"
}, },
type: "GET", type: "GET",
beforeSend: function () {
NProgress.start();
},
complete: function () {
NProgress.done();
},
success: function( data ) { success: function( data ) {
var form = $("#ajax").html(); var form = $("#ajax").html();
$("#ajax").html(data); $("#ajax").html(data);
@ -214,6 +201,15 @@ function showConfig() {
} }
$( function() { $( function() {
$( "#serv" ).on('selectmenuchange',function() {
$("#show").css("pointer-events", "inherit");
$("#show").css("cursor", "pointer");
});
if ($( "#serv option:selected" ).val() == "Choose server") {
$("#show").css("pointer-events", "none");
$("#show").css("cursor", "not-allowed");
}
var pause = '<a onclick="pauseAutoRefresh()" title="Pause auto-refresh" class="auto-refresh-pause"></a>' var pause = '<a onclick="pauseAutoRefresh()" title="Pause auto-refresh" class="auto-refresh-pause"></a>'
var autoRefresh = Cookies.get('auto-refresh'); var autoRefresh = Cookies.get('auto-refresh');

View File

@ -19,9 +19,6 @@ h2 {
margin-top: 0px; margin-top: 0px;
margin-bottom: 0px; margin-bottom: 0px;
} }
h2 span {
width: 300px;
}
h3 { h3 {
margin-top: 10px; margin-top: 10px;
margin-bottom: 0px; margin-bottom: 0px;
@ -90,7 +87,10 @@ pre {
padding-bottom: 10px; padding-bottom: 10px;
} }
.auto-refresh { .auto-refresh {
margin-left: 86%; margin-left: auto;
float: right;
margin-top: 5px;
margin-right: 30px;
} }
.auto-refresh a { .auto-refresh a {
color: #fff !important; color: #fff !important;
@ -112,14 +112,13 @@ pre {
cursor: pointer; cursor: pointer;
} }
.auto-refresh-head { .auto-refresh-head {
margin-top: 0;
font-size: 16px; font-size: 16px;
color: #2d2d2d; color: #2d2d2d;
font-weight: bold; font-weight: bold;
margin-left: 77%; margin-left: 83%;
} }
.auto-refresh-interval { .auto-refresh-interval {
float: left; float: right;
padding: 0px 15px; padding: 0px 15px;
margin-left: 75%; margin-left: 75%;
} }