first commit

Change-Id: I8a65ee5527dd16d81e87c8ac5d4bdb471e5e759d
Signed-off-by: lombardof <flombardo@cnit.it>
diff --git a/static/src/adminlte_session_storage.js b/static/src/adminlte_session_storage.js
new file mode 100644
index 0000000..d18cbbe
--- /dev/null
+++ b/static/src/adminlte_session_storage.js
@@ -0,0 +1,55 @@
+/*
+   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.
+*/
+
+function setCookie(cname, cvalue, exdays) {
+    var d = new Date();
+    d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
+    var expires = "expires=" + d.toUTCString();
+    document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/";
+}
+
+function getCookie(cname) {
+    var name = cname + "=";
+    var ca = document.cookie.split(';');
+    for (var i = 0; i < ca.length; i++) {
+        var c = ca[i];
+        while (c.charAt(0) == ' ') {
+            c = c.substring(1);
+        }
+        if (c.indexOf(name) == 0) {
+            return c.substring(name.length, c.length);
+        }
+    }
+    return "";
+}
+
+
+$(document).ready(function () {
+
+    //event section
+
+    // save if sidebar is collapsed or not
+    $('.sidebar-toggle').click(function (event) {
+        event.preventDefault();
+        var cookie = getCookie("collapsed_sidebar");
+        if (cookie != "") {
+            setCookie("collapsed_sidebar", "")
+        } else {
+            setCookie("collapsed_sidebar", "1")
+        }
+    });
+
+});
\ No newline at end of file
diff --git a/static/src/instancehandler/instance_list.js b/static/src/instancehandler/instance_list.js
new file mode 100644
index 0000000..161cc51
--- /dev/null
+++ b/static/src/instancehandler/instance_list.js
@@ -0,0 +1,138 @@
+/*
+   Copyright 2018 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.
+*/
+
+function performAction(url) {
+    $("#formActionNS").attr("action", url);
+    $('#modal_instance_new_action').modal('show');
+}
+
+function deleteNs(url) {
+    bootbox.confirm("Are you sure want to delete?", function (result) {
+        if (result) {
+            location.href = url
+        }
+    })
+}
+
+var addFormGroup = function (event) {
+    event.preventDefault();
+
+    var $formGroup = $(this).closest('.form-group');
+    var $formGroupClone = $formGroup.clone();
+
+    $(this)
+        .toggleClass('btn-success btn-add btn-danger btn-remove')
+        .html('–');
+
+    $formGroupClone.find('input').val('');
+    $formGroupClone.insertAfter($formGroup);
+
+};
+
+var removeFormGroup = function (event) {
+    event.preventDefault();
+    var $formGroup = $(this).closest('.form-group');
+    $formGroup.remove();
+};
+
+function showInstanceDetails(url_info) {
+    var dialog = bootbox.dialog({
+        message: '<div class="text-center"><i class="fa fa-spin fa-spinner"></i> Loading...</div>',
+        closeButton: true
+    });
+    $.ajax({
+        url: url_info,
+        type: 'GET',
+        dataType: "json",
+        contentType: "application/json;charset=utf-8",
+        success: function (result) {
+            editorJSON.setValue(JSON.stringify(result, null, "\t"));
+            editorJSON.setOption("autoRefresh", true);
+            dialog.modal('hide');
+            $('#modal_show_instance').modal('show');
+        },
+        error: function (result) {
+            dialog.modal('hide');
+            bootbox.alert("An error occurred while retrieving the information for the NS");
+        }
+    });
+}
+
+var editorJSON;
+
+$(document).ready(function () {
+    var json_editor_settings = {
+        mode: "javascript",
+        showCursorWhenSelecting: true,
+        autofocus: true,
+        lineNumbers: true,
+        lineWrapping: true,
+        foldGutter: true,
+        gutters: ["CodeMirror-linenumbers", "CodeMirror-foldgutter"],
+        autoCloseBrackets: true,
+        matchBrackets: true,
+        extraKeys: {
+            "F11": function (cm) {
+                cm.setOption("fullScreen", !cm.getOption("fullScreen"));
+            },
+            "Esc": function (cm) {
+                if (cm.getOption("fullScreen")) cm.setOption("fullScreen", false);
+            },
+            "Ctrl-Q": function (cm) {
+                cm.foldCode(cm.getCursor());
+            }
+        },
+        theme: "neat",
+        keyMap: "sublime"
+    };
+    var myJsonTextArea = document.getElementById("instance_view_json");
+    editorJSON = CodeMirror(function (elt) {
+        myJsonTextArea.parentNode.replaceChild(elt, myJsonTextArea);
+    }, json_editor_settings);
+
+
+    $(document).on('click', '.btn-add', addFormGroup);
+    $(document).on('click', '.btn-remove', removeFormGroup);
+
+    $("#formActionNS").submit(function (event) {
+        event.preventDefault(); //prevent default action
+        var post_url = $(this).attr("action"); //get form action url
+        var request_method = $(this).attr("method"); //get form GET/POST method
+        var form_data = new FormData(this); //Encode form elements for submission
+        console.log(post_url);
+        $.ajax({
+            url: post_url,
+            type: request_method,
+            data: form_data,
+            headers: {
+                "Accept": 'application/json'
+            },
+            contentType: false,
+            processData: false
+        }).done(function (response,textStatus, jqXHR) {
+            $('#modal_instance_new_action').modal('hide');
+        }).fail(function(result){
+            var data  = result.responseJSON;
+            var title = "Error " + (data.code ? data.code: 'unknown');
+                var message = data.detail ? data.detail: 'No detail available.';
+                bootbox.alert({
+                    title: title,
+                    message: message
+                });
+        });
+    });
+
+});
\ No newline at end of file
diff --git a/static/src/projecthandler/descriptorslist.js b/static/src/projecthandler/descriptorslist.js
new file mode 100644
index 0000000..4a5975a
--- /dev/null
+++ b/static/src/projecthandler/descriptorslist.js
@@ -0,0 +1,69 @@
+
+function startFromAgent(start) {
+
+
+    if (start == 'exist'){
+        $('#div_new_agent').hide();
+        $('#div_available_agent').show();
+    }
+    else if (start == 'new'){
+        $('#div_available_agent').hide();
+        $('#div_new_agent').show();
+    }
+
+    $('.required').prop('required', function(){
+        return  $(this).is(':visible');
+    });
+
+}
+/*
+function InvalidGitUrl(textbox) {
+    console.log('InvalidGitUrl', textbox,textbox.value == '' ,textbox.validity.typeMismatch)
+    if (textbox.value === '') {
+        textbox.setCustomValidity('Required git URL');
+    }
+    else if (textbox.validity.typeMismatch){
+        textbox.setCustomValidity('please enter a valid git URL');
+
+    }
+    else {
+        textbox.setCustomValidity('please enter a valid git URL');
+    }
+    return true;
+}
+*/
+function startFromRepo(start) {
+
+
+    if (start == 'exist'){
+        $('#div_new_repo').hide();
+        $('#div_available_repo').show();
+    }
+    else if (start == 'new'){
+        $('#div_available_repo').hide();
+        $('#div_new_repo').show();
+    }
+
+    $('.required').prop('required', function(){
+        return  $(this).is(':visible');
+    });
+
+}
+
+$(document).ready(function () {
+    $("#startButtonsSelect :input").change(function () {
+        console.log("select")
+        startFromAgent(this.value);
+    });
+    $("#push_start_buttons_select :input").change(function () {
+        console.log("select")
+        startFromRepo(this.value);
+    });
+
+    // Bind events
+    $("form").submit(function(e) {
+        console.log("on submit form")
+        $("#start_new_deployment").button('loading');
+    });
+
+});
\ No newline at end of file
diff --git a/static/src/projecthandler/new_project.js b/static/src/projecthandler/new_project.js
new file mode 100644
index 0000000..9ca4c9e
--- /dev/null
+++ b/static/src/projecthandler/new_project.js
@@ -0,0 +1,84 @@
+/**
+ *      New Project page
+ **/
+function handleTypeChoose(type) {
+    resetStartFromInputs()
+    $('#projectType').val(type);
+    $('#startGroup').show();
+    $('input[id="scratch"]').prop('checked', true);
+    $('#startButtonsSelect label').removeClass("active");
+    $('#s-scratch').addClass("active");
+    $('#createButton').prop('disabled', false);
+    //$('#projectName').val('New_'+type+'_project')
+}
+
+function startFromChoose(start) {
+    resetStartFromInputs()
+    //resetSelectors();
+    var type = $('#select_type').val();
+
+    if (start == 'files')
+        $('#div-file-upload-' + type).show();
+    else if (start == 'example')
+        //document.getElementById['#div-example-' + type].style.display = "block";
+       $('#div-example-' + type).css("display", "inline");
+
+}
+
+function resetStartFromInputs() {
+    $('div[class="start-selector"]').hide();
+    $('input[type="file"]').val('');
+    $('select[class="example-selector"]').val(null).trigger("change");
+}
+
+$(document).ready(function () {
+
+    // init selector
+    $(".start-selector").css("display", "inline");
+    $('#select_type').select2({
+        placeholder: {
+            id: '-1',
+            text: 'Select an option'
+        },
+        data: data_type_selector
+    });
+
+
+    $('#select_type').on("select2:select", function (evt) {
+        if (evt) {
+            var args = evt.params;
+            handleTypeChoose(args.data.value)
+        }
+    });
+
+    if (type_example_files) {
+        for (var key in type_example_files) {
+            $('select[id="example-' + key + '"]').select2({
+                placeholder: {
+                    id: '-1',
+                    text: 'Select an option'
+                },
+                data: type_example_files[key]
+            });
+        }
+
+
+    }
+
+
+
+    $("#startButtonsSelect :input").change(function () {
+        startFromChoose(this.value);
+    });
+
+
+
+    $("body").bind("ajaxSend", function (elm, xhr, s) {
+        if (s.type == "POST") {
+            xhr.setRequestHeader('csrftoken', $('#csrfmiddlewaretoken').val());
+        }
+    });
+
+    $(".start-selector").css("display", "none");
+
+});
\ No newline at end of file
diff --git a/static/src/projecthandler/osm/controller.js b/static/src/projecthandler/osm/controller.js
new file mode 100644
index 0000000..e39e332
--- /dev/null
+++ b/static/src/projecthandler/osm/controller.js
@@ -0,0 +1,107 @@
+if (typeof dreamer === 'undefined') {
+    var dreamer = {};
+}
+var level = {}
+
+dreamer.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 data_to_send = {
+            'group_id': node.info.group[0],
+            'element_id': node.id,
+            'element_type': node.info.type,
+            'element_desc_id': node.info.desc_id,
+            'x': node.x,
+            'y': node.y
+         };
+        new dreamer.GraphRequests().addNode(data_to_send, null, function() {
+            if (success)
+                success();
+        },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
+        };
+        new dreamer.GraphRequests().addLink(link, null, function() {
+            graph_editor._deselectAllNodes();
+
+            if (typeof old_link !== 'undefined' && old_link.length > 0 && old_link[0].index !== 'undefined') {
+                graph_editor.parent.removeLink.call(graph_editor, old_link[0].index);
+            }
+            if (success) {
+                success();
+            }
+        },error);
+    };
+
+    OsmController.prototype.removeNode = function(graph_editor, node, success, error) {
+        log('removeNode');
+        var data_to_send = {
+            'group_id': node.info.group[0],
+            'element_id': node.id,
+            'element_type': node.info.type,
+            'element_desc_id': node.info.desc_id,
+            };
+        new dreamer.GraphRequests().removeNode(data_to_send, null, function() {
+            if (success) {
+                success();
+            }
+        },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
+        };
+        new dreamer.GraphRequests().removeLink(data_to_send, function() {
+            if (success) {
+                success();
+            }
+        },error);
+    };
+
+    /**
+     * Log utility
+     */
+    function log(text) {
+        if (DEBUG)
+            console.log("::OsmController::", text);
+    }
+
+    return OsmController;
+}(this));
+
+if (typeof module === 'object') {
+    module.exports = dreamer.OsmController;
+}
\ No newline at end of file
diff --git a/static/src/projecthandler/osm/gui_properties.js b/static/src/projecthandler/osm/gui_properties.js
new file mode 100644
index 0000000..1af3ef4
--- /dev/null
+++ b/static/src/projecthandler/osm/gui_properties.js
@@ -0,0 +1,128 @@
+//***STEFANO
+var example_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"
+      },
+      "ns_cp": {
+        "image" : "cp-80.png",
+        // "shape": "circle",
+        "color": "#F27220",
+        "size": 20,
+        "name": "CP"
+      },
+      "vnf": {
+        "image": "vnf-100.png",
+        // "shape": "square",
+        "color": "#54A698",
+        "size": 35,
+        "name": "VNF"
+      },
+      "vnf_vl": {
+        "shape": "triangle",
+        //"color": "#5FC9DB",
+        "color": "#196B90",
+        "size": 11,
+        "name": "IntVL"
+      },
+      "vnf_ext_cp": {
+        "shape": "circle",
+        //"#00CC66",
+        "color": "#F27220",
+        "size": 15,
+        "name": "ExtCP"
+      },
+      "vnf_vdu_cp": {
+        "shape": "circle",
+        //"color": "#E74C35",
+        "color": "#fce0cf",
+        "size": 15,
+        "name": "VduCP"
+      },
+      "vnf_vdu": {
+        "shape": "square",
+        //"color": "#50A7CC",
+        "color": "#54A698",
+        "size": 18,
+        "name": "VDU"
+      }
+    },
+    "graphs": null
+
+  },
+  "v0" : {
+    "default": {
+      "shape": "cross",
+      "color": "#42f44e",
+      "label_color": "black",
+      "size": 15
+    },
+    "nodes": {
+      "pippo": {
+        "image": "image.png",
+        "size": 25
+      },
+      "ns_vl": {
+        "shape": "triangle",
+        "color": "#196B90",
+        "size": 11,
+        "name": "VL"
+      },
+      "ns_cp": {
+        "shape": "circle",
+        "color": "#F27220",
+        "size": 15,
+        "name": "CP"
+      },
+      "vnf": {
+        "shape": "square",
+        "color": "#54A698",
+        "image": "router.png",
+        "size": 40,
+        "name": "VNF"
+      },
+      "vnf_vl": {
+        "shape": "triangle",
+        //"color": "#5FC9DB",
+        "color": "#196B90",
+        "size": 11,
+        "name": "IntVL"
+      },
+      "vnf_ext_cp": {
+        "shape": "circle",
+        //"#00CC66",
+        "color": "#F27220",
+        "size": 15,
+        "name": "ExtCP"
+      },
+      "vnf_vdu_cp": {
+        "shape": "circle",
+        //"color": "#E74C35",
+        "color": "#fce0cf",
+        "size": 15,
+        "name": "VduCP"
+      },
+      "vnf_vdu": {
+        "shape": "square",
+        //"color": "#50A7CC",
+        "color": "#54A698",
+        "size": 18,
+        "name": "VDU"
+      }
+    },
+    "graphs": null
+
+  },
+
+}
\ No newline at end of file
diff --git a/static/src/projecthandler/osm/project_graph.js b/static/src/projecthandler/osm/project_graph.js
new file mode 100644
index 0000000..072129f
--- /dev/null
+++ b/static/src/projecthandler/osm/project_graph.js
@@ -0,0 +1,354 @@
+//GraphEditor instance
+var graph_editor = new dreamer.ModelGraphEditor();
+var selected_vnffgId = null;
+var show_all = null;
+
+// Enable Drop Action on the Graph
+initDropOnGraph();
+
+
+
+$(document).ready(function() {
+    var descriptor_type = getUrlParameter('type') == 'ns' || getUrlParameter('type') == 'nsd' ? 'ns' : 'vnf'
+    var allowed_types = descriptor_type == 'ns' ? ['vnf', 'ns_cp', 'ns_vl'] : ['vnf_vl', 'vnf_ext_cp', 'vnf_vdu_cp', 'vnf_vdu'];
+    var params = {
+        node: {
+            type: allowed_types,
+            group: [getUrlParameter('id')]
+        },
+        link: {
+            group: [getUrlParameter('id')],
+            view: [descriptor_type]
+        }
+    }
+
+    graph_editor.addListener("refresh_graph_parameters", refreshGraphParameters);
+
+
+    // graph_editor initialization
+    graph_editor.init({
+        width: $('#graph_ed_container').width(),
+        height: $('#graph_ed_container').height(),
+        gui_properties: example_gui_properties,
+        filter_base: params,
+        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);
+    graph_editor.addListener("filters_changed", changeFilter);
+    graph_editor.addListener("edit_descriptor", openEditorEvent);
+
+});
+
+
+function initDropOnGraph() {
+
+    var dropZone = document.getElementById('graph_ed_container');
+    dropZone.ondrop = function(e) {
+        var group = graph_editor.getCurrentGroup()
+        e.preventDefault();
+        var nodetype = e.dataTransfer.getData("text/plain");
+        if (nodetype) {
+            var type_name = graph_editor.getTypeProperty()[nodetype].name;
+            if (nodetype == 'vnf') {
+                new dreamer.GraphRequests().getUnusedVnf(group, function(vnfs) {
+                    $('#div_chose_id').hide();
+                    $('#div_chose_vnf').show();
+                    $('#input_choose_node_id').val(nodetype + "_" + generateUID());
+                    $('#selection_chooser_vnf').empty();
+                    $('#selection_chooser_vnf').append('<option >None</option>');
+                    $('#modal_chooser_title_add_node').text('Add ' + type_name);
+                    for (var i in vnfs) {
+                        $('#selection_chooser_vnf').append('<option id="' + vnfs[i] + '">' + vnfs[i] + '</option>');
+                    }
+                    $('#save_choose_node_id').off('click').on('click', function() {
+                        var choice = $("#selection_chooser_vnf option:selected").text();
+                        var name = $('#input_choose_node_id').val();
+                        if (choice == 'None') {
+                            var node_information = {
+                                'id': name,
+                                'info': {
+                                    'type': nodetype,
+                                    'group': [group]
+                                },
+                                'x': e.layerX,
+                                'y': e.layerY
+                            }
+                            graph_editor.addNode(node_information, function() {
+                                $('#modal_choose_node_id').modal('hide');
+                            }, function(error){
+                        showAlert(error)
+                    });
+                        } else {
+                            var node_information = {
+                                'existing_element': true,
+                                'id': choice,
+                                'info': {
+                                    'type': nodetype,
+                                    'group': [group]
+                                },
+                                'x': e.layerX,
+                                'y': e.layerY
+                            }
+                            graph_editor.addNode(node_information, function() {
+                                $('#modal_choose_node_id').modal('hide');
+                            }, function(error){
+                        showAlert(error)
+                    });
+                        }
+
+                    });
+
+                    $('#modal_choose_node_id').modal('show');
+                });
+
+            } else {
+                $('#div_chose_id').show();
+                $('#div_chose_vnf').hide();
+                $('#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]
+                        },
+                        'x': e.layerX,
+                        'y': e.layerY
+                    }
+                    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);
+
+}
+
+function changeFilter(e, c) {
+    var type_property = graph_editor.getTypeProperty();
+    if (c.link.view == 'ns') {
+        $("#title_header").text("NS Graph Editor")
+        $("#vnffg_options").prop("disabled", false);
+        graph_editor.refreshGraphParameters();
+    } else {
+
+        $("#title_header").text("VNF Graph Editor");
+        $("#vnffg_box").hide();
+        $("#vnffg_options").prop("disabled", true);
+    }
+
+   new dreamer.GraphRequests().getAvailableNodes({layer: c.link.view[0]}, buildPalette, showAlert);
+   updateBredCrumb(c);
+}
+
+var filters = function(e, params) {
+    graph_editor.handleFiltersParams(params);
+    $('#' + e).nextAll('li').remove();
+}
+
+function updateBredCrumb(filter_parameters){
+     var newLi = $("<li id=" + JSON.stringify(graph_editor.getCurrentGroup()) + "><a href='javascript:filters(" + JSON.stringify(graph_editor.getCurrentGroup()) + "," + JSON.stringify(filter_parameters) + ")'>" + graph_editor.getCurrentGroup() + "</a></li>");
+     $('#breadcrumb').append(newLi);
+}
+
+
+function openEditor(project_id) {
+    window.location.href = '/projects/' + project_id + '/descriptors/' + graph_editor.getCurrentView() + 'd/' + graph_editor.getCurrentGroup();
+}
+
+
+function showChooserModal(title, chooses, callback) {
+    console.log('showchooser')
+    $('#selection_chooser').empty();
+    for (var i in chooses) {
+        $('#selection_chooser').append('<option id="' + chooses[i].id + '">' + chooses[i].id + '</option>');
+    }
+    $('#modal_chooser_title').text(title)
+    var self = this;
+    $('#save_chooser').off('click').on('click', function() {
+        var choice = $("#selection_chooser option:selected").text();
+        callback(choice);
+
+    });
+    $('#modal_create_link_chooser').modal('show');
+
+}
+
+function refreshGraphParameters(e, graphParameters) {
+
+    var self = $(this);
+    if (graphParameters == null) return;
+    var vnffgIds = graphParameters.vnffgIds;
+    if (vnffgIds == null) return;
+
+    $("#selection_vnffg").empty();
+    $("#selection_vnffg").append('<option value="Global">Global</option>')
+    for (var i in vnffgIds) {
+        var vnffgId = vnffgIds[i]
+        var child = $('<option value="' + vnffgId + '">' + vnffgId + '</option>');
+        $("#selection_vnffg").append(child)
+    }
+}
+
+function changeVnffg(e) {
+    var vnffgId = e.value;
+    selected_vnffgId = vnffgId;
+    show_all_change();
+}
+
+function newVnffg() {
+    var group = graph_editor.getCurrentGroup()
+    $('#div_chose_id').show();
+    $('#div_chose_vnf').hide();
+    $('#input_choose_node_id').val("vnffg_" + generateUID());
+    $('#modal_chooser_title_add_node').text('Add VNFFG');
+    $('#save_choose_node_id').off('click').on('click', function() {
+        var name = $('#input_choose_node_id').val();
+        var node_information = {
+            'element_id': name,
+            'element_type': "vnffg",
+            'group_id': group,
+        }
+        console.log(JSON.stringify(node_information))
+        new dreamer.GraphRequests().addVnffg(node_information, function(result) {
+
+            $('#modal_choose_node_id').modal('hide');
+            graph_editor.d3_graph.graph_parameters.vnffgIds.push(node_information.id)
+            refreshGraphParameters(null, graph_editor.d3_graph.graph_parameters)
+        });
+
+
+
+    });
+    $('#modal_choose_node_id').modal('show');
+}
+
+function show_all_change(e) {
+    if (!selected_vnffgId) return;
+    var vnffgId = selected_vnffgId;
+    if (e) show_all = e.checked;
+    if (show_all) {
+        handleVnffgParameter("Global", "invisible");
+        handleVnffgParameter(vnffgId, "matted");
+    } else {
+        handleVnffgParameter("Global", "matted");
+        handleVnffgParameter(vnffgId, "invisible");
+    }
+}
+
+function clickVnffg() {
+    if ($("#vnffg_box").is(':visible'))
+        $("#vnffg_box").hide();
+    else
+        $("#vnffg_box").show();
+
+}
+
+function handleVnffgParameter(vnffgId, class_name) {
+
+    if (vnffgId != "Global") {
+        selected_vnffgId = vnffgId;
+        graph_editor.setNodeClass(class_name, function(d) {
+            var result = false;
+            if (d.info.group.indexOf(vnffgId) < 0) {
+                result = true;
+            }
+            console.log(result);
+            return result;
+        });
+
+        graph_editor.setLinkClass(class_name, function(d) {
+            var result = false;
+            if (d.group.indexOf(vnffgId) < 0) {
+                result = true;
+            }
+            console.log(result);
+            return result;
+        });
+
+    } else {
+        selected_vnffgId = null;
+        graph_editor.setNodeClass(class_name, function(d) {
+            var result = false;
+            return result;
+        });
+
+        graph_editor.setLinkClass(class_name, function(d) {
+            var result = false;
+            return result;
+        });
+    }
+}
+
+function buildBehaviorsOnEvents(){
+    var contextmenuNodesAction = [
+        {
+                title: 'Show graph',
+                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 behavioursOnEvents = {
+            'nodes': contextmenuNodesAction,
+
+        };
+
+    return behavioursOnEvents;
+}
\ No newline at end of file
diff --git a/static/src/utils.js b/static/src/utils.js
new file mode 100644
index 0000000..6d5e820
--- /dev/null
+++ b/static/src/utils.js
@@ -0,0 +1,153 @@
+function generateUID() {
+    return ("0000" + (Math.random() * Math.pow(36, 4) << 0).toString(36)).slice(-4)
+}
+
+function openProject(pId) {
+    window.location.href = '/projects/' + pId;
+}
+
+
+function openDescriptorView(project_id, descriptor_type, descriptor_id) {
+    console.log("openDescriptorView", project_id, descriptor_type, descriptor_id);
+    window.location.href = '/projects/' + project_id + '/descriptors/' + descriptor_type + '/' + descriptor_id;
+
+}
+
+
+function openEditorEvent(e, id) {
+    openEditor(id);
+}
+
+function nodeDragStart(event) {
+    event.dataTransfer.setData("Text", event.target.id);
+}
+
+function savePositions(el) {
+    graph_editor.savePositions();
+}
+
+function buildPalette(args) {
+    $("#paletteContainer").empty();
+    var type_property = graph_editor.getTypeProperty();
+    if (args.length > 0) {
+        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('<div id="' + category_id + '" class="palette-category" ><div class="palette-header" onClick="handlePaletteCat(this);" category_id="' + category_id + '"> ' +
+                '<i class="fa fa-chevron-down "></i>' +
+                '<span>  ' + category.category_name + '</span>' +
+                '</div>' +
+                '<div id="' + content_id + '" class="palette-content">' +
+
+                '</div>' +
+                '</div>');
+            category.types.forEach(function (type) {
+                console.log(graph_editor.get_name_from_d3_symbol(d3.symbolCircle))
+                var type_id = type.id.replace(/[\s.*+?^${}()|[\]\\]/g, "_");
+                var palette_node_icon;
+                if (type_property[type.id] && type_property[type.id].image && type_property[type.id].image != '') {
+                    palette_node_icon = '<div class="palette-node-icon" style="background-image: url(' + (type_property[type.id].image || "") + ')"></div>';
+                }
+                else if (type_property[type.id] && type_property[type.id].shape) {
+                    palette_node_icon = buildHtmlShape({
+                        shape: type_property[type.id].shape,
+                        color: type_property[type.id].color
+                    });
+
+                }
+                else {//#1F77B4
+                    palette_node_icon = '<div class="palette-node-icon"> <div class="palette-node-square" style="background:#1F77B4;"></div></div>';
+                }
+
+                var html_to_append = '<div class="palette-node ui-draggable" draggable="true" type-name="' + type.id + '" id="' + type_id + '" ondragstart="nodeDragStart(event)">' +
+                    '<div class="palette-node-label">' + type.name + '</div>' +
+                    '<div class="palette-node-icon-container">' +
+                    palette_node_icon +
+                    '</div>' +
+                    '</div>'
+                $("#" + content_id).append(html_to_append);
+            });
+
+        });
+    }
+    togglePaletteSpinner(true);
+
+
+}
+
+function handlePaletteCat(item) {
+    console.log("handlePaletteContainer")
+    var category_id = $(item).attr("category_id")
+    $('#' + category_id).toggleClass("palette-close");
+
+}
+
+function togglePaletteSpinner(addOrRemove) {
+    $('#palette').toggleClass("palette-status-hidden", addOrRemove);
+}
+
+function showAlert(msg) {
+    // modal_alert_text
+    var alert_msg = ""
+    if (typeof msg == "string")
+        alert_msg = msg
+    else
+        alert_msg = JSON.stringify(msg)
+    $('#modal_alert_text').text(alert_msg);
+    $('#modal_alert').modal('show');
+}
+
+function getUrlParameter(par_name) {
+    var results = new RegExp('[\?&]' + par_name + '=([^&#]*)').exec(window.location.href);
+    if (results == null) {
+        return null;
+    } else {
+        return results[1] || 0;
+    }
+}
+
+function buildHtmlShape(args) {
+    var mySymbol = args.shape;
+    switch (mySymbol) {
+        case d3.symbolCircle:
+            return '<div class="palette-node-icon"> <div class="palette-node-circle" style="background:' + args.color + ';"></div></div>';
+            break;
+        case d3.symbolSquare:
+            return '<div class="palette-node-icon"> <div class="palette-node-square" style="background:' + args.color + ';"></div></div>';
+            break;
+        case d3.symbolDiamond:
+            return '<div class="palette-node-icon" style="background-color:' + args.color + '"></div>';
+            ;
+            break;
+        case d3.symbolTriangle:
+            return '<div class="palette-node-icon"> <div class="palette-node-triangle" style="border-color: transparent transparent ' + args.color + ' transparent;"></div></div>';
+            break;
+        case d3.symbolStar:
+            return '<div class="palette-node-icon" style="background-color:' + args.color + '"></div>';
+            ;
+            break;
+        case d3.symbolCross:
+            return '<div class="palette-node-icon" style="background-color:' + args.color + '"></div>';
+            ;
+            break;
+        default:
+            // if the string is not recognized
+            return "unknown";
+        //return d3.symbolCircleUnknown;
+    }
+
+
+}
+
+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' ?
+                args[number] :
+                match;
+        });
+    };
+}
\ No newline at end of file