Update role assignment and network mapping.

Use $q to fix multiple asynchronous ajax calls.

Change-Id: Ifc18fcaa0a4ab1c70a91d4f2a134d5e302fb8ff6
This commit is contained in:
jiahuay 2014-07-10 16:13:46 -07:00
parent 65cb094350
commit ae9da1d1b4
13 changed files with 1057 additions and 366 deletions

View File

@ -69,6 +69,32 @@ select {
} }
.partition-chart { .partition-chart {
padding-top: 30px; padding-top: 30px;
}
.margin-top-minus10 {
margin-top: -10px !important;
}
.drag-enter {
background: none repeat scroll 0 0 #F0F9FF;
border: 2px dashed #BED2DB !important;
box-sizing: border-box;
margin: 5px 0;
min-height: 50px;
padding: 0;
}
.network-draggable {
position: relative;
width: 200px;
}
.network-placeholder {
min-height: 200px;
}
.interface-placeholder {
border: 1px solid #BED2DB;
box-sizing: border-box;
margin: 5px 0;
min-height: 50px;
padding: 10px;
}
.btn-clstr { .btn-clstr {
border: none !important; border: none !important;
background-color: inherit!important; background-color: inherit!important;

View File

@ -3,33 +3,25 @@
"id": 10, "id": 10,
"name": "demo", "name": "demo",
"adapter_id": 1, "adapter_id": 1,
"os_id":1 "os_id": 1
}, },
"partition": { "partition": {
"/swap": {
"size_percentage": 10
},
"/boot": {
"size_percentage": 10
},
"/var": { "/var": {
"size_percentage": 30 "size_percentage": 30
}, },
"/home": { "/home": {
"size_percentage": 20 "size_percentage": 30
},
"/tmp": {
"size_percentage": 10
}, },
"/spare": { "/spare": {
"size_percentage": 40 "size_percentage": 20
} }
}, },
"subnet": [{
"name": "subnet1",
"subnet": "192.168.10.1",
"netmask": "255.255.255.0",
"subnet_id": 1
}, {
"name": "subnet2",
"subnet": "172.1.100.1",
"netmask": "255.255.255.0",
"subnet_id": 2
}],
"interface": { "interface": {
"eth0": { "eth0": {
"subnet_id": 1, "subnet_id": 1,
@ -49,14 +41,16 @@
} }
}, },
"general": { "general": {
"timezone": "-8.00", "timezone": "-4.00",
"language": "en", "language": "en",
"http_proxy": "", "http_proxy": [""],
"https_proxy": [""],
"default_no_proxy":[""],
"ntp_server": "", "ntp_server": "",
"domain": "compass.com",
"gateway": "172.19.100.1",
"dns_servers": [""], "dns_servers": [""],
"search_path": ["compass.com"] "search_path": ["compass.com"],
"domain": "compass.com",
"default_gateway": "172.19.100.1"
}, },
"server_credentials": { "server_credentials": {
"username": "admin", "username": "admin",
@ -87,11 +81,11 @@
"username": "ceilometer", "username": "ceilometer",
"password": "ceilometer" "password": "ceilometer"
}, },
"super": { "mysql": {
"username": "root", "username": "root",
"password": "root" "password": "root"
}, },
"volumn": { "volume": {
"username": "cinder", "username": "cinder",
"password": "cinder" "password": "cinder"
} }
@ -125,10 +119,27 @@
"username": "swift", "username": "swift",
"password": "swift" "password": "swift"
}, },
"volumn": { "volume": {
"username": "cinder", "username": "cinder",
"password": "cinder" "password": "cinder"
} }
},
"network_mapping": {
"management": {
"display": "Management Network",
"mapping_interface": ""
},
"tenant": {
"display": "Tenant Network",
"mapping_interface": ""
},
"storage": {
"display": "Storage Network",
"mapping_interface": ""
},
"public": {
"display": "Public Network",
"mapping_interface": ""
}
} }
} }

View File

@ -17,7 +17,7 @@
"visible": true "visible": true
}, { }, {
"title": "Hostname", "title": "Hostname",
"field": "hostname", "field": "name",
"visible": true "visible": true
}, { }, {
"title": "Clusters", "title": "Clusters",
@ -58,7 +58,7 @@
"visible": false "visible": false
}, { }, {
"title": "Hostname", "title": "Hostname",
"field": "hostname", "field": "name",
"visible": true "visible": true
}, { }, {
"title": "Clusters", "title": "Clusters",
@ -80,5 +80,50 @@
"title": "State", "title": "State",
"field": "state", "field": "state",
"visible": false "visible": false
}],
"review": [{
"title": "Host MAC Addr",
"field": "mac",
"visible": true
}, {
"title": "Switch IP",
"field": "switch_ip",
"visible": true
}, {
"title": "Port",
"field": "port",
"visible": true
}, {
"title": "VLAN",
"field": "vlan",
"visible": false
}, {
"title": "Hostname",
"field": "name",
"visible": true
}, {
"title": "Clusters",
"field": "clusters",
"visible": false
}, {
"title": "OS",
"field": "os",
"visible": false
}, {
"title": "OS Reinstall",
"field": "os_installed",
"visible": false
}, {
"title": "Adapter",
"field": "adapter",
"visible": false
}, {
"title": "Roles",
"field": "roles",
"visible": true
}, {
"title": "State",
"field": "state",
"visible": false
}] }]
} }

View File

@ -21,8 +21,10 @@
<!--<script type="text/javascript" src="../vendor/angular/angular-resource.min.js"></script>--> <!--<script type="text/javascript" src="../vendor/angular/angular-resource.min.js"></script>-->
<script type="text/javascript" src="vendor/angular-ui-router/angular-ui-router.min.js"></script> <script type="text/javascript" src="vendor/angular-ui-router/angular-ui-router.min.js"></script>
<script type="text/javascript" src="vendor/angular-bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script> <script type="text/javascript" src="vendor/angular-bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
<script type="text/javascript" src="vendor/angular-dragdrop/draganddrop.js"></script>
<script type="text/javascript" src="vendor/ng-table/ng-table.min.js"></script> <script type="text/javascript" src="vendor/ng-table/ng-table.min.js"></script>
<script type="text/javascript" src="vendor/d3/d3.min.js"></script> <script type="text/javascript" src="vendor/d3/d3.min.js"></script>
<script type="text/javascript" src="src/app/app.js"></script> <script type="text/javascript" src="src/app/app.js"></script>
<script type="text/javascript" src="src/app/appDev.js"></script> <script type="text/javascript" src="src/app/appDev.js"></script>
<script type="text/javascript" src="src/app/services.js"></script> <script type="text/javascript" src="src/app/services.js"></script>

View File

@ -58,6 +58,38 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, adapters, {}]; return [200, adapters, {}];
}); });
$httpBackend.whenGET(/\.*\/adapters\/[1-9][0-9]*/).respond(function(method, url, data) {
console.log(method, url);
var adapter = {
"id": 1,
"name": "openstack",
"display": "OpenStack",
"os_installer": "cobbler",
"package_installer": "chef",
"roles": [{
"display_name": "Compute",
"name": "os-compute-worker"
}, {
"display_name": "Controller",
"name": "os-controller"
}, {
"display_name": "Network",
"name": "os-network"
}, {
"display_name": "Storage",
"name": "os-block-storage-worker"
}],
"compatible_os": [{
"name": "CentOs",
"os_id": 1
}, {
"name": "Ubuntu",
"os_id": 2
}]
};
return [200, adapter, {}];
});
$httpBackend.whenGET(settings.apiUrlBase + '/machines-hosts').respond(function(method, url, data) { $httpBackend.whenGET(settings.apiUrlBase + '/machines-hosts').respond(function(method, url, data) {
console.log(method, url); console.log(method, url);
var servers = [{ var servers = [{
@ -66,7 +98,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
"switch_ip": "172.29.8.40", "switch_ip": "172.29.8.40",
"vlan": "1", "vlan": "1",
"port": "1", "port": "1",
"hostname": "sv-1", "name": "sv-1",
"clusters": ["cluster1", "cluster2"], "clusters": ["cluster1", "cluster2"],
"os": "CentOS", "os": "CentOS",
"adapter": "OpenStack", "adapter": "OpenStack",
@ -91,7 +123,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
"switch_ip": "172.29.8.40", "switch_ip": "172.29.8.40",
"vlan": "2", "vlan": "2",
"port": "2", "port": "2",
"hostname": "sv-2", "name": "sv-2",
"clusters": ["cluster1"], "clusters": ["cluster1"],
"os": "CentOS", "os": "CentOS",
"adapter": "OpenStack", "adapter": "OpenStack",
@ -175,7 +207,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, config, {}]; return [200, config, {}];
}); });
$httpBackend.whenGET(/\.*\/clusters\/[1-9][0-9]*\/subnet-config/).respond(function(method, url, data) { $httpBackend.whenGET(settings.apiUrlBase + '/subnetworks').respond(function(method, url, data) {
console.log(method, url); console.log(method, url);
var subnetworks = [{ var subnetworks = [{
"subnet_id": 1, "subnet_id": 1,
@ -191,7 +223,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, subnetworks, {}]; return [200, subnetworks, {}];
}); });
$httpBackend.whenPOST(/\.*\/clusters\/[1-9][0-9]*\/subnet-config/).respond(function(method, url, data) { $httpBackend.whenPOST(settings.apiUrlBase + '/subnetworks').respond(function(method, url, data) {
console.log(method, url, data); console.log(method, url, data);
var subnetConfig = JSON.parse(data); var subnetConfig = JSON.parse(data);
@ -201,7 +233,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, subnetConfig, {}]; return [200, subnetConfig, {}];
}); });
$httpBackend.whenPUT(/\.*\/clusters\/[1-9][0-9]*\/subnet-config\/[1-9][0-9]*/).respond(function(method, url, data) { $httpBackend.whenPUT(/\.*\/subnetworks\/[1-9][0-9]*/).respond(function(method, url, data) {
console.log(method, url, data); console.log(method, url, data);
var subnetConfig = JSON.parse(data); var subnetConfig = JSON.parse(data);
@ -210,6 +242,8 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, subnetConfig, {}]; return [200, subnetConfig, {}];
}); });
// keep routing table for later use
/*
$httpBackend.whenPOST(/\.*\/clusters\/[1-9][0-9]*\/routing-table/).respond(function(method, url, data) { $httpBackend.whenPOST(/\.*\/clusters\/[1-9][0-9]*\/routing-table/).respond(function(method, url, data) {
console.log(method, url, data); console.log(method, url, data);
@ -220,7 +254,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, routingTable, {}]; return [200, routingTable, {}];
}); });
$httpBackend.whenPUT(/\.*\/clusters\/[1-9][0-9]*\/routing-table\/[1-9][0-9]*/).respond(function(method, url, data) { $httpBackend.whenPUT(/\.*\/clusters\/[1-9][0-9]*\/routing-table\/[1-9][0-9]/).respond(function(method, url, data) {
console.log(method, url, data); console.log(method, url, data);
var routingTable = JSON.parse(data); var routingTable = JSON.parse(data);
@ -228,6 +262,7 @@ compassAppDev.run(function($httpBackend, settings, $http) {
console.log(routingTable); console.log(routingTable);
return [200, routingTable, {}]; return [200, routingTable, {}];
}); });
*/
$httpBackend.whenPOST(/\.*\/clusters\/[1-9][0-9]*\/action/).respond(function(method, url, data) { $httpBackend.whenPOST(/\.*\/clusters\/[1-9][0-9]*\/action/).respond(function(method, url, data) {
console.log(method, url, data); console.log(method, url, data);
@ -243,10 +278,28 @@ compassAppDev.run(function($httpBackend, settings, $http) {
return [200, actionResponse, {}]; return [200, actionResponse, {}];
}); });
$httpBackend.whenPUT(/\.*\/hosts\/[1-9][0-9]*/).respond(function(method, url, data) {
console.log(method, url, data);
var host_config = JSON.parse(data);
return [200, host_config, {}];
});
$httpBackend.whenPOST(/\.*\/hosts\/[1-9][0-9]*\/network/).respond(function(method, url, data) { $httpBackend.whenPOST(/\.*\/hosts\/[1-9][0-9]*\/network/).respond(function(method, url, data) {
console.log(method, url, data); console.log(method, url, data);
var network = JSON.parse(data); var network = JSON.parse(data);
network.id = Math.floor((Math.random() * 100) + 1); network.id = Math.floor((Math.random() * 100) + 1);
return [200, network, {}]; return [200, network, {}];
}); });
$httpBackend.whenPUT(/\.*\/hosts\/[1-9][0-9]*\/network\/[1-9][0-9]/).respond(function(method, url, data) {
console.log(method, url, data);
var network = JSON.parse(data);
return [200, network, {}];
});
$httpBackend.whenPUT(/\.*\/clusters\/[1-9][0-9]*\/hosts\/[1-9][0-9]*\/config/).respond(function(method, url, data) {
console.log(method, url, data);
var config = JSON.parse(data);
return [200, config, {}];
});
}); });

View File

@ -58,6 +58,10 @@ angular.module('compass.services', [])
return $http.get(settings.apiUrlBase + '/adapters'); return $http.get(settings.apiUrlBase + '/adapters');
}; };
this.getAdapter = function(id) {
return $http.get(settings.apiUrlBase + '/adapters/' + id);
};
this.createCluster = function(cluster) { this.createCluster = function(cluster) {
return $http.post(settings.apiUrlBase + '/clusters', angular.toJson(cluster)); return $http.post(settings.apiUrlBase + '/clusters', angular.toJson(cluster));
}; };
@ -70,18 +74,20 @@ angular.module('compass.services', [])
return $http.put(settings.apiUrlBase + '/clusters/' + id + '/config', angular.toJson(config)); return $http.put(settings.apiUrlBase + '/clusters/' + id + '/config', angular.toJson(config));
}; };
this.getClusterSubnetConfig = function(id) { this.getSubnetConfig = function() {
return $http.get(settings.apiUrlBase + '/clusters/' + id + '/subnet-config'); return $http.get(settings.apiUrlBase + '/subnetworks');
}; };
this.postClusterSubnetConfig = function(id, subnet_config) { this.postSubnetConfig = function(subnet_config) {
return $http.post(settings.apiUrlBase + '/clusters/' + id + '/subnet-config', angular.toJson(subnet_config)); return $http.post(settings.apiUrlBase + '/subnetworks', angular.toJson(subnet_config));
}; };
this.putClusterSubnetConfig = function(id, subnetId, subnet_config) { this.putSubnetConfig = function(id, subnet_config) {
return $http.put(settings.apiUrlBase + '/clusters/' + id + '/subnet-config/' + subnetId, angular.toJson(subnet_config)); return $http.put(settings.apiUrlBase + '/subnetworks/' + id, angular.toJson(subnet_config));
}; };
// keep routing table for later use
/*
this.postRoutingTable = function(id, routing_table) { this.postRoutingTable = function(id, routing_table) {
return $http.post(settings.apiUrlBase + '/clusters/' + id + '/routing-table', angular.toJson(routing_table)); return $http.post(settings.apiUrlBase + '/clusters/' + id + '/routing-table', angular.toJson(routing_table));
}; };
@ -89,6 +95,7 @@ angular.module('compass.services', [])
this.putRoutingTable = function(id, routingId, routing_table) { this.putRoutingTable = function(id, routingId, routing_table) {
return $http.put(settings.apiUrlBase + '/clusters/' + id + '/routing-table/' + routingId, angular.toJson(routing_table)); return $http.put(settings.apiUrlBase + '/clusters/' + id + '/routing-table/' + routingId, angular.toJson(routing_table));
}; };
*/
this.getTimezones = function() { this.getTimezones = function() {
return $http.get(settings.metadataUrlBase + '/timezone.json'); return $http.get(settings.metadataUrlBase + '/timezone.json');
@ -98,9 +105,21 @@ angular.module('compass.services', [])
return $http.post(settings.apiUrlBase + '/clusters/' + id + '/action', angular.toJson(actions)); return $http.post(settings.apiUrlBase + '/clusters/' + id + '/action', angular.toJson(actions));
}; };
this.putHost = function(id, config) {
return $http.put(settings.apiUrlBase + '/hosts/' + id, angular.toJson(config));
};
this.postHostNetwork = function(id, network) { this.postHostNetwork = function(id, network) {
return $http.post(settings.apiUrlBase + '/hosts/' + id + '/network', angular.toJson(network)); return $http.post(settings.apiUrlBase + '/hosts/' + id + '/network', angular.toJson(network));
}; };
this.putHostNetwork = function(id, networkId, network) {
return $http.put(settings.apiUrlBase + '/hosts/' + id + '/network/' + networkId, angular.toJson(network));
};
this.updateClusterHostConfig = function(clusterId, hostId, config) {
return $http.put(settings.apiUrlBase + '/hosts/' + clusterId + '/hosts/' + hostId + '/config', angular.toJson(config));
};
} }
]) ])
@ -121,20 +140,23 @@ angular.module('compass.services', [])
wizard.generalConfig = {}; wizard.generalConfig = {};
wizard.interfaces = {}; wizard.interfaces = {};
wizard.partition = {}; wizard.partition = {};
wizard.server_credentials = {};
wizard.service_credentials = {}; wizard.service_credentials = {};
wizard.management_credentials = {}; wizard.management_credentials = {};
wizard.network_mapping = {};
}; };
wizard.init(); wizard.init();
wizard.preConfig = function(config) { wizard.preConfig = function(config) {
wizard.setClusterInfo(config.cluster); wizard.setClusterInfo(config.cluster);
wizard.setSubnetworks(config.subnet);
wizard.setInterfaces(config.interface); wizard.setInterfaces(config.interface);
wizard.setGeneralConfig(config.general); wizard.setGeneralConfig(config.general);
wizard.setPartition(config.partition); wizard.setPartition(config.partition);
wizard.setServerCredentials(config.server_credentials);
wizard.setServiceCredentials(config.service_credentials); wizard.setServiceCredentials(config.service_credentials);
wizard.setManagementCredentials(config.management_credentials); wizard.setManagementCredentials(config.management_credentials);
wizard.setNetworkMapping(config.network_mapping);
}; };
wizard.setClusterInfo = function(cluster) { wizard.setClusterInfo = function(cluster) {
@ -142,7 +164,7 @@ angular.module('compass.services', [])
}; };
wizard.getClusterInfo = function() { wizard.getClusterInfo = function() {
return wizard.cluster; return angular.copy(wizard.cluster);
}; };
wizard.setSteps = function(steps) { wizard.setSteps = function(steps) {
@ -150,7 +172,7 @@ angular.module('compass.services', [])
}; };
wizard.getSteps = function() { wizard.getSteps = function() {
return wizard.steps; return angular.copy(wizard.steps);
}; };
wizard.setCommitState = function(commitState) { wizard.setCommitState = function(commitState) {
@ -166,7 +188,7 @@ angular.module('compass.services', [])
}; };
wizard.getAllMachinesHost = function() { wizard.getAllMachinesHost = function() {
return wizard.allServers; return angular.copy(wizard.allServers);
}; };
wizard.setServers = function(servers) { wizard.setServers = function(servers) {
@ -174,7 +196,7 @@ angular.module('compass.services', [])
}; };
wizard.getServers = function() { wizard.getServers = function() {
return wizard.servers; return angular.copy(wizard.servers);
}; };
wizard.setAdapter = function(adapter) { //// wizard.setAdapter = function(adapter) { ////
@ -182,7 +204,7 @@ angular.module('compass.services', [])
}; };
wizard.getAdapter = function() { ///// wizard.getAdapter = function() { /////
return wizard.adapter; return angular.copy(wizard.adapter);
}; };
wizard.setGeneralConfig = function(config) { wizard.setGeneralConfig = function(config) {
@ -190,7 +212,7 @@ angular.module('compass.services', [])
}; };
wizard.getGeneralConfig = function() { wizard.getGeneralConfig = function() {
return wizard.generalConfig; return angular.copy(wizard.generalConfig);
}; };
wizard.setSubnetworks = function(subnetworks) { wizard.setSubnetworks = function(subnetworks) {
@ -198,9 +220,11 @@ angular.module('compass.services', [])
}; };
wizard.getSubnetworks = function() { wizard.getSubnetworks = function() {
return wizard.subnetworks; return angular.copy(wizard.subnetworks);
}; };
// keey routing table for later use
/*
wizard.setRoutingTable = function(routingTb) { wizard.setRoutingTable = function(routingTb) {
wizard.routingtable = routingTb; wizard.routingtable = routingTb;
}; };
@ -208,13 +232,14 @@ angular.module('compass.services', [])
wizard.getRoutingTable = function() { wizard.getRoutingTable = function() {
return wizard.routingtable; return wizard.routingtable;
}; };
*/
wizard.setInterfaces = function(interfaces) { wizard.setInterfaces = function(interfaces) {
wizard.interfaces = interfaces; wizard.interfaces = interfaces;
}; };
wizard.getInterfaces = function() { wizard.getInterfaces = function() {
return wizard.interfaces; return angular.copy(wizard.interfaces);
}; };
wizard.setPartition = function(partition) { wizard.setPartition = function(partition) {
@ -222,15 +247,22 @@ angular.module('compass.services', [])
}; };
wizard.getPartition = function() { wizard.getPartition = function() {
return wizard.partition; return angular.copy(wizard.partition);
}; };
wizard.setServerCredentials = function(credentials) {
wizard.server_credentials = credentials;
};
wizard.getServerCredentials = function() {
return angular.copy(wizard.server_credentials);
}
wizard.setServiceCredentials = function(credentials) { wizard.setServiceCredentials = function(credentials) {
wizard.service_credentials = credentials; wizard.service_credentials = credentials;
}; };
wizard.getServiceCredentials = function() { wizard.getServiceCredentials = function() {
return wizard.service_credentials; return angular.copy(wizard.service_credentials);
}; };
wizard.setManagementCredentials = function(credentials) { wizard.setManagementCredentials = function(credentials) {
@ -238,7 +270,15 @@ angular.module('compass.services', [])
}; };
wizard.getManagementCredentials = function() { wizard.getManagementCredentials = function() {
return wizard.management_credentials; return angular.copy(wizard.management_credentials);
};
wizard.setNetworkMapping = function(mapping) {
wizard.network_mapping = mapping;
};
wizard.getNetworkMapping = function() {
return angular.copy(wizard.network_mapping);
}; };
return wizard; return wizard;

View File

@ -22,15 +22,106 @@
<!--TODO: use json to generate inputs--> <!--TODO: use json to generate inputs-->
<div class="form-group"> <div class="form-group">
<div> <div>
<label class="col-sm-4 control-label no-padding-right">HTTP Proxy</label> <label class="col-sm-4 control-label no-padding-right">
Language
<span class="text-danger">*</span>
</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input ng-model="general.http_proxy" type="text" class="col-xs-10 col-sm-5" placeholder="HTTP Proxy" name="http_proxy"> <select ng-model="general.language" name="language" class="col-xs-10 col-sm-5">
<option value="en">English</option>
<option value="cn">Chinese</option>
</select>
</div> </div>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<div> <div>
<label class="col-sm-4 control-label no-padding-right">NTP Server</label> <label class="col-sm-4 control-label no-padding-right">
Timezone
<span class="text-danger">*</span>
</label>
<div class="col-sm-8">
<select ng-model="general.timezone" name="timezone" class="col-xs-10 col-sm-5">
<option ng-repeat="tm in timezones" value="{{tm.value}}">(GMT {{tm.value}}) {{tm.timezone}}</option>
</select>
</div>
</div>
</div>
<div ng-repeat="http_proxy in general.http_proxy track by $index" class="form-group">
<div>
<label class="col-sm-4 control-label no-padding-right">
<span ng-if="$index==0">
HTTP Proxy
<span class="text-danger opacity-zero">*</span>
</span>
</label>
<div class="col-sm-8">
<input ng-model="general.http_proxy[$index]" type="text" class="col-xs-10 col-sm-5" placeholder="HTTP Proxy" name="http_proxy">
<span class="col-xs-2 col-sm-3">
<!--Add Action-->
<span class="action" ng-click="addValue('http_proxy')">
<i class="fa fa-plus-circle bigger-140 blue"></i>
</span>
<!--Remove Action-->
<span ng-show="general.http_proxy.length > 1" class="action" ng-click="general.http_proxy.splice($index,1)">
<i class="fa fa-minus-circle bigger-140 blue"></i>
</span>
</span>
</div>
</div>
</div>
<div ng-repeat="https_proxy in general.https_proxy track by $index" class="form-group">
<div>
<label class="col-sm-4 control-label no-padding-right">
<span ng-if="$index==0">
HTTPS Proxy
<span class="text-danger opacity-zero">*</span>
</span>
</label>
<div class="col-sm-8">
<input ng-model="general.https_proxy[$index]" type="text" class="col-xs-10 col-sm-5" placeholder="HTTPS Proxy" name="https_proxy">
<span class="col-xs-2 col-sm-3">
<!--Add Action-->
<span class="action" ng-click="addValue('https_proxy')">
<i class="fa fa-plus-circle bigger-140 blue"></i>
</span>
<!--Remove Action-->
<span ng-show="general.https_proxy.length > 1" class="action" ng-click="general.https_proxy.splice($index,1)">
<i class="fa fa-minus-circle bigger-140 blue"></i>
</span>
</span>
</div>
</div>
</div>
<div ng-repeat="no_proxy in general.default_no_proxy track by $index" class="form-group">
<div>
<label class="col-sm-4 control-label no-padding-right">
<span ng-if="$index==0">
Default No Proxy
<span class="text-danger opacity-zero">*</span>
</span>
</label>
<div class="col-sm-8">
<input ng-model="general.default_no_proxy[$index]" type="text" class="col-xs-10 col-sm-5" placeholder="Default No Proxy" name="default_no_proxy">
<span class="col-xs-2 col-sm-3">
<!--Add Action-->
<span class="action" ng-click="addValue('default_no_proxy')">
<i class="fa fa-plus-circle bigger-140 blue"></i>
</span>
<!--Remove Action-->
<span ng-show="general.default_no_proxy.length > 1" class="action" ng-click="general.default_no_proxy.splice($index,1)">
<i class="fa fa-minus-circle bigger-140 blue"></i>
</span>
</span>
</div>
</div>
</div>
<div class="form-group">
<div>
<label class="col-sm-4 control-label no-padding-right">
NTP Server
<span class="text-danger">*</span>
</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input ng-model="general.ntp_server" type="text" class="col-xs-10 col-sm-5" placeholder="NTP Server" name="ntp_server"> <input ng-model="general.ntp_server" type="text" class="col-xs-10 col-sm-5" placeholder="NTP Server" name="ntp_server">
</div> </div>
@ -39,13 +130,16 @@
<div ng-repeat="dns_server in general.dns_servers track by $index" class="form-group"> <div ng-repeat="dns_server in general.dns_servers track by $index" class="form-group">
<div> <div>
<label class="col-sm-4 control-label no-padding-right"> <label class="col-sm-4 control-label no-padding-right">
<span ng-if="$index==0">DNS Servers</span> <span ng-if="$index==0">
DNS Servers
<span class="text-danger">*</span>
</span>
</label> </label>
<div class="col-sm-8"> <div class="col-sm-8">
<input ng-model="general.dns_servers[$index]" type="text" class="col-xs-10 col-sm-5" placeholder="DNS Server" name="dns_servers"> <input ng-model="general.dns_servers[$index]" type="text" class="col-xs-10 col-sm-5" placeholder="DNS Server" name="dns_servers">
<span class="col-xs-2 col-sm-3"> <span class="col-xs-2 col-sm-3">
<!--Add Action--> <!--Add Action-->
<span class="action" ng-click="addDNSServer()"> <span class="action" ng-click="addValue('dns_servers')">
<i class="fa fa-plus-circle bigger-140 blue"></i> <i class="fa fa-plus-circle bigger-140 blue"></i>
</span> </span>
<!--Remove Action--> <!--Remove Action-->
@ -59,13 +153,16 @@
<div ng-repeat="search_path in general.search_path track by $index" class="form-group"> <div ng-repeat="search_path in general.search_path track by $index" class="form-group">
<div> <div>
<label class="col-sm-4 control-label no-padding-right"> <label class="col-sm-4 control-label no-padding-right">
<span ng-if="$index==0">Search Path</span> <span ng-if="$index==0">
Search Path
<span class="text-danger">*</span>
</span>
</label> </label>
<div class="col-sm-8"> <div class="col-sm-8">
<input ng-model="general.search_path[$index]" type="text" class="col-xs-10 col-sm-5" placeholder="Search Path" name="search_path"> <input ng-model="general.search_path[$index]" type="text" class="col-xs-10 col-sm-5" placeholder="Search Path" name="search_path">
<span class="col-xs-2 col-sm-3"> <span class="col-xs-2 col-sm-3">
<!--Add Action--> <!--Add Action-->
<span class="action" ng-click="addSearchPath()"> <span class="action" ng-click="addValue('search_path')">
<i class="fa fa-plus-circle bigger-140 blue"></i> <i class="fa fa-plus-circle bigger-140 blue"></i>
</span> </span>
<!--Remove Action--> <!--Remove Action-->
@ -78,7 +175,10 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<div> <div>
<label class="col-sm-4 control-label no-padding-right">Domain</label> <label class="col-sm-4 control-label no-padding-right">
Domain
<span class="text-danger">*</span>
</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input ng-model="general.domain" type="text" class="col-xs-10 col-sm-5" placeholder="Domain" name="domain"> <input ng-model="general.domain" type="text" class="col-xs-10 col-sm-5" placeholder="Domain" name="domain">
</div> </div>
@ -86,33 +186,16 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<div> <div>
<label class="col-sm-4 control-label no-padding-right">Gateway</label> <label class="col-sm-4 control-label no-padding-right">
Default Gateway
<span class="text-danger">*</span>
</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input ng-model="general.gateway" type="text" class="col-xs-10 col-sm-5" placeholder="Gateway" name="gateway"> <input ng-model="general.default_gateway" type="text" class="col-xs-10 col-sm-5" placeholder="Gateway" name="gateway">
</div>
</div>
</div>
<div class="form-group">
<div>
<label class="col-sm-4 control-label no-padding-right">Timezone</label>
<div class="col-sm-8">
<select ng-model="general.timezone" name="timezone" class="col-xs-10 col-sm-5">
<option ng-repeat="tm in timezones" value="{{tm.value}}">(GMT {{tm.value}}) {{tm.timezone}}</option>
</select>
</div>
</div>
</div>
<div class="form-group">
<div>
<label class="col-sm-4 control-label no-padding-right">Language</label>
<div class="col-sm-8">
<select ng-model="general.language" name="language" class="col-xs-10 col-sm-5">
<option value="en">English</option>
<option value="cn">Chinese</option>
</select>
</div> </div>
</div> </div>
</div> </div>
</form> </form>
</div> </div>
</div> </div>
@ -167,7 +250,8 @@
</accordion-group> </accordion-group>
<accordion-group is-open="status.open"> <!--Keep routing table for later use-->
<!--<accordion-group is-open="status.open">
<accordion-heading> <accordion-heading>
<i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status.open, 'fa-angle-right': !status.open}"></i> Routing Table <i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status.open, 'fa-angle-right': !status.open}"></i> Routing Table
</accordion-heading> </accordion-heading>
@ -200,11 +284,9 @@
<input type="text" ng-model="route.gateway" placeholder="Gateway" /> <input type="text" ng-model="route.gateway" placeholder="Gateway" />
</td> </td>
<td> <td>
<!--Add Action-->
<span class="action" ng-click="addRoute()"> <span class="action" ng-click="addRoute()">
<i class="fa fa-plus-circle bigger-140 blue"></i> <i class="fa fa-plus-circle bigger-140 blue"></i>
</span> </span>
<!--Remove Action-->
<span ng-show="routingtable.length > 1" class="action" ng-click="removeRoute($index)"> <span ng-show="routingtable.length > 1" class="action" ng-click="removeRoute($index)">
<i class="fa fa-minus-circle bigger-140 blue"></i> <i class="fa fa-minus-circle bigger-140 blue"></i>
</span> </span>
@ -217,7 +299,7 @@
<div class="col-sm-2"> <div class="col-sm-2">
</div> </div>
</div> </div>
</accordion-group> </accordion-group>-->
</accordion> </accordion>
</div> </div>
</div> </div>

View File

@ -25,77 +25,125 @@
</div> </div>
</div> </div>
<div class="pull-right"> <div class="pull-right">
<button class="btn btn-sm btn-info" ng-init="addInterface.isCollapsed = true;" ng-click="addInterface.isCollapsed = !addInterface.isCollapsed">Add Interface&nbsp;&nbsp;<i class="ace-icon fa fa-plus" ng-class="{'fa-minus': !addInterface.isCollapsed}"></i> <button class="btn btn-sm btn-info" ng-init="addInterfacePanel.isCollapsed = true;" ng-click="addInterfacePanel.isCollapsed = !addInterfacePanel.isCollapsed">
Add Interface&nbsp;&nbsp;
<i class="ace-icon fa fa-plus" ng-class="{'fa-minus': !addInterfacePanel.isCollapsed}"></i>
</button> </button>
<button class="btn btn-sm btn-info" ng-init="autoFill.isCollapsed = true;" ng-click="autoFill.isCollapsed = !autoFill.isCollapsed"> <button class="btn btn-sm btn-info" ng-init="autoFillPanel.isCollapsed = true;" ng-click="autoFillPanel.isCollapsed = !autoFillPanel.isCollapsed">
Autofill&nbsp;&nbsp;<i class="ace-icon fa fa-plus" ng-class="{'fa-minus': !autoFill.isCollapsed}"></i> Autofill&nbsp;&nbsp;<i class="ace-icon fa fa-plus" ng-class="{'fa-minus': !autoFillPanel.isCollapsed}"></i>
</button> </button>
</div> </div>
</div> </div>
<div class="row"> <div class="row">
<div collapse="addInterface.isCollapsed"> <div collapse="addInterfacePanel.isCollapsed">
<div class="well well-lg"> <div class="widget-box">
<div class="row"> <div class="widget-body">
<div class="col-xs-12"> <div class="widget-main">
<table class="table table-hover nowrap"> <div class="row">
<thead> <div class="col-lg-2"></div>
<tr> <div class="col-lg-8">
<th>Interface</th> <table class="table table-hover nowrap">
<th>Subnet</th> <thead>
<th>Is Mgmt Network</th> <tr>
<th>Action</th> <th>Interface</th>
</tr> <th>Subnet</th>
</thead> <th>Is Mgmt Network</th>
<tbody ng-init="network={};"> <th>Action</th>
<tr> </tr>
<td> </thead>
<input type="text" ng-model="newInterface.name" placeholder="Interface" required /> <tbody ng-init="network={};">
</td> <tr>
<td> <td>
<select ng-model="newInterface.subnet_id" class="max-width-200"> <input type="text" ng-model="newInterface.name" placeholder="Interface" required />
<option ng-repeat="sub in subnetworks" value="{{sub.subnet_id}}"> </td>
{{sub.name}} <td>
</option> <select ng-model="newInterface.subnet_id" class="max-width-200">
</select> <option ng-repeat="sub in subnetworks" value="{{sub.subnet_id}}">
</td> {{sub.name}}
<td>-</td> </option>
<td> </select>
<button type="button" class="btn btn-sm btn-info" ng-click="addInterface(newInterface)"> </td>
Add <td>-</td>
</button> <td>
</td> <button type="button" class="btn btn-sm btn-info" ng-click="addInterface(newInterface)">
</tr> Add
<tr ng-repeat="(name, value) in interfaces"> </button>
<td> </td>
{{name}} </tr>
</td> <tr ng-repeat="(name, value) in interfaces">
<td> <td>
<span ng-repeat="sub in subnetworks"> {{name}}
<span ng-if="sub.subnet_id == value.subnet_id">{{sub.name}}</span> </td>
</span> <td>
</td> <span ng-repeat="sub in subnetworks">
<td> <span ng-if="sub.subnet_id == value.subnet_id">{{sub.name}}</span>
<input ng-model="value.is_mgmt" type="checkbox" name="is-mgmt" /> </span>
</td> </td>
<td> <td>
<!--Remove Action--> <input ng-model="value.is_mgmt" type="checkbox" name="is-mgmt" />
<button class="btn btn-xs btn-danger" ng-click="deleteInterface(name)"><i class="fa fa-trash-o bigger-120"></i> </td>
</button> <td>
</td> <!--Remove Action-->
</tr> <button class="btn btn-xs btn-danger" ng-click="deleteInterface(name)"><i class="fa fa-trash-o bigger-120"></i>
</tbody> </button>
</table> </td>
</tr>
</tbody>
</table>
</div>
<div class="col-lg-2"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> <div collapse="autoFillPanel.isCollapsed">
<div class="row"> <div class="widget-box">
<div collapse="autoFill.isCollapsed"> <div class="widget-body">
<div class="well well-lg"> <div class="widget-main">
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-lg-2"></div>
Autofill Panel <div class="col-lg-8">
<form role="form" class="form-horizontal ng-pristine ng-valid" id="autoForm">
<div class="form-group">
<div>
<label class="col-sm-3 control-label no-padding-right">
Hostname
</label>
<div class="col-sm-9">
<select class="col-xs-10 col-sm-5 ng-pristine ng-valid">
<option value="host">Host</option>
<option value="switch_ip">Switch IP</option>
<option value="switch_alias">Switch Alias</option>
</select>
</div>
</div>
</div>
<div ng-repeat="(name, value) in interfaces" class="form-group">
<label class="col-sm-3 control-label no-padding-right">
{{name}}&nbsp;IP
</label>
<div class="col-sm-9">
<input type="text" placeholder="IP Start">
<select>
<option value="1">Increase by 1</option>
<option value="2">Increase by 2</option>
<option value="3">Increase by 3</option>
<option value="4">Increase by 4</option>
<option value="5">Increase by 5</option>
</select>
</div>
</div>
<div class="col-sm-offset-4">
<button ng-click="autofill()" class="btn btn-sm btn-primary">
Fill Values
</button>
</div>
</form>
</div>
<div class="col-lg-2"></div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -122,10 +170,10 @@
<tbody> <tbody>
<tr ng-repeat="server in $data | filter: search" ng-init="serverIndex = $index"> <tr ng-repeat="server in $data | filter: search" ng-init="serverIndex = $index">
<td ng-repeat="column in server_columns" ng-show="column.visible" sortable="column.field"> <td ng-repeat="column in server_columns" ng-show="column.visible" sortable="column.field">
<span ng-if="column.field=='hostname'"> <span ng-if="column.field=='name'">
<input ng-model="server[column.field]" placeholder="Hostname" class="form-control margin-bottom-10 max-width-200" type="text"> <input ng-model="server[column.field]" placeholder="Hostname" class="form-control margin-bottom-10 max-width-200" type="text">
</span> </span>
<span ng-if="column.field!='hostname'"> <span ng-if="column.field!='name'">
{{server[column.field]}} {{server[column.field]}}
</span> </span>

View File

@ -1,64 +1,45 @@
<div ng-controller="networkCtrl"> <div ng-controller="networkMappingCtrl">
<div class="row"> <div class="row">
<div class="pull-left"> <div class="col-sm-6">
<span class="input-icon"> <div class="widget-box transparent margin-top-minus10">
<input type="text" placeholder="Search" ng-model="search"> <div class="widget-header">
<i class="ace-icon fa fa-search blue"></i> <h4>Interfaces</h4>
</span> </div>
</div> <div class="widget-body">
<div class="pull-right"> <div class="widget-main">
<div ng-repeat="(interface_key, interface_value) in interfaces">
{{interface_key}}
<div ui-on-Drop="onDrop($event, interface_key)" drag-hover-class="drag-enter" class="interface-placeholder">
</div> <div ng-repeat="(network_key, network_value) in networking" ui-draggable="true" on-drop-success="dropSuccessHandler($event, network_key, networking)" class="external-event label-purple ui-draggable network-draggable" ng-if="network_value.mapping_interface==interface_key">
</div> <i class="ace-icon fa fa-arrows"></i>
{{network_value.display}}
</div>
</div>
<div class="row">{{servers}} </div>
<table class="table table-hover table-striped"> </div>
<thead> </div>
<tr> </div>
<th> </div>
<input type="checkbox">
</th> <div class="col-sm-6">
<th>Host MAC</th> <div class="widget-box transparent margin-top-minus10">
<th>Switch IP</th> <div class="widget-header">
<th>Port</th> <h4>Networks</h4>
<th>Hostname</th> </div>
<th>Management Network</th>
<th>Tenant Network</th> <div class="widget-body">
<th>Storage Network</th> <div class="widget-main">
<th>Public Network</th> <div ui-on-Drop="onDrop($event, '')" drag-hover-class="drag-enter" class="network-placeholder">
</tr> <div ng-repeat="(key, value) in networking" ui-draggable="true" on-drop-success="dropSuccessHandler($event, key, networking)" class="external-event label-purple ui-draggable network-draggable" ng-if="!value.mapping_interface">
</thead> <i class="ace-icon fa fa-arrows"></i>
<tbody> {{value.display}}
<tr ng-repeat="server in servers | filter:search"> </div>
<td> </div>
<input ng-model="server.checked" type="checkbox"> </div>
</td> </div>
<td>{{server["mac"]}}</td> </div>
<td>{{server["switch_ip"]}}</td> </div>
<td>{{server["port"]}}</td>
<td>{{server["hostname"]}}</td>
<td>
<select ng-model="server.management">
<option ng-repeat="interface in interfaces" value="{{interface}}">{{interface}}</option>
</select>
</td>
<td>
<select ng-model="server.tenant">
<option ng-repeat="interface in interfaces" value="{{interface}}">{{interface}}</option>
</select>
</td>
<td>
<select ng-model="server.storage">
<option ng-repeat="interface in interfaces" value="{{interface}}">{{interface}}</option>
</select>
</td>
<td>
<select ng-model="server.public">
<option ng-repeat="interface in interfaces" value="{{interface}}">{{interface}}</option>
</select>
</td>
</tr>
</tbody>
</table>
</div> </div>
</div> </div>

View File

@ -1,10 +1,28 @@
<div ng-controller="roleAssignCtrl"> <div ng-controller="roleAssignCtrl">
<div class="row"> <div class="row">
<div class="pull-left"> <div class="pull-left">
<!--Search Input-->
<span class="input-icon"> <span class="input-icon">
<input type="text" placeholder="Search" ng-model="search"> <input type="text" placeholder="Search" ng-model="search.$">
<i class="ace-icon fa fa-search blue"></i> <i class="ace-icon fa fa-search blue"></i>
</span> </span>
<!-- Column Show / Hide button -->
<div class="btn-group" dropdown>
<button type="button" class="btn btn-white btn-default dropdown-toggle">
Column Show / Hide
<span class="ace-icon fa fa-caret-down icon-on-right"></span>
</button>
<ul class="dropdown-menu" role="menu">
<li ng-repeat="column in server_columns" ng-click="column.visible=!column.visible">
<a class="action">
<span ng-class="{'opacity-zero': !column.visible}">
<i class="ace-icon fa fa-check blue"></i>
</span>
{{column.title}}
</a>
</li>
</ul>
</div>
</div> </div>
<div class="pull-right"> <div class="pull-right">
<div class="btn-group" dropdown> <div class="btn-group" dropdown>
@ -14,7 +32,9 @@
</button> </button>
<ul class="dropdown-menu dropdown-info dropdown-menu-right" role="menu"> <ul class="dropdown-menu dropdown-info dropdown-menu-right" role="menu">
<li ng-repeat="role in roles"> <li ng-repeat="role in roles">
<a href value="{{role.name}}" ng-click="assignRole(role)">{{role.display_name}}</a> <a class="action" ng-click="assignRole(role)">
{{role.display_name}}
</a>
</li> </li>
</ul> </ul>
@ -23,29 +43,29 @@
</div> </div>
<div class="row"> <div class="row">
<table class="table table-hover table-striped"> <table ng-table="tableParams" class="table table-hover table-striped">
<thead> <thead>
<tr> <tr>
<th> <th>
<input type="checkbox"> <input type="checkbox" ng-model="selectall" ng-change="selectAllServers(selectall)">
</th>
<th ng-repeat="column in server_columns" ng-show="column.visible" class="sortable"
ng-class="{'sort-asc': tableParams.isSortBy(column.field, 'asc'),
'sort-desc': tableParams.isSortBy(column.field, 'desc')}"
ng-click="tableParams.sorting(column.field, tableParams.isSortBy(column.field, 'asc') ? 'desc' : 'asc')">
{{column.title}}
</th> </th>
<th>Host MAC</th>
<th>Switch IP</th>
<th>Port</th>
<th>Hostname</th>
<th>Roles</th> <th>Roles</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr ng-repeat="server in servers | filter:search"> <tr ng-repeat="server in $data | filter: search">
<td> <td>
<input ng-model="server.checked" type="checkbox"> <input ng-model="server.checked" type="checkbox">
</td> </td>
<td>{{server["mac"]}}</td> <td ng-repeat="column in server_columns" ng-show="column.visible" sortable="column.field">
<td>{{server["switch_ip"]}}</td> {{server[column.field]}}
<td>{{server["port"]}}</td> </td>
<td>{{server["hostname"]}}</td>
<td> <td>
<alert ng-repeat="role in server['roles']" class="role-tag" close="removeRole(server, role)"> <alert ng-repeat="role in server['roles']" class="role-tag" close="removeRole(server, role)">
{{role.display_name}} {{role.display_name}}

View File

@ -14,19 +14,19 @@
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label no-padding-right">Username</label> <label class="col-sm-4 control-label no-padding-right">Username</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" class="col-xs-10 col-sm-5" placeholder="Username" id="server-username"> <input type="text" class="col-xs-10 col-sm-5" placeholder="Username" id="server-username" ng-model="server_credentials.username">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="col-sm-4 control-label no-padding-right">Password</label> <label class="col-sm-4 control-label no-padding-right">Password</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" class="col-xs-10 col-sm-5" placeholder="Password" id="server-password"> <input type="password" class="col-xs-10 col-sm-5" placeholder="Password" id="server-password" ng-model="server_credentials.password">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="{{key}}" class="col-sm-4 control-label no-padding-right">Confirm Password</label> <label class="col-sm-4 control-label no-padding-right">Confirm Password</label>
<div class="col-sm-8"> <div class="col-sm-8">
<input type="text" class="col-xs-10 col-sm-5" placeholder="Confirm Password" id="{{key}}"> <input type="password" class="col-xs-10 col-sm-5" placeholder="Confirm Password" value="{{server_credentials.password}}">
</div> </div>
</div> </div>
</form> </form>
@ -36,12 +36,12 @@
<accordion-group is-open="status2.open"> <accordion-group is-open="status2.open">
<accordion-heading> <accordion-heading>
<i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status2.open, 'fa-angle-right': !status2.open}"></i> OpenStack Services Credentials <i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status2.open, 'fa-angle-right': !status2.open}"></i> OpenStack Database & Queue Credentials
</accordion-heading> </accordion-heading>
<div class="row"> <div class="row">
<div class="col-lg-2"> <div class="col-lg-1">
</div> </div>
<div class="col-lg-8"> <div class="col-lg-10">
<table class="table table-hover nowrap"> <table class="table table-hover nowrap">
<thead> <thead>
<tr> <tr>
@ -83,17 +83,19 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="col-lg-2"> <div class="col-lg-1">
</div> </div>
</div> </div>
</accordion-group> </accordion-group>
<accordion-group is-open="status.open"> <accordion-group is-open="status.open">
<accordion-heading> <accordion-heading>
<i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status.open, 'fa-angle-right': !status.open}"></i> OpenStack Management Console Credentials <i class="ace-icon fa fa-angle-right" ng-class="{'fa-angle-down': status.open, 'fa-angle-right': !status.open}"></i> OpenStack Keystone User Credentials
</accordion-heading> </accordion-heading>
<div class="row"> <div class="row">
<div class="col-xs-12"> <div class="col-lg-1">
</div>
<div class="col-lg-10">
<table class="table table-hover nowrap"> <table class="table table-hover nowrap">
<thead> <thead>
<tr> <tr>
@ -136,6 +138,8 @@
</tbody> </tbody>
</table> </table>
</div> </div>
<div class="col-lg-1">
</div>
</div> </div>
</accordion-group> </accordion-group>

View File

@ -2,7 +2,8 @@ angular.module('compass.wizard', [
'ui.router', 'ui.router',
'ui.bootstrap', 'ui.bootstrap',
'ngTable', 'ngTable',
'compass.charts' 'compass.charts',
'ngDragDrop'
]) ])
.config(function config($stateProvider) { .config(function config($stateProvider) {
@ -15,14 +16,12 @@ angular.module('compass.wizard', [
}) })
.controller('wizardCtrl', function($scope, dataService, wizardFactory, $stateParams) { .controller('wizardCtrl', function($scope, dataService, wizardFactory, $stateParams) {
if($stateParams.config == "true") { if ($stateParams.config == "true") {
dataService.getWizardPreConfig().success(function(data) { dataService.getWizardPreConfig().success(function(data) {
wizardFactory.preConfig(data); wizardFactory.preConfig(data);
}); });
} }
$scope.clusterInfo = wizardFactory.getClusterInfo();
// current step for create-cluster wizard // current step for create-cluster wizard
$scope.currentStep = 1; $scope.currentStep = 1;
@ -61,8 +60,6 @@ angular.module('compass.wizard', [
$scope.$watch(function() { $scope.$watch(function() {
return wizardFactory.getCommitState() return wizardFactory.getCommitState()
}, function(newCommitState, oldCommitState) { }, function(newCommitState, oldCommitState) {
switch (newCommitState.name) { switch (newCommitState.name) {
case "sv_selection": case "sv_selection":
case "os_global": case "os_global":
@ -72,10 +69,11 @@ angular.module('compass.wizard', [
case "role_assign": case "role_assign":
case "network_mapping": case "network_mapping":
if (newCommitState.name == $scope.steps[$scope.currentStep - 1].name && newCommitState.state == "success") { if (newCommitState.name == $scope.steps[$scope.currentStep - 1].name && newCommitState.state == "success") {
console.info("### catch success in wizardCtrl ###", newCommitState, oldCommitState); console.warn("### catch success in wizardCtrl ###", newCommitState, oldCommitState);
$scope.next(); $scope.next();
} else if (newCommitState.state == "error") { } else if (newCommitState.state == "error") {
// TODO: error handling / display error message // TODO: error handling / display error message
console.warn("### catch error in wizardCtrl ###", newCommitState, oldCommitState);
} }
break; break;
case "review": case "review":
@ -105,11 +103,14 @@ angular.module('compass.wizard', [
}; };
}); });
dataService.getAllMachineHosts().success(function(data) { dataService.getAllMachineHosts().success(function(data) {
wizardFactory.setAllMachinesHost(data); wizardFactory.setAllMachinesHost(data);
}); });
dataService.getSubnetConfig().success(function(data) {
wizardFactory.setSubnetworks(data);
});
}) })
.controller('svSelectCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams) { .controller('svSelectCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams) {
@ -193,22 +194,34 @@ angular.module('compass.wizard', [
}; };
}) })
.controller('globalCtrl', function($scope, wizardFactory, dataService) { .controller('globalCtrl', function($scope, wizardFactory, dataService, $q) {
var cluster = wizardFactory.getClusterInfo(); var cluster = wizardFactory.getClusterInfo();
//For General Section //For General Section
$scope.general = wizardFactory.getGeneralConfig(); $scope.general = wizardFactory.getGeneralConfig();
//TODO: bug - should not set dns_servers and search_path to empty if (!$scope.general["dns_servers"]) {
$scope.general["dns_servers"] = [""]; $scope.general["dns_servers"] = [""];
$scope.general["search_path"] = [""]; }
if (!$scope.general["search_path"]) {
$scope.general["search_path"] = [""];
}
if (!$scope.general["http_proxy"]) {
$scope.general["http_proxy"] = [""];
}
if (!$scope.general["https_proxy"]) {
$scope.general["https_proxy"] = [""];
}
if (!$scope.general["default_no_proxy"]) {
$scope.general["default_no_proxy"] = [""];
}
$scope.addDNSServer = function() { $scope.addValue = function(key) {
$scope.general['dns_servers'].push(""); $scope.general[key].push("");
}; console.log($scope.general);
$scope.addSearchPath = function() { console.log($scope.general.http_proxy.length)
$scope.general['search_path'].push("");
}; };
dataService.getTimezones().success(function(data) { dataService.getTimezones().success(function(data) {
$scope.timezones = data; $scope.timezones = data;
}); });
@ -229,6 +242,8 @@ angular.module('compass.wizard', [
}, true); }, true);
//For Routing Table Section //For Routing Table Section
//keep routing table for later use
/*
$scope.routingtable = wizardFactory.getRoutingTable(); $scope.routingtable = wizardFactory.getRoutingTable();
$scope.addRoute = function() { $scope.addRoute = function() {
$scope.routingtable.push({}); $scope.routingtable.push({});
@ -242,6 +257,7 @@ angular.module('compass.wizard', [
$scope.routingtable.push({}); $scope.routingtable.push({});
} }
}, true); }, true);
*/
$scope.$watch(function() { $scope.$watch(function() {
return wizardFactory.getCommitState() return wizardFactory.getCommitState()
@ -255,63 +271,62 @@ angular.module('compass.wizard', [
}); });
$scope.commit = function() { $scope.commit = function() {
$scope.updateClusterConfig(); var promises = [];
$scope.updateSubnet();
$scope.updateRoutingTable();
console.info("$$$$ ", wizardFactory.getSubnetworks(), wizardFactory.getRoutingTable(), wizardFactory.getGeneralConfig())
//TODO: should have check here to see if each part is updated successfully
var commitState = {
"name": "os_global",
"state": "success",
"message": ""
};
wizardFactory.setCommitState(commitState);
};
$scope.updateClusterConfig = function() {
var os_global_general = { var os_global_general = {
"os_config": { "os_config": {
"general": $scope.general "general": $scope.general
} }
}; };
// put cluster config var updateClusterConfig = dataService.updateClusterConfig(cluster.id, os_global_general).then(function(configData) {
dataService.updateClusterConfig(cluster.id, os_global_general).success(function(configData) { wizardFactory.setGeneralConfig(configData.data["os_config"]["general"]);
wizardFactory.setGeneralConfig(configData["os_config"]["general"]); }, function(response) {
return $q.reject(response);
});
promises.push(updateClusterConfig);
var subnetworks = [];
angular.forEach($scope.subnetworks, function(subnet) {
if (subnet.subnet_id === undefined) {
// post subnetworks
var updateSubnetConfig = dataService.postSubnetConfig(subnet).then(function(subnetData) {
subnetworks.push(subnetData.data);
}, function(response) {
return $q.reject(response);
});
promises.push(updateSubnetConfig);
} else {
// put subnetworks
var updateSubnetConfig = dataService.putSubnetConfig(subnet.subnet_id, subnet).then(function(subnetData) {
subnetworks.push(subnetData.data);
}, function(response) {
return $q.reject(response);
});
promises.push(updateSubnetConfig);
}
});
$q.all(promises).then(function() {
$scope.subnetworks = subnetworks;
wizardFactory.setSubnetworks($scope.subnetworks);
var commitState = {
"name": "os_global",
"state": "success",
"message": ""
};
wizardFactory.setCommitState(commitState);
}, function(response) {
console.log("promises error", response);
var commitState = {
"name": "os_global",
"state": "error",
"message": response.statusText
};
wizardFactory.setCommitState(commitState);
}); });
}; };
$scope.updateSubnet = function() { // keey routing table for later use
var subnetCount = $scope.subnetworks.length; /*
var subnetworks = [];
var i = 0;
angular.forEach($scope.subnetworks, function(subnet) {
if (subnet.subnet_id === undefined) {
// post cluster subnet-config
dataService.postClusterSubnetConfig(cluster.id, subnet).success(function(subnetData) {
subnetworks.push(subnetData);
i++;
if (i == subnetCount) {
$scope.subnetworks = subnetworks;
wizardFactory.setSubnetworks($scope.subnetworks);
}
})
} else {
// put cluster subnet-config
dataService.putClusterSubnetConfig(cluster.id, subnet.subnet_id, subnet).success(function(subnetData) {
subnetworks.push(subnetData);
i++;
if (i == subnetCount) {
$scope.subnetworks = subnetworks;
wizardFactory.setSubnetworks($scope.subnetworks);
}
})
}
})
};
$scope.updateRoutingTable = function() { $scope.updateRoutingTable = function() {
var routingCount = $scope.routingtable.length; var routingCount = $scope.routingtable.length;
var routingTable = []; var routingTable = [];
@ -340,9 +355,10 @@ angular.module('compass.wizard', [
} }
}) })
}; };
*/
}) })
.controller('networkCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams) { .controller('networkCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, $q) {
var cluster = wizardFactory.getClusterInfo(); var cluster = wizardFactory.getClusterInfo();
$scope.subnetworks = wizardFactory.getSubnetworks(); $scope.subnetworks = wizardFactory.getSubnetworks();
$scope.interfaces = wizardFactory.getInterfaces(); $scope.interfaces = wizardFactory.getInterfaces();
@ -391,27 +407,29 @@ angular.module('compass.wizard', [
}) })
}; };
$scope.initHostIpByInterface = function(interfaceName) { $scope.$watch('addInterfacePanel', function(value) {
if ($scope.servers.network[interfaceName] === undefinded) { if (!$scope.addInterfacePanel.isCollapsed) {
$scope.servers.network[interfaceName] = {}; $scope.autoFillPanel.isCollapsed = true;
} }
}; }, true);
$scope.$watch('autoFillPanel', function(value) {
if (!$scope.autoFillPanel.isCollapsed) {
$scope.addInterfacePanel.isCollapsed = true;
}
}, true);
$scope.$watch(function() { $scope.$watch(function() {
return wizardFactory.getCommitState() return wizardFactory.getCommitState()
}, function(newCommitState, oldCommitState) { }, function(newCommitState, oldCommitState) {
console.info("### catch commit change in networkCtrl ###", newCommitState);
if (newCommitState !== undefined) { if (newCommitState !== undefined) {
if (newCommitState.name == "network" && newCommitState.state == "triggered") { if (newCommitState.name == "network" && newCommitState.state == "triggered") {
$scope.commitNetwork(); $scope.commit();
} else if (newCommitState.name == "network_mapping" && newCommitState.state == "triggered") {
$scope.commitNetworkMapping();
} }
} }
}); });
$scope.commitNetwork = function() { $scope.commit = function() {
var addHostsAction = { var addHostsAction = {
"add_hosts": { "add_hosts": {
"machines": [] "machines": []
@ -445,13 +463,23 @@ angular.module('compass.wizard', [
} }
} }
} }
wizardFactory.setServers($scope.servers);
$scope.serverCount = $scope.servers.length; var hostnamePromises = [];
var i = 0; var hostNetworkPromises = [];
// post host network
angular.forEach($scope.servers, function(server) { angular.forEach($scope.servers, function(server) {
$scope.networkCount = Object.keys(server.network).length; var hostname = {
"name": server["name"]
};
// update hostname
var updateHostname = dataService.putHost(server.host_id, hostname).then(function(hostData) {
// success callback
}, function(response) {
// error callback
return $q.reject(response);
});
hostnamePromises.push(updateHostname);
angular.forEach(server.network, function(value, key) { angular.forEach(server.network, function(value, key) {
var network = { var network = {
"interface": key, "interface": key,
@ -459,39 +487,58 @@ angular.module('compass.wizard', [
"subnet_id": $scope.interfaces[key].subnet_id, "subnet_id": $scope.interfaces[key].subnet_id,
"is_mgmt": $scope.interfaces[key].is_mgmt "is_mgmt": $scope.interfaces[key].is_mgmt
}; };
if (value.id === undefined) {
// post host network
var updateNetwork = dataService.postHostNetwork(server.host_id, network).then(function(networkData) {
// success callback
console.log("post networkdata", networkData.data);
var interface = networkData.data.interface;
var networkId = networkData.data.id;
server.network[interface].id = networkId;
}, function(response) {
// error callback
return $q.reject(response);
});
hostNetworkPromises.push(updateNetwork);
} else {
// put host network
var updateNetwork = dataService.putHostNetwork(server.host_id, value.id, network).then(function(networkData) {
// success callback
console.log("put networkdata", networkData.data);
}, function(response) {
// error callback
return $q.reject(response);
});
hostNetworkPromises.push(updateNetwork);
}
});
});
dataService.postHostNetwork(server.host_id, network).success(function(data) { $q.all(hostnamePromises.concat(hostNetworkPromises)).then(function() {
i++; // update hostname and network for all hosts successfully
if (i == $scope.serverCount * $scope.networkCount) { wizardFactory.setServers($scope.servers);
wizardFactory.setInterfaces($scope.interfaces); var commitState = {
wizardFactory.setServers($scope.servers); "name": "network",
var commitState = { "state": "success",
"name": "network", "message": ""
"state": "success", };
"message": "" wizardFactory.setCommitState(commitState);
}; }, function(response) {
wizardFactory.setCommitState(commitState); var commitState = {
} "name": "network",
}); "state": "error",
}) "message": response.statusText
};
wizardFactory.setCommitState(commitState);
}); });
}); });
} }
}; };
$scope.commitNetworkMapping = function() {
var commitState = {
"name": "network_mapping",
"state": "success",
"message": ""
};
wizardFactory.setCommitState(commitState);
};
$scope.autofill = function() { $scope.autofill = function() {
//TODO: add auto fill //TODO: add auto fill
alert("Autofill coming soon"); alert("Autofill coming soon");
} };
}) })
.controller('partitionCtrl', function($scope, wizardFactory, dataService) { .controller('partitionCtrl', function($scope, wizardFactory, dataService) {
@ -511,7 +558,6 @@ angular.module('compass.wizard', [
}; };
$scope.$watch('partition', function() { $scope.$watch('partition', function() {
console.log("changed")
$scope.partitionarray = []; $scope.partitionarray = [];
angular.forEach($scope.partition, function(value, key) { angular.forEach($scope.partition, function(value, key) {
$scope.partitionarray.push({ $scope.partitionarray.push({
@ -524,7 +570,6 @@ angular.module('compass.wizard', [
$scope.$watch(function() { $scope.$watch(function() {
return wizardFactory.getCommitState() return wizardFactory.getCommitState()
}, function(newCommitState, oldCommitState) { }, function(newCommitState, oldCommitState) {
console.info("### catch commit change in partitionCtrl ###", newCommitState);
if (newCommitState !== undefined) { if (newCommitState !== undefined) {
if (newCommitState.name == "partition" && newCommitState.state == "triggered") { if (newCommitState.name == "partition" && newCommitState.state == "triggered") {
$scope.commit(); $scope.commit();
@ -553,13 +598,13 @@ angular.module('compass.wizard', [
.controller('securityCtrl', function($scope, wizardFactory, dataService) { .controller('securityCtrl', function($scope, wizardFactory, dataService) {
var cluster = wizardFactory.getClusterInfo(); var cluster = wizardFactory.getClusterInfo();
$scope.server_credentials = wizardFactory.getServerCredentials();
$scope.service_credentials = wizardFactory.getServiceCredentials(); $scope.service_credentials = wizardFactory.getServiceCredentials();
$scope.management_credentials = wizardFactory.getManagementCredentials(); $scope.management_credentials = wizardFactory.getManagementCredentials();
$scope.$watch(function() { $scope.$watch(function() {
return wizardFactory.getCommitState() return wizardFactory.getCommitState()
}, function(newCommitState, oldCommitState) { }, function(newCommitState, oldCommitState) {
console.info("### catch commit change in securityCtrl ###", newCommitState);
if (newCommitState !== undefined) { if (newCommitState !== undefined) {
if (newCommitState.name == "security" && newCommitState.state == "triggered") { if (newCommitState.name == "security" && newCommitState.state == "triggered") {
$scope.commit(); $scope.commit();
@ -568,8 +613,19 @@ angular.module('compass.wizard', [
}); });
$scope.commit = function() { $scope.commit = function() {
var partitionData = {}; var securityData = {
dataService.updateClusterConfig(cluster.id, partitionData).success(function(data) { "os_config": {
"username": $scope.server_credentials.username,
"password": $scope.server_credentials.password
},
"package_config": {
"security": {
"service_credentials": $scope.service_credentials,
"console_crendentials": $scope.management_credentials
}
}
};
dataService.updateClusterConfig(cluster.id, securityData).success(function(data) {
var commitState = { var commitState = {
"name": "security", "name": "security",
"state": "success", "state": "success",
@ -580,11 +636,30 @@ angular.module('compass.wizard', [
}; };
}) })
.controller('roleAssignCtrl', function($scope, wizardFactory, dataService) { .controller('roleAssignCtrl', function($scope, wizardFactory, dataService, $filter, ngTableParams, $q) {
var cluster = wizardFactory.getClusterInfo(); var cluster = wizardFactory.getClusterInfo();
$scope.servers = wizardFactory.getServers(); $scope.servers = wizardFactory.getServers();
$scope.roles = wizardFactory.getAdapter().roles; dataService.getAdapter(cluster.adapter_id).success(function(data) {
wizardFactory.setAdapter(data);
$scope.roles = data.roles;
});
dataService.getServerColumns().success(function(data) {
$scope.server_columns = data.showless;
});
$scope.selectAllServers = function(flag) {
if (flag) {
angular.forEach($scope.servers, function(sv) {
sv.checked = true;
})
} else {
angular.forEach($scope.servers, function(sv) {
sv.checked = false;
})
}
};
$scope.removeRole = function(server, role) { $scope.removeRole = function(server, role) {
var serverIndex = $scope.servers.indexOf(server); var serverIndex = $scope.servers.indexOf(server);
@ -593,28 +668,52 @@ angular.module('compass.wizard', [
}; };
$scope.assignRole = function(role) { $scope.assignRole = function(role) {
// get selected servers and assign role to them var serverChecked = false;
var roleExist = false;
for (var i = 0; i < $scope.servers.length; i++) { for (var i = 0; i < $scope.servers.length; i++) {
if ($scope.servers[i].checked) { if ($scope.servers[i].checked) {
for (var j = 0; j < $scope.servers[i].roles.length; j++) { serverChecked = true;
if (role.name == $scope.servers[i].roles[j].name) { }
roleExist = true; }
if (!serverChecked) {
alert("Please select at least one server");
} else {
// get selected servers and assign role to them
var roleExist = false;
for (var i = 0; i < $scope.servers.length; i++) {
if ($scope.servers[i].checked) {
for (var j = 0; j < $scope.servers[i].roles.length; j++) {
if (role.name == $scope.servers[i].roles[j].name) {
roleExist = true;
}
}
if (!roleExist) {
$scope.servers[i].roles.push(role);
} else {
roleExist = false;
} }
} }
} }
if (!roleExist) {
$scope.servers[i].roles.push(role);
} else {
roleExist = false;
}
} }
}; };
$scope.tableParams = new ngTableParams({
page: 1, // show first page
count: $scope.servers.length + 1 // count per page
}, {
counts: [], // hide count-per-page box
total: $scope.servers.length, // length of data
getData: function($defer, params) {
// use build-in angular filter
var orderedData = params.sorting() ?
$filter('orderBy')($scope.servers, params.orderBy()) : $scope.servers;
$defer.resolve(orderedData.slice((params.page() - 1) * params.count(), params.page() * params.count()));
}
});
$scope.$watch(function() { $scope.$watch(function() {
return wizardFactory.getCommitState() return wizardFactory.getCommitState()
}, function(newCommitState, oldCommitState) { }, function(newCommitState, oldCommitState) {
console.info("### catch commit change in networkCtrl ###", newCommitState);
if (newCommitState !== undefined) { if (newCommitState !== undefined) {
if (newCommitState.name == "role_assign" && newCommitState.state == "triggered") { if (newCommitState.name == "role_assign" && newCommitState.state == "triggered") {
$scope.commit(); $scope.commit();
@ -623,11 +722,90 @@ angular.module('compass.wizard', [
}); });
$scope.commit = function() { $scope.commit = function() {
var commitState = { var promises = [];
"name": "role_assign", angular.forEach($scope.servers, function(server) {
"state": "success", var roles = [];
"message": "" angular.forEach(server.roles, function(role) {
}; roles.push(role.name);
wizardFactory.setCommitState(commitState); });
var config = {
"package_config": {
"roles": roles
}
};
var updateRoles = dataService.updateClusterHostConfig(cluster.id, server.host_id, config).then(function(configData) {
// success callback
}, function(response) {
// error callback
return $q.reject(response);
});
});
$q.all(promises).then(function() {
wizardFactory.setServers($scope.servers);
var commitState = {
"name": "role_assign",
"state": "success",
"message": ""
};
wizardFactory.setCommitState(commitState);
}, function(response) {
console.log("promises error", response);
var commitState = {
"name": "role_assign",
"state": "error",
"message": response.statusText
};
wizardFactory.setCommitState(commitState);
});
}; };
}) })
.controller('networkMappingCtrl', function($scope, wizardFactory, dataService) {
var cluster = wizardFactory.getClusterInfo();
$scope.interfaces = wizardFactory.getInterfaces();
$scope.networking = wizardFactory.getNetworkMapping();
$scope.pendingInterface = "";
$scope.onDrop = function($event, key) {
$scope.pendingInterface = key;
};
$scope.dropSuccessHandler = function($event, key, dict) {
dict[key].mapping_interface = $scope.pendingInterface;
};
$scope.$watch(function() {
return wizardFactory.getCommitState()
}, function(newCommitState, oldCommitState) {
if (newCommitState !== undefined) {
if (newCommitState.name == "network_mapping" && newCommitState.state == "triggered") {
$scope.commit();
}
}
});
$scope.commit = function() {
var networks = {};
angular.forEach($scope.networking, function(value, key) {
networks[key] = value.mapping_interface;
});
var network_mapping = {
"package_config": {
"network_mapping": networks
}
};
dataService.updateClusterConfig(cluster.id, network_mapping).success(function(data) {
wizardFactory.setNetworkMapping($scope.networking);
var commitState = {
"name": "network_mapping",
"state": "success",
"message": ""
};
wizardFactory.setCommitState(commitState);
});
//TODO: error handling
};
})

View File

@ -0,0 +1,201 @@
/**
* Created with IntelliJ IDEA.
* User: Ganaraj.Pr
* Date: 11/10/13
* Time: 11:27
* To change this template use File | Settings | File Templates.
*/
if (window.jQuery && (-1 == window.jQuery.event.props.indexOf("dataTransfer"))) {
window.jQuery.event.props.push("dataTransfer");
}
angular.module("ngDragDrop",[])
.directive("uiDraggable", [
'$parse',
'$rootScope',
function ($parse, $rootScope) {
return function (scope, element, attrs) {
var dragData = "",
isDragHandleUsed = false,
dragHandleClass,
dragHandles,
dragTarget;
element.attr("draggable", false);
attrs.$observe("uiDraggable", function (newValue) {
element.attr("draggable", newValue);
});
if (attrs.drag) {
scope.$watch(attrs.drag, function (newValue) {
dragData = newValue || "";
});
}
if (angular.isString(attrs.dragHandleClass)) {
isDragHandleUsed = true;
dragHandleClass = attrs.dragHandleClass.trim() || "drag-handle";
dragHandles = element.find('.' + dragHandleClass).toArray();
element.bind("mousedown", function (e) {
dragTarget = e.target;
});
}
element.bind("dragstart", function (e) {
var isDragAllowed = !isDragHandleUsed || -1 != dragHandles.indexOf(dragTarget);
if (isDragAllowed) {
var sendData = angular.toJson(dragData);
var sendChannel = attrs.dragChannel || "defaultchannel";
var dragImage = attrs.dragImage || null;
if (dragImage) {
var dragImageFn = $parse(attrs.dragImage);
scope.$apply(function() {
var dragImageParameters = dragImageFn(scope, {$event: e});
if (dragImageParameters && dragImageParameters.image) {
var xOffset = dragImageParameters.xOffset || 0,
yOffset = dragImageParameters.yOffset || 0;
e.dataTransfer.setDragImage(dragImageParameters.image, xOffset, yOffset);
}
});
}
e.dataTransfer.setData("text/plain", sendData);
e.dataTransfer.effectAllowed = "copyMove";
$rootScope.$broadcast("ANGULAR_DRAG_START", sendChannel);
}
else {
e.preventDefault();
}
});
element.bind("dragend", function (e) {
var sendChannel = attrs.dragChannel || "defaultchannel";
$rootScope.$broadcast("ANGULAR_DRAG_END", sendChannel);
if (e.dataTransfer && e.dataTransfer.dropEffect !== "none") {
if (attrs.onDropSuccess) {
var fn = $parse(attrs.onDropSuccess);
scope.$apply(function () {
fn(scope, {$event: e});
});
}
}
});
};
}
])
.directive("uiOnDrop", [
'$parse',
'$rootScope',
function ($parse, $rootScope) {
return function (scope, element, attr) {
var dragging = 0; //Ref. http://stackoverflow.com/a/10906204
var dropChannel = "defaultchannel";
var dragChannel = "";
var dragEnterClass = attr.dragEnterClass || "on-drag-enter";
var dragHoverClass = attr.dragHoverClass || "on-drag-hover";
function onDragOver(e) {
if (e.preventDefault) {
e.preventDefault(); // Necessary. Allows us to drop.
}
if (e.stopPropagation) {
e.stopPropagation();
}
e.dataTransfer.dropEffect = e.shiftKey ? 'copy' : 'move';
return false;
}
function onDragLeave(e) {
dragging--;
if (dragging == 0) {
element.removeClass(dragHoverClass);
}
}
function onDragEnter(e) {
dragging++;
$rootScope.$broadcast("ANGULAR_HOVER", dropChannel);
element.addClass(dragHoverClass);
}
function onDrop(e) {
if (e.preventDefault) {
e.preventDefault(); // Necessary. Allows us to drop.
}
if (e.stopPropagation) {
e.stopPropagation(); // Necessary. Allows us to drop.
}
var data = e.dataTransfer.getData("text/plain");
data = angular.fromJson(data);
var fn = $parse(attr.uiOnDrop);
scope.$apply(function () {
fn(scope, {$data: data, $event: e});
});
element.removeClass(dragEnterClass);
}
function isDragChannelAccepted(dragChannel, dropChannel) {
if (dropChannel === "*") {
return true;
}
var channelMatchPattern = new RegExp("(\\s|[,])+(" + dragChannel + ")(\\s|[,])+", "i");
return channelMatchPattern.test("," + dropChannel + ",");
}
$rootScope.$on("ANGULAR_DRAG_START", function (event, channel) {
dragChannel = channel;
if (isDragChannelAccepted(dragChannel, dropChannel)) {
element.bind("dragover", onDragOver);
element.bind("dragenter", onDragEnter);
element.bind("dragleave", onDragLeave);
element.bind("drop", onDrop);
element.addClass(dragEnterClass);
}
});
$rootScope.$on("ANGULAR_DRAG_END", function (e, channel) {
dragChannel = "";
if (isDragChannelAccepted(channel, dropChannel)) {
element.unbind("dragover", onDragOver);
element.unbind("dragenter", onDragEnter);
element.unbind("dragleave", onDragLeave);
element.unbind("drop", onDrop);
element.removeClass(dragHoverClass);
element.removeClass(dragEnterClass);
}
});
$rootScope.$on("ANGULAR_HOVER", function (e, channel) {
if (isDragChannelAccepted(channel, dropChannel)) {
element.removeClass(dragHoverClass);
}
});
attr.$observe('dropChannel', function (value) {
if (value) {
dropChannel = value;
}
});
};
}
]);