From e6eb7437628e932ef823800b5a8380790a6b22d7 Mon Sep 17 00:00:00 2001 From: lombardofr Date: Sun, 28 Oct 2018 19:43:46 +0100 Subject: [PATCH] [wip] NS instance topology view Change-Id: I69dd246298d04860414bc0ad60ec3272426d0141 Signed-off-by: lombardofr --- instancehandler/template/instance_list.html | 91 ++-- .../template/instance_topology_view.html | 54 ++- instancehandler/views.py | 168 +------ lib/osm/osm_rdcl_parser.py | 255 ++++++++++- .../project/osm/osm_project_descriptors.html | 6 +- static/TopologyComposer/css/composer.css | 177 ++++++++ .../TopologyComposer/css/d3-context-menu.css | 78 ++++ .../js/d3-context-menu.js | 0 .../js/event.js | 21 +- .../js/graph_editor.js | 329 +++++++------- .../js/model_graph_editor.js | 188 ++++---- static/TopologyComposer/js/settings.js | 32 ++ static/src/instancehandler/instance_list.js | 5 + .../instancehandler/instance_topology_view.js | 303 ++++++++----- static/src/osm_gui_properties.js | 88 ++-- static/src/utils.js | 36 +- static/topology3D/css/d3-context-menu.css | 78 ---- static/topology3D/css/graph_editor_d3js.css | 415 ------------------ static/topology3D/js/graph_request.js | 318 -------------- 19 files changed, 1127 insertions(+), 1515 deletions(-) create mode 100644 static/TopologyComposer/css/composer.css create mode 100644 static/TopologyComposer/css/d3-context-menu.css rename static/{topology3D => TopologyComposer}/js/d3-context-menu.js (100%) rename static/{topology3D => TopologyComposer}/js/event.js (82%) rename static/{topology3D => TopologyComposer}/js/graph_editor.js (79%) rename static/{topology3D => TopologyComposer}/js/model_graph_editor.js (75%) create mode 100644 static/TopologyComposer/js/settings.js delete mode 100644 static/topology3D/css/d3-context-menu.css delete mode 100755 static/topology3D/css/graph_editor_d3js.css delete mode 100644 static/topology3D/js/graph_request.js diff --git a/instancehandler/template/instance_list.html b/instancehandler/template/instance_list.html index de47e62..97eac57 100644 --- a/instancehandler/template/instance_list.html +++ b/instancehandler/template/instance_list.html @@ -131,41 +131,54 @@ }, "targets": 5 },{ - // "width": "10%", + "width": "20%", "render": function (data, type, row) { - return '
\n' + - ' \n' + - ' \n' + - ' \n' + - ' \n' + + var template = '
' + + ' '; + }else{ + template += ' '; + } + template += ' ' + + ' ' + + ' ' + '
'; + return template; }, "targets": 5 }, @@ -203,12 +216,12 @@ }, { "render": function (data, type, row) { - return '
\n' + - ' \n' + + return '
' + + ' ' + '
'; }, "targets": 5 diff --git a/instancehandler/template/instance_topology_view.html b/instancehandler/template/instance_topology_view.html index fb67fbc..d1183f5 100644 --- a/instancehandler/template/instance_topology_view.html +++ b/instancehandler/template/instance_topology_view.html @@ -6,12 +6,11 @@ {% block head_block %} {{ block.super }} - - - - - + + + + {% endblock %} {% block title_header_big %} @@ -31,21 +30,25 @@ {% block content_body %} {{ block.super }} {% csrf_token %} - -
-
- {% block topology_toolbar %} - {{ block.super }} - {% include 'topology_toolbar_instance.html' %} - {% endblock %} -
+
+
+
+
+ + +
+
+
+
+
- - {% endblock %} {% block resource_block %} @@ -53,20 +56,15 @@ - - - - - - - - - - - - + + + + + + + + diff --git a/instancehandler/views.py b/instancehandler/views.py index 45120e2..e38e586 100644 --- a/instancehandler/views.py +++ b/instancehandler/views.py @@ -21,6 +21,7 @@ import yaml import json import logging from lib.osm.osmclient.clientv2 import Client +from lib.osm.osm_rdcl_parser import OsmParser import authosm.utils as osmutils from sf_t3d.decorators import login_required @@ -154,156 +155,33 @@ def delete(request, instance_id=None, type=None): print result return __response_handler(request, result, 'instances:list', to_redirect=True, type='ns') - +@login_required def show_topology(request, instance_id=None, type=None): user = osmutils.get_user(request) project_id = user.project_id raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',') if 'application/json' in raw_content_types: - result = {'vertices': [ - {"info": {"type": "vnf", "property": {"custom_label": ""}, - "group": []}, "id": "ping"}, - {"info": {"type": "vnf", "property": {"custom_label": ""}, - "group": []}, "id": "pong"}, - {"info": {"type": "vdu", "property": {"custom_label": ""}, - "group": ['pong']}, "id": "pong/ubuntu"}, - {"info": {"type": "vdu", "property": {"custom_label": ""}, - "group": ['ping']}, "id": "ping/ubuntu"}, - {"info": {"type": "cp", "property": {"custom_label": ""}, - "group": ['ping']}, "id": "ping/cp0"}, - {"info": {"type": "cp", "property": {"custom_label": ""}, - "group": ['ping']}, "id": "ping/cp1"}, - {"info": {"type": "cp", "property": {"custom_label": ""}, - "group": ['pong']}, "id": "pong/cp0"}, - {"info": {"type": "cp", "property": {"custom_label": ""}, - "group": ['pong']}, "id": "pong/cp1"}, - {"info": {"type": "ns_vl", "property": {"custom_label": ""}, - "group": []}, "id": "mgmt_vl"}, - ], - 'edges': [ - # {"source": "ping", "group": [], "target": "ping/cp0", "view": "Data"}, - {"source": "pong/ubuntu", "group": ['pong'], "target": "pong/cp0", "view": "vnf"}, - {"source": "ping/ubuntu", "group": ['ping'], "target": "ping/cp0", "view": "vnf"}, - {"source": "pong/ubuntu", "group": ['pong'], "target": "pong/cp1", "view": "vnf"}, - {"source": "ping/ubuntu", "group": ['ping'], "target": "ping/cp1", "view": "vnf"}, - {"source": "pong", "group": [], "target": "mgmt_vl", "view": "ns"}, - {"source": "ping", "group": [], "target": "mgmt_vl", "view": "ns"}, - ], 'graph_parameters': [], - 'model': { - "layer": { - - "ns": { - "nodes": { - "vnf": { - "addable": { - "callback": "addNode" - }, - "removable": { - "callback": "removeNode" - }, - "expands": "vnf" - }, - "ns_vl": { - "addable": { - "callback": "addNode" - }, - "removable": { - "callback": "removeNode" - } - }, - - }, - "allowed_edges": { - "ns_vl": { - "destination": { - "vnf": { - "callback": "addLink", - "direct_edge": False, - "removable": { - "callback": "removeLink" - } - } - } - }, - "vnf": { - "destination": { - "ns_vl": { - "callback": "addLink", - "direct_edge": False, - "removable": { - "callback": "removeLink" - } - }, - - } - } - - } - }, - "vnf": { - "nodes": { - "vdu": { - "addable": { - "callback": "addNode" - }, - "removable": { - "callback": "removeNode" - } - }, - "cp": { - "addable": { - "callback": "addNode" - }, - "removable": { - "callback": "removeNode" - } - }, - - }, - "allowed_edges": { - "vdu": { - "destination": { - "cp": { - "callback": "addLink", - "direct_edge": False, - "removable": { - "callback": "removeLink" - } - } - } - }, - "cp": { - "destination": { - "vdu": { - "callback": "addLink", - "direct_edge": False, - "removable": { - "callback": "removeLink" - } - } - } - } - } - }, - "name": "OSM", - "version": 1, - "nodes": { - "vnf": { - "label": "vnf" - }, - "ns_vl": { - "label": "vl" - }, - "cp": { - "label": "cp" - }, - "vdu": { - "label": "vdu" - } - }, - "description": "osm" - } - }} + client = Client() + nsr_object = {'nsr': {}, 'vnfr': {}, 'vnfd': {}} + if type == 'ns': + + nsr_resp = client.ns_get(user.get_token(), instance_id) + nsr_object['nsr'] = nsr_resp['data'] + if 'constituent-vnfr-ref' in nsr_object['nsr'] : + for vnfr_id in nsr_object['nsr']['constituent-vnfr-ref']: + vnfr_resp = client.vnf_get(user.get_token(), vnfr_id) + vnfr = vnfr_resp['data'] + nsr_object['vnfr'][vnfr['id']] = vnfr + if vnfr['vnfd-id'] not in nsr_object['vnfd']: + vnfd_resp = client.vnfd_get(user.get_token(), vnfr['vnfd-id']) + nsr_object['vnfd'][vnfr['vnfd-id']] = vnfd_resp['vnfd:vnfd-catalog']['vnfd'][0] + + + + test = OsmParser() + #print nsr_object + + result = test.nsr_to_graph(nsr_object) return __response_handler(request, result) else: result = {'type': type, 'project_id': project_id, 'instance_id': instance_id} diff --git a/lib/osm/osm_rdcl_parser.py b/lib/osm/osm_rdcl_parser.py index e9fbecd..0ba27aa 100644 --- a/lib/osm/osm_rdcl_parser.py +++ b/lib/osm/osm_rdcl_parser.py @@ -14,21 +14,254 @@ # limitations under the License. # -import json -import pyaml -import yaml -from lib.util import Util -from lib.parser import Parser + import logging -import traceback -import glob -import os +# from lib.rdcl_graph import RdclGraph +import copy logging.basicConfig(level=logging.DEBUG) log = logging.getLogger('OsmParser') -class OsmParser(Parser): - """Parser methods for osm project type +class RdclGraph(object): + """ Operates on the graph representation used for the GUI graph views """ + node_ids = [] + node_t3d_base = { + 'info': { + 'property': { + 'custom_label': '', + }, + 'type': '', + 'group': [] + } + } + + def __init__(self): + pass + + def add_link(self, source, target, view, group, graph_object, optional={}): + if (source is None or source not in self.node_ids) or (target is None or target not in self.node_ids): + return + edge_obj = { + 'source': source, + 'target': target, + 'view': view, + 'group': [group], + } + + edge_obj.update(optional) + if edge_obj not in graph_object['edges']: + graph_object['edges'].append(edge_obj) + + def add_node(self, id, type, group, positions, graph_object, optional={}): + if id is None: + return + node = next((x for x in graph_object['vertices'] if x['id'] == id), None) + if node is not None: + node['info']['group'].append(group) + else: + node = copy.deepcopy(self.node_t3d_base) + node['id'] = id + node['info']['type'] = type + if group is not None: + node['info']['group'].append(group) + if positions and id in positions['vertices'] and 'x' in positions['vertices'][id] and 'y' in \ + positions['vertices'][id]: + node['fx'] = positions['vertices'][id]['x'] + node['fy'] = positions['vertices'][id]['y'] + node['info'].update(optional) + graph_object['vertices'].append(node) + self.node_ids.append(id) + + def is_directed_edge(self, source_type=None, target_type=None, layer=None, model={}): + if source_type is None or target_type is None or layer is None: + return None + if layer in model['layer'] and 'allowed_edges' in model['layer'][layer]: + if source_type in model['layer'][layer]['allowed_edges'] and target_type in \ + model['layer'][layer]['allowed_edges'][source_type]['destination']: + edge_pro = model['layer'][layer]['allowed_edges'][source_type]['destination'][target_type] + return edge_pro['direct_edge'] if 'direct_edge' in edge_pro else False + + return None + + +class OsmParser(RdclGraph): + """ Operates on the graph representation used for the GUI graph views """ + + def nsr_to_graph(self, nsr_full): + + graph = {'vertices': [], 'edges': [], 'model': { + "layer": { + + "nsr": { + "nodes": { + "vnfr": { + "addable": {}, + "removable": {}, + "expands": "vnfr" + }, + "ns_vl": { + "addable": {}, + "removable": {} + }, + "ns_cp": { + "addable": {}, + "removable": {} + }, + + }, + "allowed_edges": { + "ns_vl": { + "destination": { + "vnfr": { + "callback": "addLink", + "direct_edge": False, + "removable": {} + } + } + }, + "vnfr": { + "destination": { + "ns_vl": { + "callback": "addLink", + "direct_edge": False, + "removable": {} + }, + + } + } + + } + }, + + "vnfr": { + "nodes": { + "vdur": {}, + "cp": {}, + "int_cp": {}, + "vnf_vl": {} + + }, + "allowed_edges": { + "vdur": { + "destination": { + "cp": { + "direct_edge": False, + }, + "int_cp": { + "direct_edge": False, + }, + "vnf_vl": { + "direct_edge": False, + } + } + }, + "cp": { + "destination": { + "vdur": { + "direct_edge": False, + } + } + }, + "int_cp": { + "destination": { + "vdur": { + "direct_edge": False, + }, + "vnf_vl": { + "direct_edge": False, + } + } + }, + "vnf_vl": { + "destination": { + "vdur": { + "direct_edge": False + } + } + } + } + }, + "name": "OSM", + "version": 1, + "description": "osm" + } + }, 'graph_parameters': {'view': {'nsr': {}, 'vnfr': {}}}} + + nsr = nsr_full['nsr'] + + graph['graph_parameters']['view']['nsr'] = {} + nsr_graph_param = graph['graph_parameters']['view']['nsr'] + nsr_graph_param['id'] = nsr['_id'] if '_id' in nsr else None + nsr_graph_param['nsdId'] = nsr['nsdId'] if 'nsdId' in nsr else None + nsr_graph_param['name-ref'] = nsr['name-ref'] if 'name-ref' in nsr else None + nsr_graph_param['operational-status'] = nsr['operational-status'] if 'operational-status' in nsr else None + nsr_graph_param['config-status'] = nsr['config-status'] if 'config-status' in nsr else None + nsr_graph_param['detailed-status'] = nsr['detailed-status'] if 'detailed-status' in nsr else None + nsr_graph_param['create-time'] = nsr['create-time'] if 'create-time' in nsr else None + nsr_graph_param['instantiate_params'] = nsr['instantiate_params'] if 'instantiate_params' in nsr else None + + map_vnf_index_to_id = {} + for vnfr_id in nsr['constituent-vnfr-ref']: + current_vnfr = nsr_full['vnfr'][vnfr_id] + + graph['graph_parameters']['view']['vnfr'][vnfr_id] = {} + vnfr_graph_param = graph['graph_parameters']['view']['vnfr'][vnfr_id] + vnfr_graph_param['id'] = vnfr_id + vnfr_graph_param['vnfd-id'] = current_vnfr['vnfd-id'] + vnfr_graph_param['vnfd-ref'] = current_vnfr['vnfd-ref'] + vnfr_graph_param['member-vnf-index-ref'] = current_vnfr['member-vnf-index-ref'] + vnfr_graph_param['vim-account-id'] = current_vnfr['vim-account-id'] + vnfr_graph_param['created-time'] = current_vnfr['created-time'] + + vnfr_label = current_vnfr['vnfd-ref'] + ':' + current_vnfr['member-vnf-index-ref'] + map_vnf_index_to_id[current_vnfr['member-vnf-index-ref']] = vnfr_id + self.add_node(vnfr_id, 'vnfr', None, None, graph, + {'property': {'custom_label': vnfr_label}, 'osm': current_vnfr}) + + for cp in current_vnfr['connection-point']: + if cp['id']: + cp_id = vnfr_label + ':' + cp['id'] + self.add_node(cp_id, 'cp', vnfr_id, None, graph, {'osm': cp}) + + for vdur in current_vnfr['vdur']: + vdur_id = vnfr_label + ':' + vdur['vdu-id-ref'] + self.add_node(vdur_id, 'vdur', vnfr_id, None, graph, {'osm': vdur}) + if current_vnfr['vnfd-id'] in nsr_full['vnfd']: + for vdu in nsr_full['vnfd'][current_vnfr['vnfd-id']]['vdu']: + if vdu['id'] == vdur['vdu-id-ref']: + if 'internal-connection-point' in vdu: + for int_cp in vdu['internal-connection-point']: + cp_id = vnfr_label + ':' + int_cp['id'] + self.add_node(cp_id, 'int_cp', vnfr_id, None, graph, {'osm': int_cp}) + for interface in vdu['interface']: + if interface['type'] == "EXTERNAL": + cp_id = vnfr_label + ':' + interface['external-connection-point-ref'] + self.add_link(cp_id, vdur_id, 'vnfr', vnfr_id, graph) + elif interface['type'] == "INTERNAL": + cp_id = vnfr_label + ':' + interface['internal-connection-point-ref'] + self.add_link(cp_id, vdur_id, 'vnfr', vnfr_id, graph) + + if current_vnfr['vnfd-id'] in nsr_full['vnfd'] and 'internal-vld' in nsr_full['vnfd'][ + current_vnfr['vnfd-id']]: + for vnfd_vld in nsr_full['vnfd'][current_vnfr['vnfd-id']]['internal-vld']: + vld_id = vnfr_label + ':' + vnfd_vld['id'] + self.add_node(vld_id, 'vnf_vl', vnfr_id, None, graph, {'osm': vnfd_vld}) + if vnfd_vld['internal-connection-point']: + for int_cp in vnfd_vld['internal-connection-point']: + int_cp_id = vnfr_label + ':' + int_cp['id-ref'] + self.add_link(vld_id, int_cp_id, 'vnfr', vnfr_id, graph) + + for ns_vld in nsr['nsd']['vld']: + self.add_node(ns_vld['id'], 'ns_vl', None, None, graph, + {'property': {'custom_label': ns_vld['name']}, 'osm': ns_vld}) + for cp_ref in ns_vld['vnfd-connection-point-ref']: + self.add_link(map_vnf_index_to_id[str(cp_ref['member-vnf-index-ref'])], ns_vld['id'], 'nsr', None, + graph) + + return graph + - """ +if __name__ == '__main__': + parser = OsmParser() + print parser.nsr_to_graph({}) diff --git a/projecthandler/template/project/osm/osm_project_descriptors.html b/projecthandler/template/project/osm/osm_project_descriptors.html index 877e7f2..83a8b38 100644 --- a/projecthandler/template/project/osm/osm_project_descriptors.html +++ b/projecthandler/template/project/osm/osm_project_descriptors.html @@ -55,7 +55,7 @@ var descr_list_url = '{% url "projects:list_descriptors" descriptor_type=descriptor_type%}'; var vim_list_url = '{% url "vims:list" %}'; var new_desc_url ="{% url 'projects:new_descriptor' descriptor_type=descriptor_type %}"; - var descriptor_type = '{{ descriptor_type }}'; + var descriptor_type = '{{ descriptor_type | safe }}'; var project_id = '{{ project_id }}'; var table; @@ -78,9 +78,7 @@ } }, "error": function (hxr, error, thrown) { - console.log(hxr) - console.log(thrown) - console.log(error); + } }, diff --git a/static/TopologyComposer/css/composer.css b/static/TopologyComposer/css/composer.css new file mode 100644 index 0000000..ac19770 --- /dev/null +++ b/static/TopologyComposer/css/composer.css @@ -0,0 +1,177 @@ + +.node_path { + opacity: 1; + stroke: #2F3550; + stroke-width: 1; +} + +.node_selected { + opacity: 1 !important; + stroke: #2F3550 !important; + stroke-width: 3 !important; +} + +.node_text { + font-family: Lucida Console; + text-anchor: middle; + user-select: none; +} + +.hidden_circle { + opacity: 0; + stroke: #FF0000 !important; + stroke-width: 2 !important; +} + +.hidden_circle:hover { + opacity: 1; + stroke: #FF0000 !important; + stroke-width: 2; +} + +.node_path:hover { + opacity: 1; + stroke: #2F3550; + stroke-width: 3; +} + +.node_path:hover text { + opacity: 0.4; + +} + +.link { + fill: none; +} + +.link path { + stroke-width: 2; + stroke: lightgray; +} + +.matted { + opacity: 0.3; +} + +.invisible { + visibility: hidden; +} + +.left-tool-bar-monitoring { + position: absolute; + top: 20px; + left: 20px; + z-index: 1; + text-align: center; + font-size: 12px; + + cursor: default; + padding: 0 6px; + line-height: 22px; + position: absolute; + + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.container-fluid { + min-height: 100vh !important; + background-color: white; +} + +#main { + height: 100%; + display: flex; +} + +#graph_editor_container { + position: relative; + min-height: 100vh; + border-right: 1px solid #AFAFAF; + flex: 1 1 auto; + display: flex; + align-items: center; + justify-content: center; +} + +#legenda { + position: absolute; + top: 20px; + right: 20px; + border: 1px solid #cdcdcd; + border-radius: 2px; + padding: 15px; +} + +#legenda > .node { + margin-top: 10px; + font-size: 13px; + display: flex; + align-items: center; +} + +#legenda > .node:first-child { + margin-top: 0; +} + +#legenda > .node > .icon { + width: 20px; + height: 20px; + border-radius: 1px; + margin-right: 10px; +} + +#side { + flex: 0 0 auto; + max-width: 500px; + min-width: 300px; + padding: 20px 30px; + display: flex; + flex-direction: column; +} + +.section { + font-size: 16px; + line-height: 40px; + letter-spacing: 0.4px; + border-bottom: 1px solid #ccc; + margin-bottom: 10px; + margin-top: 20px; + display: flex; + justify-content: space-between; +} + +.section > .status { + display: flex; + align-items: center; + font-size: 12px +} + +.section > .status > .indicator { + width: 8px; + height: 8px; + background-color: red; + border-radius: 50%; + display: block; + margin-right: 7px; +} + +.section > .status.active > .indicator { + background-color: green; +} + +.children td { + padding: 5px 7px; + font-size: 13px; + line-height: 15px; +} + +.children td:first-child { + padding-left: 0; + font-weight: 500; + text-align: right +} \ No newline at end of file diff --git a/static/TopologyComposer/css/d3-context-menu.css b/static/TopologyComposer/css/d3-context-menu.css new file mode 100644 index 0000000..dc47e62 --- /dev/null +++ b/static/TopologyComposer/css/d3-context-menu.css @@ -0,0 +1,78 @@ +.d3-context-menu { + position: absolute; + display: none; + background-color: #f2f2f2; + border-radius: 4px; + + font-family: Arial, sans-serif; + font-size: 14px; + min-width: 150px; + border: 1px solid #d4d4d4; + + z-index:1200; +} + +.d3-context-menu ul { + list-style-type: none; + margin: 4px 0px; + padding: 0px; + cursor: default; +} + +.d3-context-menu ul li { + padding: 4px 16px; + + -webkit-touch-callout: none; /* iOS Safari */ + -webkit-user-select: none; /* Chrome/Safari/Opera */ + -khtml-user-select: none; /* Konqueror */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* Internet Explorer/Edge */ + user-select: none; +} + +.d3-context-menu ul li:hover { + background-color: #4677f8; + color: #fefefe; +} + +/* + Header +*/ + +.d3-context-menu ul li.is-header, +.d3-context-menu ul li.is-header:hover { + background-color: #f2f2f2; + color: #444; + font-weight: bold; + font-style: italic; +} + +/* + Disabled +*/ + +.d3-context-menu ul li.is-disabled, +.d3-context-menu ul li.is-disabled:hover { + background-color: #f2f2f2; + color: #888; + cursor: not-allowed; +} + +/* + Divider +*/ + +.d3-context-menu ul li.is-divider { + padding: 0px 0px; +} + +.d3-context-menu ul li.is-divider:hover { + background-color: #f2f2f2; +} + +.d3-context-menu ul hr { + border: 0; + height: 0; + border-top: 1px solid rgba(0, 0, 0, 0.1); + border-bottom: 1px solid rgba(255, 255, 255, 0.3); +} diff --git a/static/topology3D/js/d3-context-menu.js b/static/TopologyComposer/js/d3-context-menu.js similarity index 100% rename from static/topology3D/js/d3-context-menu.js rename to static/TopologyComposer/js/d3-context-menu.js diff --git a/static/topology3D/js/event.js b/static/TopologyComposer/js/event.js similarity index 82% rename from static/topology3D/js/event.js rename to static/TopologyComposer/js/event.js index cfe815c..6519b7d 100755 --- a/static/topology3D/js/event.js +++ b/static/TopologyComposer/js/event.js @@ -1,5 +1,6 @@ /* Copyright 2017 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni + Copyright 2018 EveryUP srl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -14,33 +15,33 @@ limitations under the License. */ -if (typeof dreamer === 'undefined') { - var dreamer = {}; +if (typeof TCD3 === 'undefined') { + var TCD3 = {}; } -dreamer.Event = (function (global) { +TCD3.Event = (function () { 'use strict'; function Event () { - this._listeners = {}; + this._listeners = {}; } Event.prototype.addL = function (type, listener) { - if (typeof this._listeners[type] == "undefined"){ + if (typeof this._listeners[type] === "undefined"){ this._listeners[type] = []; } this._listeners[type].push(listener); }; Event.prototype.fire = function (event, args) { - if (typeof event == "string"){ + if (typeof event === "string"){ event = { type: event }; } if (!event.target){ event.target = this; } - if (!event.type){ //falsy + if (!event.type){ throw new Error("Event object missing 'type' property."); } @@ -52,7 +53,7 @@ dreamer.Event = (function (global) { } }; - Event.prototype.addListener = function (type, listener) { + /*Event.prototype.addListener = function (type, listener) { if (this._listeners[type] instanceof Array){ var listeners = this._listeners[type]; for (var i=0, len=listeners.length; i < len; i++){ @@ -63,11 +64,11 @@ dreamer.Event = (function (global) { } } - }; + };*/ return Event; }()); if (typeof module === 'object') { - module.exports = dreamer.Event; + module.exports = TCD3.Event; } diff --git a/static/topology3D/js/graph_editor.js b/static/TopologyComposer/js/graph_editor.js similarity index 79% rename from static/topology3D/js/graph_editor.js rename to static/TopologyComposer/js/graph_editor.js index 8343f05..4cc8663 100755 --- a/static/topology3D/js/graph_editor.js +++ b/static/TopologyComposer/js/graph_editor.js @@ -1,5 +1,6 @@ /* Copyright 2017 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni + Copyright 2018 EveryUP srl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,23 +14,20 @@ See the License for the specific language governing permissions and limitations under the License. */ -if (typeof dreamer === 'undefined') { - var dreamer = {}; + +if (typeof TCD3 === 'undefined') { + var TCD3 = {}; } -var level = {} -dreamer.GraphEditor = (function (global) { +TCD3.GraphEditor = (function () { 'use strict'; var DEBUG = true; var SHIFT_BUTTON = 16; var CANC_BUTTON = 46; - var default_link_color = "#888"; - var nominal_text_size = 15; + var nominal_text_size = 14; var nominal_stroke = 1.5; - var EventHandler = dreamer.Event; - // var IMAGE_PATH = "/static/assets/img/"; - + var EventHandler = TCD3.Event; /** @@ -65,19 +63,13 @@ dreamer.GraphEditor = (function (global) { } - GraphEditor.prototype.init = function (args) { - args = args || {} + args = args || {}; var self = this; - this.width = 550//args.width || 500; - this.height = 550// args.height || 500; + this.width = args.width || 1500; + this.height = args.height || 1500; this.forceSimulationActive = false; - //FixMe - this.width = this.width - this.width * 0.007; - this.height = this.height - this.height * 0.07; - - //console.log("this.width", this.width, "this.height", this.height); var min_zoom = 0.1; var max_zoom = 7; this._setupBehaviorsOnEvents(); @@ -86,35 +78,36 @@ dreamer.GraphEditor = (function (global) { this.type_property = { "unrecognized": { "shape": d3.symbolCircle, - "color": "white", - "node_label_color": "black", + "color": "#fff", + "node_label_color": "#000", "size": 15 }, }; this.type_property_link = { "unrecognized": { - "color": "#888", - //"color": "red", + "color": "lightgray", }, }; this.force = d3.forceSimulation() - .force("collide", d3.forceCollide().radius(40)) - .force("link", d3.forceLink().distance(80).iterations(1).id(function (d) { + .force("charge", d3.forceManyBody()) + .force("collide", d3.forceCollide().radius(80)) + // .force("link", d3.forceLink().distance(80).iterations(1).id(function (d) { + .force("link", d3.forceLink().distance(100).id(function (d) { return d.id; })) .force("center", d3.forceCenter(this.width / 2, this.height / 2)); - var zoom = d3.zoom().scaleExtent([min_zoom, max_zoom]) + var zoom = d3.zoom().scaleExtent([min_zoom, max_zoom]); var size = d3.scalePow().exponent(2) .domain([1, 100]) .range([8, 24]); - this.svg = d3.select("#graph_ed_container").append("svg") + this.svg = d3.select("#graph_editor_container").append("svg") .attr("id", "graph_svg") - .attr("perserveAspectRatio", "xMinYMid") + .attr("preserveAspectRatio", "xMinYMid") .attr("width", this.width) .attr("height", this.height); @@ -142,9 +135,9 @@ dreamer.GraphEditor = (function (global) { //d3.event.preventDefault(); if (self.lastKeyDown !== -1) return; self.lastKeyDown = d3.event.keyCode; - if (self.lastKeyDown === CANC_BUTTON && self._selected_node != undefined) { + if (self.lastKeyDown === CANC_BUTTON && self._selected_node !== undefined) { self.removeNode(self._selected_node, null, showAlert); - } else if (self.lastKeyDown === CANC_BUTTON && self._selected_link != undefined) { + } else if (self.lastKeyDown === CANC_BUTTON && self._selected_link !== undefined) { self.removeLink(self._selected_link, null, showAlert); } @@ -159,37 +152,35 @@ dreamer.GraphEditor = (function (global) { .attr("opacity", "0") .attr("transform", "translate(1 1)") .call(d3.drag() - .on("start", dragstarted) - .on("drag", dragged) - .on("end", dragended)); + .on("start", dragstarted) + .on("drag", dragged) + .on("end", dragended)); function dragstarted(d) { - //d3.select(this).raise().classed("active", true); + //d3.select(this).raise().classed("active", true); } function dragged(d) { //console.log(JSON.stringify(d)) - d3.select(this).attr("transform", function () { - return "translate("+d3.event.x+","+d3.event.y+")"; + d3.select(this).attr("transform", function () { + return "translate(" + d3.event.x + "," + d3.event.y + ")"; }) } function dragended(d) { - //d3.select(this).classed("active", false); + //d3.select(this).classed("active", false); } var chart = $("#graph_svg"); this.aspect = chart.width() / chart.height(); - this.container = chart.parent(); - $(window).on("resize", function() { + this.container = $("#graph_editor_container"); + $(window).on("resize", function () { - var palette_width = ($("#palette").length > 0) ? $("#palette").width() : 0; - var working_width = self.container.width() - palette_width; - self.width = (working_width < 0) ? 0 : working_width; + self.width = self.container.width(); self.height = self.container.height(); - chart.attr("width", self.width); - chart.attr("height", self.height); + chart.attr("width", self.container.width()); + chart.attr("height", self.container.height()); }).trigger("resize"); } @@ -199,60 +190,47 @@ dreamer.GraphEditor = (function (global) { function (myString) { switch (myString) { - case "circle": - return d3.symbolCircle; - break; - case "square": - return d3.symbolSquare; - break; - case "diamond": - return d3.symbolDiamond; - break; - case "triangle": - return d3.symbolTriangle; - break; - case "star": - return d3.symbolStar; - break; - case "cross": - return d3.symbolCross; - break; - default: - // if the string is not recognized - return d3.symbolCross; - //return d3.symbolCircleUnknown; + case "circle": + return d3.symbolCircle; + case "square": + return d3.symbolSquare; + case "diamond": + return d3.symbolDiamond; + case "triangle": + return d3.symbolTriangle; + case "star": + return d3.symbolStar; + case "cross": + return d3.symbolCross; + default: + // if the string is not recognized + return d3.symbolCross; } - } + }; - GraphEditor.prototype.get_name_from_d3_symbol = + GraphEditor.prototype.get_name_from_d3_symbol = function (mySymbol) { switch (mySymbol) { - case d3.symbolCircle: - return "circle"; - break; - case d3.symbolSquare: - return "square"; - break; - case d3.symbolDiamond: - return "diamond"; - break; - case d3.symbolTriangle: - return "triangle"; - break; - case d3.symbolStar: - return "star"; - break; - case d3.symbolCross: - return "cross"; - break; - default: - // if the string is not recognized - return "unknown"; + case d3.symbolCircle: + return "circle"; + case d3.symbolSquare: + return "square"; + case d3.symbolDiamond: + return "diamond"; + case d3.symbolTriangle: + return "triangle"; + case d3.symbolStar: + return "star"; + case d3.symbolCross: + return "cross"; + default: + // if the string is not recognized + return "unknown"; //return d3.symbolCircleUnknown; } - } + }; /** * Start or Stop force layout @@ -280,9 +258,8 @@ dreamer.GraphEditor = (function (global) { * */ GraphEditor.prototype.handleFiltersParams = function (filtersParams, notFireEvent) { - console.log("handleFiltersParams", filtersParams) - this.filter_parameters = (filtersParams != undefined) ? filtersParams : this.filter_parameters; - this.current_view_id = (this.filter_parameters != undefined && this.filter_parameters.link.view[0] != undefined) ? this.filter_parameters.link.view[0] : this.current_view_id + this.filter_parameters = (filtersParams !== undefined) ? filtersParams : this.filter_parameters; + this.current_view_id = (this.filter_parameters !== undefined && this.filter_parameters.link.view[0] !== undefined) ? this.filter_parameters.link.view[0] : this.current_view_id this.cleanAll(); this.refresh(); this.startForce(); @@ -334,20 +311,17 @@ dreamer.GraphEditor = (function (global) { if (node != undefined) { var node_id = node.id; this.d3_graph['nodes'].forEach(function (n, index, object) { - if (n.id == node_id) { + if (n.id === node_id) { object.splice(index, 1); - } - }); - //TODO trovare una metodo piu efficace + var self = this; var links_to_remove = []; this.d3_graph['links'].forEach(function (l, index, object) { if (node_id === l.source.id || node_id === l.target.id) { links_to_remove.push(index); } - }); var links_removed = 0; links_to_remove.forEach(function (l_index) { @@ -371,7 +345,7 @@ dreamer.GraphEditor = (function (global) { * @returns {boolean} */ GraphEditor.prototype.addLink = function (link) { - console.log("addLink" + JSON.stringify(link)) + console.log("addLink" + JSON.stringify(link)); if (link.source && link.target) { this.force.stop(); this.cleanAll(); @@ -456,7 +430,7 @@ dreamer.GraphEditor = (function (global) { .filter(this.node_filter_cb)) .filter(function (d) { - return (d.info.type == undefined) || (self._node_property_by_type(d.info.type, 'image', d) == undefined) + return (d.info.type === undefined) || (self._node_property_by_type(d.info.type, 'image', d) === undefined) }) .append("svg:path") @@ -551,13 +525,11 @@ dreamer.GraphEditor = (function (global) { .on("end", dragended)); - this.node = this.svg.selectAll('.node') .data(self.d3_graph.nodes .filter(this.node_filter_cb)).selectAll("image, path, circle"); - this.node.on("contextmenu", self.behavioursOnEvents.nodes["contextmenu"]) .on("mouseover", self.behavioursOnEvents.nodes["mouseover"]) .on("mouseout", self.behavioursOnEvents.nodes["mouseout"]) @@ -571,36 +543,29 @@ dreamer.GraphEditor = (function (global) { .on("mouseout", self.behavioursOnEvents.links["mouseout"]); - this.text = this.svg.selectAll(".node") .data(self.d3_graph.nodes .filter(this.node_filter_cb)) .append("svg:text") - .attr("class", "nodetext") - .attr("class", "cleanable") - .attr("dy", function(d) { - if (self._node_property_by_type(d.info.type, 'image', d) == undefined) { - //shape - return "-5" - } - else { - //image - return (-self._node_property_by_type(d.info.type, 'size', d)/2).toString() - } + .attr("class", "node_text cleanable") + .attr("dy", function (d) { + return "-5"; }) .attr("pointer-events", "none") .style("font-size", nominal_text_size + "px") - .style("font-family", "Lucida Console") + .style("font-family", "'Source Sans Pro','Helvetica Neue',Helvetica,Arial,sans-serif") .style("fill", function (d) { return self._node_property_by_type(d.info.type, 'node_label_color', d); }) - .style("text-anchor", "middle") + //.style("text-anchor", "middle") .text(function (d) { - return d.id; + if(d.info && d.info.property.custom_label && d.info.property.custom_label !==''){ + return d.info.property.custom_label + } else + return d.id; }); - function dragstarted(d) { d.draggednode = true; if (!d3.event.active) self.force.alphaTarget(0.3).restart(); @@ -636,8 +601,8 @@ dreamer.GraphEditor = (function (global) { * */ GraphEditor.prototype.startForce = function () { - //this.force.stop(); - var self = this + this.force.stop(); + var self = this; this.force .nodes(this.d3_graph.nodes) .on("tick", ticked); @@ -649,8 +614,8 @@ dreamer.GraphEditor = (function (global) { function ticked() { self.node.attr("cx", function (d) { - return d.x = Math.max(self._node_property_by_type(d.info.type, 'size', d), Math.min(self.width - self._node_property_by_type(d.info.type, 'size', d), d.x)); - }) + return d.x = Math.max(self._node_property_by_type(d.info.type, 'size', d), Math.min(self.width - self._node_property_by_type(d.info.type, 'size', d), d.x)); + }) .attr("cy", function (d) { return d.y = Math.max(self._node_property_by_type(d.info.type, 'size', d), Math.min(self.height - self._node_property_by_type(d.info.type, 'size', d), d.y)); }); @@ -666,11 +631,10 @@ dreamer.GraphEditor = (function (global) { return "translate(" + d.x + "," + d.y + ")"; }); self.text.attr("transform", function (d) { - var label_pos_y = d.y + self._node_property_by_type(d.info.type, 'size', d) + 10; + var label_pos_y = d.y + self._node_property_by_type(d.info.type, 'size', d)/2 +nominal_text_size; return "translate(" + d.x + "," + label_pos_y + ")"; }); - }; - + } }; @@ -683,7 +647,7 @@ dreamer.GraphEditor = (function (global) { */ GraphEditor.prototype.addListener = function (event_name, cb) { this.eventHandler.addL(event_name, cb); - } + }; /** * This method removes an event handler that has been attached with the addListener() method. @@ -693,7 +657,7 @@ dreamer.GraphEditor = (function (global) { */ GraphEditor.prototype.removeListener = function (event_name, cb) { - } + }; GraphEditor.prototype.setNodeClass = function (class_name, filter_cb) { @@ -702,7 +666,7 @@ dreamer.GraphEditor = (function (global) { this.svg.selectAll('.node').classed(class_name, false); this.svg.selectAll('.node') .classed(class_name, filter_cb); - } + }; GraphEditor.prototype.setLinkClass = function (class_name, filter_cb) { log("setLinkClass"); @@ -710,13 +674,14 @@ dreamer.GraphEditor = (function (global) { this.svg.selectAll('.link').classed(class_name, false); this.svg.selectAll('.link') .classed(class_name, filter_cb); - } + }; - GraphEditor.prototype.showNodeInfo = function(args){ + GraphEditor.prototype.showNodeInfo = function (args) { this.addLinesToPopup(args['node_info'], "Info about node selected") this.handlePopupVisibility(true, 'right') - } - GraphEditor.prototype.addLinesToPopup = function(data, title) { + }; + + GraphEditor.prototype.addLinesToPopup = function (data, title) { var self = this; var index = 1; var translate_y = 0; @@ -740,7 +705,7 @@ dreamer.GraphEditor = (function (global) { return 80 }) .type(function (d) { - console.log("popiup") + console.log("popup") return (self.get_d3_symbol()); }) ) @@ -752,7 +717,7 @@ dreamer.GraphEditor = (function (global) { .attr("stroke-width", 2.4) .attr("id", "close_popup") .attr("class", "popupcleanable cleanable") - .on("click", function(d) { + .on("click", function (d) { self.handlePopupVisibility(false); }); @@ -766,7 +731,7 @@ dreamer.GraphEditor = (function (global) { //console.log(i, data, data[i]) //var typeofvalue = typeof data[i]; var record = data[i]; - index = this._addRecordToPopup(i, record,index) + index = this._addRecordToPopup(i, record, index) } @@ -775,47 +740,49 @@ dreamer.GraphEditor = (function (global) { GraphEditor.prototype._addRecordToPopup = function (key, record, index, tab) { //console.log("_addRecordToPopup", key, record, index) var translate_y = 23 * index; - var summary = d3.select(".popup").append("g") - .attr("class", "popup summary d popupcleanable cleanable") - .attr("transform", "translate(10 " + translate_y + ")"); - if(Object.prototype.toString.call( record ) !== '[object Array]'){ //is a record simple key:value + var summary = d3.select(".popup").append("g") + .attr("class", "popup summary d popupcleanable cleanable") + .attr("transform", "translate(10 " + translate_y + ")"); + if (Object.prototype.toString.call(record) !== '[object Array]') { //is a record simple key:value //console.log(key, record) var summary_g = summary.append("g"); - summary_g.append("rect") - .attr("class", "popup summary bg popupcleanable cleanable") - .attr("width", "380") - .attr("height", "20"); - - summary_g.append("text") - .attr("class", "popup summary popupcleanable cleanable") - .attr("x", (tab)? tab: 10) - .attr("y", "17") - .attr("width", "100") - .text(function(d){ - return key.toUpperCase() + ":"; - }); - - summary_g.append("text") - .attr("class", "popup summary popupcleanable cleanable") - .attr("x", "370") - .attr("y", "17") - .attr("text-anchor", "end") - .text(function(d){return record}); + summary_g.append("rect") + .attr("class", "popup summary bg popupcleanable cleanable") + .attr("width", "380") + .attr("height", "20"); + + summary_g.append("text") + .attr("class", "popup summary popupcleanable cleanable") + .attr("x", (tab) ? tab : 10) + .attr("y", "17") + .attr("width", "100") + .text(function (d) { + return key.toUpperCase() + ":"; + }); + + summary_g.append("text") + .attr("class", "popup summary popupcleanable cleanable") + .attr("x", "370") + .attr("y", "17") + .attr("text-anchor", "end") + .text(function (d) { + return record + }); } else {//is a record simple complex: have a list of sub record key:value - //index ++; - this._addRecordToPopup(key, "", index) - for(var r in record){ - //console.log(i, r, record, record[r]) - for(var k in record[r]){ - //console.log(i, r, k, record[r][k]) - var curr_key = k; - var recordValue = record[r][k] - - index ++; - this._addRecordToPopup(curr_key, recordValue, index, 20) - } + //index ++; + this._addRecordToPopup(key, "", index) + for (var r in record) { + //console.log(i, r, record, record[r]) + for (var k in record[r]) { + //console.log(i, r, k, record[r][k]) + var curr_key = k; + var recordValue = record[r][k] + + index++; + this._addRecordToPopup(curr_key, recordValue, index, 20) } + } } @@ -825,7 +792,6 @@ dreamer.GraphEditor = (function (global) { }; - /** * Remove all the graph objects from the view */ @@ -945,7 +911,7 @@ dreamer.GraphEditor = (function (global) { 'click': function (d) { d3.event.preventDefault(); log('click', d); - if (self.lastKeyDown == SHIFT_BUTTON && self._selected_node != undefined) { + if (self.lastKeyDown === SHIFT_BUTTON && self._selected_node !== undefined) { var source_id = self._selected_node.id; var target_id = d.id; log("--" + JSON.stringify(self.filter_parameters.link.view)); @@ -965,7 +931,8 @@ dreamer.GraphEditor = (function (global) { 'mouseover': function (d) { }, - 'mouseout': function (d) {}, + 'mouseout': function (d) { + }, 'dblclick': function (d) { d3.event.preventDefault(); log('dblclick'); @@ -1014,6 +981,11 @@ dreamer.GraphEditor = (function (global) { this._deselectAllLinks(); d3.select(node_instance).classed(activeClass, !alreadyIsActive); this._selected_node = (alreadyIsActive) ? undefined : node_instance.__data__; + if(this._selected_node){ + this.eventHandler.fire("node:selected", this._selected_node) + } else { + this.eventHandler.fire("node:deselected", this._selected_node) + } }; /** @@ -1044,10 +1016,10 @@ dreamer.GraphEditor = (function (global) { } - GraphEditor.prototype.handlePopupVisibility = function(visible, side) { + GraphEditor.prototype.handlePopupVisibility = function (visible, side) { var opacity = (visible) ? 1 : 0; - var translate_op = (side == "left") ? "translate(50 50)" : "translate("+(this.width - 450).toString()+" 50)"; + var translate_op = (side === "left") ? "translate(50 50)" : "translate(" + (this.width - 450).toString() + " 50)"; if (!visible) { d3.selectAll(".popupcleanable").remove(); @@ -1062,7 +1034,7 @@ dreamer.GraphEditor = (function (global) { GraphEditor.prototype.refreshGraphParameters = function (graphParameters) { this.eventHandler.fire("refresh_graph_parameters", graphParameters); - } + }; /** * Log utility @@ -1073,12 +1045,11 @@ dreamer.GraphEditor = (function (global) { } - return GraphEditor; }(this)); if (typeof module === 'object') { - module.exports = dreamer.GraphEditor; -} \ No newline at end of file + module.exports = TCD3.GraphEditor; +} diff --git a/static/topology3D/js/model_graph_editor.js b/static/TopologyComposer/js/model_graph_editor.js similarity index 75% rename from static/topology3D/js/model_graph_editor.js rename to static/TopologyComposer/js/model_graph_editor.js index be092a4..2f5f6c8 100644 --- a/static/topology3D/js/model_graph_editor.js +++ b/static/TopologyComposer/js/model_graph_editor.js @@ -1,5 +1,6 @@ /* Copyright 2017 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni + Copyright 2018 EveryUP srl Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -13,23 +14,21 @@ See the License for the specific language governing permissions and limitations under the License. */ -if (typeof dreamer === 'undefined') { - var dreamer = {}; +if (typeof TCD3 === 'undefined') { + var TCD3 = {}; } -var level = {} -dreamer.ModelGraphEditor = (function (global) { +TCD3.ModelGraphEditor = (function () { 'use strict'; var DEBUG = true; var SHIFT_BUTTON = 16; var IMAGE_PATH = "/static/assets/img/"; - var GUI_VERSION = "v1"; - ModelGraphEditor.prototype = new dreamer.GraphEditor(); + ModelGraphEditor.prototype = new TCD3.GraphEditor(); ModelGraphEditor.prototype.constructor = ModelGraphEditor; - ModelGraphEditor.prototype.parent = dreamer.GraphEditor.prototype; + ModelGraphEditor.prototype.parent = TCD3.GraphEditor.prototype; /** * Constructor @@ -43,73 +42,54 @@ dreamer.ModelGraphEditor = (function (global) { ModelGraphEditor.prototype.init = function (args) { this.parent.init.call(this, args); + var self = this; + this.desc_id = args.desc_id || undefined; //TODO remove it - if (args.gui_properties[GUI_VERSION] != undefined) { - args.gui_properties = args.gui_properties[GUI_VERSION]; - } - - this.desc_id = args.desc_id || undefined; this.type_property = {}; - this.type_property["unrecognized"] = args.gui_properties["default"]; - this.type_property["unrecognized"]["default_node_label_color"] = args.gui_properties["default"]["label_color"]; - //this.type_property["unrecognized"]["shape"] = d3.symbolCross; - this._edit_mode = (args.edit_mode != undefined) ? args.edit_mode : this._edit_mode; + this.type_property["unrecognized"] = args.gui_properties["nodes"]["default"]; + + this._edit_mode = args.edit_mode || false; Object.keys(args.gui_properties["nodes"]).forEach(function (key, index) { - console.log(key + " ####") + this.type_property[key] = args.gui_properties["nodes"][key]; - if ( this.type_property[key]['property'] != undefined){ - for(var c_prop in this.type_property[key]){ - if(c_prop != 'property'){ - - this.type_property[key][c_prop]['shape'] = this.parent.get_d3_symbol(this.type_property[key][c_prop]['shape']); - if(this.type_property[key][c_prop]["image"] != undefined){ - this.type_property[key][c_prop]["image"] = IMAGE_PATH + this.type_property[key][c_prop]["image"] - } - } - } - } - else{ - this.type_property[key]["shape"] = this.parent.get_d3_symbol(this.type_property[key]["shape"]); - if (this.type_property[key]["image"] != undefined) { - this.type_property[key]["image"] = IMAGE_PATH + this.type_property[key]["image"]; - } + this.type_property[key]["shape"] = this.parent.get_d3_symbol(this.type_property[key]["shape"]); + if (this.type_property[key]["image"] !== undefined) { + this.type_property[key]["image"] = IMAGE_PATH + this.type_property[key]["image"]; } - - }, this); - if(args.gui_properties["edges"]){ + + if (args.gui_properties["edges"]) { this.type_property_link = args.gui_properties["edges"]; - var self = this; var link_types = ['unrecognized'].concat(Object.keys(self.type_property_link)) - this.defs.selectAll("marker") - .data(link_types) - .enter() - .append("svg:marker") // This section adds in the arrows - .attr("id", function(d){ - return d; - }) - .attr("viewBox", "-5 -5 10 10") - .attr("refX", 13) /*must be smarter way to calculate shift*/ - .attr("refY", 0) - .attr("markerUnits", "userSpaceOnUse") - .attr("markerWidth", 12) - .attr("markerHeight", 12) - .attr("orient", "auto") - .append("path") - .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z") - .attr('fill', function(d){ - return self.type_property_link[d].color; - }); + this.defs.selectAll("marker") + .data(link_types) + .enter() + .append("svg:marker") // This section adds in the arrows + .attr("id", function (d) { + return d; + }) + .attr("viewBox", "-5 -5 10 10") + .attr("refX", 13) /*must be smarter way to calculate shift*/ + .attr("refY", 0) + .attr("markerUnits", "userSpaceOnUse") + .attr("markerWidth", 12) + .attr("markerHeight", 12) + .attr("orient", "auto") + .append("path") + .attr("d", "M 0,0 m -5,-5 L 5,0 L -5,5 Z") + .attr('fill', function (d) { + return self.type_property_link[d].color; + }); } this.customBehavioursOnEvents = args.behaviorsOnEvents || undefined; - var self = this; - var data_url = (args.data_url) ? args.data_url : "graph_data/"; - if (!args.graph_data) { + + var data_url = args.data_url || undefined; + if (!args.graph_data && args.data_url) { d3.json(data_url, function (error, data) { //console.log(JSON.stringify(data)) self.d3_graph.nodes = data.vertices; @@ -122,17 +102,8 @@ dreamer.ModelGraphEditor = (function (global) { //if(args.filter_base != undefined) setTimeout(function () { - //self.handleForce(self.forceSimulationActive); - //var f_t = {"node":{"type":[],"group":["vlan_r3u0"]},"link":{"group":["vlan_r3u0"],"view":[""]}} - //var f_t ={"node":{"type":["vnf_vl","vnf_ext_cp","vnf_vdu_cp","vnf_vdu","vnf_click_vdu"],"group":["vlan_r3u0"]},"link":{"group":["vlan_r3u0"],"view":["vnf"]}} + self.handleForce(true); self.handleFiltersParams(args.filter_base); - //self.handleFiltersParams(f_t); - //console.log(JSON.stringify(args.filter_base)) - //console.log(self.d3_graph.nodes.length) - //console.log(JSON.stringify(self.d3_graph.nodes)) - //self.d3_graph.nodes.forEach(function(key, index){ - //console.log(key, index); - //}) }, 500); }); @@ -179,7 +150,7 @@ dreamer.ModelGraphEditor = (function (global) { if (self.model.layer[current_layer] && self.model.layer[current_layer].nodes[node_type] && self.model.layer[current_layer].nodes[node_type].addable) { if (self.model.layer[current_layer].nodes[node_type].addable.callback) { var c = self.model.callback[self.model.layer[current_layer].nodes[node_type].addable.callback].class; - var controller = new dreamer[c](); + var controller = new TCD3[c](); controller[self.model.layer[current_layer].nodes[node_type].addable.callback](self, node, function () { self.parent.addNode.call(self, node); success && success(); @@ -198,7 +169,6 @@ dreamer.ModelGraphEditor = (function (global) { }; - /** * Update the data properties of the node * @param {Object} Required. An object that specifies tha data of the node. @@ -219,13 +189,13 @@ dreamer.ModelGraphEditor = (function (global) { var self = this; var current_layer = self.getCurrentView(); var node_type = node.info.type; - if (node.info.desc_id == undefined){ + if (node.info.desc_id == undefined) { node.info.desc_id = self.desc_id; } if (self.model.layer[current_layer] && self.model.layer[current_layer].nodes[node_type] && self.model.layer[current_layer].nodes[node_type].removable) { if (self.model.layer[current_layer].nodes[node_type].removable.callback) { var c = self.model.callback[self.model.layer[current_layer].nodes[node_type].removable.callback].class; - var controller = new dreamer[c](); + var controller = new TCD3[c](); controller[self.model.layer[current_layer].nodes[node_type].removable.callback](self, node, function () { self.parent.removeNode.call(self, node); success && success(); @@ -270,7 +240,7 @@ dreamer.ModelGraphEditor = (function (global) { var direct_edge = 'direct_edge' in self.model.layer[current_layer].allowed_edges[source_type].destination[destination_type] ? self.model.layer[current_layer].allowed_edges[source_type].destination[destination_type]['direct_edge'] : false; link.directed_edge = direct_edge; var c = self.model.callback[callback].class; - var controller = new dreamer[c](); + var controller = new TCD3[c](); controller[callback](self, link, function () { self._deselectAllNodes(); self.parent.addLink.call(self, link); @@ -308,7 +278,7 @@ dreamer.ModelGraphEditor = (function (global) { if (self.model.layer[current_layer].allowed_edges[source_type].destination[destination_type].removable.callback) { var callback = self.model.layer[current_layer].allowed_edges[source_type].destination[destination_type].removable.callback; var c = self.model.callback[callback].class; - var controller = new dreamer[c](); + var controller = new TCD3[c](); controller[callback](self, link, function () { self._deselectAllNodes(); self._deselectAllLinks(); @@ -331,13 +301,13 @@ dreamer.ModelGraphEditor = (function (global) { ModelGraphEditor.prototype.savePositions = function (data) { - var vertices = {} + var vertices = {}; this.node.each(function (d) { vertices[d.id] = {}; vertices[d.id]['x'] = d.x; vertices[d.id]['y'] = d.y; }); - new dreamer.GraphRequests().savePositions({ + new TCD3.GraphRequests().savePositions({ 'vertices': vertices }); @@ -347,11 +317,6 @@ dreamer.ModelGraphEditor = (function (global) { * Internal functions */ - /** - * - * - */ - ModelGraphEditor.prototype._setupBehaviorsOnEvents = function (layer) { var self = this; @@ -363,15 +328,15 @@ dreamer.ModelGraphEditor = (function (global) { edit_mode: true }]; var contextMenuNodesAction = [{ - title: 'Edit', - action: function (elm, d, i) { - if (d.info.type != undefined) { - self.eventHandler.fire("edit_descriptor", self.project_id, d); - } - }, - nodes: [], - edit_mode: true + title: 'Edit', + action: function (elm, d, i) { + if (d.info.type != undefined) { + self.eventHandler.fire("edit_descriptor", self.project_id, d); + } }, + nodes: [], + edit_mode: true + }, { title: 'Delete', action: function (elm, d, i) { @@ -381,12 +346,12 @@ dreamer.ModelGraphEditor = (function (global) { } ]; - if(this.customBehavioursOnEvents){ + if (this.customBehavioursOnEvents) { contextMenuNodesAction = contextMenuNodesAction.concat(this.customBehavioursOnEvents['behaviors'].nodes); } - if ( self.model && self.model.layer && self.model.layer[layer] && self.model.layer[layer].action && self.model.layer[layer].action.node) { + if (self.model && self.model.layer && self.model.layer[layer] && self.model.layer[layer].action && self.model.layer[layer].action.node) { for (var i in self.model.layer[layer].action.node) { var action = self.model.layer[layer].action.node[i] contextMenuNodesAction.push({ @@ -394,16 +359,16 @@ dreamer.ModelGraphEditor = (function (global) { action: function (elm, d, i) { var callback = action.callback; var c = self.model.callback[callback].class; - var controller = new dreamer[c](); + var controller = new TCD3[c](); var args = { elm: elm, d: d, i: i - } + }; controller[callback](self, args); }, - edit_mode: (action.edit_mode != undefined) ? action.edit_mode: undefined + edit_mode: (action.edit_mode !== undefined) ? action.edit_mode : undefined }); } } @@ -414,7 +379,7 @@ dreamer.ModelGraphEditor = (function (global) { d3.event.preventDefault(); - if (self._edit_mode && self.lastKeyDown == SHIFT_BUTTON && self._selected_node != undefined) { + if (self._edit_mode && self.lastKeyDown === SHIFT_BUTTON && self._selected_node !== undefined) { self.addLink(self._selected_node, d, null, showAlert); } else { self._selectNodeExclusive(this, d); @@ -450,7 +415,7 @@ dreamer.ModelGraphEditor = (function (global) { d3.select(this).style('stroke-width', 4); }, 'mouseout': function (d) { - if (d != self._selected_link) + if (d !== self._selected_link) d3.select(this).style('stroke-width', 2); }, 'contextmenu': d3.contextMenu(contextMenuLinksAction, { @@ -465,22 +430,19 @@ dreamer.ModelGraphEditor = (function (global) { ModelGraphEditor.prototype.handleFiltersParams = function (filtersParams, notFireEvent) { this.parent.handleFiltersParams.call(this, filtersParams, notFireEvent); - this._setupBehaviorsOnEvents(filtersParams.link.view[0]); + if (filtersParams && filtersParams.link && filtersParams.link.view) + this._setupBehaviorsOnEvents(filtersParams.link.view[0]); }; ModelGraphEditor.prototype.getAvailableNodes = function () { log('getAvailableNodes'); - log(this.model) - if (this.model && this.model.layer[this.getCurrentView()] != undefined) + log(this.model); + if (this.model && this.model.layer[this.getCurrentView()] !== undefined) return this.model.layer[this.getCurrentView()].nodes; return []; - } - - - ModelGraphEditor.prototype.exploreLayer = function (args) { - }; + ModelGraphEditor.prototype.getTypeProperty = function () { return this.type_property; }; @@ -488,12 +450,19 @@ dreamer.ModelGraphEditor = (function (global) { ModelGraphEditor.prototype.getCurrentGroup = function () { return this.filter_parameters.node.group[0]; - } + }; ModelGraphEditor.prototype.getCurrentView = function () { return this.filter_parameters.link.view[0]; + }; + ModelGraphEditor.prototype.getCurrentFilters = function () { + return this.filter_parameters; + }; + + ModelGraphEditor.prototype.getGraphParams = function () { + return this.d3_graph.graph_parameters; + }; - } /** * Log utility */ @@ -503,12 +472,11 @@ dreamer.ModelGraphEditor = (function (global) { } - return ModelGraphEditor; }(this)); if (typeof module === 'object') { - module.exports = dreamer.ModelGraphEditor; -} \ No newline at end of file + module.exports = TCD3.ModelGraphEditor; +} diff --git a/static/TopologyComposer/js/settings.js b/static/TopologyComposer/js/settings.js new file mode 100644 index 0000000..5893dc4 --- /dev/null +++ b/static/TopologyComposer/js/settings.js @@ -0,0 +1,32 @@ +/* + Copyright 2017 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni + Copyright 2018 EveryUP srl + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +if (typeof TCD3 === 'undefined') { + var TCD3 = {}; +} + + +TCD3.settings = (function () { + 'use strict'; + + + return Event; +}()); + +if (typeof module === 'object') { + module.exports = TCD3.Event; +} diff --git a/static/src/instancehandler/instance_list.js b/static/src/instancehandler/instance_list.js index fa9bef4..a2c2003 100644 --- a/static/src/instancehandler/instance_list.js +++ b/static/src/instancehandler/instance_list.js @@ -87,6 +87,11 @@ var removeFormGroup = function (event) { $formGroup.remove(); }; +function showTopology(type, instance_id) { + var url = '/instances/'+type+'/'+instance_id+'/topology'; + window.location = url; +} + function showInstanceDetails(type, instance_id) { var url_info = '/instances/'+type+'/'+instance_id; var dialog = bootbox.dialog({ diff --git a/static/src/instancehandler/instance_topology_view.js b/static/src/instancehandler/instance_topology_view.js index f306443..1193b18 100644 --- a/static/src/instancehandler/instance_topology_view.js +++ b/static/src/instancehandler/instance_topology_view.js @@ -1,159 +1,69 @@ //GraphEditor instance -var graph_editor = new dreamer.ModelGraphEditor(); -var selected_vnffgId = null; -var show_all = null; - -// Enable Drop Action on the Graph -initDropOnGraph(); +var graph_editor = new TCD3.ModelGraphEditor(); var type_view = { - "ns": ["vnf", "ns_vl"], - "vnf": ["vdu", "cp"] + "nsr": ["vnfr", "ns_vl"], + "vnfr": ["vdur", "cp", "vnf_vl"] }; var params = { - node: { - type: type_view['ns'], - group: [] - }, - link: { - group: [], - view: ['ns'] - } - }; -$(document).ready(function() { + node: { + type: type_view['nsr'], + group: [] + }, + link: { + group: [], + view: ['nsr'] + } +}; + +$(document).ready(function () { graph_editor.addListener("filters_changed", changeFilter); - graph_editor.addListener("refresh_graph_parameters", refreshGraphParameters); + graph_editor.addListener("node:selected", refreshElementInfo); + graph_editor.addListener("node:deselected", refreshElementInfo); - console.log(osm_gui_properties) // graph_editor initialization graph_editor.init({ - width: $('#graph_ed_container').width(), - height: $('#graph_ed_container').height(), + width: $('#graph_editor_container').width(), + height: $('#graph_editor_container').height(), data_url: window.location.href, - desc_id: getUrlParameter('id'), + //desc_id: getUrlParameter('id'), gui_properties: osm_gui_properties, edit_mode: false, - behaviorsOnEvents:{ + behaviorsOnEvents: { viewBased: false, behaviors: buildBehaviorsOnEvents() } }); - // this will filter in the different views, excluding the node types that are not listed in params graph_editor.handleFiltersParams(params); }); -var filters = function(e, params) { - graph_editor.handleFiltersParams(params); - $('#' + e).nextAll('li').remove(); -} - -function initDropOnGraph() { - - var dropZone = document.getElementById('graph_ed_container'); - dropZone.ondrop = function(e) { - var group = graph_editor.getCurrentGroup() - e.preventDefault(); - var elemet_id = e.dataTransfer.getData("text/plain"); - var nodetype = $('#'+elemet_id).attr('type-name'); - console.log(nodetype); - if (nodetype) { - var type_name = graph_editor.getTypeProperty()[nodetype].name; - $('#div_chose_id').show(); - $('#input_choose_node_id').val(nodetype + "_" + generateUID()); - $('#modal_chooser_title_add_node').text('Add ' + type_name); - $('#save_choose_node_id').off('click').on('click', function() { - var name = $('#input_choose_node_id').val(); - var node_information = { - 'id': name, - 'info': { - 'type': nodetype, - 'group': [group], - 'desc_id': getUrlParameter('id'), - }, - 'x': e.layerX, - 'y': e.layerY - } - console.log(JSON.stringify(node_information)) - graph_editor.addNode(node_information, function() { - $('#modal_choose_node_id').modal('hide'); - }, function(error){ - showAlert(error) - }); - }); - $('#modal_choose_node_id').modal('show'); - - - } - - } - - dropZone.ondragover = function(ev) { - console.log("ondragover"); - return false; - } - - dropZone.ondragleave = function() { - console.log("ondragleave"); - return false; - } -} function handleForce(el) { - if (el.id == "topology_play") { - $("#topology_pause").removeClass('active'); - $("#topology_play").addClass('active'); - } else { - $("#topology_pause").addClass('active'); - $("#topology_play").removeClass('active'); - } - - graph_editor.handleForce((el.id == "topology_play") ? true : false); - + graph_editor.handleForce((el.getAttribute('aria-pressed') === "true")); } function changeFilter(e, c) { - - console.log("changeFilter", JSON.stringify(c)); - //$("#title_header").text("OSHI Graph Editor"); - //updateNodeDraggable({type_property: type_property, nodes_layer: graph_editor.getAvailableNodes()}) - if(c) - new dreamer.GraphRequests().getAvailableNodes({layer: c.link.view[0]}, buildPalette, showAlert); - -} - -function refreshGraphParameters(e, graphParameters) { - var self = $(this); - if (graphParameters == null) return; - + if (c && c.link && c.link.view[0]) { + updateLegend(c.link.view[0]); + } + layerDetails(graph_editor.getCurrentFilters()) } -function resetFilters(){ +function resetFilters() { graph_editor.handleFiltersParams(params); } function buildBehaviorsOnEvents() { var self = this; - var contextmenuNodesAction = [{ - title: 'Show info', - action: function (elm, d, i) { - // console.log('Show NodeInfo', elm, d, i); - var nodeData = { - "node": { - "id": d.id - } - }; - }, - edit_mode: false - - }, + var contextmenuNodesAction = [ { title: 'Explore', action: function (elm, c_node, i) { - if (c_node.info.type != undefined) { + if (c_node.info.type !== undefined) { var current_layer_nodes = Object.keys(graph_editor.model.layer[graph_editor.getCurrentView()].nodes); if (current_layer_nodes.indexOf(c_node.info.type) >= 0) { if (graph_editor.model.layer[graph_editor.getCurrentView()].nodes[c_node.info.type].expands) { @@ -178,10 +88,161 @@ function buildBehaviorsOnEvents() { }, edit_mode: false }]; - var behavioursOnEvents = { - 'nodes': contextmenuNodesAction + return { + 'nodes': contextmenuNodesAction }; - return behavioursOnEvents; +} + +function refreshElementInfo(event, element) { + if (event.type === 'node:selected') { + switch (element.info.type) { + case 'vnfr': + vnfrDetails(element.info.osm); + break; + case 'vdur': + vdurDetails(element.info.osm); + break; + case 'int_cp': + case 'cp': + cpDetails(element.info.osm); + break; + case 'vnf_vl': + case 'ns_vl': + vlDetails(element.info.osm); + break; + } + } + else if (event.type === 'node:deselected') { + layerDetails(graph_editor.getCurrentFilters()) + } +} + +function layerDetails(filters) { + var side = $('#side'); + var graph_parameters = graph_editor.getGraphParams(); + var layer_template = ''; + if(graph_parameters['view'] && filters.link.view.length >0 && filters.link.view[0]){ + if(filters.link.view[0] === 'nsr') { + layer_template = getMainSection('NS View'); + layer_template += getChildrenTable(graph_parameters['view']['nsr']); + } + else if(filters.link.view[0] === 'vnfr') { + layer_template = getMainSection('VNF View'); + var vnfr_id = filters.link.group[0]; + layer_template += getChildrenTable(graph_parameters['view']['vnfr'][vnfr_id]); + } + } + + side.empty(); + side.append(layer_template) +} + +function updateLegend(view) { + var legend = $('#legenda'); + var nodes = type_view[view]; + var legend_template = ''; + var nodes_properties = osm_gui_properties['nodes']; + for (var n in nodes){ + var node = nodes[n]; + if(nodes_properties[node]){ + legend_template += '
' + + '
' + + '
' +nodes_properties[node].name + '
'; + } + } + + legend.empty(); + legend.append(legend_template) + +} + +var map = { + 'ip-address': 'IP', 'vnfd-id': 'Vnfd Id', 'vnfd-ref': 'Vnfd Ref', 'vim-account-id': 'Vim Id', + 'member-vnf-index-ref': 'Member index', 'created-time': 'Created', 'id': 'Id', 'mgmt-network': 'Mgmt network', + 'name': 'Name', 'type': 'Type', 'vim-network-name': 'Vim network name', 'connection-point-id': 'Cp Id', + 'vdu-id-ref': 'Vdu Id', 'nsr-id-ref': 'Nsr Id' +}; + +function vnfrDetails(vnfr) { + var side = $('#side'); + var vnfr_template = getMainSection('VNFR'); + + vnfr_template += getChildrenTable(vnfr); + side.empty(); + side.append(vnfr_template) +} + +function vdurDetails(vdur) { + var side = $('#side'); + var vdur_template = getMainSectionWithStatus('VDUR', vdur['status'] === 'ACTIVE'); + vdur_template += getChildrenTable(vdur); + + if (vdur['interfaces'].length > 0) { + vdur_template += getSubSection('Interfaces:'); + vdur_template += ''; + + for (var i = 0; i < vdur['interfaces'].length; ++i) { + var interface = vdur['interfaces'][i]; + var interface_template = '' + + '' + + ''; + vdur_template += interface_template; + } + vdur_template += '
' + interface['name'] + 'IP:' + interface['ip-address'] + 'MAC:' + interface['mac-address'] + '
'; + } + + side.empty(); + side.append(vdur_template) +} + +function cpDetails(cp) { + var side = $('#side'); + var cp_template = getMainSection('Connection Point'); + + cp_template += getChildrenTable(cp); + side.empty(); + side.append(cp_template); +} + +function vlDetails(vl) { + var side = $('#side'); + var vl_template = getMainSection('Virtual Link'); + + vl_template += getChildrenTable(vl); + side.empty(); + side.append(vl_template); +} + + +function getMainSection(title) { + return '
' + title + '
'; +} + +function getSubSection(title) { + return '
' + title + '
'; +} + +function getMainSectionWithStatus(title, status) { + var template = '
' + title + ''; + if (status) + template += '
ACTIVE
'; + else + template += '
NO ACTIVE
'; + template += '
'; + return template; +} + +function getChildrenTable(data) { + var template = ''; + + for (var key in data) { + if (typeof data[key] === 'string') { + var key_map = (map[key]) ? map[key] : key; + template += ''; + } + } + template += '
' + key_map + '' + data[key] + '
'; + return template; } \ No newline at end of file diff --git a/static/src/osm_gui_properties.js b/static/src/osm_gui_properties.js index 25a6aba..45abaf7 100644 --- a/static/src/osm_gui_properties.js +++ b/static/src/osm_gui_properties.js @@ -1,50 +1,70 @@ var osm_gui_properties = { - "v1": { - "default": { - "shape": "cross", - "color": "#42f44e", - "label_color": "black", - "size": 15 - }, "nodes": { - "ns_vl": { - "image": "vl-80.png", - // "shape": "triangle", - "color": "#196B90", - "size": 20, - "name": "VL" - }, - "cp": { - "image": "cp-80.png", - // "shape": "circle", - "color": "#F27220", - "size": 20, - "name": "CP" + "default": { + "shape": "square", + "color": "#36c2f3", + "label_color": "black", + "default_node_label_color": "#000", + "size": 15 }, + "vnf": { - "image": "vnf-100.png", - // "shape": "square", + //"image": "vnf-100.png", + "shape": "square", "color": "#54A698", "size": 35, + "width": 40, + "height": 20, "name": "VNF" }, - "vnf_vl": { - "shape": "triangle", - //"color": "#5FC9DB", - "color": "#196B90", - "size": 11, - "name": "IntVL" - }, - "vdu": { "shape": "square", //"color": "#50A7CC", "color": "#54A698", "size": 30, + "width": 40, + "height": 20, "name": "VDU" - } + }, + "cp": { + //"image": "cp-80.png", + "shape": "square", + "color": "#c6b63f", + "size": 40, + "name": "CP" + }, + "int_cp": { + //"image": "cp-80.png", + "shape": "square", + "color": "#e3bfad", + "size": 40, + "name": "CP" + }, + "ns_vl": { + "shape": "triangle", + "color": "#5ba56e", + "size": 30, + "name": "VL" + }, + "vnf_vl": { + "shape": "triangle", + "color": "#f8a800", + "size": 30, + "name": "IntVL" + }, + "vdur": { + "shape": "square", + "color": "#cf1c24", + "size": 60, + "name": "VDUR" + }, + "vnfr": { + "shape": "square", + "color": "#605ca8", + "size": 60, + "name": "VNFR" + }, + }, "graphs": null - - } -} \ No newline at end of file + }; \ No newline at end of file diff --git a/static/src/utils.js b/static/src/utils.js index 6763f78..79d88c2 100644 --- a/static/src/utils.js +++ b/static/src/utils.js @@ -29,20 +29,19 @@ function savePositions(el) { function buildPalette(args) { $("#paletteContainer").empty(); var type_property = graph_editor.getTypeProperty(); + if (args.length > 0) { - args.forEach(function (category) { + $('#paletteContainer').append('
Legenda
'); + args.forEach(function (category) { var category_id = "category_" + category.category_name.replace(/[\s.*+?^${}()\/|[\]\\]/g, "_");//.replace(/\s/g, ''); var content_id = "palette-content-" + category.category_name.replace(/[\s.*+?^${}()\/|[\]\\]/g, "_");//.replace(/\s/g, ''); - $("#paletteContainer").append('
' + - '' + - ' ' + category.category_name + '' + - '
' + + $("#paletteContainer").append('
' + '
' + - '
' + '
'); + category.types.forEach(function (type) { console.log(graph_editor.get_name_from_d3_symbol(d3.symbolCircle)) var type_id = type.id.replace(/[\s.*+?^${}()|[\]\\]/g, "_"); @@ -66,7 +65,7 @@ function buildPalette(args) { '
' + palette_node_icon + '
' + - '
' + '
'; $("#" + content_id).append(html_to_append); }); @@ -74,12 +73,11 @@ function buildPalette(args) { } togglePaletteSpinner(true); - } function handlePaletteCat(item) { console.log("handlePaletteContainer") - var category_id = $(item).attr("category_id") + var category_id = $(item).attr("category_id"); $('#' + category_id).toggleClass("palette-close"); } @@ -90,11 +88,11 @@ function togglePaletteSpinner(addOrRemove) { function showAlert(msg) { // modal_alert_text - var alert_msg = "" - if (typeof msg == "string") - alert_msg = msg + var alert_msg = ""; + if (typeof msg === "string") + alert_msg = msg; else - alert_msg = JSON.stringify(msg) + alert_msg = JSON.stringify(msg); $('#modal_alert_text').text(alert_msg); $('#modal_alert').modal('show'); } @@ -113,25 +111,17 @@ function buildHtmlShape(args) { switch (mySymbol) { case d3.symbolCircle: return '
'; - break; case d3.symbolSquare: return '
'; - break; case d3.symbolDiamond: return '
'; - ; - break; + case d3.symbolTriangle: return '
'; - break; case d3.symbolStar: return '
'; - ; - break; case d3.symbolCross: return '
'; - ; - break; default: // if the string is not recognized return "unknown"; @@ -145,7 +135,7 @@ if (!String.format) { String.format = function (format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { - return typeof args[number] != 'undefined' ? + return typeof args[number] !== 'undefined' ? args[number] : match; }); diff --git a/static/topology3D/css/d3-context-menu.css b/static/topology3D/css/d3-context-menu.css deleted file mode 100644 index 334513c..0000000 --- a/static/topology3D/css/d3-context-menu.css +++ /dev/null @@ -1,78 +0,0 @@ -.d3-context-menu { - position: absolute; - display: none; - background-color: #f2f2f2; - border-radius: 4px; - - font-family: Arial, sans-serif; - font-size: 14px; - min-width: 150px; - border: 1px solid #d4d4d4; - - z-index:1200; -} - -.d3-context-menu ul { - list-style-type: none; - margin: 4px 0px; - padding: 0px; - cursor: default; -} - -.d3-context-menu ul li { - padding: 4px 16px; - - -webkit-touch-callout: none; /* iOS Safari */ - -webkit-user-select: none; /* Chrome/Safari/Opera */ - -khtml-user-select: none; /* Konqueror */ - -moz-user-select: none; /* Firefox */ - -ms-user-select: none; /* Internet Explorer/Edge */ - user-select: none; -} - -.d3-context-menu ul li:hover { - background-color: #4677f8; - color: #fefefe; -} - -/* - Header -*/ - -.d3-context-menu ul li.is-header, -.d3-context-menu ul li.is-header:hover { - background-color: #f2f2f2; - color: #444; - font-weight: bold; - font-style: italic; -} - -/* - Disabled -*/ - -.d3-context-menu ul li.is-disabled, -.d3-context-menu ul li.is-disabled:hover { - background-color: #f2f2f2; - color: #888; - cursor: not-allowed; -} - -/* - Divider -*/ - -.d3-context-menu ul li.is-divider { - padding: 0px 0px; -} - -.d3-context-menu ul li.is-divider:hover { - background-color: #f2f2f2; -} - -.d3-context-menu ul hr { - border: 0; - height: 0; - border-top: 1px solid rgba(0, 0, 0, 0.1); - border-bottom: 1px solid rgba(255, 255, 255, 0.3); -} \ No newline at end of file diff --git a/static/topology3D/css/graph_editor_d3js.css b/static/topology3D/css/graph_editor_d3js.css deleted file mode 100755 index 0433236..0000000 --- a/static/topology3D/css/graph_editor_d3js.css +++ /dev/null @@ -1,415 +0,0 @@ - -.node_path { - opacity: 1; - stroke: #2F3550; - stroke-width: 1; -} - -.node_selected { - opacity: 1 !important; - stroke: #2F3550 !important; - stroke-width: 3 !important; -} - -.hidden_circle { - opacity: 0; - stroke: #FF0000 !important; - stroke-width: 2 !important; -} - -.hidden_circle:hover { - opacity: 1; - stroke: #FF0000 !important; - stroke-width: 2; -} - -.node_path:hover { - opacity: 1; - stroke: #2F3550; - stroke-width: 3; -} - -.node_path:hover text { - opacity: 0.4; - -} - -.link { - fill: none; -} - -.link path { - stroke-width: 2; -} - -.matted { - opacity: 0.3; -} - -.invisible { - visibility: hidden; -} - -.drag_box { - padding: 0 40px 0 0; - margin-bottom: 0px !important; - padding-top: 0px; - top: 14px; - /* right: 25px !important; */ - /* width: 15%; */ - position: absolute; - z-index: 1; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - right: 0; - cursor: move; -} - -.selector_box { - padding: 0 40px 0 0; - margin-bottom: 0px !important; - padding-top: 0px; - top: 70px; - /* right: 25px !important; */ - /* width: 15%; */ - position: absolute; - z-index: 1; - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - right: 0; - cursor: move; -} - -.drag_button { - cursor: move !important; - /*border-style: dashed;*/ - border-width: thin; - border-color: black; - color: white; - border-radius: 50% !important; - height: 50px !important; - width: 50px !important; - margin-right: 5px; -} - -.drag_button p { - font-family: "Lucida Console", Monaco, monospace;; - font-size: 0.6em; - font-weight: bold; - text-decoration: none; - color: black; - text-align: center; - padding-top: 50%; - padding-bottom: 50%; - width: 100%; -} - -.left-tool-bar { - top: 14px; - cursor: default; - line-height: 22px; - position: absolute; - - padding: 0px 6px; - - /* top: 7px; */ - /* right: 6px; */ - z-index: 1; - text-align: center; - font-size: 12px; - /*color: #777; - /* border-radius: 20px; */ - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.left-tool-bar-monitoring { - - z-index: 1; - text-align: center; - font-size: 12px; - - top: 64px; - cursor: default; - padding: 0 6px; - line-height: 22px; - position: absolute; - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -.vnffg-box { - top: 80px; - left: 100px; - cursor: default; - position: absolute; - width: 130px; - - padding-top: 0px; - padding-bottom: 0px; - - /* top: 7px; */ - /* right: 6px; */ - z-index: 1; - text-align: center; - font-size: 12px; - /*color: #777; - /* border-radius: 20px; */ - - -webkit-touch-callout: none; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; -} - -textarea { - font-family: "Lucida Console", Monaco, monospace; - height: 350px !important; - resize: none; -} - -.form-group { - margin-bottom: 0px !important; - margin-top: 0px !important; -} - -.modal-body { - overflow-y: auto; -} - -[draggable=true] { - -khtml-user-drag: element; - -webkit-user-drag: element; - -khtml-user-select: none; - -webkit-user-select: none; -} - -.help-key { - border: 1px solid #ddd; - padding: 4px; - border-radius: 3px; - background: #f6f6f6; - font-family: Courier, monospace; - box-shadow: #999 1px 1px 1px; -} - -/* -Palette section -*/ -#palette { - position: absolute; - top: 20px; - bottom: 20px; - right: 22px; - background: #f3f3f3; - width: 170px; - text-align: center; - -webkit-user-select: none; - -khtml-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - border: 1px solid #bbb; - box-sizing: border-box; - padding: 0 0 0 0; -} - -.palette-status-indicator { - top: 50%; - position: relative; - justify-content: center; -} - -.palette-status-hidden > .palette-status-indicator { - top: 50%; - position: relative; - justify-content: center; - display: none; -} - -.palette-container { - #display: none; - position: absolute; - top: 0px; - right: 0; - bottom: 25px; - left: 0; - padding: 0; - overflow-y: auto; - box-sizing: border-box; -} - -.palette-category { - - border-bottom: 1px solid #ccc; -} - -.palette-hide { - display: none; -} - -.palette-header { - position: relative; - background: #f3f3f3; - cursor: pointer; - text-align: left; - padding: 1px; - font-weight: bold; - font-size: 16px; - overflow: hidden; - white-space: nowrap; - text-overflow: ellipsis; -} - -.palette-content { - - background: #fff; - padding: 3px; -} - -.palette-close > .palette-content { - background: #fff; - padding: 3px; - display: none; -} - -.palette-close > .palette-header > i.fa.fa-chevron-down { - - filter: none; - -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=1)"; - -webkit-transform: rotate(-90deg); - -ms-transform: rotate(-90deg); - transform: rotate(-90deg); -} - -.palette-node { - cursor: move; - margin: 3px auto; - height: 35px; - border-radius: 5px; - border: 1px solid #999; - background: #ddd no-repeat 5% 50%; - width: 80%; - background-size: contain; - position: relative; -} - -.palette-node-label { - font-size: 13px; - font-weight: bold; - padding-left: 30px; - margin-left: auto; - margin-right: auto; - position: relative; - top: 50%; - transform: translateY(-50%); -} - -.palette-node-icon-container { - position: absolute; - text-align: center; - top: 0; - bottom: 0; - left: 0; - width: 30px; - border-right: 1px solid rgba(0, 0, 0, 0.1); - background-color: rgba(0, 0, 0, 0.05); -} - -.palette-node-icon { - /* display: inline-block;*/ - width: 30px; - height: 100%; - background-position: 50% 50%; - background-size: contain; - background-repeat: no-repeat; -} - -.palette-node-circle { - display: inline-block; - margin-top: 2px; - width: 28px; - height: 28px; - -webkit-border-radius: 14px; - -moz-border-radius: 14px; - border-radius: 14px; - background: red; -} - -.palette-node-square { - display: inline-block; - margin-top: 4px; - padding-top: 1px; - width: 26px; - height: 26px; - background: red; -} - -.palette-node-triangle { - padding-top: 1px; - width: 0px; - height: 0px; - border-left: 15px solid transparent; - border-right: 15px solid transparent; - border-bottom: 30px solid #2f2f2f; -} - -/* -END Palette section -*/ - -/* -Popup section -*/ -.popup.bg { - fill: black; - opacity: 0.21; - border-radius: 3px; -} - -.popup.summary.bg { - fill: white; - opacity: 1; -} - -.popup.summary.counter { - overflow: hidden; - text-overflow: ellipsis; - font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -.popup.summary.countervalue { - overflow: hidden; - text-overflow: ellipsis; - font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -.popup.title { - fill: black; - font-size: 16px; - font-family: 'Source Sans Pro', 'Helvetica Neue', Helvetica, Arial, sans-serif; -} - -/* -Popup section -*/ \ No newline at end of file diff --git a/static/topology3D/js/graph_request.js b/static/topology3D/js/graph_request.js deleted file mode 100644 index 055fc1c..0000000 --- a/static/topology3D/js/graph_request.js +++ /dev/null @@ -1,318 +0,0 @@ -/* - Copyright 2017 CNIT - Consorzio Nazionale Interuniversitario per le Telecomunicazioni - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -if (typeof dreamer === 'undefined') { - var dreamer = {}; -} -var level = {} - -dreamer.GraphRequests = (function(global) { - 'use strict'; - - var DEBUG = true; - - GraphRequests.prototype.constructor = GraphRequests; - - /** - * Constructor - */ - function GraphRequests(args) { - - - } - - GraphRequests.prototype.addNode = function(args, choice, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - - data = args_to_formdata(args, data); - - //FIXME questo metodo dovrebbere essere generico - if(args.existing_element) - data.append('existing_element', args.existing_element ? args.existing_element : false) - //if (choice) - // data.append('choice', choice); - $.ajax({ - url: "addelement", - type: 'POST', - data: data, - cache: false, - contentType: false, - processData: false, - success: function(result) { - if (success) - success(); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - }; - - GraphRequests.prototype.removeNode = function(args, choice, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - - data = args_to_formdata(args, data); - - $.ajax({ - url: "removeelement", - type: 'POST', - data: data, - cache: false, - contentType: false, - processData: false, - success: function(result) { - if (success) - success(); - }, - error: function(result) { - if (error) - error(result); - } - }); - }; - - GraphRequests.prototype.getNodeOverview = function(args, success, error) { - - var params = jQuery.param(args) - console.log("params", params) - $.ajax({ - url: "overviewelement?"+params, - type: 'GET', - success: function(result) { - if (success) - success(result); - }, - error: function(result) { - if (error) - error(result); - } - }); - }; - - GraphRequests.prototype.addLink = function(args, choice, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - data = args_to_formdata(args, data); - - //data.append('destination', JSON.stringify(destination)); - if (choice) - data.append('choice', choice); - //if(link.desc_id) - // data.append('element_desc_id', link.desc_id || ''); - $.ajax({ - url: "addlink", - type: 'POST', - data: data, - cache: false, - contentType: false, - processData: false, - success: function(result) { - if (success) - success(); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - }; - - GraphRequests.prototype.removeLink = function(args, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - data = args_to_formdata(args, data); - - $.ajax({ - url: "removelink", - type: 'POST', - data: data, - cache: false, - contentType: false, - processData: false, - success: function(result) { - if (success) - success(); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - }; - - // - GraphRequests.prototype.getAvailableNodes = function(args, success, error){ - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - $.ajax({ - url: "availablenodes?layer="+args.layer, - type: 'GET', - success: function(result) { - if (success) - success(result); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - } - - GraphRequests.prototype.savePositions = function(positions, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - data.append('positions', JSON.stringify(positions)); - $.ajax({ - url: "positions", - type: 'POST', - data: data, - cache: false, - contentType: false, - processData: false, - success: function(result) { - if (success) - success(); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - }; - - /* START ETSI methods */ - GraphRequests.prototype.addVnffg = function(args, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - /* data.append('group_id', args.info.group[0]); - data.append('element_id', args.id); - data.append('element_type', args.info.type);*/ - data = args_to_formdata(args, data); - $.ajax({ - url: "addelement", - type: 'POST', - data: data, - cache: false, - contentType: false, - processData: false, - success: function(result) { - if (success) - success(result); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - }; - - GraphRequests.prototype.addNodeToVnffg = function(args, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - /* data.append('group_id', args.info.group[0]); - data.append('element_id', args.id); - data.append('element_type', args.info.type); - data.append('vnffg_id', args.vnffgId);*/ - data = args_to_formdata(args, data); - - $.ajax({ - url: "addnodetovnffg", - type: 'POST', - data: data, - cache: false, - contentType: false, - processData: false, - success: function(result) { - if (success) - success(result); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - }; - - GraphRequests.prototype.getUnusedVnf = function(nsd_id, success, error) { - var data = new FormData(); - data.append('csrfmiddlewaretoken', this.getCookie('csrftoken')); - $.ajax({ - url: "unusedvnf/" + nsd_id, - type: 'GET', - success: function(result) { - if (success) - success(result); - }, - error: function(result) { - if (error) - error(result); - log("some error: " + result); - } - }); - - }; - /* END ETSI methods */ - - GraphRequests.prototype.getCookie = function(name) { - var cookieValue = null; - if (document.cookie && document.cookie !== '') { - var cookies = document.cookie.split(';'); - for (var i = 0; i < cookies.length; i++) { - var cookie = jQuery.trim(cookies[i]); - // Does this cookie string begin with the name we want? - if (cookie.substring(0, name.length + 1) === (name + '=')) { - cookieValue = decodeURIComponent(cookie.substring(name.length + 1)); - break; - } - } - } - return cookieValue; - }; - - function args_to_formdata(args, form_data){ - for ( var key in args ) { - form_data.append(key, args[key]); - } - return form_data; - }; - - - /** - * Log utility - */ - function log(text) { - if (DEBUG) - console.log("::GraphRequests::", text); - } - - return GraphRequests; - - -}(this)); - -if (typeof module === 'object') { - module.exports = dreamer.GraphRequests; -} -- 2.17.1