Commit add0c504 by zdc

new user interface

* new style for user interface
* now you can serve user interface without a lookis service (or with - it's your choice)
* changed nginx template
parent 11e34d43
......@@ -30,11 +30,11 @@ user@pc:/tmp$ go build lookis.go
#### **Install**
After you build **lookis**:
* copy this files to target system:
* copy this files and directories to target system:
```
lookis
config.toml
page_main.gtpl
html/
```
* place it to selected directory (**`/opt/lookis/`**, for example).
* edit **`config.toml`** to satisfy your needs.
......
......@@ -5,16 +5,22 @@ upstream lookis_server {
}
server {
listen 80;
server_name lookis.domain;
listen 80;
server_name lookis.domain;
location / {
proxy_redirect off;
proxy_read_timeout 300s;
limit_req zone=lookis_lim burst=20 nodelay;
root /opt/lookis/html;
index index.html;
}
location /json {
proxy_redirect off;
proxy_read_timeout 300s;
limit_req zone=lookis_lim burst=10 nodelay;
if (!-f $request_filename) {
proxy_pass http://lookis_server;
proxy_pass http://lookis_server;
break;
}
}
......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Looking Glass</title>
<script type="text/javascript" src="/jquery-3.1.1.min.js"></script>
<script type="text/javascript" src="/lookis-ui.js"></script>
<style>@import url('/styles.css');</style>
</head>
<body>
<section id="navigation">
<header id="header">
Looking Glass
</header>
<nav>
<select id="router">
</select>
<select id="action">
</select>
<input id="argument" type="search" name="argument" size="16" maxlength="15" placeholder="IP address" autofocus />
<button type="button" onclick="doit()">Do it!</button>
</nav>
<main>
<section id="status"></section>
<section id="output-body"></section>
</main>
</section>
<footer>
powered by <a target="_blank" href="https://gitlab.com/zdc/lookis">lookis</a>
</footer>
</body>
</html>
// setting global variables
var jsondata;
// get json data from server
$(function() {
$.getJSON( "json", function (jsonraw) {
jsondata = jsonraw;
// fill actions for selected router
FillInRouter();
FillInAction();
});
});
// action to do when router is selected
$(function() {
$( "#router" ).change ( function () {
// fill actions for selected router
FillInAction();
});
});
// handle "enter" key
$(function() {
$('#argument').keypress( function (event) {
var keycode = (event.keyCode ? event.keyCode : event.which);
if (keycode == '13') {
doit();
}
});
});
function addAction(OptionData, index, array) {
var action = document.getElementById("action");
var option = document.createElement("option");
$.each(OptionData, function() {
option.value = OptionData.CommandId;
option.text = OptionData.CommandName;
action.add(option);
});
}
function FillInRouter() {
var router = document.getElementById("router");
// add routers to list
$.each(jsondata, function(i, v) {
var option = document.createElement("option");
option.value = v.RouterId;
option.text = v.RouterName;
router.add(option);
});
}
function FillInAction() {
var router = document.getElementById("router");
var RouterId = router.value;
var action = document.getElementById("action");
// clear action list
$(action).empty()
// add actions to list
$.each(jsondata, function(i, v) {
if (v.RouterId == RouterId) {
v.RouterCommands.forEach(addAction);
}
});
}
function doit() {
// get selected form values
var router = document.getElementById("router").value;
var action = document.getElementById("action").value;
var argument = document.getElementById('argument').value;
// format JSON
var request_data = JSON.stringify({ "router": router, "action": action, "argument": argument });
document.getElementById("status").innerHTML = "Please wait...";
// make POST request to server with JSON data
$.ajax({
url: '/json',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: request_data,
dataType: "json",
error: DrawTryLater,
success: DrawResult
});
}
// slide up navigation bar
function SlideUpNav() {
var navId = document.getElementById("navigation");
var navTop = parseInt(window.getComputedStyle(navId).getPropertyValue("top"));
document.getElementById("header").style.fontSize = "2.5em";
for (i = 0; i < navTop; i++) {
(function(i){
var top = navTop - i + "px";
window.setTimeout(function() { document.getElementById("navigation").style.top = top; }, i * 1);
}(i));
}
}
// show result to user
function DrawResult(jsonresult) {
if (jsonresult['Status'] != "Error") {
SlideUpNav();
} else {
document.getElementById("output-body").style.textAlign = "center";
document.getElementById("output-body").style.marginLeft = "0";
}
document.getElementById("output-body").style.textAlign = "left";
document.getElementById("output-body").style.marginLeft = "15%";
document.getElementById("status").innerHTML = jsonresult['Status'];
document.getElementById("output-body").innerHTML = jsonresult['Result'];
}
// ask user to try later
function DrawTryLater() {
document.getElementById("output-body").style.textAlign = "center";
document.getElementById("output-body").style.marginLeft = "0";
document.getElementById("status").innerHTML = "Error";
document.getElementById("output-body").innerHTML = "Request limit reached";
}
body {
font-family: Arial;
}
#navigation {
position: absolute;
left: 0;
top: 25%;
width: 100%;
text-align: center;
}
header {
font-size: 3em;
text-align: left;
margin-top: 10px;
margin-left: 20px;
}
nav {
margin-top: 20px;
padding-top: 20px;
padding-bottom: 20px;
background: #8A9B68;
}
form {
font-family: monospace;
}
select, input, button {
font-family: monospace;
font-weight: bold;
font-size: 1.5em;
border-style: none;
border-width: 3px;
border-color: #797D81;
border-radius: 10px;
padding: 16px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
}
select {
cursor: pointer;
}
main {
position: static;
text-align: left;
}
#status {
margin-top: 20px;
text-align: center;
font-weight: bold;
font-size: 1.5em;
}
#output-body {
margin-top: 20px;
margin-left: 15%;
margin-bottom: 4rem;
text-align: left;
font-family: monospace;
white-space: pre;
}
footer {
bottom: 0;
right: 0;
left: 0;
position: fixed;
text-align: center;
background-color: #D5DDBC;
padding: 1rem;
opacity: 0.5;
}
......@@ -42,7 +42,7 @@ func PrepareJson (StatusRaw, ResultRaw string) JsonOut {
if StatusRaw == "Error" {
log.Printf("Error! \"%s\"", ResultRaw)
}
output := JsonOut{ Status: "<strong>"+StatusRaw+"</strong>", Result: "<pre>"+ResultRaw+"</pre>" }
output := JsonOut{ Status: StatusRaw, Result: ResultRaw }
return output
}
......@@ -190,16 +190,6 @@ func ParseRoutersFromConfig () []Router {
return routers
}
// show page
func ShowPage (w http.ResponseWriter, r *http.Request) {
// check HTTP method
if r.Method == "GET" {
http.ServeFile(w, r, datapath+"/page_main.gtpl")
} else {
w.Write([]byte("Not allowed!"))
}
}
// show JSON with routers and commands
func ShowJSON (w http.ResponseWriter, r *http.Request) {
// check method
......@@ -301,7 +291,8 @@ func main() {
// set http server variables
server_address := viper.GetString("server.address")
server_port := viper.GetString("server.port")
http.HandleFunc("/", ShowPage)
server_html := http.FileServer(http.Dir(datapath+"/html"))
http.Handle("/", server_html)
http.HandleFunc("/json", ShowJSON)
// run server
......
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.1.js"></script>
<title>Looking Glass</title>
</head>
<body>
<p>&nbsp;</p>
<form>
<table style="margin-left: auto; margin-right: auto;">
<tbody>
<tr>
<td style="text-align: center;" colspan="3">
<p><strong>Looking Glass</strong></p>
<p>&nbsp;</p>
</td>
</tr>
<tr>
<td>Router</td>
<td style="width: 50px;">&nbsp;</td>
<td>
<select id="router" name="router">
</select>
</td>
</tr>
<tr>
<td>Action</td>
<td>&nbsp;</td>
<td>
<select id="action" name="action">
</select>
</td>
</tr>
<tr>
<td>Argument</td>
<td>&nbsp;</td>
<td><input id="argument" name="argument" type="text" /></td>
</tr>
<tr>
<td style="text-align: center;" colspan="3">
<p>&nbsp;</p>
<p><button type="button" onclick="doit()">Do it!</button></p>
</td>
</tr>
</tbody>
</table>
</form>
<table style="margin-left: auto; margin-right: auto;">
<tbody>
<tr>
<td id="output-header" style="text-align: center;"></td>
</tr>
<tr>
<td id="output-body"><pre></pre></td>
</tr>
</tbody>
</table>
<script type="text/javascript">
// setting global variables
var jsondata;
var action = document.getElementById("action");
// get json data from server
$.getJSON( "json", function (jsonraw) {
jsondata = jsonraw;
// fill actions for selected router
FillInRouter();
FillInAction();
});
// action to do when router is selected
$( "#router" ).change ( function () {
// fill actions for selected router
FillInAction();
});
function addAction(OptionData, index, array) {
var option = document.createElement("option");
$.each(OptionData, function() {
option.value = OptionData.CommandId;
option.text = OptionData.CommandName;
action.add(option);
});
}
function FillInRouter() {
var router = document.getElementById('router');
// add routers to list
$.each(jsondata, function(i, v) {
var option = document.createElement("option");
option.value = v.RouterId;
option.text = v.RouterName;
router.add(option);
});
}
function FillInAction() {
var router = document.getElementById('router');
var RouterId = router.value;
// clear action list
$(action).empty()
// add actions to list
$.each(jsondata, function(i, v) {
if (v.RouterId == RouterId) {
v.RouterCommands.forEach(addAction);
}
});
}
function doit() {
// get selected form values
var router = document.getElementById('router').value;
var action = document.getElementById('action').value;
var argument = document.getElementById('argument').value;
// format JSON
var request_data = JSON.stringify({ "router": router, "action": action, "argument": argument });
document.getElementById("output-header").innerHTML = "Please wait...";
// make POST request to server with JSON data
$.ajax({
url: '/json',
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: request_data,
dataType: "json"
}).done(DrawResult);
}
// show result to user
function DrawResult(jsonresult) {
document.getElementById("output-header").innerHTML = jsonresult['Status'];
document.getElementById("output-body").innerHTML = jsonresult['Result'];
}
</script>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment