[wip] composer nsd 91/6891/3
authorlombardofr <lombardo@everyup.it>
Thu, 15 Nov 2018 16:25:25 +0000 (17:25 +0100)
committerlombardofr <lombardo@everyup.it>
Mon, 19 Nov 2018 13:34:28 +0000 (14:34 +0100)
Change-Id: Iba2924273ab065c90ce85c5d41de90ff15f915d1
Signed-off-by: lombardofr <lombardo@everyup.it>
20 files changed:
descriptorhandler/template/composer.html
descriptorhandler/template/descriptorlist.html
descriptorhandler/template/modal/modal_keyboard_info_base.html [new file with mode: 0644]
descriptorhandler/urls.py
descriptorhandler/views.py
instancehandler/template/instance_topology_view.html
lib/osm/osm_rdcl_parser.py
lib/osm/osm_util.py [new file with mode: 0644]
projecthandler/template/project/modal/modal_keyboard_info_base.html [deleted file]
projecthandler/template/project/osm/modal/modal_keyboard_info.html [deleted file]
projecthandler/template/project/osm/osm_project_delete.html [deleted file]
projecthandler/template/project/osm/osm_project_descriptors.html
projecthandler/template/project/project_delete.html [deleted file]
static/TopologyComposer/css/composer.css
static/TopologyComposer/js/graph_editor.js
static/TopologyComposer/js/model_graph_editor.js
static/css/lwui.css
static/src/descriptorhandler/composer.js
static/src/descriptorhandler/controller.js [new file with mode: 0644]
static/src/instancehandler/instance_topology_view.js

index 2de4ae8..7647151 100644 (file)
@@ -15,6 +15,7 @@
 {% endblock %}
 {% block title_header_big %}
     {{ block.super }}
+    {{ type|upper }} Composer
 {% endblock %}
 {% block left_sidebar %}
     {% include 'osm/osm_project_left_sidebar.html' %}
@@ -23,8 +24,8 @@
 
 {% block breadcrumb_body %}
     {{ block.super }}
-    {% comment %}<li><a href="{% url 'projects:descriptors:list_descriptors'  type=type %}">{{ type|upper }} Descriptors</a></li>
-    <li><a href="#"><i class="fa fa-sitemap"></i> {{ type|upper }} Topology</a></li>{% endcomment %}
+    <li><a href="{% url 'projects:descriptors:list_descriptors'  descriptor_type=type %}">{{ type|upper }} Descriptors</a></li>
+    <li><a href="#"><i class="fa fa-sitemap"></i> {{ type|upper }} Composer</a></li>
 {% endblock %}
 
 {% block content_body %}
                     <span style="font-weight: 500;">Select Element</span>
                 </div>
                 <div id="palette">
-                    <div class="node" draggable="true">
-                        <div class="icon" style="background-color: #cf1c24" ></div>
-                        <div class="name">VDU</div>
-                    </div>
-                    <div class="node" draggable="true">
-                        <div class="icon" style="background-color: #f8a800" ></div>
-                        <div class="name">VL</div>
-                    </div>
-                    <div class="node" draggable="true">
-                        <div class="icon" style="background-color: #e3bfad" ></div>
-                        <div class="name">intCP</div>
-                    </div>
-                    <div class="node" draggable="true">
-                        <div class="icon" style="background-color: #c6b63f" ></div>
-                        <div class="name">extCp</div>
-                    </div>
+
 
                 </div>
 
                     <button id="topology_force" type="button" class="btn btn btn-default" onclick="handleForce(this)"
                             data-toggle="button" aria-pressed="false" autocomplete="off"><i
                             class="fas fa-thumbtack"></i></button>
-                    <button id="reset_filter" type="button" class="btn btn btn-default" onclick="resetFilters(this)"><i
-                            class="fa fa-backward"></i></button>
+                    <button id="reset_filter" type="button" data-container="body" data-toggle="tooltip" data-placement="top" title="Text view"  class="btn btn btn-default" onclick="openTextedit(this)"><i
+                            class="fa fa-edit"></i></button>
+                    <button id="info_button" type="button" data-container="body" data-toggle="tooltip" data-placement="top" title="Help"  class="btn btn btn-default "onclick="openHelp(this)" ><i class="fa fa-info"></i></button>
                 </div>
                 <div id="legenda">
                 </div>
             </div>
             <div id="side">
-
+                <form id="side_form" method="post" enctype="multipart/form-data" action="">
+                    {% csrf_token %}
+                </form>
             </div>
         </div>
     </div>
 
+    {% include 'modal/modal_keyboard_info_base.html' %}
 {% endblock %}
 
 {% block resource_block %}
     {{ block.super }}
-    <script>
-        var topology_data = {};//{{topology_data|safe }};
-    </script>
+
     <!-- d3.js -->
     <script src="/static/bower_components/d3/d3.js"></script>
     <script src="/static/bower_components/moment/moment.js"></script>
     <script src="/static/TopologyComposer/js/model_graph_editor.js"></script>
     <script src="/static/TopologyComposer/js/d3-context-menu.js"></script>
 
-
     <script src="/static/src/osm_gui_properties.js"></script>
+    <script src="/static/src/descriptorhandler/controller.js"></script>
     <script src="/static/src/descriptorhandler/composer.js"></script>
-{#    <script src="/static/src/instancehandler/instance_topology_view.js"></script>#}
 
 {% endblock %}
 
index df7bda2..5285125 100644 (file)
@@ -20,7 +20,7 @@
                    role="grid">
                 <thead>
                 <tr role="row">
-                    <th>Name</th>
+                    <th>Short Name</th>
                     <th>Identified</th>
                     <th>Description</th>
                     <th style="width:10%">Vendor</th>
diff --git a/descriptorhandler/template/modal/modal_keyboard_info_base.html b/descriptorhandler/template/modal/modal_keyboard_info_base.html
new file mode 100644 (file)
index 0000000..2be28a9
--- /dev/null
@@ -0,0 +1,35 @@
+<div id="modalTopologyInfoButton" class="modal fade" tabindex="-1" role="dialog">
+       <div class="modal-dialog ">
+               <div class="modal-content">
+                       <div class="modal-header">
+
+                               <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                                       <span aria-hidden="true">&times;</span>
+                               </button>
+                               <h4 class="modal-title">Keyboard shortcuts</h4>
+                       </div>
+                       <div class="modal-body">
+                <ul>
+
+                    <li>
+                        <p>Create edge: Select the first vertex by clicking on it. <span class="help-key">Shift</span> + <span class="help-key">left-click</span> on another vertex (different than the selected one).</p>
+                    </li>
+                    <li>
+                        <p> <span class="help-key">Delete</span> Delete selected nodes or link.</p>
+                    </li>
+
+
+                                       {% block left_sidebar %}
+
+                                       {% endblock %}
+                </ul>
+                       </div>
+                       <div class="modal-footer">
+
+                       </div>
+               </div>
+               <!-- /.modal-content -->
+       </div>
+       <!-- /.modal-dialog -->
+</div>
+<!-- /.modal -->
\ No newline at end of file
index c6e987e..b0972d9 100644 (file)
@@ -20,9 +20,16 @@ from descriptorhandler import views
 urlpatterns = [
     url(r'(?P<descriptor_type>\w+)/list$', views.show_descriptors, name='list_descriptors'),
     url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)(/$)', views.edit_descriptor, name='edit_descriptor'),
-    url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/delete$', views.delete_descriptor, name='delete_descriptor'),
+    url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/delete$', views.delete_descriptor,
+        name='delete_descriptor'),
     url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/clone', views.clone_descriptor, name='clone_descriptor'),
-    url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/action/(?P<action_name>[-\w]+)',views.custom_action,
+    url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/addElement/(?P<element_type>\w+)', views.addElement,
+        name='addElement'),
+    url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/removeElement/(?P<element_type>\w+)', views.removeElement,
+        name='removeElement'),
+    url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/updateElement/(?P<element_type>\w+)', views.updateElement,
+        name='updateElement'),
+    url(r'(?P<descriptor_type>\w+)/(?P<descriptor_id>[-\w]+)/action/(?P<action_name>[-\w]+)', views.custom_action,
         name='custom_action'),
     url(r'(?P<descriptor_type>\w+)/new$', views.new_descriptor, name='new_descriptor'),
     url(r'composer$', views.open_composer, name='open_composer'),
index c80af8a..1bdb9b4 100644 (file)
@@ -26,6 +26,7 @@ from django.shortcuts import render, redirect
 from lib.util import Util
 from lib.osm.osmclient.clientv2 import Client
 from lib.osm.osm_rdcl_parser import OsmParser
+from lib.osm.osm_util import OsmUtil
 import authosm.utils as osmutils
 
 logging.basicConfig(level=logging.DEBUG)
@@ -37,7 +38,6 @@ def show_descriptors(request, descriptor_type=None):
     user = osmutils.get_user(request)
     project_id = user.project_id
     client = Client()
-    print descriptor_type
     try:
         if descriptor_type == 'nsd':
             descriptors = client.nsd_list(user.get_token())
@@ -115,6 +115,74 @@ def clone_descriptor(request, descriptor_type=None, descriptor_id=None):
     else:
         return __response_handler(request, {}, url=None, status=200)
 
+@login_required
+def addElement(request, descriptor_type=None, descriptor_id=None, element_type=None):
+    user = osmutils.get_user(request)
+    project_id = user.project_id
+    client = Client()
+    if descriptor_type == 'nsd':
+        descriptor_result = client.nsd_get(user.get_token(), descriptor_id)
+        element_id = request.POST.get('id', '')
+        util = OsmUtil()
+        descriptor_updated = util.add_base_node('nsd', descriptor_result, element_type, element_id, request.POST.dict())
+        result = client.nsd_update(user.get_token(), descriptor_id, descriptor_updated)
+        if result['error'] == True:
+            return __response_handler(request, result['data'], url=None,
+                                      status=result['data']['status'] if 'status' in result['data'] else 500)
+        else:
+            parser = OsmParser()
+            # print nsr_object
+            if descriptor_type == 'nsd':
+                result_graph = parser.nsd_to_graph(descriptor_updated)
+
+        return __response_handler(request, result_graph, url=None, status=200)
+
+@login_required
+def removeElement(request, descriptor_type=None, descriptor_id=None, element_type=None):
+    user = osmutils.get_user(request)
+    project_id = user.project_id
+    client = Client()
+    if descriptor_type == 'nsd':
+        descriptor_result = client.nsd_get(user.get_token(), descriptor_id)
+        element_id = request.POST.get('id', '')
+        util = OsmUtil()
+        descriptor_updated = util.remove_node('nsd', descriptor_result, element_type, element_id, request.POST.dict())
+        result = client.nsd_update(user.get_token(), descriptor_id, descriptor_updated)
+        if result['error'] == True:
+            return __response_handler(request, result['data'], url=None,
+                                      status=result['data']['status'] if 'status' in result['data'] else 500)
+        else:
+            parser = OsmParser()
+            # print nsr_object
+            if descriptor_type == 'nsd':
+                result_graph = parser.nsd_to_graph(descriptor_updated)
+
+        return __response_handler(request, result_graph, url=None, status=200)
+
+@login_required
+def updateElement(request, descriptor_type=None, descriptor_id=None, element_type=None):
+    user = osmutils.get_user(request)
+    project_id = user.project_id
+    client = Client()
+    if descriptor_type == 'nsd':
+        descriptor_result = client.nsd_get(user.get_token(), descriptor_id)
+        util = OsmUtil()
+        payload = request.POST.dict()
+        if element_type == 'graph_params':
+            descriptor_updated = util.update_graph_params('nsd', descriptor_result, json.loads(payload['update']))
+        else:
+            descriptor_updated = util.update_node('nsd', descriptor_result, element_type, json.loads(payload['old']), json.loads(payload['update']))
+        result = client.nsd_update(user.get_token(), descriptor_id, descriptor_updated)
+        if result['error'] == True:
+            return __response_handler(request, result['data'], url=None,
+                                      status=result['data']['status'] if 'status' in result['data'] else 500)
+        else:
+            parser = OsmParser()
+            # print nsr_object
+            if descriptor_type == 'nsd':
+                result_graph = parser.nsd_to_graph(descriptor_updated)
+
+        return __response_handler(request, result_graph, url=None, status=200)
 
 @login_required
 def new_descriptor(request, descriptor_type=None):
@@ -266,8 +334,12 @@ def open_composer(request):
     project_id = user.project_id
     descriptor_id = request.GET.get('id')
     descriptor_type = request.GET.get('type')
+    result = {}
     client = Client()
     if descriptor_id:
+        raw_content_types = request.META.get('HTTP_ACCEPT', '*/*').split(',')
+        if 'application/json' not in raw_content_types:
+            return __response_handler(request, {'type': descriptor_type}, 'composer.html')
         try:
             if descriptor_type == 'nsd':
                 descriptor_result = client.nsd_get(user.get_token(), descriptor_id)
@@ -286,185 +358,28 @@ def open_composer(request):
             result = test.nsd_to_graph(descriptor_result)
         elif descriptor_type == 'vnfd':
             result = test.vnfd_to_graph(descriptor_result)
-        return __response_handler(request, result,'composer.html')
-
-    result = {'project_id': project_id,
-              'vertices': [
-                  {"info": {"type": "vnf", "property": {"custom_label": ""},
-                            "group": []}, "id": "vm"},
-                  {"info": {"type": "vnf", "property": {"custom_label": ""},
-                            "group": []}, "id": "vlan"},
-                  {"info": {"type": "vnf", "property": {"custom_label": ""},
-                            "group": []}, "id": "firewall"},
-                  {"info": {"type": "vnf", "property": {"custom_label": ""},
-                            "group": []}, "id": "ping"},
-
-                  {"info": {"type": "ns_vl", "property": {"custom_label": ""},
-                            "group": []}, "id": "vl1"},
-                  {"info": {"type": "ns_vl", "property": {"custom_label": ""},
-                            "group": []}, "id": "vl2"},
-                  {"info": {"type": "ns_vl", "property": {"custom_label": ""},
-                            "group": []}, "id": "vl3"},
-              ],
-              'edges': [
-                  {"source": "vm", "group": [], "target": "vl3", "view": "ns"},
-                  {"source": "vlan", "group": [], "target": "vl3", "view": "ns"},
-                  {"source": "vlan", "group": [], "target": "vl1", "view": "ns"},
-                  {"source": "firewall", "group": [], "target": "vl1", "view": "ns"},
-                  {"source": "firewall", "group": [], "target": "vl2", "view": "ns"},
-                  {"source": "ping", "group": [], "target": "vl2", "view": "ns"},
-              ],
-              '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",
-                    "callback": {
-                        "addNode": {
-                            "file": "osm_controller.js",
-                            "class": "OsmController"
-                        },
-                        "removeNode": {
-                            "file": "osm_controller.js",
-                            "class": "OsmController"
-                        },
-                        "addLink": {
-                            "file": "osm_controller.js",
-                            "class": "OsmController"
-                        },
-                        "removeLink": {
-                            "file": "osm_controller.js",
-                            "class": "OsmController"
-                        }
-                    }
-
-                }
-            }}
+        return __response_handler(request, result, 'composer.html')
+
     return __response_handler(request, result, 'composer.html')
 
 
 def get_available_nodes(request):
-
+    user = osmutils.get_user(request)
     params = request.GET.dict()
-    nodes = {
-        'ns': [{"types": [{"name": "Generic", "id": "vnf"},
-                          {"name": "ping", "id": "vnf"},
-                          {"name": "pong", "id": "vnf"},
-                          {"name": "hackfest1-vm", "id": "vnf"}], "category_name": "Vnf"},
-               {"types": [{"name": "VL", "id": "ns_vl"}], "category_name": "VirtualLink"}],
-        'vnf': [{"types": [{"name": "VDU", "id": "vdu"}], "category_name": "Vdu"},
-                {"types": [{"name": "CP", "id": "cp"}], "category_name": "CP"}]
-    }
-
-    return __response_handler(request, nodes[params['layer']])
+    client = Client()
+    result = []
+    try:
+        if params['layer'] == 'nsd':
+            descriptors = client.vnfd_list(user.get_token())
+    except Exception as e:
+        log.exception(e)
+        descriptors = []
+    if descriptors and descriptors['error'] is False:
+        for desc in descriptors['data']:
+            # print desc
+            result.append({'_id': desc['_id'],'id': desc['id'], 'name': desc['short-name']})
+
+    return __response_handler(request, {'descriptors': result})
 
 
 @login_required
index d1183f5..54b872a 100644 (file)
@@ -37,6 +37,8 @@
                     <button id="topology_force" type="button" class="btn btn btn-default" onclick="handleForce(this)"
                             data-toggle="button" aria-pressed="false" autocomplete="off"><i
                             class="fas fa-thumbtack"></i></button>
+                    <button id="reset_filter" type="button" data-container="body" data-toggle="tooltip" data-placement="top" title="YAML data"  class="btn btn btn-default" onclick="show(this)"><i
+                            class="fa fa-edit"></i></button>
                     <button id="reset_filter" type="button" class="btn btn btn-default" onclick="resetFilters(this)"><i
                             class="fa fa-backward"></i></button>
                 </div>
index 009c0e7..84814f2 100644 (file)
@@ -270,8 +270,14 @@ class OsmParser(RdclGraph):
                         "vdu": {},
                         "cp": {},
                         "int_cp": {},
-                        "vnf_vl": {}
-
+                        "vnf_vl": {
+                            "addable": {
+                                "callback": "addNode"
+                            },
+                            "removable": {
+                                "callback": "removeNode"
+                            }
+                        }
                     },
                     "allowed_edges": {
                         "vdu": {
@@ -316,7 +322,7 @@ class OsmParser(RdclGraph):
                 "name": "OSM",
                 "version": 1,
                 "description": "osm"
-            }
+            }, "callback": {"addNode": {"class": "OSMController"}, "removeNode": {"class": "OSMController"}}
         }, 'graph_parameters': {'view': {'vnfd': {}}}}
         if 'vnfd-catalog' in vnfd_catalog:
             vnfd = vnfd_catalog['vnfd-catalog']['vnfd'][0]
@@ -324,6 +330,13 @@ class OsmParser(RdclGraph):
             vnfd = vnfd_catalog['vnfd:vnfd-catalog']['vnfd'][0]
         else:
             return graph
+        vnfd_graph_param = graph['graph_parameters']['view']['vnfd']
+        vnfd_graph_param['id'] = vnfd['id'] if 'id' in vnfd else None
+        vnfd_graph_param['name'] = vnfd['name'] if 'name' in vnfd else None
+        vnfd_graph_param['short-name'] = vnfd['short-name'] if 'short-name' in vnfd else None
+        vnfd_graph_param['description'] = vnfd['description'] if 'description' in vnfd else None
+        vnfd_graph_param['version'] = vnfd['version'] if 'version' in vnfd else None
+        vnfd_graph_param['vendor'] = vnfd['vendor'] if 'vendor' in vnfd else None
         if 'connection-point' in vnfd:
             for extCp in vnfd['connection-point']:
                 self.add_node(extCp['name'], 'cp', vnfd['id'], None, graph,
@@ -356,9 +369,21 @@ class OsmParser(RdclGraph):
             "layer": {
                 "nsd": {
                     "nodes": {
-                        "vnfd": {},
+                        "vnf": {"addable": {
+                                "callback": "addNode"
+                            },
+                            "removable": {
+                                "callback": "removeNode"
+                            }},
                         "cp": {},
-                        "ns_vl": {}
+                        "ns_vl": {
+                            "addable": {
+                                "callback": "addNode"
+                            },
+                            "removable": {
+                                "callback": "removeNode"
+                            }
+                        }
                     },
                     "allowed_edges": {
                         "cp": {
@@ -368,17 +393,25 @@ class OsmParser(RdclGraph):
                                 }
                             }
                         },
-                        "vnfd":{
+                        "vnf":{
                             "destination": {
                                 "ns_vl": {
                                     "direct_edge": False,
+                                    "callback": "addLink",
+                                    "removable" : {
+                                        "callback": "removeLink",
+                                    }
                                 }
                             }
                         },
                         "ns_vl": {
                             "destination": {
-                                "vnfd": {
+                                "vnf": {
                                     "direct_edge": False,
+                                    "callback": "addLink",
+                                    "removable": {
+                                        "callback": "removeLink",
+                                    }
                                 }
                             }
                         }
@@ -434,17 +467,27 @@ class OsmParser(RdclGraph):
                 "name": "OSM",
                 "version": 1,
                 "description": "osm"
-            }
-        }, 'graph_parameters': {'view': {'vnfd': {}}}}
+            }, "callback": {"addNode": {"class": "OSMController"}, "removeNode": {"class": "OSMController"},
+                            "removeLink": {"class": "OSMController"}, "addLink": {"class": "OSMController"}}
+        }, 'graph_parameters': {'view': {'nsd': {}}}}
         if 'nsd-catalog' in nsd_catalog:
             nsd = nsd_catalog['nsd-catalog']['nsd'][0]
         elif 'nsd:nsd-catalog' in nsd_catalog:
             nsd = nsd_catalog['nsd:nsd-catalog']['nsd'][0]
         else:
             return graph
+
+        nsd_graph_param = graph['graph_parameters']['view']['nsd']
+        nsd_graph_param['id'] = nsd['id'] if 'id' in nsd else None
+        nsd_graph_param['name'] = nsd['name'] if 'name' in nsd else None
+        nsd_graph_param['short-name'] = nsd['short-name'] if 'short-name' in nsd else None
+        nsd_graph_param['description'] = nsd['description'] if 'description' in nsd else None
+        nsd_graph_param['version'] = nsd['version'] if 'version' in nsd else None
+        nsd_graph_param['vendor'] = nsd['vendor'] if 'vendor' in nsd else None
+
         if 'constituent-vnfd' in nsd:
             for vnfd in nsd['constituent-vnfd']:
-                costinuent_id = vnfd['vnfd-id-ref']+":"+vnfd['member-vnf-index']
+                costinuent_id = vnfd['vnfd-id-ref']+":"+str(vnfd['member-vnf-index'])
                 self.add_node(costinuent_id, 'vnf', None, None, graph,
                               {'property': {'custom_label': costinuent_id}, 'osm': vnfd})
 
@@ -456,7 +499,6 @@ class OsmParser(RdclGraph):
                     for cp_ref in vld['vnfd-connection-point-ref']:
                         vnfd_id = cp_ref['vnfd-id-ref'] + ':' + str(cp_ref['member-vnf-index-ref'])
                         self.add_link(vld['id'], vnfd_id, 'nsd', None, graph)
-
         return graph
 
 
diff --git a/lib/osm/osm_util.py b/lib/osm/osm_util.py
new file mode 100644 (file)
index 0000000..5d314ce
--- /dev/null
@@ -0,0 +1,106 @@
+class OsmUtil():
+
+    @staticmethod
+    def remove_node(descriptor_type, descriptor, node_type, element_id, args):
+        if descriptor_type == 'nsd':
+            if 'nsd-catalog' in descriptor:
+                nsd = descriptor['nsd-catalog']['nsd'][0]
+            elif 'nsd:nsd-catalog' in descriptor:
+                nsd = descriptor['nsd:nsd-catalog']['nsd'][0]
+
+            if node_type == 'ns_vl':
+                for k, v in enumerate(nsd['vld']):
+                    if v['id'] == args['id']:
+                        nsd['vld'].pop(k)
+            elif node_type == 'vnf':
+                for k, v in enumerate(nsd['constituent-vnfd']):
+                    if str(v['member-vnf-index']) == str(args['member-vnf-index']) and str(v['vnfd-id-ref']) == str(
+                            args['vnfd-id-ref']):
+                        nsd['constituent-vnfd'].pop(k)
+                        for j, vld in enumerate(nsd['vld']):
+                            vld['vnfd-connection-point-ref'] = [item for item in vld['vnfd-connection-point-ref'] if
+                                                                str(item['member-vnf-index-ref']) != str(
+                                                                    args['member-vnf-index']) or str(
+                                                                    item['vnfd-id-ref']) != str(args['vnfd-id-ref'])]
+            elif node_type == 'cp':
+                for vld in nsd['vld']:
+                    if vld['id'] == args['vld_id']:
+                        vld['vnfd-connection-point-ref'] = [item for item in vld['vnfd-connection-point-ref'] if
+                                                            str(item['member-vnf-index-ref']) != str(
+                                                                args['member-vnf-index-ref']) or str(
+                                                                item['vnfd-id-ref']) != str(args['vnfd-id-ref'])]
+
+        return descriptor
+
+    @staticmethod
+    def update_node(descriptor_type, descriptor, node_type, old, updated):
+        if descriptor_type == 'nsd':
+            if 'nsd-catalog' in descriptor:
+                nsd = descriptor['nsd-catalog']['nsd'][0]
+            elif 'nsd:nsd-catalog' in descriptor:
+                nsd = descriptor['nsd:nsd-catalog']['nsd'][0]
+
+            if node_type == 'ns_vl':
+                for k, v in enumerate(nsd['vld']):
+                    if v['id'] == old['id']:
+                        nsd['vld'][k].update(updated)
+                        print 'update here'
+                        print old
+            elif node_type == 'vnf':
+                for k, v in enumerate(nsd['constituent-vnfd']):
+                    if str(v['member-vnf-index']) == str(old['member-vnf-index']) and str(v['vnfd-id-ref']) == str(
+                            old['vnfd-id-ref']):
+                        print 'update here'
+                        print old
+
+        return descriptor
+
+    @staticmethod
+    def add_base_node(descriptor_type, descriptor, node_type, element_id, args):
+        if descriptor_type == 'nsd':
+            if 'nsd-catalog' in descriptor:
+                nsd = descriptor['nsd-catalog']['nsd'][0]
+            elif 'nsd:nsd-catalog' in descriptor:
+                nsd = descriptor['nsd:nsd-catalog']['nsd'][0]
+            if node_type == 'ns_vl':
+                nsd['vld'].append({
+                    "vim-network-name": "PUBLIC",
+                    "name": element_id,
+                    "vnfd-connection-point-ref": [],
+                    "mgmt-network": "true",
+                    "type": "ELAN",
+                    "id": element_id
+                })
+            if node_type == 'vnf':
+                indexes = []
+                for cvnfd in nsd['constituent-vnfd']:
+                    indexes.append(int(cvnfd["member-vnf-index"]))
+                memberindex = max(indexes) + 1
+                nsd['constituent-vnfd'].append({
+                    "member-vnf-index": memberindex,
+                    "vnfd-id-ref": element_id
+                })
+            if node_type == 'cp':
+                for vld in nsd['vld']:
+                    if vld['id'] == args['vld_id']:
+                        if'vnfd-connection-point-ref' not in vld:
+                            vld['vnfd-connection-point-ref'] = []
+                        vld['vnfd-connection-point-ref'].append(
+                            {
+                                "vnfd-connection-point-ref": args['vnfd-connection-point-ref'],
+                                "member-vnf-index-ref": args['member-vnf-index-ref'],
+                                "vnfd-id-ref": args['vnfd-id-ref']
+                            },
+                        )
+        return descriptor
+
+    @staticmethod
+    def update_graph_params(descriptor_type, descriptor, updated):
+        if descriptor_type == 'nsd':
+            if 'nsd-catalog' in descriptor:
+                nsd = descriptor['nsd-catalog']['nsd'][0]
+            elif 'nsd:nsd-catalog' in descriptor:
+                nsd = descriptor['nsd:nsd-catalog']['nsd'][0]
+            nsd.update(updated)
+
+        return descriptor
\ No newline at end of file
diff --git a/projecthandler/template/project/modal/modal_keyboard_info_base.html b/projecthandler/template/project/modal/modal_keyboard_info_base.html
deleted file mode 100644 (file)
index 1986d5d..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-<div id="modalTopologyInfoButton" class="modal fade" tabindex="-1" role="dialog">
-       <div class="modal-dialog ">
-               <div class="modal-content">
-                       <div class="modal-header">
-
-                               <button type="button" class="close" data-dismiss="modal" aria-label="Close">
-                                       <span aria-hidden="true">&times;</span>
-                               </button>
-                               <h4 class="modal-title">Keyboard shortcuts</h4>
-                       </div>
-                       <div class="modal-body">
-                <ul>
-
-                    <li>
-                        <p>Create edge: Select the first vertex by clicking on it. <span class="help-key">Shift</span> + <span class="help-key">left-click</span> on another vertex (different than the selected one).</p>
-                    </li>
-                    <li>
-                        <p> <span class="help-key">Delete</span> Delete selected nodes or link.</p>
-                    </li>
-
-                    <li>
-                        <p>Switch to automatic node positioning: Play/Pause</p>
-                    </li>
-                                       {% block left_sidebar %}
-
-                                       {% endblock %}
-                </ul>
-                       </div>
-                       <div class="modal-footer">
-
-                       </div>
-               </div>
-               <!-- /.modal-content -->
-       </div>
-       <!-- /.modal-dialog -->
-</div>
-<!-- /.modal -->
\ No newline at end of file
diff --git a/projecthandler/template/project/osm/modal/modal_keyboard_info.html b/projecthandler/template/project/osm/modal/modal_keyboard_info.html
deleted file mode 100644 (file)
index bf39e69..0000000
+++ /dev/null
@@ -1 +0,0 @@
-{% extends "modal/modal_keyboard_info_base.html" %}
\ No newline at end of file
diff --git a/projecthandler/template/project/osm/osm_project_delete.html b/projecthandler/template/project/osm/osm_project_delete.html
deleted file mode 100644 (file)
index 50bf685..0000000
+++ /dev/null
@@ -1,36 +0,0 @@
-{% extends "project_delete.html" %}
-
-{% block head_base %}
-    {% with skin_css="AdminLTE/dist/css/skins/skin-purple.min.css"%}
-        {{ block.super }}
-    {% endwith %}
-{% endblock %}
-
-{% block body %}
-    {% with skin="purple"%}
-        {{ block.super }}
-    {% endwith %}
-{% endblock %}
-{% block logo_sidebar %}
-    {% with logo_mini="assets/img/osm_small_logo.png" logo="assets/img/OSM-logo.png"%}
-        {{ block.super }}
-    {% endwith %}
-{% endblock %}
-
-{% block head_block %}
-       {{ block.super }}
-
-{% endblock %}
-
-{% block left_sidebar %}
-    {% include 'osm/osm_project_left_sidebar.html' %}
-{% endblock %}
-
-{% block breadcrumb_body %}
-       {{ block.super }}
-
-{% endblock %}
-
-{% block footer %}
-    {% include "footer.html" %}
-{% endblock %}
\ No newline at end of file
index bfbc355..0957ba2 100644 (file)
                             '<button type="button" class="btn btn-default" data-container="body"\n' +
                            '        data-toggle="tooltip" data-placement="top" title="Clone"\n' +
                            '        onclick="javascript:clonePackage(\''+ descriptor_type +'\', \''+row["_id"]+'\')">\n' +
-                           '    <i class="fa fa-clone"></i></button>\n' +
-                           '<button type="button" class="btn btn-default" data-container="body"\n' +
+                           '    <i class="fa fa-clone"></i></button>\n';
+                        if(descriptor_type == "nsd")
+                           result += '<button type="button" class="btn btn-default" data-container="body"\n' +
                            '        data-toggle="tooltip" data-placement="top" title="Show Graph"\n' +
                            '  onclick="location.href=\'/projects/descriptors/composer?type='+descriptor_type+'&id='+row["_id"] +'\'"\n' +
-                           ' disabled       ><i class="fa fa-sitemap fa-fw"></i></button>\n' +
+                           '        ><i class="fa fa-sitemap fa-fw"></i></button>\n';
+                        result +=
                            '<button type="button" class="btn btn-default" data-container="body"\n' +
                            '        data-toggle="tooltip" data-placement="top" title="Download package"\n' +
                            '        onclick="location.href=\'/projects/descriptors/'+descriptor_type+'/'+ row["_id"] +'/action/download_pkg\'">\n' +
diff --git a/projecthandler/template/project/project_delete.html b/projecthandler/template/project/project_delete.html
deleted file mode 100644 (file)
index 4ae063e..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-{% extends "base.html" %}
-
-{% load staticfiles %}
-
-{% block head_block %}
-       {{ block.super }}
-
-{% endblock %}
-
-{% block left_sidebar %}
-
-{% endblock %}
-
-{% block breadcrumb_body %}
-       {{ block.super }}
-    {% if project_id  %}
-    <li><a href="{% url 'projects:open_project' %}">{{project_overview_data.name}}</a></li>
-    <li>Delete Project</li>
-    {% endif %}
-{% endblock %}
-
-{% block content_body %}
-       {{ block.super }}
-    <div class="row">
-    {% if project_id  %}
-        <div class="col-sm-5">
-      <div class="box box-danger">
-        <div class="box-header with-border">
-              <i class="fa fa-warning"></i>
-
-              <h3 class="box-title">Warning</h3>
-        </div>
-          <div class="box-body">
-              <form role="form" method="post">
-                  {% csrf_token %}
-                  <div class="box-body">
-                        <p>The Project <strong>{{project_name}}</strong> will be deleted!</p>
-                      <!-- /.box-body -->
-                  </div>
-                   <div class="box-footer">
-                          <button type="submit" class="btn btn-danger pull-right"><i class="far fa-trash-alt"></i> Delete</button>
-                   </div>
-              </form>
-
-        </div><!-- /.box-body -->
-      </div><!-- /.box -->
-    </div>
-    {% endif %}
-</div>
-
-{% endblock %}
-
-{% block resource_block %}
-       {{ block.super }}
-
-
-    <script>
-
-
-
-
-$(document).ready(function () {
-    {% if project_id == None %}
-      window.location.href='{% url "home"  %}';
-    {% endif %}
-
-});
-
-
-
-    </script>
-{% endblock %}
-
index e7ecc59..12be9e7 100644 (file)
     padding-left: 0;
     font-weight: 500;
     text-align: right
+}
+
+.left-tool-bar-monitoring > .btn-default {
+    background-color: transparent!important;
 }
\ No newline at end of file
index ff4a21f..50e4f44 100755 (executable)
@@ -396,12 +396,13 @@ TCD3.GraphEditor = (function () {
         //log(data)
         var self = this;
 
-        this.link = this.svg
+        var link = this.svg
             .selectAll()
             .data(self.d3_graph.links
                 .filter(this.link_filter_cb)
-            )
-            .enter().append("g")
+            );
+        link.exit().remove();
+         this.link = link.enter().append("g")
             .attr("class", "link cleanable")
             .append("path")
             .attr("class", "link")
@@ -418,24 +419,26 @@ TCD3.GraphEditor = (function () {
                 return (d.directed_edge ? "url(#" + marker_url + ")" : '');
             });
 
-        this.nodeContainer = this.svg
+        var nodeContainer = this.svg
             .selectAll()
             .data(self.d3_graph.nodes
-                .filter(this.node_filter_cb))
-            .enter()
+                .filter(this.node_filter_cb));
+        nodeContainer.exit().remove();
+        nodeContainer.enter()
             .append("g")
             // .attr("class", "nodosdads")
             .attr("class", "node cleanable");
 
-        this.svg.selectAll('.node')
+        var nodes_symbols = this.svg.selectAll('.node')
             .data(self.d3_graph.nodes
                 .filter(this.node_filter_cb))
 
             .filter(function (d) {
                 return (d.info.type === undefined) || (self._node_property_by_type(d.info.type, 'image', d) === undefined)
-            })
+            });
+            nodes_symbols.exit().remove();
 
-            .append("svg:path")
+            nodes_symbols.append("svg:path")
             .attr("d", d3.symbol()
                 .size(function (d) {
                     return Math.PI * Math.pow(self._node_property_by_type(d.info.type, 'size', d), 2) / 4;
@@ -471,7 +474,7 @@ TCD3.GraphEditor = (function () {
             .filter(function (d) {
                 return self._node_property_by_type(d.info.type, 'image', d) != undefined
             });
-
+            figure_node.exit().remove();
         figure_node.append("svg:image")
             .attr("xlink:href", function (d) {
                 return self._node_property_by_type(d.info.type, 'image', d)
index 6cee85d..fd80822 100644 (file)
@@ -118,23 +118,26 @@ TCD3.ModelGraphEditor = (function () {
      * @returns {boolean}
      */
     ModelGraphEditor.prototype.updateData = function (args) {
-        this.d3_graph.nodes = args.graph_data.vertices;
-        this.d3_graph.links = args.graph_data.edges;
-        this.d3_graph.graph_parameters = args.graph_data.graph_parameters;
+        this.d3_graph.nodes = args.vertices;
+        this.d3_graph.links = args.edges;
+        this.d3_graph.graph_parameters = args.graph_parameters;
         this.model = args.model;
         this.refreshGraphParameters(this.d3_graph.graph_parameters);
+        this.cleanAll();
         this.refresh();
         this.startForce();
+        this.handleForce(this.forceSimulationActive);
+        //this.force.restart();
         //if(args.filter_base != undefined)
 
-        //if(args.filter_base){
-        var self = this;
-        setTimeout(function () {
-            self.handleForce(true);
-            self.handleFiltersParams(args.filter_base);
-        }, 500);
-        //}
-    }
+        if(args.filter_base){
+            var self = this;
+            setTimeout(function () {
+                self.handleForce(true);
+                self.handleFiltersParams(args.filter_base);
+            }, 500);
+        }
+    };
 
     /**
      * Add a new node to the graph.
@@ -145,13 +148,16 @@ TCD3.ModelGraphEditor = (function () {
         var self = this;
         var current_layer = self.getCurrentView();
         var node_type = node.info.type;
-
         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) {
+                console.log(self.model.callback)
                 var c = self.model.callback[self.model.layer[current_layer].nodes[node_type].addable.callback].class;
-                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);
+                var controller = new TCD3.OsmController();
+                controller[self.model.layer[current_layer].nodes[node_type].addable.callback](self, node, function (result) {
+                    console.log(result)
+                    console.log(node)
+                    self.updateData(result);
+                    // self.parent.addNode.call(self, node);
                     success && success();
                 }, error);
 
@@ -173,9 +179,24 @@ TCD3.ModelGraphEditor = (function () {
      * @param {Object} Required. An object that specifies tha data of the node.
      * @returns {boolean}
      */
-    ModelGraphEditor.prototype.updateDataNode = function (args) {
-        //FIXME updating a node properties need commit to server side!
-        this.parent.updateDataNode.call(this, args);
+    ModelGraphEditor.prototype.updateDataNode = function (node, args, success, error) {
+        console.log(node)
+        var controller = new  TCD3.OsmController();
+        controller.updateNode(this,node, args, function(){
+
+        }, error);
+    };
+
+    /**
+     * Update the data properties of the node
+     * @param {Object} Required. An object that specifies tha data of the node.
+     * @returns {boolean}
+     */
+    ModelGraphEditor.prototype.updateGraphParams = function (args, success, error) {
+        var controller = new  TCD3.OsmController();
+        controller.updateGraphParams(args, function(){
+
+        }, error);
     };
 
     /**
@@ -194,7 +215,7 @@ TCD3.ModelGraphEditor = (function () {
         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 TCD3[c]();
+                var controller = new  TCD3.OsmController();
                 controller[self.model.layer[current_layer].nodes[node_type].removable.callback](self, node, function () {
                     self.parent.removeNode.call(self, node);
                     success && success();
@@ -239,7 +260,7 @@ TCD3.ModelGraphEditor = (function () {
                 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 TCD3[c]();
+                var controller = new  TCD3.OsmController();
                 controller[callback](self, link, function () {
                     self._deselectAllNodes();
                     self.parent.addLink.call(self, link);
@@ -270,14 +291,14 @@ TCD3.ModelGraphEditor = (function () {
         var d = link.target;
         var source_type = s.info.type;
         var destination_type = d.info.type;
-        var current_layer = self.getCurrentView()
+        var current_layer = self.getCurrentView();
         if (self.model.layer[current_layer].allowed_edges && self.model.layer[current_layer].allowed_edges[source_type] && self.model.layer[current_layer].allowed_edges[source_type].destination[destination_type] &&
             self.model.layer[current_layer].allowed_edges[source_type].destination[destination_type].removable
         ) {
             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 TCD3[c]();
+                var controller = new  TCD3.OsmController();
                 controller[callback](self, link, function () {
                     self._deselectAllNodes();
                     self._deselectAllLinks();
@@ -326,16 +347,7 @@ TCD3.ModelGraphEditor = (function () {
             },
             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
-        },
+        var contextMenuNodesAction = [
             {
                 title: 'Delete',
                 action: function (elm, d, i) {
@@ -405,7 +417,6 @@ TCD3.ModelGraphEditor = (function () {
             'links': {
                 'click': function (d) {
                     self._selectLinkExclusive(this, d);
-
                 },
                 'dblclick': function (event) {
 
@@ -448,7 +459,6 @@ TCD3.ModelGraphEditor = (function () {
 
     ModelGraphEditor.prototype.getCurrentGroup = function () {
         return this.filter_parameters.node.group[0];
-
     };
 
     ModelGraphEditor.prototype.getCurrentView = function () {
index 858666d..1b12db5 100644 (file)
@@ -1,4 +1,13 @@
 .skin-purple .sidebar-menu > li.menu-open > a {
   color: #b8c7ce !important;
   background: #1e282c;
+}
+
+.help-key {
+    border: 1px solid #ddd;
+    padding: 4px;
+    border-radius: 3px;
+    background: #f6f6f6;
+    font-family: Courier, monospace;
+    box-shadow: #999 1px 1px 1px;
 }
\ No newline at end of file
index a21c14f..175f46b 100644 (file)
@@ -22,6 +22,13 @@ var type_view = {
     "vnfd": ["vdu", "cp", "vnf_vl", "int_cp"]
 };
 
+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'
+};
+
 var params = {
     node: {
         type: type_view[getUrlParameter('type')],
@@ -47,17 +54,108 @@ $(document).ready(function () {
         data_url: window.location.href,
         //desc_id: getUrlParameter('id'),
         gui_properties: osm_gui_properties,
-        edit_mode: false,
+        edit_mode: true,
         behaviorsOnEvents: {
             viewBased: false,
             behaviors: buildBehaviorsOnEvents()
         }
     });
     graph_editor.handleFiltersParams(params);
+    initDropOnGraph();
+
+
+    $("#side_form").submit(function (event) {
+        event.preventDefault(); //prevent default action
+        console.log("ON submit")
+        var form_data = new FormData(this); //Encode form elements for submission
+        var formDataJson = {};
+        form_data.forEach(function (value, key) {
+            formDataJson[key] = value;
+        });
+        if (graph_editor._selected_node) {
+            graph_editor.updateDataNode(graph_editor._selected_node, formDataJson, function () {
+
+            }, function (result) {
+                var data = result.responseJSON;
+                var title = "Error " + (data && data.code ? data.code : 'unknown');
+                var message = data && data.detail ? data.detail : 'No detail available.';
+                bootbox.alert({
+                    title: title,
+                    message: message
+                });
+            })
+        } else {
+            graph_editor.updateGraphParams(formDataJson, function () {
+
+            }, function (result) {
+                var data = result.responseJSON;
+                var title = "Error " + (data && data.code ? data.code : 'unknown');
+                var message = data && data.detail ? data.detail : 'No detail available.';
+                bootbox.alert({
+                    title: title,
+                    message: message
+                });
+            })
+        }
 
+    });
 });
 
 
+function initDropOnGraph() {
+
+    var dropZone = document.getElementById('graph_editor_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');
+        var random_name = nodetype + "_" + generateUID();
+
+        var node_information = {
+            'id': random_name,
+            'info': {
+                'type': nodetype,
+                'property': {
+                    'custom_label': random_name
+                },
+                'group': null,
+                'desc_id': getUrlParameter('id'),
+                'desc_type': getUrlParameter('type'),
+                'osm': {}
+            },
+            'x': e.layerX,
+            'y': e.layerY
+        };
+        if (nodetype === 'ns_vl') {
+
+            graph_editor.addNode(node_information, function () {
+                console.log("OK")
+            }, function (error) {
+                showAlert(error)
+            })
+        } else if (nodetype === 'vnf') {
+            node_information['id'] = $('#' + elemet_id).attr('desc_id');
+            graph_editor.addNode(node_information, function () {
+                console.log("OK")
+            }, function (error) {
+                showAlert(error)
+            })
+        }
+    };
+
+    dropZone.ondragover = function (ev) {
+        console.log("ondragover");
+        return false;
+    };
+
+    dropZone.ondragleave = function () {
+        console.log("ondragleave");
+        return false;
+    };
+}
+
 
 function handleForce(el) {
     graph_editor.handleForce((el.getAttribute('aria-pressed') === "true"));
@@ -66,8 +164,9 @@ function handleForce(el) {
 function changeFilter(e, c) {
     if (c && c.link && c.link.view[0]) {
         updateLegend(c.link.view[0]);
+        updatePalette(c.link.view[0]);
     }
-    //layerDetails(graph_editor.getCurrentFilters())
+    layerDetails(graph_editor.getCurrentFilters())
 }
 
 function resetFilters() {
@@ -75,37 +174,7 @@ function resetFilters() {
 }
 
 function buildBehaviorsOnEvents() {
-    var self = this;
-    var contextmenuNodesAction = [
-        {
-            title: 'Explore',
-            action: function (elm, c_node, i) {
-                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) {
-                            var new_layer = graph_editor.model.layer[graph_editor.getCurrentView()].nodes[c_node.info.type].expands;
-                            graph_editor.handleFiltersParams({
-                                node: {
-                                    type: Object.keys(graph_editor.model.layer[new_layer].nodes),
-                                    group: [c_node.id]
-                                },
-                                link: {
-                                    group: [c_node.id],
-                                    view: [new_layer]
-                                }
-                            });
-
-                        }
-                        else {
-                            showAlert('This is not an explorable node.')
-                        }
-                    }
-                }
-            },
-            edit_mode: false
-        }];
-
+    var contextmenuNodesAction = [];
     return {
         'nodes': contextmenuNodesAction
     };
@@ -115,7 +184,7 @@ function buildBehaviorsOnEvents() {
 function refreshElementInfo(event, element) {
     if (event.type === 'node:selected') {
         switch (element.info.type) {
-            case 'vnfd':
+            case 'vnf':
                 vnfDetails(element.info.osm);
                 break;
             case 'vdu':
@@ -137,19 +206,18 @@ function refreshElementInfo(event, element) {
 }
 
 function layerDetails(filters) {
-    var side = $('#side');
+    var side = $('#side_form');
     var graph_parameters = graph_editor.getGraphParams();
     var layer_template = '';
-    console.log(graph_parameters)
-    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']);
+    if (graph_parameters['view'] && filters.link.view.length > 0 && filters.link.view[0]) {
+        if (filters.link.view[0] === 'nsd') {
+            layer_template = getMainSectionWithSubmitButton('NSD');
+            layer_template += getChildrenTable(graph_parameters['view']['nsd']);
         }
-        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]);
+        else if (filters.link.view[0] === 'vnfd') {
+            layer_template = getMainSectionWithSubmitButton('VNFD');
+
+            layer_template += getChildrenTable(graph_parameters['view']['vnfd']);
         }
     }
 
@@ -162,12 +230,12 @@ function updateLegend(view) {
     var nodes = type_view[view];
     var legend_template = '';
     var nodes_properties = osm_gui_properties['nodes'];
-    for (var n in nodes){
+    for (var n in nodes) {
         var node = nodes[n];
-        if(nodes_properties[node]){
+        if (nodes_properties[node]) {
             legend_template += '<div class="node">' +
-                '<div class="icon" style="background-color:' + nodes_properties[node].color +'"></div>' +
-                '<div class="name">' +nodes_properties[node].name + '</div></div>';
+                '<div class="icon" style="background-color:' + nodes_properties[node].color + '"></div>' +
+                '<div class="name">' + nodes_properties[node].name + '</div></div>';
         }
     }
 
@@ -176,48 +244,74 @@ function updateLegend(view) {
 
 }
 
-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 updatePalette(view) {
+    var palette = $('#palette');
+    var palette_template = '';
+    palette.empty();
+    if (view === 'vnfd') {
+        var nodes = type_view[view];
+        var nodes_properties = osm_gui_properties['nodes'];
+        for (var n in nodes) {
+            var node = nodes[n];
+            if (nodes_properties[node]) {
+                palette_template += '<div id="drag_' + n + '" class="node ui-draggable"' +
+                    'type-name="' + n + '" draggable="true" ondragstart="nodeDragStart(event)">' +
+                    '<div class="icon" style="background-color:' + nodes_properties[node].color + '"></div>' +
+                    '<div class="name">' + nodes_properties[node].name + '</div></div>';
+            }
+        }
+
+        palette.append(palette_template)
+    } else if (view === 'nsd') {
+        $.ajax({
+            url: '/projects/descriptors/composer/availablenodes?layer=nsd',
+            type: 'GET',
+            cache: false,
+            success: function (result) {
+                palette_template += '<div id="drag_ns_vl" class="node ui-draggable"' +
+                    'type-name="ns_vl" draggable="true" ondragstart="nodeDragStart(event)">' +
+                    '<div class="icon" style="background-color:' + osm_gui_properties['nodes']['ns_vl'].color + '"></div>' +
+                    '<div class="name">' + osm_gui_properties['nodes']['ns_vl'].name + '</div></div>';
+                palette_template += getSubSection('VNFD');
+                for (var d in result['descriptors']) {
+                    var desc = result['descriptors'][d];
+                    palette_template += '<div id="drag_' + desc.id + '" class="node ui-draggable"' +
+                        'type-name="vnf" desc_id="' + desc.id + '" draggable="true" ondragstart="nodeDragStart(event)">' +
+                        '<div class="icon" style="background-color:#605ca8"></div>' +
+                        '<div class="name">' + desc.name + '</div></div>';
+                }
+                palette.append(palette_template)
+            },
+            error: function (result) {
+                showAlert(result);
+            }
+        });
+    }
+
+}
+
 
 function vnfDetails(vnfr) {
-    var side = $('#side');
+    var side = $('#side_form');
     var vnfr_template = getMainSection('VNF');
 
-    vnfr_template += getChildrenTable(vnfr);
+    vnfr_template += getChildrenTable(vnfr, true);
     side.empty();
     side.append(vnfr_template)
 }
 
 function vduDetails(vdur) {
-    var side = $('#side');
-    var vdur_template = getMainSectionWithStatus('VDU', vdur['status'] === 'ACTIVE');
+    var side = $('#side_form');
+    var vdur_template = getMainSectionWithSubmitButton('VDU');
     vdur_template += getChildrenTable(vdur);
 
-    if (vdur['interface'] && vdur['interface'].length > 0) {
-        vdur_template += getSubSection('Interfaces:');
-        vdur_template += '<table class="children">';
-
-        for (var i = 0; i < vdur['interface'].length; ++i) {
-            var interface = vdur['interface'][i];
-            var interface_template = '<tr><td>' + interface['name'] + '</td>'
-                + '<td>IP:' + interface['ip-address'] + '</td>'
-                + '<td>MAC:' + interface['mac-address'] + '</td>';
-            vdur_template += interface_template;
-        }
-        vdur_template += '</table>';
-    }
-
     side.empty();
     side.append(vdur_template)
 }
 
 function cpDetails(cp) {
-     var side = $('#side');
-    var cp_template = getMainSection('Connection Point');
+    var side = $('#side_form');
+    var cp_template = getMainSectionWithSubmitButton('Connection Point');
 
     cp_template += getChildrenTable(cp);
     side.empty();
@@ -225,8 +319,8 @@ function cpDetails(cp) {
 }
 
 function vlDetails(vl) {
-    var side = $('#side');
-    var vl_template = getMainSection('Virtual Link');
+    var side = $('#side_form');
+    var vl_template = getMainSectionWithSubmitButton('Virtual Link');
 
     vl_template += getChildrenTable(vl);
     side.empty();
@@ -238,6 +332,11 @@ function getMainSection(title) {
     return '<div class="section"><span style="font-weight: 500;">' + title + '</span></div>';
 }
 
+function getMainSectionWithSubmitButton(title) {
+    return '<div class="section"><span style="font-weight: 500;">' + title + '</span>' +
+        '<div class="status"><button id="update_button" class="btn btn-xs btn-default" ><i class="fa fa-save"></i> SAVE</button></div></div>';
+}
+
 function getSubSection(title) {
     return '<div class="section"><span>' + title + '</span></div>';
 }
@@ -252,15 +351,27 @@ function getMainSectionWithStatus(title, status) {
     return template;
 }
 
-function getChildrenTable(data) {
+function getChildrenTable(data, ro) {
     var template = '<table class="children">';
 
     for (var key in data) {
-        if (typeof data[key] === 'string') {
+        if (typeof data[key] !== 'object') {
             var key_map = (map[key]) ? map[key] : key;
-            template += '<tr><td>' + key_map + '</td><td><input name="'+key+'" class="form-control input-sm" type="text"  value="' + data[key] + '"></td></tr>';
+            if (ro)
+                template += '<tr><td>' + key_map + '</td><td>' + data[key] + '</td></tr>';
+            else
+                template += '<tr><td>' + key_map + '</td><td><input name="' + key + '" class="form-control input-sm" type="text"  value="' + data[key] + '"></td></tr>';
+
         }
     }
     template += '</table>';
     return template;
+}
+
+function openHelp() {
+    $('#modalTopologyInfoButton').modal('show');
+}
+
+function openTextedit() {
+    window.location.href = '/projects/descriptors/' + getUrlParameter('type') + '/' + getUrlParameter('id')
 }
\ No newline at end of file
diff --git a/static/src/descriptorhandler/controller.js b/static/src/descriptorhandler/controller.js
new file mode 100644 (file)
index 0000000..3a96ea2
--- /dev/null
@@ -0,0 +1,209 @@
+if (typeof TCD3 === 'undefined') {
+    var TCD3 = {};
+}
+
+TCD3.OsmController = (function (global) {
+    'use strict';
+
+    var DEBUG = true;
+
+    OsmController.prototype.constructor = OsmController;
+
+    /**
+     * Constructor
+     */
+    function OsmController() {
+
+
+    }
+
+
+    OsmController.prototype.addNode = function (graph_editor, node, success, error) {
+        log('addNode');
+        var element_type = node.info.type;
+        var desc_id = node.info.desc_id;
+        var desc_type = node.info.desc_type;
+        var data_form = new FormData();
+        data_form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
+        for (var key in node) {
+            data_form.append(key, node[key]);
+        }
+        $.ajax({
+            url: '/projects/descriptors/' + desc_type + '/' + desc_id + '/addElement/' + element_type,
+            type: 'POST',
+            data: data_form,
+            cache: false,
+            contentType: false,
+            processData: false,
+            success: success,
+            error: error
+        });
+    };
+
+    OsmController.prototype.addLink = function (graph_editor, link, success, error) {
+        log('addLink');
+
+        var data_to_send = {
+            'desc_id': link.desc_id,
+            'source': link.source.id,
+            'source_type': link.source.info.type,
+            'target': link.target.id,
+            'target_type': link.target.info.type,
+            'view': link.view,
+            'group': link.group
+        };
+
+        var desc_id = getUrlParameter('id');
+        var desc_type = getUrlParameter('type');
+        if (desc_type === 'nsd') {
+            var element_type = 'cp';
+            var data_form = new FormData();
+
+            var vnfd_node = (link.source.info.type === 'vnf') ? link.source : link.target;
+            var vld_node = (link.source.info.type === 'ns_vl') ? link.source : link.target;
+
+            data_form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
+            data_form.append('vnfd-connection-point-ref', 'cp_temp');
+            data_form.append('member-vnf-index-ref', vnfd_node.info.osm['member-vnf-index']);
+            data_form.append('vnfd-id-ref', vnfd_node.info.osm['vnfd-id-ref']);
+            data_form.append('vld_id', vld_node.info.osm['id']);
+
+            $.ajax({
+                url: '/projects/descriptors/' + desc_type + '/' + desc_id + '/addElement/' + element_type,
+                type: 'POST',
+                data: data_form,
+                cache: false,
+                contentType: false,
+                processData: false,
+                success: success,
+                error: error
+            });
+        }
+
+    };
+
+    OsmController.prototype.removeNode = function (graph_editor, node, success, error) {
+        log('removeNode');
+        var desc_id = getUrlParameter('id');
+        var desc_type = getUrlParameter('type');
+        var element_type = node['info']['type'];
+        var data_form = new FormData();
+        data_form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
+        for (var key in node.info.osm) {
+            data_form.append(key, node.info.osm[key]);
+        }
+
+        $.ajax({
+            url: '/projects/descriptors/' + desc_type + '/' + desc_id + '/removeElement/' + element_type,
+            type: 'POST',
+            data: data_form,
+            cache: false,
+            contentType: false,
+            processData: false,
+            success: success,
+            error: error
+        });
+
+    };
+
+    OsmController.prototype.updateNode = function (graph_editor, node, args, success, error) {
+        log('updateNode');
+        var desc_id = getUrlParameter('id');
+        var desc_type = getUrlParameter('type');
+        var element_type = node['info']['type'];
+        console.log(args)
+        var data_form = new FormData();
+        data_form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
+        data_form.append('old', JSON.stringify( node.info.osm));
+        data_form.append('update', JSON.stringify(args));
+        /*for (var key in node.info.osm) {
+            data_form.append(key, node.info.osm[key]);
+        }
+        */
+
+        $.ajax({
+            url: '/projects/descriptors/' + desc_type + '/' + desc_id + '/updateElement/' + element_type,
+            type: 'POST',
+            data: data_form,
+            cache: false,
+            contentType: false,
+            processData: false,
+            success: success,
+            error: error
+        });
+
+    };
+
+    OsmController.prototype.updateGraphParams = function(args, success, error){
+        var desc_id = getUrlParameter('id');
+        var desc_type = getUrlParameter('type');
+        var data_form = new FormData();
+        data_form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
+        data_form.append('update', JSON.stringify(args));
+        $.ajax({
+            url: '/projects/descriptors/' + desc_type + '/' + desc_id + '/updateElement/graph_params',
+            type: 'POST',
+            data: data_form,
+            cache: false,
+            contentType: false,
+            processData: false,
+            success: success,
+            error: error
+        });
+    };
+
+    OsmController.prototype.removeLink = function (graph_editor, link, success, error) {
+        log('removeLink');
+        var data_to_send = {
+            'desc_id': link.desc_id,
+            'source': link.source.id,
+            'source_type': link.source.info.type,
+            'target': link.target.id,
+            'target_type': link.target.info.type,
+            'view': link.view,
+            'group': link.group
+        };
+
+        var desc_id = getUrlParameter('id');
+        var desc_type = getUrlParameter('type');
+
+        if (desc_type === 'nsd') {
+            var element_type = 'cp';
+            var data_form = new FormData();
+
+            var vnfd_node = (link.source.info.type === 'vnf') ? link.source : link.target;
+            var vld_node = (link.source.info.type === 'ns_vl') ? link.source : link.target;
+
+            data_form.append('csrfmiddlewaretoken', getCookie('csrftoken'));
+            data_form.append('vnfd-connection-point-ref', 'cp_temp');
+            data_form.append('member-vnf-index-ref', vnfd_node.info.osm['member-vnf-index']);
+            data_form.append('vnfd-id-ref', vnfd_node.info.osm['vnfd-id-ref']);
+            data_form.append('vld_id', vld_node.info.osm['id']);
+
+            $.ajax({
+                url: '/projects/descriptors/' + desc_type + '/' + desc_id + '/removeElement/' + element_type,
+                type: 'POST',
+                data: data_form,
+                cache: false,
+                contentType: false,
+                processData: false,
+                success: success,
+                error: error
+            });
+        }
+    };
+
+    /**
+     * Log utility
+     */
+    function log(text) {
+        if (DEBUG)
+            console.log("::OsmController::", text);
+    }
+
+    return OsmController;
+}(this));
+
+if (typeof module === 'object') {
+    module.exports = TCD3.OsmController;
+}
\ No newline at end of file
index 99bb986..95239e3 100644 (file)
@@ -26,7 +26,7 @@ var layer_map = {
         'config-status': 'Config status',
         'detailed-status': 'Detailed status',
         'create-time': 'Creation date',
-        'instantiate_params' :'Instantiation parameters'
+       // 'instantiate_params' :'Instantiation parameters'
     },
     'vnfr': {
         'id':  'VNF instance id',
@@ -170,6 +170,8 @@ function layerDetails(filters) {
                     var field_value = graph_parameters['view']['nsr'][key];
                     if(key === 'create-time'){
                         field_value = moment.unix(field_value).toISOString();
+                    } else if (key === 'instantiate_params'){
+                        field_value = JSON.stringify(field_value);
                     }
                     layer_template += '<tr><td>' + layer_map['nsr'][key] + '</td><td>' + field_value + '</td></tr>';
                 }