md-sidenav span {
color: inherit !important;
}
+
+span.md-subheader {
+ color: red;
+}
+
+div.md-primary.md-subheader.ng-scope > div > span > span {
+ color: rgb(33,150,243);
+}
+
+md-sidenav > md-toolbar > div > h2 > span {
+ margin: 20px 0;
+ color: #666;
+}
+
+span.flex-35 > strong {
+ color: rgba(0,0,0,0.87);
+}
+
+span.ng-binding.flex {
+ color: rgba(0,0,0,0.87);
+}
NavHelperProvider.addControllerUrl('app/gbp/common/gbp.controller');
NavHelperProvider.addControllerUrl('app/gbp/contract/add-contract.controller');
NavHelperProvider.addControllerUrl('app/gbp/contract/contract.controller');
+ NavHelperProvider.addControllerUrl('app/gbp/endpoints/endpoints.controller');
+ NavHelperProvider.addControllerUrl('app/gbp/endpoints/add-endpoint.controller');
NavHelperProvider.addControllerUrl('app/gbp/epg/epg.controller');
NavHelperProvider.addControllerUrl('app/gbp/policy/policy.controller');
NavHelperProvider.addControllerUrl('app/gbp/resolved-policy/resolved-policy.controller');
},
});
+ $stateProvider.state('main.gbp.index.endpoints', {
+ url: '/endpoints',
+ access: access.admin,
+ templateUrl: 'src/app/gbp/common/views/index.tpl.html',
+ views: {
+ '': {
+ controller: 'EndpointsController',
+ templateUrl: 'src/app/gbp/endpoints/endpoints.tpl.html',
+ },
+ },
+ });
+
$mdThemingProvider.theme('default')
.primaryPalette('blue')
.accentPalette('blue-grey');
--- /dev/null
+define([
+ 'app/gbp/endpoints/endpoint.service',
+], function () {
+ 'use strict';
+
+ angular.module('app.gbp').controller('AddEndpointController', AddEndpointController);
+
+ AddEndpointController.$inject = ['$mdDialog', '$scope', 'EndpointService', 'endpoint'];
+ /* @ngInject */
+ function AddEndpointController($mdDialog, $scope, EndpointService, endpoint) {
+ /* properties */
+ $scope.endpoint = endpoint ? endpoint : EndpointService.createObject();
+
+ /* methods */
+ $scope.closeDialog = closeDialog;
+ $scope.save = save;
+ $scope.checkEndpointGroup = checkEndpointGroup;
+ $scope.checkEndpointCondition = checkEndpointCondition;
+
+ console.log('$scope.rootTenants.data.Tenant', $scope.rootTenants.data.Tenant);
+ /* Implementations */
+
+ function closeDialog(){
+ $mdDialog.cancel();
+ $scope.getEndpointsList();
+ }
+
+ function save() {
+ $scope.endpoint.post(function () {
+ $scope.closeDialog();
+ }, function () {
+ } );
+ }
+
+ function checkEndpointGroup(){
+ // $scope.bgpRouteForm.nextHopVal.invalidHops = $scope.bgpRoute.getInvalidHops();
+ }
+
+ function checkEndpointCondition(){
+ }
+ }
+});
--- /dev/null
+<md-dialog ng-cloak class="gbpDialogWrapper" ng-cloak>
+ <form name="endpointForm">
+ <md-toolbar>
+ <div class="md-toolbar-tools">
+ <h2>Add Endpoint</h2>
+ <span flex></span>
+ <md-button ng-click="closeDialog()" class="md-button">Close dialog</md-button>
+ </div>
+ </md-toolbar>
+ <md-dialog-content style="width:800px;min-height:550px;">
+ <div layout="column" class="layout-padding-lr15">
+ <div layout="row">
+ <md-input-container flex>
+ <label>Tenant Id</label>
+ <!-- <input name="tenant" ng-model="endpoint.data.tenant"> -->
+
+ <md-select ng-model="endpoint.data.tenant">
+ <md-option ng-repeat="tenant in rootTenants.data" value="tenant.data.id">{{ tenant.data.id }}</md-option>
+ </md-select>
+
+
+ </md-input-container>
+ <md-input-container flex>
+ <label>Context Type</label>
+ <input name="context-type" ng-model="endpoint.data['context-type']" ng-required="true">
+ <div ng-messages="endpointForm['context-type'].$error">
+ <div ng-message="required">Required field</div>
+ </div>
+ </md-input-container>
+ <md-input-container flex>
+ <label>Context Id</label>
+ <input name="context-id" ng-model="endpoint.data['context-id']" ng-required="true">
+ <div ng-messages="endpointForm['context-id'].$error">
+ <div ng-message="required">Required field.</div>
+ </div>
+ </md-input-container>
+ </div>
+ <div layout="row">
+ <md-input-container flex>
+ <label>Address Type</label>
+ <input name="address-type" ng-model="endpoint.data['address-type']">
+ </md-input-container>
+ <md-input-container flex>
+ <label>Address</label>
+ <input name="address" ng-model="endpoint.data.address" ng-required="true">
+ <div ng-messages="endpointForm.address.$error">
+ <div ng-message="required">Required field</div>
+ </div>
+ </md-input-container>
+ </div>
+ <div layout="row">
+ <md-input-container flex>
+ <label>Network Containment - Network Domain Type</label>
+ <input name="network-domain-type" ng-model="endpoint.data['network-containment']['network-domain-type']">
+ </md-input-container>
+ <md-input-container flex>
+ <label>Network Containment - Network Domain Id</label>
+ <input name="network-domain-id" ng-model="endpoint.data['network-containment']['network-domain-id']">
+ </md-input-container>
+ </div>
+ <div layout="row">
+ <md-input-container flex>
+ <label>Endpoint Group</label>
+ <md-chips ng-model="endpoint.data['endpoint-group']"
+ placeholder="Add an item"
+ md-on-add="checkEndpointGroup()"
+ md-on-remove="checkEndpointGroup()">
+ </md-chips>
+ </md-input-container>
+ </div>
+ <div layout="row">
+ <md-input-container flex>
+ <label>Condition</label>
+ <md-chips ng-model="endpoint.data.condition"
+ placeholder="Add an item"
+ md-on-add="checkEndpointCondition()"
+ md-on-remove="checkEndpointCondition()">
+ </md-chips>
+ </md-input-container>
+ </div>
+ </div>
+</md-dialog-content>
+<md-dialog-actions layout="row">
+ <span flex></span>
+ <md-button ng-click="closeDialog()" class="md-primary">
+ Close
+ </md-button>
+ <md-button ng-click="save()" style="margin-right:20px;" ng-disabled="endpointForm.$invalid" class="md-primary">
+ Save
+ </md-button>
+</md-dialog-actions>
+</form>
+</md-dialog>
--- /dev/null
+define([], function () {
+ 'use strict';
+
+ angular.module('app.gbp').service('EndpointService', EndpointService);
+
+ EndpointService.$inject = ['Restangular'];
+
+ function EndpointService(Restangular) {
+ /* methods */
+ this.createObject = createObject;
+
+ /**
+ * Endpoint constructor
+ * @constructor
+ */
+ function Endpoint() {
+ /* properties */
+ this.data = {};
+ this.data['endpoint-group'] = [];
+ this.data.condition = [];
+ /* methods */
+ this.setData = setData;
+ this.get = get;
+ // this.put = put;
+ this.post = post;
+ this.deleteEndpoint = deleteEndpoint;
+
+ /* Implementation */
+ /**
+ * fills Endpoint object with data
+ * @param data
+ */
+ function setData(data) {
+ this.data['context-type'] = data['context-type'];
+ this.data['context-id'] = data['context-id'];
+ this.data['address-type'] = data['address-type'];
+ this.data.address = data.address;
+ this.data['network-containment'] = data['network-containment'];
+ this.data.tenant = data.tenant;
+ this.data.timestamp = Date();
+ this.data['endpoint-group'] = data['endpoint-group'];
+ }
+ /**
+ * gets one Endpoint object from Restconf
+ * @param id
+ * @returns {*}
+ */
+ function get() {
+ var self = this;
+
+ var restObj = Restangular
+ .one('restconf')
+ .one('config')
+ .one('policy:tenants')
+ .one('tenant')
+ .one(id)
+ .one('policy')
+ .one('Endpoint')
+ .one(id);
+
+ return restObj.get().then(function (data) {
+ self.setData(data.Endpoint[0]);
+ });
+ }
+
+ function post(successCbk) {
+
+ var self = this,
+ restObj = Restangular.one('restconf').one('operations').one('base-endpoint:register-endpoint'),
+ reqData = {
+ 'input': {
+ 'address-endpoint-reg': [
+ self.data,
+ ],
+ },
+ };
+ restObj.customPOST(reqData).then(function (data) {
+ successCbk(data);
+ }, function () {
+
+ });
+ }
+
+ function deleteEndpoint(id, successCallback) {
+ var self = this;
+
+ var restObj = Restangular
+ .one('restconf')
+ .one('config')
+ .one('policy:tenants')
+ .one('tenant')
+ .one(id)
+ .one('policy')
+ .one('Endpoint')
+ .one(self.data.id);
+
+ return restObj.remove().then(function (data) {
+ successCallback(data);
+ }, function () {
+
+ });
+ }
+
+ }
+
+ /**
+ * creates Endpoint object and fills it with data if available
+ * @param data
+ * @returns {Endpoint}
+ */
+ function createObject(data) {
+ var obj = new Endpoint();
+
+ if (data) {
+ obj.setData(data);
+ }
+
+ return obj;
+ }
+ }
+
+ return EndpointService;
+});
--- /dev/null
+define([], function () {
+ 'use strict';
+
+ angular.module('app.gbp').service('EndpointsListService', EndpointsListService);
+
+ EndpointsListService.$inject = ['Restangular', 'EndpointService'];
+
+ function EndpointsListService(Restangular, EndpointService) {
+ /* methods */
+ this.createList = createList;
+
+ function EndpointsList() {
+ /* properties */
+ this.data = [];
+
+ /* methods */
+ this.setData = setData;
+ this.get = get;
+ this.clearData = clearData;
+
+ /* Implementation */
+ /**
+ * fills EndpointsList object with data
+ * @param data
+ */
+ function setData(data) {
+ var self = this;
+ data.forEach(function (dataElement) {
+ self.data.push(EndpointService.createObject(dataElement));
+ });
+ }
+
+ function clearData() {
+ var self = this;
+ self.data = [];
+ }
+
+ function get() {
+ /* jshint validthis:true */
+ var self = this;
+ var restObj = Restangular.one('restconf').one('operational').one('base-endpoint:endpoints');
+
+ return restObj.get().then(function (data) {
+ self.setData(data.endpoints['address-endpoints']['address-endpoint']);
+ });
+ }
+ }
+
+ function createList() {
+ var obj = new EndpointsList();
+
+ return obj;
+ }
+ }
+
+ return EndpointsListService;
+});
--- /dev/null
+define([
+ 'app/gbp/endpoints/endpoint.service',
+ 'app/gbp/endpoints/endpoints-list.service',
+], function () {
+ 'use strict';
+
+ angular.module('app.gbp').controller('EndpointsController', EndpointsController);
+
+ EndpointsController.$inject = ['$scope', '$mdDialog', 'EndpointsListService', 'EndpointService'];
+
+ function EndpointsController($scope, $mdDialog, EndpointsListService, EndpointService) {
+ $scope.endpoints = EndpointsListService.createList();
+ $scope.openEndpointDialog = openEndpointDialog;
+ $scope.getEndpointsList = getEndpointsList;
+ $scope.deleteEndpointDialog = deleteEndpointDialog;
+ $scope.endpointsTableQuery = {
+ order: "data['context-id']",
+ limit: 25,
+ page: 1,
+ options: [25, 50, 100],
+ filter: '',
+ };
+
+ getEndpointsList();
+
+ function getEndpointsList() {
+ $scope.endpoints.clearData();
+ $scope.endpoints.get();
+ }
+
+ function openEndpointDialog(endpointData) {
+ $mdDialog.show({
+ clickOutsideToClose: true,
+ controller: 'AddEndpointController',
+ preserveScope: true,
+ templateUrl: $scope.viewPath + 'endpoints/dialog-add-endpoint.tpl.html',
+ parent: angular.element(document.body),
+ scope: $scope,
+ locals: {
+ endpoint: endpointData,
+ },
+ });
+ }
+
+ function deleteEndpointDialog(endpointData) {
+ var confirm = $mdDialog.confirm()
+ .title('Delete endpoint')
+ .textContent('Do you want to delete endpoint?')
+ .ok('Delete')
+ .cancel('Cancel');
+
+ $mdDialog.show(confirm).then(function () {
+ contractData.deleteEndpoint($scope.rootTenant.data.id,
+ function () {
+ $scope.getEndpointsList();
+ }
+ );
+ }, function () {
+
+ });
+ }
+ }
+});
--- /dev/null
+<section flex layout="column">
+ <div flex layout="row">
+ <md-button ng-click="openEndpointDialog()" class="md-primary">Add</md-button>
+ <md-button ng-click="getEndpointsList()" class="md-primary">Reload</md-button>
+ </div>
+ <md-table-container ng-if="endpoints.data.length">
+ <table md-table>
+ <thead md-head md-order="endpointsTableQuery.order">
+ <tr md-row>
+ <th md-column md-order-by="data['context-id']"><span>Context Id</span></th>
+ <th md-column md-order-by="data.address"><span>Address</span></th>
+ <th md-column md-order-by="data.tenant"><span>Tenant</span></th>
+ <th md-column ><span>Endpoint Group</span></th>
+ <th md-column><span>Actions</span></th>
+ </tr>
+ </thead>
+ <tbody md-body>
+ <tr md-row ng-repeat="endpoint in endpoints.data | filter: endpointsTableQuery.filter | orderBy : endpointsTableQuery.order | limitTo: endpointsTableQuery.limit : (endpointsTableQuery.page -1) * endpointsTableQuery.limit">
+ <td md-cell class="pointer" ng-click="openSidePanel('endpoints/side_panel_endpoints_detail', endpoint.data, null);">{{ endpoint.data['context-id'] }}</td>
+ <td md-cell class="pointer" ng-click="openSidePanel('endpoints/side_panel_endpoints_detail', endpoint.data, null);">{{ endpoint.data.address }}</td>
+ <td md-cell class="pointer" ng-click="openSidePanel('endpoints/side_panel_endpoints_detail', endpoint.data, null);">{{ endpoint.data.tenant }}</td>
+ <td md-cell ng-repeat="epg in endpoint.data['endpoint-group']">{{ epg }}
+ <span ng-if="!$last">, </span>
+ </td>
+ <td md-cell>
+ <md-button class="md-icon-button" ng-click="openEndpointDialog(endpoint)">
+ <md-icon>edit</md-icon>
+ </md-button>
+ <md-button class="md-icon-button" ng-click="deleteEndpointDialog(endpoint)">
+ <md-icon>delete</md-icon>
+ </md-button>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ <md-table-pagination md-limit="endpointsTableQuery.limit"
+ md-page="endpointsTableQuery.page"
+ md-options="endpointsTableQuery.options"
+ md-total="{{endpoints.data.length}}"
+ md-page-select="options.pageSelect">
+ </md-table-pagination>
+ </md-table-container>
+</section>
--- /dev/null
+<md-subheader class="md-primary">Endpoint properties</md-subheader>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Context type</strong></span><span flex>{{ sidePanelObject['context-type'] }}</span>
+</div>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Context Id</strong></span><span flex>{{ sidePanelObject['context-id'] }}</span>
+</div>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Address type</strong></span><span flex>{{ sidePanelObject['address-type'] }}</span>
+</div>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>address</strong></span><span flex>{{ sidePanelObject.address }}</span>
+</div>
+<md-divider></md-divider>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Network domain Id</strong></span><span flex>{{ sidePanelObject['network-containment']['network-domain-id'] }}</span>
+</div>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Network domain type</strong></span><span flex>{{ sidePanelObject['network-containment']['network-domain-type'] }}</span>
+</div>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Tenant</strong></span><span flex>{{ sidePanelObject.tenant }}</span>
+</div>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Timestamp</strong></span><span flex>{{ sidePanelObject.timestamp | date: 'short'}}</span>
+</div>
+<div layout="row" class="layout-padding-5-15">
+ <span flex="35"><strong>Endpoint group</strong></span><span ng-repeat="epg in sidePanelObject['endpoint-group']" flex>{{ epg }}
+ <span ng-if="!$last">, </span>
+ </span>
+</div>