--- /dev/null
+module/node
+module/src/main/resources/gbp/node_modules
+module/src/main/resources/gbp/vendor
<property name="requireJs" value="app/gbp/main"/>
<property name="angularJs" value="app.gbp"/>
<property name="cssDependencies">
- <list></list>
+ <list>
+ <value>src/app/gbp/common/gbp.css</value>
+ <value>src/app/gbp/vendor/angular-material/angular-material.css</value>
+ <value>src/app/gbp/vendor/angular-material-data-table/dist/md-data-table.min.css</value>
+ </list>
</property>
</bean>
</blueprint>
<description>GBP UI Module Resources</description>
<packaging>jar</packaging>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>0.0.24</version>
+ <configuration>
+ <nodeVersion>v0.12.7</nodeVersion>
+ <npmVersion>3.1.3</npmVersion>
+ <workingDirectory>src/main/resources/gbp/</workingDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <id>npm</id>
+ <goals>
+ <goal>install-node-and-npm</goal>
+ <goal>npm</goal>
+ </goals>
+ <phase>generate-resources</phase>
+ </execution>
+ <execution>
+ <id>bower</id>
+ <goals>
+ <goal>bower</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
</project>
--- /dev/null
+{
+ "directory" : "vendor"
+}
\ No newline at end of file
--- /dev/null
+{
+ "name": "opendaylight-gbp",
+ "version": "0.4.0",
+ "dependencies": {
+ "angular-animate": "~1.5.0",
+ "angular-aria": "~1.5.0",
+ "angular-material": "1.0.5",
+ "roboto-fontface": "~0.4.3",
+ "angular-material-data-table": "~0.9.11"
+ }
+}
angular.module('app.gbp').controller('RootGbpCtrl', RootGbpCtrl);
- RootGbpCtrl.$inject = ['$scope', 'RootGbpService'];
+ RootGbpCtrl.$inject = ['$state', '$scope', 'RootGbpService'];
- function RootGbpCtrl($scope, RootGbpService) {
+ function RootGbpCtrl($state, $scope, RootGbpService) {
+ /* properties */
+ $scope.stateUrl = null;
+ $scope.sidePanelPage = false;
+
+ /* methods */
+ $scope.closeSidePanel = closeSidePanel;
+ $scope.openSidePanel = openSidePanel;
+
+ RootGbpService.setMainClass();
+ console.log('RootGbpCtrl initialized');
+
+ /* implementations */
+ /**
+ * Sets '$scope.sidePanelPage' to false. This variable is watched in index.tpl.html template
+ * and opens/closes side panel
+ */
+ function closeSidePanel() {
+ $scope.sidePanelPage = false;
+ }
+
+ /**
+ * fills $scope.stateUrl with loaded url
+ * It's called on $viewContentLoaded event
+ */
+ function setStateUrl() {
+ $scope.stateUrl = $state.current.url;
+ }
+
+ /**
+ * Sets '$scope.sidePanelPage' to true. This variable is watched in index.tpl.html template
+ * and opens/closes side panel
+ */
+ function openSidePanel() {
+ $scope.sidePanelPage = true;
+ }
+
+ /* event listeners */
+ /**
+ * Event fired after content loaded, setStateUrl function is called to fill stateUrl method
+ */
+ $scope.$on('$viewContentLoaded', setStateUrl);
}
});
--- /dev/null
+.gbpUiGlobalWrapper {
+ background: #ffffff;
+ margin-bottom: 0!important;
+ min-height: 100%;
+ padding: 0px;
+}
+
+.gbpUiGlobalWrapper .main {
+ top: 0px;
+}
+
+.gbpUiWrapper {
+ background-color: #414042;
+}
+
+.gbpUiWrapper .pageContent {
+ margin: 0px;
+ padding: 0px;
+ width: 100%;
+ height: 100%;
+}
+
+.gbpUiWrapper .side-panel {
+ width: 400px;
+ color: #000 ! important;
+ border: 1px solid #000;
+}
+
+.gbpUiWrapper .h100 {
+ height: 100%;
+}
+
+.gbpUiWrapper.w100 {
+ width: 100%;
+}
+
+.gbpUiWrapper.flt-r {
+ float: right;
+}
define([
'app/routingConfig',
'Restangular',
- 'angular-translate-loader-partial'], function () {
+ 'angular-translate-loader-partial',
+ 'angular-animate',
+ 'angular-aria',
+ 'angular-material',
+ 'angular-material-data-table'], function () {
var gbp = angular.module('app.gbp',
[
- 'app.core', 'ui.router.state', 'restangular',
+ 'app.core', 'ui.router.state', 'restangular', 'ngAnimate', 'ngAria', 'ngMaterial', 'md.data.table',
]);
gbp.register = gbp; // for adding services, controllers, directives etc. to angular module before bootstrap
gbp.config(function ($stateProvider, $compileProvider, $controllerProvider, $provide, NavHelperProvider,
- $translateProvider, $translatePartialLoaderProvider) {
+ $translateProvider, $translatePartialLoaderProvider, $mdThemingProvider) {
gbp.register = {
controller: $controllerProvider.register,
directive: $compileProvider.directive,
/*$translatePartialLoaderProvider.addPart('app/gbp/assets/data/locale');*/
+ NavHelperProvider.addControllerUrl('app/gbp/common/gbp.controller');
NavHelperProvider.addControllerUrl('app/gbp/contract/contract.controller');
NavHelperProvider.addControllerUrl('app/gbp/epg/epg.controller');
- NavHelperProvider.addControllerUrl('app/gbp/common/gbp.controller');
+ NavHelperProvider.addControllerUrl('app/gbp/policy/policy.controller');
NavHelperProvider.addControllerUrl('app/gbp/tenant/tenant.controller');
NavHelperProvider.addToMenu('gbp', {
},
});
- $stateProvider.state('main.gbp.tenant', {
+ $stateProvider.state('main.gbp.index.tenant', {
url: '/tenant',
access: access.admin,
+ templateUrl: 'src/app/gbp/common/views/index.tpl.html',
views: {
'': {
controller: 'TenantController',
},
});
- $stateProvider.state('main.gbp.epg', {
+ $stateProvider.state('main.gbp.index.policy', {
+ url: '/policy',
+ access: access.admin,
+ templateUrl: 'src/app/gbp/common/views/index.tpl.html',
+ views: {
+ '': {
+ controller: 'PolicyController',
+ templateUrl: 'src/app/gbp/policy/policy.tpl.html',
+ },
+ },
+ });
+
+ $stateProvider.state('main.gbp.index.policy.epg', {
url: '/epg',
access: access.admin,
+ templateUrl: 'src/app/gbp/common/views/index.tpl.html',
views: {
'': {
+ controller: 'PolicyController',
+ templateUrl: 'src/app/gbp/policy/policy.tpl.html',
+ },
+ 'sidePanel': {
controller: 'EpgController',
templateUrl: 'src/app/gbp/epg/epg.tpl.html',
},
},
});
- $stateProvider.state('main.gbp.contract', {
+ $stateProvider.state('main.gbp.index.policy.contract', {
url: '/contract',
access: access.admin,
+ templateUrl: 'src/app/gbp/common/views/index.tpl.html',
views: {
'': {
+ controller: 'PolicyController',
+ templateUrl: 'src/app/gbp/policy/policy.tpl.html',
+ },
+ 'sidePanel': {
controller: 'ContractController',
templateUrl: 'src/app/gbp/contract/contract.tpl.html',
},
},
});
+ $mdThemingProvider.theme('default')
+ .primaryPalette('blue')
+ .accentPalette('blue-grey');
});
return gbp;
RootGbpService.$inject = [];
function RootGbpService() {
+ this.setMainClass = setMainClass;
+ /**
+ * Sets gbpUiGlobalWrapper to override padding on parent class
+ */
+ function setMainClass(){
+ if ($('.gbpUiWrapper').length) {
+ $('.gbpUiWrapper').closest('.col-xs-12').addClass('gbpUiGlobalWrapper');
+ }
+ }
}
+
+ return RootGbpService;
});
-<section class="gbpWrapper clearfix">
- New GBP UI
-</section>
+<div layout="row" class="gbpUiWrapper" flex>
+ <div layout="column" role="main" flex class="master-view">
+ <md-toolbar>
+ <div class="md-toolbar-tools">
+ <md-button ng-href="#/gbp/index/tenant" ng-click="closeSidePanel()" class="md-primary">Tenant</md-button>
+ <md-button ng-href="#/gbp/index/policy" ng-click="closeSidePanel()" class="md-primary">Policy</md-button>
+ <span flex></span>
+ <md-button ng-if="stateUrl === '/policy'" ng-href="#/gbp/index/policy/epg" ng-click="openSidePanel()" class="md-primary">EPGs</md-button>
+ <md-button ng-if="stateUrl === '/policy'" ng-href="#/gbp/index/policy/contract" ng-click="openSidePanel()" class="md-primary">Contracts</md-button>
+ </div>
+ </md-toolbar>
+ <md-content md-scroll-y flex ui-view></md-content>
+ </div>
+ <md-sidenav class="md-sidenav-right md-whiteframe-z1 detail-view" md-is-locked-open="sidePanelPage">
+ <md-toolbar>
+ <div class="md-toolbar-tools">
+ <h2>
+ <span>Sidepanel</span>
+ </h2>
+ <span flex></span>
+ <md-button ng-href="#/gbp/index/policy" ng-click="closeSidePanel()" class="md-button">Close panel</md-button>
+ </div>
+ </md-toolbar>
+ <md-content flex>
+ <div flex layout="column" ui-view="sidePanel"></div>
+ </md-content>
+ </md-sidenav>
+</div>
require.config({
- paths: {},
- shim: {},
+ paths: {
+ 'angular-material': 'app/gbp/vendor/angular-material/angular-material.min',
+ 'angular-animate': 'app/gbp/vendor/angular-animate/angular-animate.min',
+ 'angular-aria': 'app/gbp/vendor/angular-aria/angular-aria.min',
+ 'lodash': 'app/gbp/vendor/lodash/dist/lodash.min',
+ 'angular-material-data-table': 'app/gbp/vendor/angular-material-data-table/dist/md-data-table.min',
+ },
+ shim: {
+ 'angular-material': ['angular'],
+ 'angular-animate': ['angular'],
+ 'angular-aria': ['angular'],
+ 'angular-material-data-table': ['angular', 'angular-material'],
+ },
});
define(['app/gbp/common/gbp.module']);
--- /dev/null
+{
+ "author": "Daniel Malachovsky",
+ "name": "opendaylight-gbp",
+ "description": "openDayLight GBP UI",
+ "version": "0.1.0",
+ "homepage": "http://opendaylight.org",
+ "license": "EPL-1.0",
+ "bugs": "https://bugs.opendaylight.org/",
+ "repository": {
+ "type": "git",
+ "url": "https://git.opendaylight.org/gerrit/groupbasedpolicy.git"
+ },
+ "dependencies": {
+ "bower": "1.7.7"
+ },
+ "devDependencies": {}
+}
--- /dev/null
+define([], function () {
+ 'use strict';
+
+ angular.module('app.gbp').controller('PolicyController', PolicyController);
+
+ PolicyController.$inject = ['$scope'];
+
+ /* @ngInject */
+ function PolicyController($scope) {
+ console.log('PolicyController initialized');
+ }
+
+});
+
--- /dev/null
+<div ui-view="epg"></div>
+<div ui-view="contract"></div>
angular.module('app.gbp').controller('TenantController', TenantController);
TenantController.$inject = ['$scope', 'TenantService', 'TenantListService'];
-
+ /* @ngInject */
function TenantController($scope, TenantService, TenantListService) {
- $scope.tenant = TenantService.createObject();
- $scope.tenant.get('newTenant');
- console.log('Tenant', $scope.tenant);
+ $scope.tenantsTableQuery = {
+ order: "data.id",
+ limit: 25,
+ page: 1,
+ options: [25, 50, 100],
+ filter: ''
+ };
$scope.tenants = TenantListService.createList();
$scope.tenants.get('config');
-
- console.log('Tenants', $scope.tenants);
}
});
angular.module('app.gbp').service('TenantService', TenantService);
TenantService.$inject = ['Restangular'];
-
+ /* @ngInject */
function TenantService(Restangular) {
/* methods */
this.createObject = createObject;
-Tenant<br/>
-id: {{tenant.data.id}}<br/>
-name: {{tenant.data.name}}<br/>
-description: {{tenant.data.description}}<br/>
+<section flex layout="column">
+ <md-table-container ng-if="tenants.data.length">
+ <table md-table>
+ <thead md-head md-order="tenantsTableQuery.order">
+ <tr md-row>
+ <th md-column md-order-by="data.id"><span>Id</span></th>
+ <th md-column md-order-by="data.name"><span>Name</span></th>
+ <th md-column md-order-by="data.description"><span>Description</span></th>
+ <th md-column><span>Actions</span></th>
+ </tr>
+ </thead>
+ <tbody md-body>
+ <tr md-row ng-repeat="tenant in tenants.data | filter: tenantsTableQuery.filter | orderBy : tenantsTableQuery.order | limitTo: tenantsTableQuery.limit : (tenantsTableQuery.page -1) * tenantsTableQuery.limit">
+ <td md-cell>{{tenant.data.id}}</td>
+ <td md-cell>{{tenant.data.name}}</td>
+ <td md-cell>{{tenant.data.description}}</td>
+ <td md-cell>
+ <md-button class="md-icon-button" ng-click="edit(tenant)">
+ <md-icon>edit</md-icon>
+ </md-button>
+ <md-button class="md-icon-button" ng-click="delete(tenant)">
+ <md-icon>delete</md-icon>
+ </md-button>
+ </td>
+ </tr>
-<section ng-repeat="tenantElement in tenants.data">
- {{tenantElement.data.id}}, {{tenantElement.data.name}}, {{tenantElement.data.description}}<br/>
+ </tbody>
+ </table>
+ <md-table-pagination md-limit="tenantsTableQuery.limit"
+ md-page="tenantsTableQuery.page"
+ md-options="tenantsTableQuery.options"
+ md-total="{{tenants.data.length}}"
+ md-page-select="options.pageSelect">
+ </md-table-pagination>
+ </md-table-container>
</section>