Improved dashboardManager and Dashboard View tosca definition to allow specify custom icons

Change-Id: I61b097814c811ab30e719387e0bcee68202e312c
diff --git a/views/ngXosViews/dashboardManager/src/icons/dashboardManager-icon-active.png b/views/ngXosViews/dashboardManager/src/icons/dashboardManager-icon-active.png
new file mode 100644
index 0000000..3dba74a
--- /dev/null
+++ b/views/ngXosViews/dashboardManager/src/icons/dashboardManager-icon-active.png
Binary files differ
diff --git a/views/ngXosViews/dashboardManager/src/icons/dashboardManager-icon.png b/views/ngXosViews/dashboardManager/src/icons/dashboardManager-icon.png
new file mode 100644
index 0000000..1d60a9a
--- /dev/null
+++ b/views/ngXosViews/dashboardManager/src/icons/dashboardManager-icon.png
Binary files differ
diff --git a/views/ngXosViews/dashboardManager/src/index.html b/views/ngXosViews/dashboardManager/src/index.html
index 55613ae..c62eac8 100644
--- a/views/ngXosViews/dashboardManager/src/index.html
+++ b/views/ngXosViews/dashboardManager/src/index.html
@@ -15,10 +15,10 @@
 </div>
 
 <!-- bower:js -->
-<script src="vendor/angular/angular.js"></script>
-<script src="vendor/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js"></script>
 <script src="vendor/js-yaml/dist/js-yaml.js"></script>
 <script src="vendor/jquery/dist/jquery.js"></script>
+<script src="vendor/angular/angular.js"></script>
+<script src="vendor/angular-drag-and-drop-lists/angular-drag-and-drop-lists.js"></script>
 <script src="vendor/angular-mocks/angular-mocks.js"></script>
 <script src="vendor/angular-ui-router/release/angular-ui-router.js"></script>
 <script src="vendor/angular-cookies/angular-cookies.js"></script>
diff --git a/views/ngXosViews/dashboardManager/src/js/dashboard-form.directive.js b/views/ngXosViews/dashboardManager/src/js/dashboard-form.directive.js
index 1895856..674e53d 100644
--- a/views/ngXosViews/dashboardManager/src/js/dashboard-form.directive.js
+++ b/views/ngXosViews/dashboardManager/src/js/dashboard-form.directive.js
@@ -36,7 +36,9 @@
             'no_policy',
             'no_sync',
             'policed',
-            'write_protect'
+            'write_protect',
+            'icon',
+            'icon_active'
           ],
           actions: [
             {
diff --git a/views/ngXosViews/dashboardManager/src/js/user-dashboards.directive.js b/views/ngXosViews/dashboardManager/src/js/user-dashboards.directive.js
index 2912ad7..0884e25 100644
--- a/views/ngXosViews/dashboardManager/src/js/user-dashboards.directive.js
+++ b/views/ngXosViews/dashboardManager/src/js/user-dashboards.directive.js
@@ -32,6 +32,7 @@
 
         this.addToList = (listName, item) => {
           this.list[listName].push(item)
+          location.reload();
         };
 
         this.isInList = (listName, item) => {
diff --git a/xos/core/xoslib/static/images/dashboardManager-icon-active.png b/xos/core/xoslib/static/images/dashboardManager-icon-active.png
new file mode 100644
index 0000000..3dba74a
--- /dev/null
+++ b/xos/core/xoslib/static/images/dashboardManager-icon-active.png
Binary files differ
diff --git a/xos/core/xoslib/static/images/dashboardManager-icon.png b/xos/core/xoslib/static/images/dashboardManager-icon.png
new file mode 100644
index 0000000..1d60a9a
--- /dev/null
+++ b/xos/core/xoslib/static/images/dashboardManager-icon.png
Binary files differ
diff --git a/xos/core/xoslib/static/js/xosDashboardManager.js b/xos/core/xoslib/static/js/xosDashboardManager.js
index 2d0edee..c8d12f9 100644
--- a/xos/core/xoslib/static/js/xosDashboardManager.js
+++ b/xos/core/xoslib/static/js/xosDashboardManager.js
@@ -1 +1 @@
-"use strict";angular.module("xos.dashboardManager",["ngResource","ngCookies","ui.router","xos.helpers","dndLists"]).config(["$stateProvider",function(e){e.state("manage-user-dashboards",{url:"/",template:"<user-dashboards></user-dashboards>"}).state("add-dashboards",{url:"/add",template:"<dashboard-form></dashboard-form>"}).state("edit-dashboards",{url:"/dashboards/:id",template:"<dashboard-form></dashboard-form>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).service("UserDashboards",["$http","$q",function(e,n){this.query=function(){var a=n.defer();return e.get("/api/utility/dashboards").then(function(e){a.resolve(e.data)})["catch"](function(e){a.reject(e)}),{$promise:a.promise}},this.update=function(a){var s=n.defer();return e.post("/api/utility/dashboards/",a).then(function(e){s.resolve(e.data)})["catch"](function(e){s.reject(e)}),{$promise:s.promise}}}]);var _slicedToArray=function(){function e(e,n){var a=[],s=!0,i=!1,r=void 0;try{for(var o,t=e[Symbol.iterator]();!(s=(o=t.next()).done)&&(a.push(o.value),!n||a.length!==n);s=!0);}catch(d){i=!0,r=d}finally{try{!s&&t["return"]&&t["return"]()}finally{if(i)throw r}}return a}return function(n,a){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,a);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();!function(){angular.module("xos.dashboardManager").directive("userDashboards",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/user-dashboards.tpl.html",controller:["$q","_","UserDashboards","Dashboards",function(e,n,a,s){var i=this;e.all([a.query().$promise,s.query({enabled:"False"}).$promise]).then(function(e){var a=_slicedToArray(e,2),s=a[0],r=a[1];i.disabled=r,i.list={enabled:n.filter(s,{shown:!0}),disabled:n.filter(s,{shown:!1})}})["catch"](function(e){throw new Error(e)}),this.removeFromList=function(e,a){n.remove(i.list[e],{id:a})},this.addToList=function(e,n){i.list[e].push(n)},this.isInList=function(e,a){return n.find(i.list[e],a)},this.reorderList=function(e,a,s,i){var r=n.filter(e,function(e){return e.id!==i.id&&(e.order<s||e.order>=a)});r=r.map(function(e){return e.order++,e})},this.addedToList=function(e,n,s,r,o){var t=void 0,d=i.isInList(o,s);d?(t=s.order,d.order=n,s.order=n):(s.order=i.list[o].length,s.shown=!s.shown);var l="enabled"===o?"disabled":"enabled";a.update(s).$promise.then(function(e){d?i.reorderList(i.list[o],n,t,e):(i.addToList(o,e),i.removeFromList(l,e.id))})}}]}})}(),angular.module("xos.dashboardManager").run(["$templateCache",function(e){e.put("templates/dashboard-form.tpl.html",'<div class="row">\n  <div class="col-xs-10">\n    <h1>Manage Dashboard</h1>\n  </div>\n  <div class="col-xs-2 text-right">\n    <a ui-sref="manage-user-dashboards" class="btn btn-success">Back</a>\n  </div>\n</div>\n<div class="row">\n  <div class="col-xs-12">\n    <xos-form ng-model="vm.dashboard" config="vm.formConfig"></xos-form>\n  </div>\n</div>\n<div class="row" ng-show="vm.tosca">\n  <div class="col-sm-6">\n    <div class="row">\n      <div class="col-xs-12">\n        <xos-alert show="true" config="{type: \'info\'}">\n          Include this lines in a TOSCA recipe to load the {{vm.dashboard.name}} dashboard in the system.\n        </xos-alert>\n      </div>\n      <div class="col-xs-12">\n        <pre>{{vm.tosca}}</pre>\n      </div>\n    </div>\n  </div>\n  <div class="col-sm-6">\n    <div class="row">\n      <div class="col-xs-12">\n        <xos-alert show="true" config="{type: \'info\'}">\n          Add this lines as a requirement for the user in a TOSCA recipe to assign the {{vm.dashboard.name}} to the user.\n        </xos-alert>\n      </div>\n      <div class="col-xs-12">\n        <pre>{{vm.toscaRequirements}}</pre>\n      </div>\n    </div>\n  </div>\n</div>'),e.put("templates/user-dashboards.tpl.html",'<div class="row">\n  <div class="col-xs-10">\n    <h1>Manage Your Dashboards</h1>\n  </div>\n  <div class="col-xs-2 text-right">\n    <a ui-sref="add-dashboards" class="btn btn-success">Add</a>\n  </div>\n</div>\n\n<div class="row">\n  <div class="col-xs-6">\n    <div class="panel panel-primary">\n      <div class="panel-heading">\n        <h3 class="panel-title">\n          Available Dashboards\n        </h3>\n      </div>\n      <div class="panel-body">\n        <ul dnd-list="vm.list.disabled"\n          dnd-drop="vm.addedToList(event, index, item, external, \'disabled\')">\n          <li ng-repeat="item in vm.list.disabled"\n            dnd-moved="vm.removeFromList(\'disabled\', item.id)"\n            dnd-draggable="item">\n            {{item.name}}\n            <a ui-sref="edit-dashboards({id: item.id,})"><i class="glyphicon glyphicon-pencil"></i></a>\n          </li>\n        </ul>\n      </div>\n    </div>\n  </div>\n  <div class="col-xs-6">\n    <div class="panel panel-primary">\n      <div class="panel-heading">\n        <h3 class="panel-title">\n          Enabled Dashboards\n        </h3>\n      </div>\n      <div class="panel-body">\n        <ul dnd-list="vm.list.enabled"\n          dnd-drop="vm.addedToList(event, index, item, external, \'enabled\')">\n          <li ng-repeat="item in vm.list.enabled | orderBy : \'order\'"\n            dnd-moved="vm.removeFromList(\'enabled\', item.id)"\n            dnd-draggable="item">\n            {{item.name}}\n            <a ui-sref="edit-dashboards({id: item.id,})"><i class="glyphicon glyphicon-pencil"></i></a>\n          </li>\n        </ul>\n      </div>\n    </div>\n  </div>\n</div>\n<div class="row" ng-show="vm.disabled.length > 0">\n  <div class="col-xs-12">\n    <h1>Disabled Dashboard</h1>\n  </div>\n  <div class="col-xs-12">\n    <div class="row">\n      <div class="col-sm-2" ng-repeat="item in vm.disabled | orderBy : \'id\'">\n        <span class="dashboard-container">\n          {{item.name}}\n          <a ui-sref="edit-dashboards({id: item.id,})"><i class="glyphicon glyphicon-pencil"></i></a>\n        </span>\n      </div>\n    </div>\n  </div>\n</div>\n')}]),function(){angular.module("xos.dashboardManager").directive("dashboardForm",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/dashboard-form.tpl.html",controller:["$stateParams","$log","Dashboards",function(e,n,a){var s=this;this.dashboard={enabled:!0},e.id&&a.get({id:e.id}).$promise.then(function(e){s.dashboard=e})["catch"](function(e){console.log(e)}),this.formConfig={exclude:["backend_register","controllers","deployments","enacted","humanReadableName","lazy_blocked","no_policy","no_sync","policed","write_protect"],actions:[{label:"Save",icon:"ok",cb:function(e,n){if(n.$valid){if(e.name&&e.url&&e.custom_icon){var a=e.url.indexOf("xos");if(a>=0){var i=e.url.slice(a+3,e.url.length).toLowerCase();e.icon=i.concat("-icon.png"),e.icon_active=i.concat("-icon-active.png")}else e.icon="default-icon.png",e.icon_active="default-icon-active.png"}else e.icon="default-icon.png",e.icon_active="default-icon-active.png";s.createOrUpdateDashboard(e)}},"class":"success"},{label:"Esport to TOSCA",icon:"export",cb:function(e){s.toTosca(e)},"class":"primary"}],formName:"dashboardForm",feedback:{show:!1,message:"Form submitted successfully !!!",type:"success"},fields:{name:{type:"string",validators:{required:!0}},url:{type:"string",validators:{required:!0}},enabled:{type:"boolean"},custom_icon:{type:"boolean"}}},this.createOrUpdateDashboard=function(e){var i=void 0;e.id?(delete e.controllers,delete e.deployments,i=e.$save()):i=a.save(e).$promise,i.then(function(e){s.formConfig.feedback.show=!0})["catch"](function(e){n.info(e),s.formConfig.feedback.show=!0,s.formConfig.feedback.message=e,s.formConfig.feedback.type="danger"})},this.toTosca=function(e){var n={};n[e.name]={type:"tosca.nodes.DashboardView",properties:{url:e.url}},s.tosca=jsyaml.dump(n).replace(/'/g,"");var a={requirements:[]},i={};i[e.name.toLowerCase()+"_dashboard"]={node:e.name,relationship:"tosca.relationships.UsesDashboard"},a.requirements.push(i),s.toscaRequirements=jsyaml.dump(a).replace(/'/g,"")}}]}})}(),angular.module("xos.dashboardManager").run(["$location",function(e){e.path("/")}]);
\ No newline at end of file
+"use strict";angular.module("xos.dashboardManager",["ngResource","ngCookies","ui.router","xos.helpers","dndLists"]).config(["$stateProvider",function(e){e.state("manage-user-dashboards",{url:"/",template:"<user-dashboards></user-dashboards>"}).state("add-dashboards",{url:"/add",template:"<dashboard-form></dashboard-form>"}).state("edit-dashboards",{url:"/dashboards/:id",template:"<dashboard-form></dashboard-form>"})}]).config(["$httpProvider",function(e){e.interceptors.push("NoHyperlinks")}]).service("UserDashboards",["$http","$q",function(e,n){this.query=function(){var a=n.defer();return e.get("/api/utility/dashboards").then(function(e){a.resolve(e.data)})["catch"](function(e){a.reject(e)}),{$promise:a.promise}},this.update=function(a){var s=n.defer();return e.post("/api/utility/dashboards/",a).then(function(e){s.resolve(e.data)})["catch"](function(e){s.reject(e)}),{$promise:s.promise}}}]);var _slicedToArray=function(){function e(e,n){var a=[],s=!0,i=!1,o=void 0;try{for(var r,t=e[Symbol.iterator]();!(s=(r=t.next()).done)&&(a.push(r.value),!n||a.length!==n);s=!0);}catch(d){i=!0,o=d}finally{try{!s&&t["return"]&&t["return"]()}finally{if(i)throw o}}return a}return function(n,a){if(Array.isArray(n))return n;if(Symbol.iterator in Object(n))return e(n,a);throw new TypeError("Invalid attempt to destructure non-iterable instance")}}();!function(){angular.module("xos.dashboardManager").directive("userDashboards",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/user-dashboards.tpl.html",controller:["$q","_","UserDashboards","Dashboards",function(e,n,a,s){var i=this;e.all([a.query().$promise,s.query({enabled:"False"}).$promise]).then(function(e){var a=_slicedToArray(e,2),s=a[0],o=a[1];i.disabled=o,i.list={enabled:n.filter(s,{shown:!0}),disabled:n.filter(s,{shown:!1})}})["catch"](function(e){throw new Error(e)}),this.removeFromList=function(e,a){n.remove(i.list[e],{id:a})},this.addToList=function(e,n){i.list[e].push(n),location.reload()},this.isInList=function(e,a){return n.find(i.list[e],a)},this.reorderList=function(e,a,s,i){var o=n.filter(e,function(e){return e.id!==i.id&&(e.order<s||e.order>=a)});o=o.map(function(e){return e.order++,e})},this.addedToList=function(e,n,s,o,r){var t=void 0,d=i.isInList(r,s);d?(t=s.order,d.order=n,s.order=n):(s.order=i.list[r].length,s.shown=!s.shown);var l="enabled"===r?"disabled":"enabled";a.update(s).$promise.then(function(e){d?i.reorderList(i.list[r],n,t,e):(i.addToList(r,e),i.removeFromList(l,e.id))})}}]}})}(),angular.module("xos.dashboardManager").run(["$templateCache",function(e){e.put("templates/dashboard-form.tpl.html",'<div class="row">\n  <div class="col-xs-10">\n    <h1>Manage Dashboard</h1>\n  </div>\n  <div class="col-xs-2 text-right">\n    <a ui-sref="manage-user-dashboards" class="btn btn-success">Back</a>\n  </div>\n</div>\n<div class="row">\n  <div class="col-xs-12">\n    <xos-form ng-model="vm.dashboard" config="vm.formConfig"></xos-form>\n  </div>\n</div>\n<div class="row" ng-show="vm.tosca">\n  <div class="col-sm-6">\n    <div class="row">\n      <div class="col-xs-12">\n        <xos-alert show="true" config="{type: \'info\'}">\n          Include this lines in a TOSCA recipe to load the {{vm.dashboard.name}} dashboard in the system.\n        </xos-alert>\n      </div>\n      <div class="col-xs-12">\n        <pre>{{vm.tosca}}</pre>\n      </div>\n    </div>\n  </div>\n  <div class="col-sm-6">\n    <div class="row">\n      <div class="col-xs-12">\n        <xos-alert show="true" config="{type: \'info\'}">\n          Add this lines as a requirement for the user in a TOSCA recipe to assign the {{vm.dashboard.name}} to the user.\n        </xos-alert>\n      </div>\n      <div class="col-xs-12">\n        <pre>{{vm.toscaRequirements}}</pre>\n      </div>\n    </div>\n  </div>\n</div>'),e.put("templates/user-dashboards.tpl.html",'<div class="row">\n  <div class="col-xs-10">\n    <h1>Manage Your Dashboards</h1>\n  </div>\n  <div class="col-xs-2 text-right">\n    <a ui-sref="add-dashboards" class="btn btn-success">Add</a>\n  </div>\n</div>\n\n<div class="row">\n  <div class="col-xs-6">\n    <div class="panel panel-primary">\n      <div class="panel-heading">\n        <h3 class="panel-title">\n          Available Dashboards\n        </h3>\n      </div>\n      <div class="panel-body">\n        <ul dnd-list="vm.list.disabled"\n          dnd-drop="vm.addedToList(event, index, item, external, \'disabled\')">\n          <li ng-repeat="item in vm.list.disabled"\n            dnd-moved="vm.removeFromList(\'disabled\', item.id)"\n            dnd-draggable="item">\n            {{item.name}}\n            <a ui-sref="edit-dashboards({id: item.id,})"><i class="glyphicon glyphicon-pencil"></i></a>\n          </li>\n        </ul>\n      </div>\n    </div>\n  </div>\n  <div class="col-xs-6">\n    <div class="panel panel-primary">\n      <div class="panel-heading">\n        <h3 class="panel-title">\n          Enabled Dashboards\n        </h3>\n      </div>\n      <div class="panel-body">\n        <ul dnd-list="vm.list.enabled"\n          dnd-drop="vm.addedToList(event, index, item, external, \'enabled\')">\n          <li ng-repeat="item in vm.list.enabled | orderBy : \'order\'"\n            dnd-moved="vm.removeFromList(\'enabled\', item.id)"\n            dnd-draggable="item">\n            {{item.name}}\n            <a ui-sref="edit-dashboards({id: item.id,})"><i class="glyphicon glyphicon-pencil"></i></a>\n          </li>\n        </ul>\n      </div>\n    </div>\n  </div>\n</div>\n<div class="row" ng-show="vm.disabled.length > 0">\n  <div class="col-xs-12">\n    <h1>Disabled Dashboard</h1>\n  </div>\n  <div class="col-xs-12">\n    <div class="row">\n      <div class="col-sm-2" ng-repeat="item in vm.disabled | orderBy : \'id\'">\n        <span class="dashboard-container">\n          {{item.name}}\n          <a ui-sref="edit-dashboards({id: item.id,})"><i class="glyphicon glyphicon-pencil"></i></a>\n        </span>\n      </div>\n    </div>\n  </div>\n</div>\n'),e.put("templates/users-list.tpl.html",'<xos-table config="vm.tableConfig" data="vm.users"></xos-table>')}]),function(){angular.module("xos.dashboardManager").directive("dashboardForm",function(){return{restrict:"E",scope:{},bindToController:!0,controllerAs:"vm",templateUrl:"templates/dashboard-form.tpl.html",controller:["$stateParams","$log","Dashboards",function(e,n,a){var s=this;this.dashboard={enabled:!0},e.id&&a.get({id:e.id}).$promise.then(function(e){s.dashboard=e})["catch"](function(e){console.log(e)}),this.formConfig={exclude:["backend_register","controllers","deployments","enacted","humanReadableName","lazy_blocked","no_policy","no_sync","policed","write_protect","icon","icon_active"],actions:[{label:"Save",icon:"ok",cb:function(e,n){if(n.$valid){if(e.name&&e.url&&e.custom_icon){var a=e.url.indexOf("xos");if(a>=0){var i=e.url.slice(a+3,e.url.length).toLowerCase();e.icon=i.concat("-icon.png"),e.icon_active=i.concat("-icon-active.png")}else e.icon="default-icon.png",e.icon_active="default-icon-active.png"}else e.icon="default-icon.png",e.icon_active="default-icon-active.png";s.createOrUpdateDashboard(e)}},"class":"success"},{label:"Esport to TOSCA",icon:"export",cb:function(e){s.toTosca(e)},"class":"primary"}],formName:"dashboardForm",feedback:{show:!1,message:"Form submitted successfully !!!",type:"success"},fields:{name:{type:"string",validators:{required:!0}},url:{type:"string",validators:{required:!0}},enabled:{type:"boolean"},custom_icon:{type:"boolean"}}},this.createOrUpdateDashboard=function(e){var i=void 0;e.id?(delete e.controllers,delete e.deployments,i=e.$save()):i=a.save(e).$promise,i.then(function(e){s.formConfig.feedback.show=!0})["catch"](function(e){n.info(e),s.formConfig.feedback.show=!0,s.formConfig.feedback.message=e,s.formConfig.feedback.type="danger"})},this.toTosca=function(e){var n={};n[e.name]={type:"tosca.nodes.DashboardView",properties:{url:e.url}},s.tosca=jsyaml.dump(n).replace(/'/g,"");var a={requirements:[]},i={};i[e.name.toLowerCase()+"_dashboard"]={node:e.name,relationship:"tosca.relationships.UsesDashboard"},a.requirements.push(i),s.toscaRequirements=jsyaml.dump(a).replace(/'/g,"")}}]}})}(),angular.module("xos.dashboardManager").run(["$location",function(e){e.path("/")}]);
\ No newline at end of file
diff --git a/xos/tosca/custom_types/xos.m4 b/xos/tosca/custom_types/xos.m4
index 99843c1..6c9f452 100644
--- a/xos/tosca/custom_types/xos.m4
+++ b/xos/tosca/custom_types/xos.m4
@@ -631,75 +631,75 @@
           # tosca definitions tosca.nodes.network.Network here rather than
           # using derived_from.
           derived_from: tosca.nodes.Root
-          description: >

-            This is a variant of the TOSCA Network object that includes additional

-            XOS-specific properties.

-          properties:

-            xos_base_props

-            ip_version:

-              type: integer

-              required: no

-              default: 4

-              constraints:

-                - valid_values: [ 4, 6 ]

-              description: >

-                The IP version of the requested network. Valid values are 4 for ipv4

-                or 6 for ipv6.

-            cidr:

-              type: string

-              required: no

-              description: >

-                The cidr block of the requested network.

-            start_ip:

-              type: string

-              required: no

-              description: >

-                 The IP address to be used as the start of a pool of addresses within

-                 the full IP range derived from the cidr block.

-            end_ip:

-              type: string

-              required: no

-              description: >

-                  The IP address to be used as the end of a pool of addresses within

-                  the full IP range derived from the cidr block.

-            gateway_ip:

-              type: string

-              required: no

-              description: >

-                 The gateway IP address.

-            network_name:

-              type: string

-              required: no

-              description: >

-                 An identifier that represents an existing Network instance in the

-                 underlying cloud infrastructure or can be used as the name of the

-                 newly created network. If network_name is provided and no other

-                 properties are provided (with exception of network_id), then an

-                 existing network instance will be used. If network_name is provided

-                 alongside with more properties then a new network with this name will

-                 be created.

-            network_id:

-              type: string

-              required: no

-              description: >

-                 An identifier that represents an existing Network instance in the

-                 underlying cloud infrastructure. This property is mutually exclusive

-                 with all other properties except network_name. This can be used alone

-                 or together with network_name to identify an existing network.

-            segmentation_id:

-              type: string

-              required: no

-              description: >

-                 A segmentation identifier in the underlying cloud infrastructure.

-                 E.g. VLAN ID, GRE tunnel ID, etc..

-            dhcp_enabled:

-              type: boolean

-              required: no

-              default: true

-              description: >

-                Indicates should DHCP service be enabled on the network or not.

-        # XOS-specific

-            ports:

+          description: >
+            This is a variant of the TOSCA Network object that includes additional
+            XOS-specific properties.
+          properties:
+            xos_base_props
+            ip_version:
+              type: integer
+              required: no
+              default: 4
+              constraints:
+                - valid_values: [ 4, 6 ]
+              description: >
+                The IP version of the requested network. Valid values are 4 for ipv4
+                or 6 for ipv6.
+            cidr:
+              type: string
+              required: no
+              description: >
+                The cidr block of the requested network.
+            start_ip:
+              type: string
+              required: no
+              description: >
+                 The IP address to be used as the start of a pool of addresses within
+                 the full IP range derived from the cidr block.
+            end_ip:
+              type: string
+              required: no
+              description: >
+                  The IP address to be used as the end of a pool of addresses within
+                  the full IP range derived from the cidr block.
+            gateway_ip:
+              type: string
+              required: no
+              description: >
+                 The gateway IP address.
+            network_name:
+              type: string
+              required: no
+              description: >
+                 An identifier that represents an existing Network instance in the
+                 underlying cloud infrastructure or can be used as the name of the
+                 newly created network. If network_name is provided and no other
+                 properties are provided (with exception of network_id), then an
+                 existing network instance will be used. If network_name is provided
+                 alongside with more properties then a new network with this name will
+                 be created.
+            network_id:
+              type: string
+              required: no
+              description: >
+                 An identifier that represents an existing Network instance in the
+                 underlying cloud infrastructure. This property is mutually exclusive
+                 with all other properties except network_name. This can be used alone
+                 or together with network_name to identify an existing network.
+            segmentation_id:
+              type: string
+              required: no
+              description: >
+                 A segmentation identifier in the underlying cloud infrastructure.
+                 E.g. VLAN ID, GRE tunnel ID, etc..
+            dhcp_enabled:
+              type: boolean
+              required: no
+              default: true
+              description: >
+                Indicates should DHCP service be enabled on the network or not.
+        # XOS-specific
+            ports:
                 type: string
                 required: false
                 description: >
@@ -716,7 +716,7 @@
                 default: true
                 description: If True, then any slice may be attached to this network.
           capabilities:
-            link:

+            link:
               type: tosca.capabilities.network.Linkable
 
     tosca.nodes.Deployment:
@@ -1006,6 +1006,10 @@
                 type: string
                 required: false
                 description: URL to the dashboard
+            custom_icon:
+                type: boolean
+                default: false
+                description: Whether the dashboard has custom icons
 
     tosca.nodes.Tag:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/custom_types/xos.yaml b/xos/tosca/custom_types/xos.yaml
index 9b902f0..0ea18a0 100644
--- a/xos/tosca/custom_types/xos.yaml
+++ b/xos/tosca/custom_types/xos.yaml
@@ -1278,10 +1278,10 @@
           # tosca definitions tosca.nodes.network.Network here rather than
           # using derived_from.
           derived_from: tosca.nodes.Root
-          description: >

-            This is a variant of the TOSCA Network object that includes additional

-            XOS-specific properties.

-          properties:

+          description: >
+            This is a variant of the TOSCA Network object that includes additional
+            XOS-specific properties.
+          properties:
             no-delete:
                 type: boolean
                 default: false
@@ -1297,71 +1297,71 @@
             replaces:
                 type: string
                 required: false
-                descrption: Replaces/renames this object

-            ip_version:

-              type: integer

-              required: no

-              default: 4

-              constraints:

-                - valid_values: [ 4, 6 ]

-              description: >

-                The IP version of the requested network. Valid values are 4 for ipv4

-                or 6 for ipv6.

-            cidr:

-              type: string

-              required: no

-              description: >

-                The cidr block of the requested network.

-            start_ip:

-              type: string

-              required: no

-              description: >

-                 The IP address to be used as the start of a pool of addresses within

-                 the full IP range derived from the cidr block.

-            end_ip:

-              type: string

-              required: no

-              description: >

-                  The IP address to be used as the end of a pool of addresses within

-                  the full IP range derived from the cidr block.

-            gateway_ip:

-              type: string

-              required: no

-              description: >

-                 The gateway IP address.

-            network_name:

-              type: string

-              required: no

-              description: >

-                 An identifier that represents an existing Network instance in the

-                 underlying cloud infrastructure or can be used as the name of the

-                 newly created network. If network_name is provided and no other

-                 properties are provided (with exception of network_id), then an

-                 existing network instance will be used. If network_name is provided

-                 alongside with more properties then a new network with this name will

-                 be created.

-            network_id:

-              type: string

-              required: no

-              description: >

-                 An identifier that represents an existing Network instance in the

-                 underlying cloud infrastructure. This property is mutually exclusive

-                 with all other properties except network_name. This can be used alone

-                 or together with network_name to identify an existing network.

-            segmentation_id:

-              type: string

-              required: no

-              description: >

-                 A segmentation identifier in the underlying cloud infrastructure.

-                 E.g. VLAN ID, GRE tunnel ID, etc..

-            dhcp_enabled:

-              type: boolean

-              required: no

-              default: true

-              description: >

-                Indicates should DHCP service be enabled on the network or not.

-        # XOS-specific

-            ports:

+                descrption: Replaces/renames this object
+            ip_version:
+              type: integer
+              required: no
+              default: 4
+              constraints:
+                - valid_values: [ 4, 6 ]
+              description: >
+                The IP version of the requested network. Valid values are 4 for ipv4
+                or 6 for ipv6.
+            cidr:
+              type: string
+              required: no
+              description: >
+                The cidr block of the requested network.
+            start_ip:
+              type: string
+              required: no
+              description: >
+                 The IP address to be used as the start of a pool of addresses within
+                 the full IP range derived from the cidr block.
+            end_ip:
+              type: string
+              required: no
+              description: >
+                  The IP address to be used as the end of a pool of addresses within
+                  the full IP range derived from the cidr block.
+            gateway_ip:
+              type: string
+              required: no
+              description: >
+                 The gateway IP address.
+            network_name:
+              type: string
+              required: no
+              description: >
+                 An identifier that represents an existing Network instance in the
+                 underlying cloud infrastructure or can be used as the name of the
+                 newly created network. If network_name is provided and no other
+                 properties are provided (with exception of network_id), then an
+                 existing network instance will be used. If network_name is provided
+                 alongside with more properties then a new network with this name will
+                 be created.
+            network_id:
+              type: string
+              required: no
+              description: >
+                 An identifier that represents an existing Network instance in the
+                 underlying cloud infrastructure. This property is mutually exclusive
+                 with all other properties except network_name. This can be used alone
+                 or together with network_name to identify an existing network.
+            segmentation_id:
+              type: string
+              required: no
+              description: >
+                 A segmentation identifier in the underlying cloud infrastructure.
+                 E.g. VLAN ID, GRE tunnel ID, etc..
+            dhcp_enabled:
+              type: boolean
+              required: no
+              default: true
+              description: >
+                Indicates should DHCP service be enabled on the network or not.
+        # XOS-specific
+            ports:
                 type: string
                 required: false
                 description: >
@@ -1378,7 +1378,7 @@
                 default: true
                 description: If True, then any slice may be attached to this network.
           capabilities:
-            link:

+            link:
               type: tosca.capabilities.network.Linkable
 
     tosca.nodes.Deployment:
@@ -1878,6 +1878,10 @@
                 type: string
                 required: false
                 description: URL to the dashboard
+            custom_icon:
+                type: boolean
+                default: false
+                description: Whether the dashboard has custom icons
 
     tosca.nodes.Tag:
         derived_from: tosca.nodes.Root
diff --git a/xos/tosca/resources/dashboardview.py b/xos/tosca/resources/dashboardview.py
index 3bce58d..cadbfed 100644
--- a/xos/tosca/resources/dashboardview.py
+++ b/xos/tosca/resources/dashboardview.py
@@ -4,18 +4,24 @@
 import tempfile
 sys.path.append("/opt/tosca")
 from translator.toscalib.tosca_template import ToscaTemplate
-
 from core.models import DashboardView, Site, Deployment, SiteDeployment
-
 from xosresource import XOSResource
 
+
 class XOSDashboardView(XOSResource):
     provides = "tosca.nodes.DashboardView"
     xos_model = DashboardView
-    copyin_props = ["url","enabled"]
+    copyin_props = ["url", "enabled"]
 
     def get_xos_args(self):
-        return super(XOSDashboardView, self).get_xos_args()
+        args = super(XOSDashboardView, self).get_xos_args()
+        if (self.get_property("custom_icon")):
+            prefix, name = self.get_property("url").split(':')
+            name = name[3:]
+            name = name[:1].lower() + name[1:]
+            args["icon"] = "%s-icon.png" % name
+            args["icon_active"] = "%s-icon-active.png" % name
+        return args
 
     def postprocess(self, obj):
         for deployment_name in self.get_requirements("tosca.relationships.SupportsDeployment"):
@@ -28,4 +34,12 @@
     def can_delete(self, obj):
         return super(XOSDashboardView, self).can_delete(obj)
 
+    def create(self):
+        xos_args = self.get_xos_args()
 
+        dashboard = DashboardView(**xos_args)
+        dashboard.save()
+
+        self.postprocess(dashboard)
+
+        self.info("Created DashboardView '%s'" % (str(dashboard), ))