aboutsummaryrefslogtreecommitdiffstats
path: root/web
diff options
context:
space:
mode:
Diffstat (limited to 'web')
-rw-r--r--web/css/nms.css9
-rw-r--r--web/index.html16
-rw-r--r--web/js/nms-info-box.js259
-rw-r--r--web/js/nms-types.js14
-rw-r--r--web/js/nms-ui-boxes.js9
-rw-r--r--web/js/nms-ui-switch.js167
6 files changed, 137 insertions, 337 deletions
diff --git a/web/css/nms.css b/web/css/nms.css
index 32f302c..8f59488 100644
--- a/web/css/nms.css
+++ b/web/css/nms.css
@@ -9,9 +9,6 @@ canvas {
-webkit-tap-highlight-color: rgba(255, 255, 255, 0); /* mobile webkit */
}
-#info-box-container {
- max-width: 700px;
-}
#info-box-container #edit-output {
word-wrap: break-word;
padding: 20px;
@@ -133,11 +130,7 @@ div.map-mode-legend button {
.graph {
max-width: 100%;
width: 100%;
- height: 240px;
-}
-.genericBox {
- position: absolute;
- z-index: 120;
+ height: 10px;
}
button,input {
diff --git a/web/index.html b/web/index.html
index 05fd582..23431b1 100644
--- a/web/index.html
+++ b/web/index.html
@@ -47,13 +47,12 @@
</a>
<ul class="dropdown-menu" role="menu">
<li class="gondul-is-private dropdown-header">Switches</li>
- <li class="gondul-is-private"><a href="#" onclick="nmsInfoBox.showWindow('addSwitch')">Add switch</a></li>
- <li class="gondul-is-private"><a href="#" onclick="nmsInfoBox.showWindow('addNetwork')">Add network</a></li>
- <li class="gondul-is-private"><a href="#" onclick="nmsInfoBox.showWindow('listNetwork')">List networks</a></li>
- <li class="gondul-is-private"><a href="#" onclick="nmsMap.moveSet(true);">Enable switch moving</a></li>
- <li class="gondul-is-private"><a href="#" onclick="nmsMap.moveSet(false);">Disable switch moving</a></li>
- <li class="gondul-is-private divider"> </li>
- <li class="divider"> </li>
+ <li class="gondul-is-private"><a href="#" onclick="new nmsNewSwitch().show();">Add switch</a></li>
+ <li class="gondul-is-private"><a href="#" onclick="new nmsNewNet().show();">Add network</a></li>
+ <li class="gondul-is-private"><a href="#" onclick="nmsInfoBox.showWindow('listNetwork')">List networks</a></li>
+ <li class="gondul-is-private"><a href="#" onclick="nmsMap.moveSet(true);">Enable switch moving</a></li>
+ <li class="gondul-is-private"><a href="#" onclick="nmsMap.moveSet(false);">Disable switch moving</a></li>
+ <li class="gondul-is-private divider"> </li>
<li class="dropdown-header">Time</li>
<li><a href="#" onclick="toggleLayer('nowPickerBox');nmsTime.startNowPicker();">Travel in time</a></li>
<li><a href="#" onclick="nmsTime.replayEvent();" title="Replay from opening 120 minutes per second">Replay event</a></li>
@@ -276,7 +275,8 @@
</div>
</div>
</div>
- <div id="info-box-container" class="col-sm-8 col-md-6 col-lg-5 hidden" style="position: absolute; z-index: 120;">
+ <div id="genericPanelContainer" style="ma-width: 60%; position: absolute; display: grid; grid-template-coumns: repeat(auto-fit,minmax(30%,100%));grid-gap: 10px; z-index: 120;">
+ <div id="info-box-container" class="hidden" style="grid-column: 1 / auto; max-width: 700px; min-width: 500px;"> </div>
</div>
</div>
diff --git a/web/js/nms-info-box.js b/web/js/nms-info-box.js
index 6915b03..8990bdb 100644
--- a/web/js/nms-info-box.js
+++ b/web/js/nms-info-box.js
@@ -145,7 +145,6 @@ nmsInfoBox.showWindow = function (windowName,argument) {
this._sw = argument;
this._windowHandler.showWindow(windowName,argument)
- this._container.style.display = "block";
$(this._windowHandler.getTitleObj()).on('mousedown', function(e) {
var cont = $(nmsInfoBox._container);
@@ -789,44 +788,6 @@ var searchResultsPanel = function() {
nmsInfoBox.addPanelType("searchResults",searchResultsPanel);
/*
- * Panel type: Add switch
- *
- * Lets you add a new switch using the switch-add api
- *
- */
-var switchAddPanel = function() {
- nmsInfoPanel.call(this,"switchAdd");
- this.refresh = function(reason) {
- var domObj = document.createElement("div");
- domObj.innerHTML = '<input type="text" class="form-control" id="create-sysname" placeholder="Space-seaprated list of system names"></br><button class="btn btn-default" onclick="nmsInfoBox._windowHandler.doInPanel(\'' + this.id +'\',\'save\');">Add switch</button>'
- this._render(domObj);
- };
- this.save = function () {
- var sysname = document.getElementById('create-sysname').value.split(" ");
- var myData = [];
- for (var v in sysname) {
- myData.push({"sysname":sysname[v]});
- }
- var myData = JSON.stringify(myData);
- $.ajax({
- type: "POST",
- url: "/api/write/switches",
- dataType: "text",
- data:myData,
- success: function (data, textStatus, jqXHR) {
- var result = JSON.parse(data);
- if(result.switches_addded.length > 0) { // FIXME unresolved variable switches_addded
- nmsInfoBox.hide();
- }
- nmsData.invalidate("switches");
- nmsData.invalidate("smanagement");
- }
- });
- };
-};
-nmsInfoBox.addPanelType("switchAdd",switchAddPanel);
-
-/*
* Panel type: Edit switch
*
* Lets you edit basic switch and switch management data through the switch-update api
@@ -915,7 +876,7 @@ var switchLatencyPanel = function() {
var latency = document.createElement("canvas");
latency.id = this.sw+'latency_chart';
latency.width = 500;
- latency.height = 250;
+ latency.height = 50;
drawLatency(this.sw+'latency_chart',this.sw, false, function(chart) { latencyChart = chart; });
topper.appendChild(latency);
this._render(topper);
@@ -992,44 +953,6 @@ var switchLinks = function() {
};
};
nmsInfoBox.addPanelType("switchLinks",switchLinks);
-/*
-* Panel type: Add network
-*
-* Lets you add a new network using the network-add api
-*
-*/
-var networkAddPanel = function() {
- nmsInfoPanel.call(this,"networkAdd");
- this.refresh = function(reason) {
- var domObj = document.createElement("div");
- domObj.innerHTML = '<input type="text" class="form-control" id="create-network-name" placeholder="Space-seaprated list of networks"><button class="btn btn-default" onclick="nmsInfoBox._windowHandler.doInPanel(\'' + this.id +'\',\'save\');">Add network</button>'
- this._render(domObj);
- };
- this.save = function () {
- var name = document.getElementById('create-network-name').value.split(" ");
- var myData = [];
- for (var v in name) {
- myData.push({"name":name[v]});
- }
- var myData = JSON.stringify(myData);
- $.ajax({
- type: "POST",
- url: "/api/write/networks",
- dataType: "text",
- data:myData,
- success: function (data, textStatus, jqXHR) {
- var result = JSON.parse(data);
- if(result.networks_added.length > 0) { // FIXME unresolved variable switches_addded
- nmsInfoBox.hide();
- }
- nmsData.invalidate("switches");
- nmsData.invalidate("smanagement");
- nmsData.invalidate("networks");
- }
- });
- };
-};
-nmsInfoBox.addPanelType("networkAdd",networkAddPanel);
/*
* List networks
@@ -1076,161 +999,6 @@ var networkSummaryPanel = function() {
nmsInfoBox.addPanelType("networkSummary",networkSummaryPanel);
/*
-* Panel type: Edit networki
-*
-* Lets you edit basic networks data through the network-update api
-*
-*/
-var networkEditPanel = function() {
- nmsInfoPanel.call(this,"networkEdit");
- this.refresh = function(reason) {
- var net = [];
- try {
- net = nmsData.networks.networks[this.sw];
- } catch(e) {}
-
-
- var domObj = document.createElement("div");
- var template = {};
-
- nmsInfoBox._editValues = {};
- var place;
- var tags;
- for (var v in net) {
- /*
- * Tags needs to be sent and edited
- * as plain JSON...
- */
- if (v == "tags") {
- tags = JSON.stringify(net[v]);
- template[v] = tags;
- continue;
- }
- template[v] = nmsInfoBox._nullBlank(net[v]);
- }
- var content = [];
- for (v in template) {
- var tmpsw = '\'' + this.sw + '\'';
- var tmpv = '\'' + v + '\'';
- var tmphandler = '"nmsInfoBox._editChange(' + tmpsw + ',' + tmpv + ');"';
- var html = '<input type="text" class="form-control" value="' + template[v] + '" id="edit-' + this.sw + '-' + v + '" onchange=' + tmphandler + ' oninput=' + tmphandler + ' ' + (v == 'name' ? "readonly" : "") + '>';
- if (v == "placement") {
- v = "placement <a onclick='var _x = document.getElementById(\"edit-" + this.sw + "-placement\"); _x.value = \"\\\"reset\\\"\"; _x.oninput();' class='pull-right'>Reset</a>";
- }
- content.push([v, html]);
- }
-
- content.sort();
-
- var table = nmsInfoBox._makeTable(content);
- domObj.appendChild(table);
-
- var outputCont = document.createElement("div");
- outputCont.id = "edit-output-cont";
- outputCont.classList.add("collapse");
- outputCont.innerHTML = "<h5>Request preview</h5>";
- var output = document.createElement("output");
- output.id = "edit-output";
- outputCont.appendChild(output);
- domObj.appendChild(outputCont);
-
- var nav = document.createElement("nav");
- nav.classList.add("nav","nav-pills");
-
- var submit = document.createElement("button");
- submit.innerHTML = "Save changes";
- submit.classList.add("btn", "btn-primary");
- submit.id = "edit-submit-" + this.sw;
- submit.setAttribute("onclick","nmsInfoBox._windowHandler.doInPanel('" + this.id + "','save');");
- nav.appendChild(submit);
-
- var toggleDetails = document.createElement("button");
- toggleDetails.innerHTML = '<span class="glyphicon glyphicon-menu-hamburger" aria-hidden="true"></span>';
- toggleDetails.classList.add("btn", "btn-default", "pull-right");
- toggleDetails.dataset.toggle = "collapse";
- toggleDetails.dataset.target = "#edit-output-cont";
- toggleDetails.title = "Show request preview";
- toggleDetails.id = "edit-toggle-details-" + this.sw;
- nav.appendChild(toggleDetails);
-
- domObj.appendChild(nav);
-
- this._render(domObj);
- if (place) {
- var pval = document.getElementById("edit-" + this.sw + "-placement");
- if (pval) {
- pval.value = place;
- }
- }
- if (tags) {
- var ptags = document.getElementById("edit-" + this.sw + "-tags");
- if (ptags) {
- ptags.value = tags;
- }
- }
-
- };
- this.save = function () {
- var myData = nmsInfoBox._editStringify(this.sw,"name");
- $.ajax({
- type: "POST",
- url: "/api/write/networks",
- dataType: "text",
- data:myData,
- success: function (data, textStatus, jqXHR) {
- var result = JSON.parse(data);
- if(result.switches_updated.length > 0) { // FIXME unresolved variable switches_addded
- nmsInfoBox.hide();
- }
- nmsData.invalidate("switches");
- nmsData.invalidate("networks");
- nmsData.invalidate("smanagement");
- }
- });
- };
-};
-nmsInfoBox.addPanelType("networkEdit",networkEditPanel);
-
-
-/*
- * General-purpose table-maker?
- *
- * Takes an array of arrays as input, and an optional caption.
- *
- * E.g.: _makeTable([["name","Kjell"],["Age","five"]], "Age list");
- */
-nmsInfoBox._makeTable = function(content, caption) {
- var table = document.createElement("table");
- var tr;
- var td1;
- var td2;
- table.className = "table";
- table.classList.add("table");
- table.classList.add("table-condensed");
- if (caption != undefined) {
- var cap = document.createElement("caption");
- cap.textContent = caption;
- table.appendChild(cap);
- }
- for (var v in content) {
- tr = table.insertRow(-1);
- tr.className = content[v][0].toLowerCase().replace(/[^a-z0-9_]/g,"");
- td1 = tr.insertCell(0);
- td1.classList.add("left");
- td2 = tr.insertCell(1);
- td1.innerHTML = content[v][0];
- td2.innerHTML = content[v][1];
- }
- return table;
-};
-
-nmsInfoBox._nullBlank = function(x) {
- if (x == null || x == false || x == undefined)
- return "";
- return x;
-};
-
-/*
* Provide common defaults for graph renders.
*
* Kept on the URL to avoid having to manage templates since we need to
@@ -1267,28 +1035,3 @@ nmsInfoBox._graphDefaults = function(title) {
return base;
}
}
-
-nmsInfoBox._editChange = function(sw, v) {
- var el = document.getElementById("edit-" + sw + "-" + v);
- var val = el.value;
- if (v == "placement") {
- try {
- val = JSON.parse(val);
- el.parentElement.classList.remove("has-error");
- el.parentElement.classList.add("has-success");
- } catch (e) {
- el.parentElement.classList.add("has-error");
- return;
- }
- }
- nmsInfoBox._editValues[v] = val;
- el.classList.add("has-warning");
- var myData = nmsInfoBox._editStringify(sw);
- var out = document.getElementById("edit-output");
- out.value = myData;
-};
-
-nmsInfoBox._editStringify = function(sw, sysname='sysname') {
- nmsInfoBox._editValues[sysname] = sw;
- return JSON.stringify([nmsInfoBox._editValues]);
-};
diff --git a/web/js/nms-types.js b/web/js/nms-types.js
index c6471f5..769bd32 100644
--- a/web/js/nms-types.js
+++ b/web/js/nms-types.js
@@ -44,7 +44,7 @@ class nmsType {
}
}
initial(v) {
- this.value = v;
+ this._value = this._valueParse(v);
if(this.priority == nmsPriority.newOnly) {
this.ro = true;
}
@@ -161,6 +161,18 @@ class nmsTypeSysname extends nmsType {
get _defaultPriority() {
return nmsPriority.newOnly;
}
+ validate(input) {
+ if (this.ro) {
+ throw "Trying to validate a r/o field"
+ }
+ var x = testTree(nmsData,["switches","switches",input])
+ if (x) {
+ this.validationReason = "Switch already exists"
+ } else {
+ this.validationReason = "OK: " + input
+ }
+ return !x;
+ }
}
class nmsTypeSysnameReference extends nmsType {
get _defaultPriority() {
diff --git a/web/js/nms-ui-boxes.js b/web/js/nms-ui-boxes.js
index 3de8ff2..ee4dc98 100644
--- a/web/js/nms-ui-boxes.js
+++ b/web/js/nms-ui-boxes.js
@@ -247,7 +247,7 @@ class nmsTable extends nmsBox {
*/
class nmsPanel extends nmsBox{
constructor(title){
- super("div",{html: { className: "col-sm-8 col-md-6 col-lg-5 genericBox"}});
+ super("div",{html:{style:{gridColumn: 2}}});
this._topBox = new nmsBox("div",{ html: { className: "panel panel-default"}});
this._body = new nmsBox("div",{html:{className: "panel-body"}});
this.nav = new nmsBox("div",{html:{className: "panel-body"}});
@@ -256,7 +256,12 @@ class nmsPanel extends nmsBox{
this._topBox.add(this._body);
super.add(this._topBox);
}
- attach(root = document.getElementById("metaContainer")) {
+ attach(root = document.getElementById("genericPanelContainer")) {
+ try {
+ var x = parseInt(root.lastElementChild.style.gridColumnStart);
+ this.html.style.gridColumnStart = x+1;
+ } catch(e) {
+ }
super.attach(root)
}
show() {
diff --git a/web/js/nms-ui-switch.js b/web/js/nms-ui-switch.js
index 7887656..507a3a9 100644
--- a/web/js/nms-ui-switch.js
+++ b/web/js/nms-ui-switch.js
@@ -10,17 +10,27 @@
* it to avoid complicating things.
*
*/
-class nmsModSwitch extends nmsBox {
- constructor(sw) {
- var title;
- if (sw == undefined) {
- title = "Add new switch"
- } else {
- title = "Edit " + sw;
- }
+
+class nmsNewSwitch extends nmsPanel {
+ constructor() {
+ super("Add new switch")
+ this.add(new nmsModSwitch(undefined))
+ }
+}
+class nmsNewNet extends nmsPanel {
+ constructor() {
+ super("Add new network")
+ this.add(new nmsModNet(undefined))
+ }
+}
+
+class nmsModThing extends nmsBox {
+ constructor(data) {
super("div",{html:{className: "panel-body"}});
- this._sw = sw;
- //this.nav.add(new nmsString("Adding and editing stuff has immediate effects and blah blah blah, insert sensible help-text here."));
+ this.identifier = data.identifier;
+ this.invalidate = data.invalidate;
+ this.api = data.api;
+ this.item = data.item;
this.generateBaseTemplate()
this.populate()
var save = new nmsButton("Save","btn-primary");
@@ -35,7 +45,7 @@ class nmsModSwitch extends nmsBox {
commit(data) {
$.ajax({
type: "POST",
- url: "/api/write/switches",
+ url: this.api,
dataType: "text",
nmsBox:this,
data:JSON.stringify(data),
@@ -45,15 +55,16 @@ class nmsModSwitch extends nmsBox {
msg.show()
this.nmsBox.destroy()
//nmsInfoBox.hide();
- nmsData.invalidate("switches");
- nmsData.invalidate("smanagement");
+ for (var x of this.nmsBox.invalidate) {
+ nmsData.invalidate(x);
+ }
}
});
}
del(e) {
- if(confirm("This will delete the switch: " + this.nmsBox.panel._sw)) {
- this.nmsBox.panel.commit([{'sysname': this.nmsBox.panel._sw, 'deleted': true}]);
+ if(confirm("This will delete the " + this.typeName + ":" + this.nmsBox.panel.item)) {
+ this.nmsBox.panel.commit([{'sysname': this.nmsBox.panel.item, 'deleted': true}]);
};
}
save(e) {
@@ -86,51 +97,9 @@ class nmsModSwitch extends nmsBox {
*
* Which means bugs.
*/
- generateBaseTemplate() {
- this._template = {
- sysname: new nmsTypeSysname("Unique systemname/switch name. Only required field. Read/only on existing equipment." ),
- mgmt_v4_addr: new nmsTypeIP("Management address IPv4"),
- mgmt_v6_addr: new nmsTypeIP("Management address IPv6"),
- mgmt_vlan: new nmsTypeNetwork("Management VLAN"),
- traffic_vlan: new nmsTypeNetwork("Traffic VLAN"),
- distro_name: new nmsTypeSysnameReference("Distro switch upstream of this system. Required for provisioning."),
- distro_phy_port: new nmsTypePort("Name of port we connect to at the distro switch. Used for provisioning, among other things."),
- poll_frequency: new nmsTypeInterval("Poll frequency for SNMP (will use default from backend)"),
- community: new nmsTypeSecret("SNMP community (will use default from backend)"),
- placement: new nmsTypePlace("Map placement (If following a regular naming scheme, the backend will place it poperly, otherwise a random place will be chose)"),
- tags: new nmsTypeTags("Additional tags in JSON text array format. Can be anything. Used to provide a simple escape hatch mechanism to tag systems.")
- }
- }
- _populateTemplate(sw) {
- var swi = [];
- var swm = [];
- try {
- swi = nmsData.switches["switches"][this._sw];
- } catch(e) {}
- try {
- swm = nmsData.smanagement.switches[this._sw];
- } catch(e) {}
-
- var template = {}
- for (var v in swi) {
- console.assert(this._template[v] instanceof nmsType)
- if (swi[v] != null) {
- this._template[v].initial(swi[v]);
- }
- }
- for (var v in swm) {
- if (v == "last_updated") {
- continue;
- }
- console.assert(this._template[v] instanceof nmsType)
- if (swm[v] != null) {
- this._template[v].initial(swm[v]);
- }
- }
- }
populate() {
- if (this._sw != undefined) {
- this._populateTemplate(this._sw);
+ if (this.item != undefined) {
+ this._populateTemplate(this.item);
}
this.table = new nmsTable();
this.rows = {}
@@ -163,7 +132,7 @@ class nmsModSwitch extends nmsBox {
if (!changed) {
return undefined;
}
- ret["sysname"] = this.rows["sysname"].value;
+ ret[this.identifier] = this.rows[this.identifier].value;
return ret;
}
}
@@ -268,3 +237,81 @@ class nmsEditRow extends nmsBox {
this.parent.changed(this)
}
}
+class nmsModSwitch extends nmsModThing {
+ constructor(sw) {
+ super({item: sw, identifier: "sysname", invalidate: ["switches","smanagement"], api: "/api/write/switches"})
+ }
+ generateBaseTemplate() {
+ this._template = {
+ sysname: new nmsTypeSysname("Unique systemname/switch name. Only required field. Read/only on existing equipment." ),
+ mgmt_v4_addr: new nmsTypeIP("Management address IPv4"),
+ mgmt_v6_addr: new nmsTypeIP("Management address IPv6"),
+ mgmt_vlan: new nmsTypeNetwork("Management VLAN"),
+ traffic_vlan: new nmsTypeNetwork("Traffic VLAN"),
+ distro_name: new nmsTypeSysnameReference("Distro switch upstream of this system. Required for provisioning."),
+ distro_phy_port: new nmsTypePort("Name of port we connect to at the distro switch. Used for provisioning, among other things."),
+ poll_frequency: new nmsTypeInterval("Poll frequency for SNMP (will use default from backend)"),
+ community: new nmsTypeSecret("SNMP community (will use default from backend)"),
+ placement: new nmsTypePlace("Map placement (If following a regular naming scheme, the backend will place it poperly, otherwise a random place will be chose)"),
+ tags: new nmsTypeTags("Additional tags in JSON text array format. Can be anything. Used to provide a simple escape hatch mechanism to tag systems.")
+ }
+ }
+ _populateTemplate(sw) {
+ var swi = [];
+ var swm = [];
+ try {
+ swi = nmsData.switches["switches"][sw];
+ swm = nmsData.smanagement.switches[sw];
+ } catch(e) {}
+
+ var template = {}
+ for (var v in swi) {
+ console.assert(this._template[v] instanceof nmsType)
+ if (swi[v] != null) {
+ this._template[v].initial(swi[v]);
+ }
+ }
+ for (var v in swm) {
+ if (v == "last_updated") {
+ continue;
+ }
+ console.assert(this._template[v] instanceof nmsType)
+ if (swm[v] != null) {
+ this._template[v].initial(swm[v]);
+ }
+ }
+ }
+}
+
+class nmsModNet extends nmsModThing {
+ constructor(net) {
+ super({item: net, identifier: "name", invalidate: ["networks","smanagement"], api: "/api/write/networks"})
+ }
+ generateBaseTemplate() {
+ this._template = {
+ name: new nmsTypeNetwork("Unique networkname. Only required field. Read/only on existing nets."),
+ gw4: new nmsTypeIP("Gateway address, IPv4"),
+ gw6: new nmsTypeIP("Gateway address, IPv6"),
+ subnet4: new nmsTypeIP("Subnet, IPv4"),
+ subnet6: new nmsTypeIP("Subnet, IPv6"),
+ router: new nmsTypeSysnameReference("Router where net is terminated. E.g.: r1.noc for floor traffic nets"),
+ tags: new nmsTypeTags("Additional tags in JSON text array format. Can be anything. Used to provide a simple escape hatch mechanism to tag systems.")
+ }
+ }
+ _populateTemplate(net) {
+ var nets = [];
+ try {
+ nets = nmsData.networks["networks"][net];
+ } catch(e) {}
+
+ var template = {}
+ for (var v in nets) {
+ console.assert(this._template[v] instanceof nmsType)
+ if (nets[v] != null) {
+ this._template[v].initial(nets[v]);
+ }
+ }
+ }
+}
+
+