web app, added emane node, got basic emane networks working and joining existing emane network
This commit is contained in:
parent
b15b838555
commit
8889d121c0
6 changed files with 157 additions and 33 deletions
|
@ -143,6 +143,11 @@ def get_sessions():
|
||||||
def create_session():
|
def create_session():
|
||||||
session = coreemu.create_session()
|
session = coreemu.create_session()
|
||||||
session.set_state(EventTypes.CONFIGURATION_STATE)
|
session.set_state(EventTypes.CONFIGURATION_STATE)
|
||||||
|
|
||||||
|
# set session location
|
||||||
|
session.location.setrefgeo(47.57917, -122.13232, 2.0)
|
||||||
|
session.location.refscale = 150.0
|
||||||
|
|
||||||
response_data = jsonify(
|
response_data = jsonify(
|
||||||
id=session.session_id,
|
id=session.session_id,
|
||||||
state=session.state,
|
state=session.state,
|
||||||
|
@ -169,6 +174,10 @@ def get_session(session_id):
|
||||||
|
|
||||||
nodes = []
|
nodes = []
|
||||||
for node in session.objects.itervalues():
|
for node in session.objects.itervalues():
|
||||||
|
emane_model = None
|
||||||
|
if nodeutils.is_node(node, NodeTypes.EMANE):
|
||||||
|
emane_model = node.model.name
|
||||||
|
|
||||||
services = [x._name for x in getattr(node, "services", [])]
|
services = [x._name for x in getattr(node, "services", [])]
|
||||||
nodes.append({
|
nodes.append({
|
||||||
"id": node.objid,
|
"id": node.objid,
|
||||||
|
@ -181,6 +190,7 @@ def get_session(session_id):
|
||||||
"z": node.position.z
|
"z": node.position.z
|
||||||
},
|
},
|
||||||
"services": services,
|
"services": services,
|
||||||
|
"emane": emane_model,
|
||||||
"url": "/sessions/%s/nodes/%s" % (session_id, node.objid)
|
"url": "/sessions/%s/nodes/%s" % (session_id, node.objid)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -190,6 +200,21 @@ def get_session(session_id):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/sessions/<int:session_id>/emane")
|
||||||
|
def get_emane_models(session_id):
|
||||||
|
session = coreemu.sessions.get(session_id)
|
||||||
|
if not session:
|
||||||
|
return jsonify(error="session does not exist"), 404
|
||||||
|
|
||||||
|
models = []
|
||||||
|
for model in session.emane._modelclsmap.keys():
|
||||||
|
if len(model.split("_")) != 2:
|
||||||
|
continue
|
||||||
|
models.append(model)
|
||||||
|
|
||||||
|
return jsonify(models=models)
|
||||||
|
|
||||||
|
|
||||||
@app.route("/sessions/<int:session_id>/nodes", methods=["POST"])
|
@app.route("/sessions/<int:session_id>/nodes", methods=["POST"])
|
||||||
@synchronized
|
@synchronized
|
||||||
def create_node(session_id):
|
def create_node(session_id):
|
||||||
|
@ -213,6 +238,17 @@ def create_node(session_id):
|
||||||
node_options.set_position(data.get("x"), data.get("y"))
|
node_options.set_position(data.get("x"), data.get("y"))
|
||||||
node_options.set_location(data.get("lat"), data.get("lon"), data.get("alt"))
|
node_options.set_location(data.get("lat"), data.get("lon"), data.get("alt"))
|
||||||
node = session.add_node(_type=node_type, _id=node_id, node_options=node_options)
|
node = session.add_node(_type=node_type, _id=node_id, node_options=node_options)
|
||||||
|
|
||||||
|
# configure emane if provided
|
||||||
|
emane_model = data.get("emane")
|
||||||
|
if emane_model:
|
||||||
|
config_data = ConfigData(
|
||||||
|
node=node_id,
|
||||||
|
object=emane_model,
|
||||||
|
type=2
|
||||||
|
)
|
||||||
|
session.config_object(config_data)
|
||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
id=node.objid,
|
id=node.objid,
|
||||||
url="/sessions/%s/nodes/%s" % (session_id, node.objid)
|
url="/sessions/%s/nodes/%s" % (session_id, node.objid)
|
||||||
|
@ -278,10 +314,16 @@ def get_node(session_id, node_id):
|
||||||
})
|
})
|
||||||
|
|
||||||
services = [x._name for x in getattr(node, "services", [])]
|
services = [x._name for x in getattr(node, "services", [])]
|
||||||
|
|
||||||
|
emane_model = None
|
||||||
|
if nodeutils.is_node(node, NodeTypes.EMANE):
|
||||||
|
emane_model = node.model.name
|
||||||
|
|
||||||
return jsonify(
|
return jsonify(
|
||||||
name=node.name,
|
name=node.name,
|
||||||
type=nodeutils.get_node_type(node.__class__).value,
|
type=nodeutils.get_node_type(node.__class__).value,
|
||||||
services=services,
|
services=services,
|
||||||
|
emane=emane_model,
|
||||||
model=node.type,
|
model=node.type,
|
||||||
interfaces=interfaces,
|
interfaces=interfaces,
|
||||||
linksurl="/sessions/%s/nodes/%s/links" % (session_id, node.objid)
|
linksurl="/sessions/%s/nodes/%s/links" % (session_id, node.objid)
|
||||||
|
|
|
@ -25,6 +25,12 @@ class NodeHelper {
|
||||||
name: 'wlan',
|
name: 'wlan',
|
||||||
display: 'WLAN'
|
display: 'WLAN'
|
||||||
},
|
},
|
||||||
|
// emane
|
||||||
|
10: {
|
||||||
|
name: 'emane',
|
||||||
|
display: 'EMANE'
|
||||||
|
},
|
||||||
|
// ptp
|
||||||
12: {
|
12: {
|
||||||
name: 'ptp',
|
name: 'ptp',
|
||||||
display: 'PTP'
|
display: 'PTP'
|
||||||
|
@ -38,16 +44,31 @@ class NodeHelper {
|
||||||
mdr: 'static/mdr.svg',
|
mdr: 'static/mdr.svg',
|
||||||
switch: 'static/lanswitch.svg',
|
switch: 'static/lanswitch.svg',
|
||||||
hub: 'static/hub.svg',
|
hub: 'static/hub.svg',
|
||||||
wlan: 'static/wlan.svg'
|
wlan: 'static/wlan.svg',
|
||||||
|
emane: 'static/wlan.svg'
|
||||||
};
|
};
|
||||||
|
|
||||||
this.defaultNode = 0;
|
this.defaultNode = 0;
|
||||||
this.ptpNode = 12;
|
this.switchNode = 4;
|
||||||
|
this.hubNode = 5;
|
||||||
this.wlanNode = 6;
|
this.wlanNode = 6;
|
||||||
|
this.emaneNode = 10;
|
||||||
|
this.ptpNode = 12;
|
||||||
|
this.controlNet = 13;
|
||||||
}
|
}
|
||||||
|
|
||||||
isNetworkNode(node) {
|
isNetworkNode(node) {
|
||||||
return [4, 5, 6, 12].includes(node.type);
|
return [
|
||||||
|
this.switchNode,
|
||||||
|
this.hubNode,
|
||||||
|
this.wlanNode,
|
||||||
|
this.emaneNode,
|
||||||
|
this.ptpNode
|
||||||
|
].includes(node.type);
|
||||||
|
}
|
||||||
|
|
||||||
|
isSkipNode(node) {
|
||||||
|
return [CoreNodeHelper.ptpNode, CoreNodeHelper.controlNet].includes(node.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
getDisplay(nodeType) {
|
getDisplay(nodeType) {
|
||||||
|
@ -82,6 +103,7 @@ class CoreNode {
|
||||||
this.emulation_id = null;
|
this.emulation_id = null;
|
||||||
this.emulation_server = null;
|
this.emulation_server = null;
|
||||||
this.interfaces = {};
|
this.interfaces = {};
|
||||||
|
this.emane = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNetworkNode() {
|
getNetworkNode() {
|
||||||
|
@ -93,7 +115,6 @@ class CoreNode {
|
||||||
y: this.y,
|
y: this.y,
|
||||||
label: this.name,
|
label: this.name,
|
||||||
coreNode: this,
|
coreNode: this,
|
||||||
//color: '#FFF',
|
|
||||||
shape: 'image',
|
shape: 'image',
|
||||||
image: icon
|
image: icon
|
||||||
};
|
};
|
||||||
|
@ -110,7 +131,8 @@ class CoreNode {
|
||||||
lat: this.lat,
|
lat: this.lat,
|
||||||
lon: this.lon,
|
lon: this.lon,
|
||||||
alt: this.alt,
|
alt: this.alt,
|
||||||
services: this.services
|
services: this.services,
|
||||||
|
emane: this.emane
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -194,6 +216,7 @@ class CoreNetwork {
|
||||||
const session = await this.coreRest.createSession();
|
const session = await this.coreRest.createSession();
|
||||||
this.coreRest.currentSession = session.id;
|
this.coreRest.currentSession = session.id;
|
||||||
this.reset();
|
this.reset();
|
||||||
|
toastr.success(`Created ${session.id}`, 'Session');
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -260,6 +283,7 @@ class CoreNetwork {
|
||||||
const coreNode = new CoreNode(node.id, node.type, node.name, position.x, position.y);
|
const coreNode = new CoreNode(node.id, node.type, node.name, position.x, position.y);
|
||||||
coreNode.model = node.model;
|
coreNode.model = node.model;
|
||||||
coreNode.services = node.services;
|
coreNode.services = node.services;
|
||||||
|
coreNode.emane = node.emane;
|
||||||
this.nodes.add(coreNode.getNetworkNode());
|
this.nodes.add(coreNode.getNetworkNode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -286,7 +310,7 @@ class CoreNetwork {
|
||||||
const nodeIds = [0];
|
const nodeIds = [0];
|
||||||
|
|
||||||
for (let node of nodes) {
|
for (let node of nodes) {
|
||||||
if (node.type === CoreNodeHelper.ptpNode) {
|
if (CoreNodeHelper.isSkipNode(node)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -319,6 +343,8 @@ class CoreNetwork {
|
||||||
|
|
||||||
this.network.fit();
|
this.network.fit();
|
||||||
|
|
||||||
|
toastr.success(`Joined ${sessionId}`, 'Session');
|
||||||
|
|
||||||
return {
|
return {
|
||||||
id: sessionId,
|
id: sessionId,
|
||||||
state: session.state
|
state: session.state
|
||||||
|
|
|
@ -62,7 +62,11 @@ class CoreRest {
|
||||||
}
|
}
|
||||||
|
|
||||||
async setSessionState(state) {
|
async setSessionState(state) {
|
||||||
return await putJson(`/sessions/${this.currentSession}/state`, {state})
|
return await putJson(`/sessions/${this.currentSession}/state`, {state});
|
||||||
|
}
|
||||||
|
|
||||||
|
async getEmaneModels() {
|
||||||
|
return await $.getJSON(`/sessions/${this.currentSession}/emane`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async createNode(node) {
|
async createNode(node) {
|
||||||
|
|
|
@ -1,3 +1,32 @@
|
||||||
|
function createRadio(name, value, label, checked = false) {
|
||||||
|
const $formCheck = $('<div>', {class: 'form-check'});
|
||||||
|
const $input = $('<input>', {
|
||||||
|
class: 'form-check-input',
|
||||||
|
type: 'radio',
|
||||||
|
name: name,
|
||||||
|
checked,
|
||||||
|
value
|
||||||
|
});
|
||||||
|
const $label = $('<label>', {class: 'form-check-label', text: label});
|
||||||
|
$formCheck.append([$input, $label]);
|
||||||
|
return $formCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
function createCheckbox(name, value, label, checked = false) {
|
||||||
|
const $formCheck = $('<div>', {class: 'form-check col'});
|
||||||
|
const $input = $('<input>', {
|
||||||
|
class: 'form-check-input',
|
||||||
|
type: 'checkbox',
|
||||||
|
value,
|
||||||
|
name,
|
||||||
|
checked
|
||||||
|
});
|
||||||
|
const $label = $('<label>', {class: 'form-check-label', text: label});
|
||||||
|
$formCheck.append([$input, $label]);
|
||||||
|
return $formCheck;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ServiceModal {
|
class ServiceModal {
|
||||||
constructor(coreRest) {
|
constructor(coreRest) {
|
||||||
this.coreRest = coreRest;
|
this.coreRest = coreRest;
|
||||||
|
@ -45,7 +74,6 @@ class ServicesModal {
|
||||||
}
|
}
|
||||||
|
|
||||||
editService(event) {
|
editService(event) {
|
||||||
//event.preventDefault();
|
|
||||||
const $target = $(event.target);
|
const $target = $(event.target);
|
||||||
const service = $target.parent().parent().find('label').text();
|
const service = $target.parent().parent().find('label').text();
|
||||||
console.log('edit service: ', service);
|
console.log('edit service: ', service);
|
||||||
|
@ -89,17 +117,8 @@ class ServicesModal {
|
||||||
const $row = $('<div>', {class: 'row mb-1'});
|
const $row = $('<div>', {class: 'row mb-1'});
|
||||||
const $button = $('<div>', {class: 'col-1'})
|
const $button = $('<div>', {class: 'col-1'})
|
||||||
.append($('<a>', {text: 'Edit', href: '#', class: 'btn btn-primary btn-sm service-button'}));
|
.append($('<a>', {text: 'Edit', href: '#', class: 'btn btn-primary btn-sm service-button'}));
|
||||||
const $formCheck = $('<div>', {class: 'form-check col'});
|
const $checkbox = createCheckbox(service, service, service, checked);
|
||||||
const $input = $('<input>', {
|
$row.append([$button, $checkbox]);
|
||||||
class: 'form-check-input',
|
|
||||||
type: 'checkbox',
|
|
||||||
value: service,
|
|
||||||
name: service,
|
|
||||||
checked
|
|
||||||
});
|
|
||||||
const $label = $('<label>', {class: 'form-check-label', text: service});
|
|
||||||
$formCheck.append([$input, $label]);
|
|
||||||
$row.append([$button, $formCheck]);
|
|
||||||
$formGroup.append($row);
|
$formGroup.append($row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,7 +208,7 @@ class NodeContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
console.log('node type: ', node.type);
|
console.log('node type: ', node.type);
|
||||||
if (node.type === CoreNodeHelper.wlanNode) {
|
if (node.type === CoreNodeHelper.emaneNode || node.type === CoreNodeHelper.wlanNode) {
|
||||||
this.$linkRfButton.removeClass('d-none');
|
this.$linkRfButton.removeClass('d-none');
|
||||||
} else {
|
} else {
|
||||||
this.$linkRfButton.addClass('d-none');
|
this.$linkRfButton.addClass('d-none');
|
||||||
|
@ -217,7 +236,7 @@ class NodeContext {
|
||||||
console.log('node context: ', nodeId, option);
|
console.log('node context: ', nodeId, option);
|
||||||
switch (option) {
|
switch (option) {
|
||||||
case 'edit':
|
case 'edit':
|
||||||
this.nodeEditModal.show(nodeId);
|
await this.nodeEditModal.show(nodeId);
|
||||||
break;
|
break;
|
||||||
case 'services':
|
case 'services':
|
||||||
await this.servicesModal.show(nodeId);
|
await this.servicesModal.show(nodeId);
|
||||||
|
@ -236,18 +255,35 @@ class NodeContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
class NodeEditModal {
|
class NodeEditModal {
|
||||||
constructor(coreNetwork) {
|
constructor(coreNetwork, coreRest) {
|
||||||
this.coreNetwork = coreNetwork;
|
this.coreNetwork = coreNetwork;
|
||||||
|
this.coreRest = coreRest;
|
||||||
this.$modal = $('#nodeedit-modal');
|
this.$modal = $('#nodeedit-modal');
|
||||||
|
this.$form = this.$modal.find('form');
|
||||||
|
this.$formCustom = $('#nodeedit-custom');
|
||||||
this.$editButton = $('#nodeedit-button');
|
this.$editButton = $('#nodeedit-button');
|
||||||
this.$editButton.click(this.onClick.bind(this));
|
this.$editButton.click(this.onClick.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
show(nodeId) {
|
async show(nodeId) {
|
||||||
const node = this.coreNetwork.getCoreNode(nodeId);
|
const node = this.coreNetwork.getCoreNode(nodeId);
|
||||||
this.$modal.data('node', nodeId);
|
this.$modal.data('node', nodeId);
|
||||||
this.$modal.find('.modal-title').text(`Edit Node: ${node.name}`);
|
this.$modal.find('.modal-title').text(`Edit Node: ${node.name}`);
|
||||||
this.$modal.find('#node-name').val(node.name);
|
this.$modal.find('#node-name').val(node.name);
|
||||||
|
|
||||||
|
this.$formCustom.html('');
|
||||||
|
if (node.type === CoreNodeHelper.emaneNode) {
|
||||||
|
const response = await this.coreRest.getEmaneModels();
|
||||||
|
this.$formCustom.append($('<label>', {class: 'form-label', text: 'EMANE Model'}));
|
||||||
|
console.log('emane models: ', response);
|
||||||
|
for (let model of response.models) {
|
||||||
|
const checked = node.emane === model;
|
||||||
|
const label = model.split('_')[1];
|
||||||
|
const $radio = createRadio('emane', model, label, checked);
|
||||||
|
this.$formCustom.append($radio);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.$modal.modal('show');
|
this.$modal.modal('show');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,6 +298,11 @@ class NodeEditModal {
|
||||||
node.coreNode.name = formData.name;
|
node.coreNode.name = formData.name;
|
||||||
this.coreNetwork.nodes.update(node);
|
this.coreNetwork.nodes.update(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (formData.emane !== undefined) {
|
||||||
|
node.coreNode.emane = formData.emane;
|
||||||
|
}
|
||||||
|
|
||||||
this.$modal.modal('hide');
|
this.$modal.modal('hide');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -427,7 +468,12 @@ class InfoPanel {
|
||||||
this.$infoCard.data('node', nodeId);
|
this.$infoCard.data('node', nodeId);
|
||||||
this.$infoCardHeader.text(node.name);
|
this.$infoCardHeader.text(node.name);
|
||||||
this.$infoCardTable.find('tbody tr').remove();
|
this.$infoCardTable.find('tbody tr').remove();
|
||||||
|
if (node.model) {
|
||||||
this.addInfoTable('Model', node.model);
|
this.addInfoTable('Model', node.model);
|
||||||
|
}
|
||||||
|
if (node.emane) {
|
||||||
|
this.addInfoTable('EMANE', node.emane);
|
||||||
|
}
|
||||||
this.addInfoTable('X', node.x);
|
this.addInfoTable('X', node.x);
|
||||||
this.addInfoTable('Y', node.y);
|
this.addInfoTable('Y', node.y);
|
||||||
for (let interfaceId in node.interfaces) {
|
for (let interfaceId in node.interfaces) {
|
||||||
|
|
|
@ -92,6 +92,7 @@
|
||||||
<a class="dropdown-item" href="#" data-node="5">Hub</a>
|
<a class="dropdown-item" href="#" data-node="5">Hub</a>
|
||||||
<a class="dropdown-item" href="#" data-node="4">Switch</a>
|
<a class="dropdown-item" href="#" data-node="4">Switch</a>
|
||||||
<a class="dropdown-item" href="#" data-node="6">WLAN</a>
|
<a class="dropdown-item" href="#" data-node="6">WLAN</a>
|
||||||
|
<a class="dropdown-item" href="#" data-node="10">EMANE</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -119,20 +120,18 @@
|
||||||
{% include 'services_modal.html' %}
|
{% include 'services_modal.html' %}
|
||||||
|
|
||||||
<div id="node-context" class="list-group context d-none">
|
<div id="node-context" class="list-group context d-none">
|
||||||
<button type="button" class="list-group-item list-group-item-action" href="#" data-option="edit">Edit Node</button>
|
<button type="button" class="list-group-item list-group-item-action" data-option="edit">Edit Node</button>
|
||||||
<button id="node-linkrf-button" type="button" class="list-group-item list-group-item-action d-none" href="#"
|
<button id="node-linkrf-button" type="button" class="list-group-item list-group-item-action d-none"
|
||||||
data-option="linkrf">Link All Routers
|
data-option="linkrf">Link All Routers
|
||||||
</button>
|
</button>
|
||||||
<button type="button" class="list-group-item list-group-item-action" href="#"
|
<button type="button" class="list-group-item list-group-item-action" data-option="services">Services</button>
|
||||||
data-option="services">Services
|
<button id="node-delete-button" type="button" class="list-group-item list-group-item-action" data-option="delete">
|
||||||
</button>
|
Delete
|
||||||
<button id="node-delete-button" type="button" class="list-group-item list-group-item-action" href="#"
|
|
||||||
data-option="delete">Delete
|
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="edge-context" class="list-group context d-none">
|
<div id="edge-context" class="list-group context d-none">
|
||||||
<button type="button" class="list-group-item list-group-item-action" href="#" data-option="edit">Edit Link</button>
|
<button type="button" class="list-group-item list-group-item-action" data-option="edit">Edit Link</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="static/jquery-3.3.1.min.js"></script>
|
<script src="static/jquery-3.3.1.min.js"></script>
|
||||||
|
@ -147,6 +146,11 @@
|
||||||
<script src="static/coreui.js"></script>
|
<script src="static/coreui.js"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
// configure global toastr
|
||||||
|
console.log(toastr.options);
|
||||||
|
toastr.options.timeOut = 2000;
|
||||||
|
toastr.options.positionClass = 'toast-bottom-right';
|
||||||
|
|
||||||
const $linkButton = $('#link-button');
|
const $linkButton = $('#link-button');
|
||||||
const $nodeButtons = $('.node-buttons a');
|
const $nodeButtons = $('.node-buttons a');
|
||||||
const $sessionId = $('#session-id');
|
const $sessionId = $('#session-id');
|
||||||
|
@ -177,7 +181,7 @@
|
||||||
const serviceModal = new ServiceModal(coreRest);
|
const serviceModal = new ServiceModal(coreRest);
|
||||||
const servicesModal = new ServicesModal(coreRest, coreNetwork, serviceModal);
|
const servicesModal = new ServicesModal(coreRest, coreNetwork, serviceModal);
|
||||||
const sessionsModal = new SessionsModal(coreRest, coreNetwork, joinSession);
|
const sessionsModal = new SessionsModal(coreRest, coreNetwork, joinSession);
|
||||||
const nodeEditModal = new NodeEditModal(coreNetwork);
|
const nodeEditModal = new NodeEditModal(coreNetwork, coreRest);
|
||||||
const nodeContext = new NodeContext(coreNetwork, coreRest, nodeEditModal, servicesModal);
|
const nodeContext = new NodeContext(coreNetwork, coreRest, nodeEditModal, servicesModal);
|
||||||
const edgeEditModal = new EdgeEditModal(coreNetwork, coreRest);
|
const edgeEditModal = new EdgeEditModal(coreNetwork, coreRest);
|
||||||
const edgeContext = new EdgeContext(coreNetwork, edgeEditModal);
|
const edgeContext = new EdgeContext(coreNetwork, edgeEditModal);
|
||||||
|
|
|
@ -14,6 +14,8 @@
|
||||||
<input id="node-name" name="name" class="form-control" type="text" placeholder="Node Name"
|
<input id="node-name" name="name" class="form-control" type="text" placeholder="Node Name"
|
||||||
required>
|
required>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div id="nodeedit-custom"></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer">
|
<div class="modal-footer">
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue