diff --git a/webapp/static/coreui.js b/webapp/static/coreui.js index 24bb9a36..1f7cb85e 100644 --- a/webapp/static/coreui.js +++ b/webapp/static/coreui.js @@ -90,3 +90,329 @@ class ServicesModal { }); } } + +class SessionsModal { + constructor(coreRest, coreNetwork, onJoin) { + this.coreRest = coreRest; + this.coreNetwork = coreNetwork; + this.onJoin = onJoin; + this.$sessionsModal = $('#sessions-modal'); + this.$sessionsTable = $('#sessions-table'); + this.onShow(); + this.onClick(); + } + + onClick() { + const self = this; + this.$sessionsTable.on('click', 'td', function (event) { + const sessionId = $(this).parent('tr').data('session'); + console.log('clicked session to join: ', sessionId); + if (sessionId === self.coreRest.currentSession) { + console.log('same session, not changing'); + } else { + self.coreNetwork.joinSession(sessionId) + .then(function (session) { + self.onJoin(session); + self.$sessionsModal.modal('hide'); + }) + .catch(function (err) { + console.log('join session error: ', err); + }); + } + }); + } + + onShow() { + const self = this; + this.$sessionsModal.on('shown.bs.modal', function () { + console.log('show sessions'); + self.$sessionsTable.find('tbody tr').remove(); + self.coreRest.getSessions() + .then(function (response) { + const sessions = response.sessions; + for (let session of sessions) { + console.log('show sessions: ', session); + const $idCell = $('', {text: session.id}); + const $nodeCell = $('', {text: session.nodes}); + const stateName = self.coreRest.getStateName(session.state); + const $stateCell = $('', {text: stateName}); + const $row = $('', {class: 'session-join', 'data-session': session.id}); + $row.append([$idCell, $nodeCell, $stateCell]); + self.$sessionsTable.find('tbody').append($row); + } + }) + .catch(function (err) { + console.log('error getting sessions: ', err); + }); + }); + } +} + +class NodeContext { + constructor(coreNetwork, nodeEditModal, servicesModal) { + this.coreNetwork = coreNetwork; + this.nodeEditModal = nodeEditModal; + this.servicesModal = servicesModal; + this.$nodeContext = $('#node-context'); + this.onClick(); + } + + show(nodeId, x, y) { + const node = this.coreNetwork.nodes.get(nodeId); + console.log('context node: ', node); + this.$nodeContext.data('node', nodeId); + this.$nodeContext.css({ + position: 'absolute', + left: x, + top: y + }); + this.$nodeContext.removeClass('d-none'); + } + + hide() { + this.$nodeContext.addClass('d-none'); + } + + onClick() { + const self = this; + this.$nodeContext.click(function (event) { + self.$nodeContext.addClass('d-none'); + console.log('node context click: ', event); + const nodeId = self.$nodeContext.data('node'); + const $target = $(event.target); + const option = $target.data('option'); + console.log('node context: ', nodeId, option); + if (option === 'edit') { + self.nodeEditModal.show(nodeId); + } else if (option === 'services') { + self.servicesModal.show(nodeId) + .catch(function (err) { + console.log('error showing services modal: ', err); + }); + } + }); + } +} + +class NodeEditModal { + constructor(coreNetwork) { + this.coreNetwork = coreNetwork; + this.$nodeEditModal = $('#nodeedit-modal'); + this.$nodeEditButton = $('#nodeedit-button'); + this.onClick(); + } + + show(nodeId) { + const node = this.coreNetwork.getCoreNode(nodeId); + this.$nodeEditModal.data('node', nodeId); + this.$nodeEditModal.find('.modal-title').text(`Edit Node: ${node.name}`); + this.$nodeEditModal.find('#node-name').val(node.name); + this.$nodeEditModal.modal('show'); + } + + onClick() { + const self = this; + this.$nodeEditButton.click(function () { + const $form = self.$nodeEditModal.find('form'); + const formData = formToJson($form); + console.log('node edit data: ', formData); + const nodeId = self.$nodeEditModal.data('node'); + const node = self.coreNetwork.nodes.get(nodeId); + if (formData.name) { + node.label = formData.name; + node.coreNode.name = formData.name; + self.coreNetwork.nodes.update(node); + } + self.$nodeEditModal.modal('hide'); + }); + } +} + +class EdgeContext { + constructor(coreNetwork, edgeEditModal) { + this.coreNetwork = coreNetwork; + this.edgeEditModal = edgeEditModal; + this.$edgeContext = $('#edge-context'); + this.onClick(); + } + + show(edgeId, x, y) { + const edge = this.coreNetwork.edges.get(edgeId); + console.log('context edge: ', edge); + this.$edgeContext.data('edge', edgeId); + this.$edgeContext.css({ + position: 'absolute', + left: x, + top: y + }); + this.$edgeContext.removeClass('d-none'); + } + + hide() { + this.$edgeContext.addClass('d-none'); + } + + onClick() { + const self = this; + this.$edgeContext.click(function (event) { + self.$edgeContext.addClass('d-none'); + console.log('edge context click: ', event); + const edgeId = self.$edgeContext.data('edge'); + const $target = $(event.target); + const option = $target.data('option'); + console.log('edge context: ', edgeId, option); + if (option === 'edit') { + self.edgeEditModal.show(edgeId); + } + }); + } +} + +class EdgeEditModal { + constructor(coreNetwork, coreRest) { + this.coreNetwork = coreNetwork; + this.coreRest = coreRest; + this.$linkEditButton = $('#linkedit-button'); + this.$linkEditModal = $('#linkedit-modal'); + this.onClick(); + } + + show(edgeId) { + // populate form with current link data + const edge = this.coreNetwork.edges.get(edgeId); + const link = edge.link; + this.$linkEditModal.data('link', edgeId); + this.$linkEditModal.find('#link-bandwidth').val(link.bandwidth); + this.$linkEditModal.find('#link-delay').val(link.delay); + this.$linkEditModal.find('#link-per').val(link.loss); + this.$linkEditModal.find('#link-dup').val(link.duplicate); + this.$linkEditModal.find('#link-jitter').val(link.jitter); + + // set modal name and show + this.$linkEditModal.find('.modal-title').text('Edit Edge'); + this.$linkEditModal.modal('show'); + } + + onClick() { + const self = this; + this.$linkEditButton.click(function () { + const $form = self.$linkEditModal.find('form'); + const formData = {}; + $form.serializeArray().map(function (x) { + let value = x.value; + if (value === '') { + value = null; + } else if (!isNaN(value)) { + value = parseInt(value); + } + formData[x.name] = value; + }); + console.log('link edit data: ', formData); + const edgeId = self.$linkEditModal.data('link'); + const edge = self.coreNetwork.edges.get(edgeId); + const link = edge.link; + + link.bandwidth = formData.bandwidth; + link.delay = formData.delay; + link.duplicate = formData.duplicate; + link.loss = formData.loss; + link.jitter = formData.jitter; + + coreRest.isRunning() + .then(function (isRunning) { + if (isRunning) { + const linkEdit = link.json(); + linkEdit.interface_one = linkEdit.interface_one.id; + linkEdit.interface_two = linkEdit.interface_two.id; + return self.coreRest.editLink(linkEdit); + } + }) + .then(function (response) { + console.log('link edit success'); + }) + .catch(function (err) { + console.log('error editing link: ', err); + }); + + self.$linkEditModal.modal('hide'); + }); + } +} + +class InfoPanel { + constructor(coreNetwork) { + this.coreNetwork = coreNetwork; + this.$infoCard = $('#info-card'); + this.$infoCardTable = $('#info-card-table'); + this.$infoCardHeader = $('#info-card-header'); + } + + addInfoTable(name, value) { + const $nameCell = $('', {text: name}); + const $valueCell = $('', {text: value}); + const $row = $('').append([$nameCell, $valueCell]); + this.$infoCardTable.find('tbody').append($row); + } + + show() { + this.$infoCard.removeClass('visible invisible'); + this.$infoCard.addClass('visible'); + } + + hide() { + this.$infoCard.removeClass('visible invisible'); + this.$infoCard.addClass('invisible'); + } + + addInterfaceInfo(nodeInterface) { + this.addInfoTable('Interface', `eth${nodeInterface.id}`); + if (nodeInterface.ip4) { + this.addInfoTable('IP4', `${nodeInterface.ip4}/${nodeInterface.ip4mask}`); + } + if (nodeInterface.ip6) { + this.addInfoTable('IP6', `${nodeInterface.ip6}/${nodeInterface.ip6mask}`); + } + } + + showNode(nodeId) { + const node = coreNetwork.getCoreNode(nodeId); + this.$infoCardHeader.text(node.name); + this.$infoCardTable.find('tbody tr').remove(); + this.addInfoTable('Model', node.model); + this.addInfoTable('X', node.x); + this.addInfoTable('Y', node.y); + for (let interfaceId in node.interfaces) { + const nodeInterface = node.interfaces[interfaceId]; + console.log('node interface: ', nodeInterface); + this.addInterfaceInfo(nodeInterface); + } + this.show(); + } + + showEdge(edgeId) { + const edge = coreNetwork.edges.get(edgeId); + const link = edge.link; + const nodeOne = coreNetwork.getCoreNode(link.nodeOne); + const nodeTwo = coreNetwork.getCoreNode(link.nodeTwo); + console.log('clicked edge: ', link); + this.$infoCard.addClass('visible'); + this.$infoCardHeader.text('Edge'); + this.$infoCardTable.find('tbody tr').remove(); + this.addInfoTable(nodeOne.name, null); + const interfaceOne = link.interfaceOne; + if (interfaceOne) { + this.addInterfaceInfo(interfaceOne); + } + this.addInfoTable(nodeTwo.name, null); + const interfaceTwo = link.interfaceTwo; + if (interfaceTwo) { + this.addInterfaceInfo(interfaceTwo); + } + this.addInfoTable('Bandwidth', edge.link.bandwidth); + this.addInfoTable('Delay', edge.link.delay); + this.addInfoTable('Duplicate', edge.link.duplicate); + this.addInfoTable('Loss', edge.link.loss); + this.addInfoTable('Jitter', edge.link.jitter); + this.show(); + } +} diff --git a/webapp/templates/index.html b/webapp/templates/index.html index 1b37b2bd..a642747e 100644 --- a/webapp/templates/index.html +++ b/webapp/templates/index.html @@ -138,20 +138,9 @@ const $nodeButtons = $('.node-buttons a'); const $sessionId = $('#session-id'); const $nodeDisplay = $('#node-display'); - const $sessionsModal = $('#sessions-modal'); - const $sessionsTable = $('#sessions-table'); const $runButton = $('#run-button'); - const $infoCard = $('#info-card'); - const $infoCardTable = $('#info-card-table'); - const $infoCardHeader = $('#info-card-header'); const $nodeSelect = $('#node-select'); const $newSessionButton = $('#new-session-button'); - const $nodeContext = $('#node-context'); - const $edgeContext = $('#edge-context'); - const $nodeEditModal = $('#nodeedit-modal'); - const $nodeEditButton = $('#nodeedit-button'); - const $linkEditModal = $('#linkedit-modal'); - const $linkEditButton = $('#linkedit-button'); function formToJson($form) { const formData = {}; @@ -171,6 +160,12 @@ const coreRest = new CoreRest(); const coreNetwork = new CoreNetwork('core-network', coreRest); const servicesModal = new ServicesModal(coreRest, coreNetwork); + const sessionsModal = new SessionsModal(coreRest, coreNetwork, joinSession); + const nodeEditModal = new NodeEditModal(coreNetwork); + const nodeContext = new NodeContext(coreNetwork, nodeEditModal, servicesModal); + const edgeEditModal = new EdgeEditModal(coreNetwork, coreRest); + const edgeContext = new EdgeContext(coreNetwork, edgeEditModal); + const infoPanel = new InfoPanel(coreNetwork); coreNetwork.initialSession() .then(function (session) { @@ -199,13 +194,6 @@ } } - function addInfoTable(name, value) { - let $nameCell = $('', {text: name}); - let $valueCell = $('', {text: value}); - const $row = $('').append([$nameCell, $valueCell]); - $infoCardTable.find('tbody').append($row); - } - function joinSession(session) { $sessionId.text(`Session: ${session.id}`); const isStartEnabled = session.state !== SessionStates.runtime; @@ -215,77 +203,25 @@ // handle network clicks coreNetwork.network.on('click', function (properties) { console.log('click properties: ', properties); - $nodeContext.addClass('d-none'); - $edgeContext.addClass('d-none'); + nodeContext.hide(); + edgeContext.hide(); - $infoCard.removeClass('visible invisible'); if (properties.nodes.length === 1) { const nodeId = properties.nodes[0]; - const node = coreNetwork.getCoreNode(nodeId); - $infoCardHeader.text(node.name); - $infoCard.addClass('visible'); - $infoCardTable.find('tbody tr').remove(); - addInfoTable('Model', node.model); - addInfoTable('X', node.x); - addInfoTable('Y', node.y); - for (let interfaceId in node.interfaces) { - const interface = node.interfaces[interfaceId]; - console.log('node interface: ', interface); - addInfoTable('Interface', `eth${interface.id}`); - if (interface.ip4) { - addInfoTable('IP4', `${interface.ip4}/${interface.ip4mask}`); - } - if (interface.ip6) { - addInfoTable('IP6', `${interface.ip6}/${interface.ip6mask}`); - } - } + infoPanel.showNode(nodeId); } else if (properties.edges.length === 1) { const edgeId = properties.edges[0]; - const edge = coreNetwork.edges.get(edgeId); - const link = edge.link; - const nodeOne = coreNetwork.getCoreNode(link.nodeOne); - const nodeTwo = coreNetwork.getCoreNode(link.nodeTwo); - console.log('clicked edge: ', link); - $infoCard.addClass('visible'); - $infoCardHeader.text('Edge'); - $infoCardTable.find('tbody tr').remove(); - addInfoTable(nodeOne.name, null); - const interfaceOne = link.interfaceOne; - if (interfaceOne) { - addInfoTable('Interface', `eth${interfaceOne.id}`); - if (interfaceOne.ip4) { - addInfoTable('IP4', `${interfaceOne.ip4}/${interfaceOne.ip4mask}`); - } - if (interfaceOne.ip6) { - addInfoTable('IP6', `${interfaceOne.ip6}/${interfaceOne.ip6mask}`); - } - } - addInfoTable(nodeTwo.name, null); - const interfaceTwo = link.interfaceTwo; - if (interfaceTwo) { - addInfoTable('Interface', `eth${interfaceTwo.id}`); - if (interfaceTwo.ip4) { - addInfoTable('IP4', `${interfaceTwo.ip4}/${interfaceTwo.ip4mask}`); - } - if (interfaceTwo.ip6) { - addInfoTable('IP6', `${interfaceTwo.ip6}/${interfaceTwo.ip6mask}`); - } - } - addInfoTable('Bandwidth', edge.link.bandwidth); - addInfoTable('Delay', edge.link.delay); - addInfoTable('Duplicate', edge.link.duplicate); - addInfoTable('Loss', edge.link.loss); - addInfoTable('Jitter', edge.link.jitter); + infoPanel.showEdge(edgeId); } else { - $infoCard.addClass('invisible'); + infoPanel.hide(); } }); coreNetwork.network.on('oncontext', function (properties) { console.log('context event: ', properties); properties.event.preventDefault(); - $nodeContext.addClass('d-none'); - $edgeContext.addClass('d-none'); + nodeContext.hide(); + edgeContext.hide(); const location = properties.pointer.DOM; const x = properties.event.pageX; @@ -293,132 +229,15 @@ const nodeId = coreNetwork.network.getNodeAt(location); if (nodeId) { - const node = coreNetwork.nodes.get(nodeId); - console.log('context node: ', node); - $nodeContext.data('node', nodeId); - $nodeContext.css({ - position: 'absolute', - left: x, - top: y - }); - $nodeContext.removeClass('d-none'); + nodeContext.show(nodeId, x, y); } else { const edgeId = coreNetwork.network.getEdgeAt(location); if (edgeId) { - const edge = coreNetwork.edges.get(edgeId); - console.log('context edge: ', edge); - $edgeContext.data('edge', edgeId); - $edgeContext.css({ - position: 'absolute', - left: x, - top: y - }); - $edgeContext.removeClass('d-none'); + edgeContext.show(edgeId, x, y); } } }); - $nodeContext.click(function (event) { - $nodeContext.addClass('d-none'); - console.log('node context click: ', event); - const nodeId = $nodeContext.data('node'); - const node = coreNetwork.nodes.get(nodeId).coreNode; - const $target = $(event.target); - const option = $target.data('option'); - console.log('node context: ', nodeId, option); - if (option === 'edit') { - $nodeEditModal.data('node', nodeId); - $nodeEditModal.find('.modal-title').text(`Edit Node: ${node.name}`); - $nodeEditModal.find('#node-name').val(node.name); - $nodeEditModal.modal('show'); - } else if (option === 'services') { - servicesModal.show(nodeId) - .catch(function(err) { - console.log('error showing services modal: ', err); - }); - } - }); - - $nodeEditButton.click(function () { - const $form = $nodeEditModal.find('form'); - const formData = formToJson($form); - console.log('node edit data: ', formData); - const nodeId = $nodeEditModal.data('node'); - const node = coreNetwork.nodes.get(nodeId); - if (formData.name) { - node.label = formData.name; - node.coreNode.name = formData.name; - coreNetwork.nodes.update(node); - } - $nodeEditModal.modal('hide'); - }); - - $edgeContext.click(function (event) { - $edgeContext.addClass('d-none'); - console.log('edge context click: ', event); - const edgeId = $edgeContext.data('edge'); - const edge = coreNetwork.edges.get(edgeId); - const link = edge.link; - const $target = $(event.target); - const option = $target.data('option'); - console.log('edge context: ', edgeId, option); - if (option === 'edit') { - // populate form with current link data - $linkEditModal.data('link', edgeId); - $linkEditModal.find('#link-bandwidth').val(link.bandwidth); - $linkEditModal.find('#link-delay').val(link.delay); - $linkEditModal.find('#link-per').val(link.loss); - $linkEditModal.find('#link-dup').val(link.duplicate); - $linkEditModal.find('#link-jitter').val(link.jitter); - - // set modal name and show - $linkEditModal.find('.modal-title').text('Edit Edge'); - $linkEditModal.modal('show'); - } - }); - - $linkEditButton.click(function () { - const $form = $linkEditModal.find('form'); - const formData = {}; - $form.serializeArray().map(function (x) { - let value = x.value; - if (value === '') { - value = null; - } else if (!isNaN(value)) { - value = parseInt(value); - } - formData[x.name] = value; - }); - console.log('link edit data: ', formData); - const edgeId = $linkEditModal.data('link'); - const edge = coreNetwork.edges.get(edgeId); - const link = edge.link; - - link.bandwidth = formData.bandwidth; - link.delay = formData.delay; - link.duplicate = formData.duplicate; - link.loss = formData.loss; - link.jitter = formData.jitter; - - coreRest.isRunning() - .then(function (isRunning) { - if (isRunning) { - const linkEdit = link.json(); - linkEdit.interface_one = linkEdit.interface_one.id; - linkEdit.interface_two = linkEdit.interface_two.id; - return coreRest.editLink(linkEdit); - } - }) - .then(function (response) { - console.log('link edit success'); - }) - .catch(function (err) { - console.log('error editing link: ', err); - }); - - $linkEditModal.modal('hide'); - }); - $newSessionButton.click(function () { coreNetwork.newSession() .then(function (session) { @@ -429,23 +248,6 @@ }); }); - $sessionsTable.on('click', 'td', function (event) { - const sessionId = $(this).parent('tr').data('session'); - console.log('clicked session to join: ', sessionId); - if (sessionId === coreRest.currentSession) { - console.log('same session, not changing'); - } else { - coreNetwork.joinSession(sessionId) - .then(function (session) { - joinSession(session); - $sessionsModal.modal('hide'); - }) - .catch(function (err) { - console.log('join session error: ', err); - }); - } - }); - $linkButton.click(function () { const linkMode = !$(this).hasClass('active'); coreNetwork.linkMode(linkMode); @@ -492,29 +294,6 @@ $nodeSelect.attr('src', icon); }); - // show sessions - $sessionsModal.on('shown.bs.modal', function () { - console.log('show sessions'); - $sessionsTable.find('tbody tr').remove(); - coreRest.getSessions() - .then(function (response) { - const sessions = response.sessions; - for (let session of sessions) { - console.log('show sessions: ', session); - const $idCell = $('', {text: session.id}); - const $nodeCell = $('', {text: session.nodes}); - const stateName = coreRest.getStateName(session.state); - const $stateCell = $('', {text: stateName}); - const $row = $('', {class: 'session-join', 'data-session': session.id}); - $row.append([$idCell, $nodeCell, $stateCell]); - $sessionsTable.find('tbody').append($row); - } - }) - .catch(function (err) { - console.log('error getting sessions: ', err); - }); - }); - console.log('connecting to ws'); const ws = io.connect(); ws.on('connection', function () {