resolved-policy view - initial commit 27/39827/5
authorĽubomír Balogh <lubomir.balogh@pantheon.sk>
Tue, 31 May 2016 13:03:11 +0000 (15:03 +0200)
committerĽubomír Balogh <lubomir.balogh@pantheon.sk>
Mon, 6 Jun 2016 12:38:36 +0000 (14:38 +0200)
- added sidepanel
- opening resolved-policy detail in sidepanel

Change-Id: Ib2ed0da6b0ad5b9a8731e9b099a68639244da57e
Signed-off-by: Ľubomír Balogh <lubomir.balogh@pantheon.sk>
groupbasedpolicy-ui/module/src/main/resources/gbp/common/gbp.controller.js
groupbasedpolicy-ui/module/src/main/resources/gbp/common/gbp.css
groupbasedpolicy-ui/module/src/main/resources/gbp/common/views/index.tpl.html
groupbasedpolicy-ui/module/src/main/resources/gbp/contract/contract.service.js
groupbasedpolicy-ui/module/src/main/resources/gbp/epg/epg.service.js
groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/clause-sidepanel.tpl.html [new file with mode: 0644]
groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/contract-sidepanel.tpl.html [new file with mode: 0644]
groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/epg-sidepanel.tpl.html [new file with mode: 0644]
groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/resolved-policy.controller.js
groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/rule-sidepanel.tpl.html [new file with mode: 0644]
groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/subject-sidepanel.tpl.html [new file with mode: 0644]

index 8575dad5f0d477f840e42c8fa500b875d720dcd8..b6913f8431139c7c7e617a0b773227c4d3c8f823 100644 (file)
@@ -3,21 +3,27 @@ define(['app/gbp/common/gbp.service'], function () {
 
     angular.module('app.gbp').controller('RootGbpCtrl', RootGbpCtrl);
 
-    RootGbpCtrl.$inject = ['$state', '$scope', 'RootGbpService', 'TenantListService', 'TenantService', 'ContractService'];
+    RootGbpCtrl.$inject = ['$state', '$scope', 'RootGbpService', 'TenantListService', 'TenantService', 'ContractService', 'EpgService'];
 
-    function RootGbpCtrl($state, $scope, RootGbpService, TenantListService, TenantService, ContractService) {
+    function RootGbpCtrl($state, $scope, RootGbpService, TenantListService, TenantService, ContractService, EpgService) {
         /* properties */
         $scope.stateUrl = null;
         $scope.sidePanelPage = false;
+        $scope.sidePanelPageEndpoint = false;
+        $scope.sidePanelObject = {};
         $scope.rootTenant = TenantService.createObject();
         $scope.rootTenants = TenantListService.createList();
         $scope.policyDisabled = true;
+        $scope.viewPath = 'src/app/gbp/';
 
         /* methods */
         $scope.broadcastFromRoot = broadcastFromRoot;
         $scope.closeSidePanel = closeSidePanel;
         $scope.openSidePanel = openSidePanel;
         $scope.setRootTenant = setRootTenant;
+        $scope.toggleExpanded = toggleExpanded;
+        $scope.openSidePanelObjId = openSidePanelObjId;
+        $scope.openSidePanelChild = openSidePanelChild;
 
         RootGbpService.setMainClass();
         console.log('RootGbpCtrl initialized');
@@ -59,18 +65,68 @@ define(['app/gbp/common/gbp.service'], function () {
          * Sets '$scope.sidePanelPage' to true. This variable is watched in index.tpl.html template
          * and opens/closes side panel
          */
-        function openSidePanel() {
-            $scope.sidePanelPage = true;
+        function openSidePanel(page, object, cbk) {
+            var samePage = page === $scope.sidePanelPage;
+
+            $scope.sidePanelCbk = cbk;
+            $scope.sidePanelPage = page;
+            $scope.sidePanelObject = object;
+
+            if ( samePage &&  $scope.sidePanelCbk) {
+                $scope.sidePanelCbk();
+            }
+        }
+
+        function openSidePanelObjId(idContract, idTenant, objType, apiType) {
+            var element;
+
+            switch(objType) {
+            case 'epg':
+                $scope.sidePanelPage = 'resolved-policy/epg-sidepanel';
+                element = EpgService.createObject();
+                break;
+            case 'contract':
+                $scope.sidePanelPage = 'resolved-policy/contract-sidepanel';
+                element = ContractService.createObject();
+                break;
+            }
+
+            element.get(idContract, idTenant, apiType);
+
+            $scope.sidePanelObject = element;
+        }
+
+        function openSidePanelChild(parent, type) {
+            switch(type) {
+            case 'subject':
+                $scope.sidePanelPage = 'resolved-policy/subject-sidepanel';
+                break;
+            case 'clause':
+                $scope.sidePanelPage = 'resolved-policy/clause-sidepanel';
+                break;
+            case 'rule':
+                $scope.sidePanelPage = 'resolved-policy/rule-sidepanel';
+                break;
+            }
+
+            $scope.sidePanelObject = parent;
         }
 
         function enableButtons() {
             $scope.policyDisabled = false;
         }
+
+        function toggleExpanded(element) {
+            if(element.expanded)
+                element.expanded = false;
+            else
+                element.expanded = true;
+        }
+
         /* event listeners */
         /**
          * Event fired after content loaded, setStateUrl function is called to fill stateUrl method
          */
         $scope.$on('$viewContentLoaded', setStateUrl);
-
     }
 });
index a0fd19975fe7f3d660e9a9cb941bd4e4d4bcf449..1ce7328503d5e22149ddee355f98283883dc1644 100644 (file)
     color: rgba(0,0,0,0.26);
 }
 
-text.node-label {
-    pointer-events: all;
+svg g.node text {
+    pointer-events: auto !important;
+}
+
+.expander .md-list-item-inner {
+    display: block;
+}
+
+#graph-container {
+    padding-left: 0;
 }
 
 /* $mdDialog.confirm */
 md-dialog button span {
     color: #000;
 }
+
+md-sidenav span {
+    color: inherit !important;
+}
index e5a295585ec26b5328a3037575813c4ddaf2b031..91227b341e5adee25c2b6f3f020e726cbd627257 100644 (file)
@@ -14,9 +14,6 @@
                 <md-button ng-click="" ng-href="#/gbp/index/endpoints" style="background-color:rgb(33,150,243);color:black;">Endpoints</md-button>
 
                 <span flex></span>
-                <md-select ng-model="rootTenant" ng-change="setRootTenant()">
-                    <md-option ng-repeat="item in rootTenants.data" ng-value="{{item}}">{{item.data.id}}</md-option>
-                </md-select>
             </div>
         </md-toolbar>
         <!-- <md-content md-scroll-y flex ui-view></md-content> -->
             <md-content md-scroll-y flex ui-view="main_bottom" class="col-md-6"></md-content>
         </md-content>
     </div>
-    <!-- <md-sidenav class="md-sidenav-right md-whiteframe-z1 detail-view" md-is-locked-open="sidePanelPage">
+    <!-- Node's side pannel -->
+    <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>
+                <md-button ng-click="closeSidePanel()" class="md-button">Close panel</md-button>
             </div>
         </md-toolbar>
         <md-content flex>
-            <div flex layout="column" ui-view="sidePanel"></div>
+            <div flex layout="column" ui-view="sidePanel">
+                <ng-include ng-if="sidePanelPage" src="viewPath + sidePanelPage + '.tpl.html'"></ng-include>
+            </div>
         </md-content>
-    </md-sidenav> -->
+    </md-sidenav>
 </div>
index 4f7073dd5dabce55cdfa4f63286ebf7d26e6f58d..6d1c66c3aae38db7fb4fdbec9546473fabe8490b 100644 (file)
@@ -45,11 +45,11 @@ define([], function () {
              * @param id
              * @returns {*}
              */
-            function get(id) {
+            function get(idContract, idTenant, apiType) {
                 var self = this;
 
-                var restObj = Restangular.one('restconf').one('config').one('policy:tenants')
-                            .one('tenant').one(id).one('policy').one('contract').one(id);
+                var restObj = Restangular.one('restconf').one(apiType).one('policy:tenants')
+                            .one('tenant').one(idTenant).one('policy').one('contract').one(idContract);
 
                 return restObj.get().then(function (data) {
                     self.setData(data.contract[0]);
index aee88c73ba4f862d749dd8af8b97d8b226051876..c31322d2d4ca99a4a2487d77cd47bd3680185f4a 100644 (file)
@@ -51,11 +51,11 @@ define([], function() {
              * @param id
              * @returns {*}
              */
-            function get(id, idTenant) {
+            function get(idEpg, idTenant, apiType) {
                 var self = this;
 
-                var restObj = Restangular.one('restconf').one('config').one('policy:tenants').one('tenant')
-                    .one(idTenant).one('policy').one('endpoint-group').one(this.data.id || id);
+                var restObj = Restangular.one('restconf').one(apiType).one('policy:tenants').one('tenant')
+                    .one(idTenant).one('policy').one('endpoint-group').one(this.data.id || idEpg);
 
                 return restObj.get().then(function(data) {
                     self.setData(data['endpoint-group'][0]);
diff --git a/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/clause-sidepanel.tpl.html b/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/clause-sidepanel.tpl.html
new file mode 100644 (file)
index 0000000..58fd356
--- /dev/null
@@ -0,0 +1,24 @@
+<md-content>
+       breadcrumb
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Clause info</md-subheader>
+       <div layout="row" class="layout-padding-lr15 layout-row">
+           <span flex="50" class="flex-50"><strong>Clause name</strong></span>
+           <span flex="" class="ng-binding flex">{{sidePanelObject.name}}</span>
+       </div>
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Subject refs ({{sidePanelObject['subject-refs'].length}})</md-subheader>
+    <md-list>
+       <ng-repeat ng-repeat="ref in sidePanelObject['subject-refs']">
+               <md-list-item ng-click="toggleExpanded(ref)">
+                       {{ref}}
+                       <md-content ng-show="ref.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Subject refs</strong></span>
+                                       <span flex class="ng-binding flex">{{ref}}</span>
+                               </div>
+                       </md-content>
+               </md-list-item>
+       </ng-repeat>
+    </md-list>
+</md-content>
\ No newline at end of file
diff --git a/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/contract-sidepanel.tpl.html b/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/contract-sidepanel.tpl.html
new file mode 100644 (file)
index 0000000..52003d3
--- /dev/null
@@ -0,0 +1,89 @@
+<md-content>
+       breadcrumb
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Contract info</md-subheader>
+       <div layout="row" class="layout-padding-lr15 layout-row">
+           <span flex="50" class="flex-50"><strong>Contract ID</strong></span>
+           <span flex="" class="ng-binding flex">{{sidePanelObject.data.id}}</span>
+       </div>
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Subject list ({{sidePanelObject.data.subject.length}})</md-subheader>
+    <md-list>
+       <ng-repeat ng-repeat="subject in sidePanelObject.data.subject">
+               <md-list-item ng-click="openSidePanelChild(subject, 'subject')">
+                       {{subject.name}}
+                       <md-content ng-show="subject.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Rule list</strong></span>
+                                       <span flex class="ng-binding flex">{{subject.rule[0].name}}</span>
+                               </div>
+                       </md-content>
+               </md-list-item>
+       </ng-repeat>
+    </md-list>
+
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Clause list ({{sidePanelObject.data.clause.length}})</md-subheader>
+    <md-list>
+       <ng-repeat ng-repeat="clause in sidePanelObject.data.clause">
+               <md-list-item ng-click="openSidePanelChild(clause, 'clause')">
+                       {{clause.name}}
+                       <md-content ng-show="clause.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Subject refs</strong></span>
+                                       <span flex class="ng-binding flex">{{clause['subject-refs'][0]}}</span>
+                               </div>
+                       </md-content>
+               </md-list-item>
+       </ng-repeat>
+    </md-list>
+
+    <div ng-if="subjectList">
+           <md-input-container>
+             <label>rule-list</label>
+             <md-select ng-model="ruleList">
+               <md-option ng-repeat="ruleList in sidePanelObject.subject[subjectList].rule" value="{{$index}}">
+                 {{ruleList.name}}
+               </md-option>
+             </md-select>
+           </md-input-container>
+
+           <div ng-if="ruleList">
+                   <md-subheader class="md-primary">rule list - order</md-subheader>
+                   <div>{{sidePanelObject.subject[subjectList].rule[ruleList].order}}</div>
+                   <md-input-container>
+                     <label>action-ref list</label>
+                     <md-select ng-model="actionRefList">
+                       <md-option ng-repeat="actionRefList in sidePanelObject.subject[subjectList].rule[ruleList]['action-ref']" value="{{$index}}">
+                         {{actionRefList.name}}
+                       </md-option>
+                     </md-select>
+                   </md-input-container>
+
+                   <div ng-if="actionRefList">
+                           <md-subheader class="md-primary">action-ref list - order</md-subheader>
+                           <div>{{sidePanelObject.subject[subjectList].rule[ruleList][actionRefList].order}}</div>
+                   </div>
+
+                   <md-input-container>
+                     <label>classifier-ref list</label>
+                     <md-select ng-model="actionRefList">
+                       <md-option ng-repeat="classifierRefList in sidePanelObject.subject[subjectList].rule[ruleList][classifier-ref]" value="{{$index}}">
+                         {{classifierRefList.name}}
+                       </md-option>
+                     </md-select>
+                   </md-input-container>
+
+                   <div ng-if="classifierRefList">
+                           <md-subheader class="md-primary">classifier-ref list - name</md-subheader>
+                           <div>{{sidePanelObject.subject[subjectList].rule[ruleList][classifierRefList].name}}</div>
+                           <md-subheader class="md-primary">classifier-ref list - instance-name</md-subheader>
+                           <div>{{sidePanelObject.subject[subjectList].rule[ruleList][classifierRefList]['instance-name']}}</div>
+                           <md-subheader class="md-primary">classifier-ref list - connection-tracking</md-subheader>
+                           <div>{{sidePanelObject.subject[subjectList].rule[ruleList][classifierRefList]['connection-tracking']}}</div>
+                           <md-subheader class="md-primary">classifier-ref list - direction</md-subheader>
+                           <div>{{sidePanelObject.subject[subjectList].rule[ruleList][classifierRefList].direction}}</div>
+                   </div>
+           </div>
+    </div>
+</md-content>
\ No newline at end of file
diff --git a/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/epg-sidepanel.tpl.html b/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/epg-sidepanel.tpl.html
new file mode 100644 (file)
index 0000000..d56ba2a
--- /dev/null
@@ -0,0 +1,47 @@
+<md-content>
+       breadcrumb
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Endpoint-group info</md-subheader>
+       <div layout="row" class="layout-padding-lr15 layout-row">
+           <span flex="50" class="flex-50"><strong>Endpoint-group ID</strong></span>
+           <span flex="" class="ng-binding flex">{{sidePanelObject.data.id}}</span>
+       </div>
+       <div layout="row" class="layout-padding-lr15 layout-row">
+           <span flex="50" class="flex-50"><strong>intra-group-policy</strong></span>
+           <span flex="" class="ng-binding flex">{{sidePanelObject.data['intra-group-policy']}}</span>
+       </div>
+
+       <md-divider></md-divider>
+       <div ng-if="sidePanelObject.data['provider-named-selector']">
+           <md-subheader class="md-primary">Provider-named selectors ({{sidePanelObject.data['provider-named-selector'].length}})</md-subheader>
+           <md-list>
+               <ng-repeat ng-repeat="providerNamedSelector in sidePanelObject.data['provider-named-selector']">
+                       <md-list-item ng-click="openSidePanelObjId(providerNamedSelector.contract[0], sidePanelObject.data.parentTenant, 'contract' ,'operational');">
+                               {{providerNamedSelector.name}}
+                               <md-content ng-show="providerNamedSelector.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                                       <div layout="row" class="layout-row">
+                                       <span flex="50" class="flex-50"><strong>Contract ID</strong></span>
+                                               <span flex class="ng-binding flex">{{providerNamedSelector.contract[0]}}</span>
+                                       </div>
+                               </md-content>
+                       </md-list-item>
+               </ng-repeat>
+           </md-list>
+    </div>
+       <div ng-if="sidePanelObject.data['consumer-named-selector']">
+           <md-subheader class="md-primary">Consumer-named selectors ({{sidePanelObject.data['consumer-named-selector'].length}})</md-subheader>
+           <md-list>
+               <ng-repeat ng-repeat="consumerNamedSelector in sidePanelObject.data['consumer-named-selector']">
+                       <md-list-item ng-click="openSidePanelObjId(consumerNamedSelector.contract[0], sidePanelObject.data.parentTenant, 'contract' ,'operational');">
+                               {{consumerNamedSelector.name}}
+                               <md-content ng-show="consumerNamedSelector.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                                       <div layout="row" class="layout-row">
+                                       <span flex="50" class="flex-50"><strong>Contract ID</strong></span>
+                                               <span flex class="ng-binding flex">{{consumerNamedSelector.contract[0]}}</span>
+                                       </div>
+                               </md-content>
+                       </md-list-item>
+               </ng-repeat>
+           </md-list>
+    </div>
+</md-content>
\ No newline at end of file
index 2bcbf1c21b409850230b3e1a2122a357be164c67..4a13e887316d1cff03ae15e0010572a8ce0d0ce1 100644 (file)
@@ -3,10 +3,10 @@ define(['app/gbp/resolved-policy/resolved-policy.service'], function () {
 
     angular.module('app.gbp').controller('ResolvedPolicyController', ResolvedPolicyController);
 
-    ResolvedPolicyController.$inject = ['$rootScope', '$scope', 'ResolvedPolicyService'];
+    ResolvedPolicyController.$inject = ['$rootScope', '$scope', 'ResolvedPolicyService', 'EpgService', 'ContractService'];
 
     /* @ngInject */
-    function ResolvedPolicyController($rootScope, $scope, ResolvedPolicyService) {
+    function ResolvedPolicyController($rootScope, $scope, ResolvedPolicyService, EpgService, ContractService) {
         $scope.topologyData = {
             nodes: [],
             links: [],
@@ -14,40 +14,40 @@ define(['app/gbp/resolved-policy/resolved-policy.service'], function () {
 
         $scope.cbkFunctions = {
             clickNode: function(node){
+                var epg = EpgService.createObject();
+                epg.get(node['_data-id'], node['_model']['_data']['tenantId'], 'operational');
+                epg.data.parentTenant = node['_model']['_data']['tenantId'];
+                $scope.openSidePanel('resolved-policy/epg-sidepanel', epg, null);
+                $scope.$apply();
+
+                // //Example of highlighting
+                // NextTopologyService.highlightNode($scope.nxTopology, 1);
+                // NextTopologyService.highlightNode($scope.nxTopology, 1, true); //without links around
+                // NextTopologyService.highlightLink($scope.nxTopology, '1-7');
+                // NextTopologyService.highlightPath($scope.nxTopology, [array of links obj]);
 
-                /*$scope.openSidePanel('side_panel_nodes', null, function () {
-                    $scope.broadcastFromRoot('SELECT_NODE', node);
-                });
-                $scope.$apply();*/
-                console.log(node);
-
-                //Example of highlighting
-                //NextTopologyService.highlightNode($scope.nxTopology, 1);
-                //NextTopologyService.highlightNode($scope.nxTopology, 1, true); without links around
-                //NextTopologyService.highlightLink($scope.nxTopology, '1-7');
-                //NextTopologyService.highlightPath($scope.nxTopology, [array of links obj]);
-
-                //Fade out or in whole topology
-                //NextTopologyService.fadeOutAllLayers();
-                //NextTopologyService.fadeInAllLayers();
+                // //Fade out or in whole topology
+                // NextTopologyService.fadeOutAllLayers();
+                // NextTopologyService.fadeInAllLayers();
             },
-             /*clickLink: function(link){
-                $scope.openSidePanel('side_panel_links', null, function () {
-                    $scope.broadcastFromRoot('SELECT_CONNECTION', link);
-                });
+            clickLink: function(link){
+                var contract = ContractService.createObject();
+                contract.get(link['_data-id'], link['_model']['_data']['tenantId'], 'operational');
+                contract.data.parentTenant = link['_model']['_data']['tenantId'];
+                $scope.openSidePanel('resolved-policy/contract-sidepanel', contract, null);
                 $scope.$apply();
-            },*/
-            topologyGenerated: function(){
+            },
+            // topologyGenerated: function(){
 
-                if ( $rootScope.updateTopoInterval ) {
-                    clearInterval($rootScope.updateTopoInterval);
-                }
+            //     if ( $rootScope.updateTopoInterval ) {
+            //         clearInterval($rootScope.updateTopoInterval);
+            //     }
 
-                $rootScope.updateTopoInterval = setInterval(function () {
-                    fillTopologyData();
-                },5000);
+            //     $rootScope.updateTopoInterval = setInterval(function () {
+            //         fillTopologyData();
+            //     },5000);
 
-            },
+            // },
         };
 
         var resolvedPolicies = ResolvedPolicyService.createObject();
@@ -58,20 +58,31 @@ define(['app/gbp/resolved-policy/resolved-policy.service'], function () {
         function fillTopologyData() {
             var topoData = {nodes: [], links: [],};
             resolvedPolicies.data.forEach(function(rp) {
-                topoData.nodes.push(createNode(rp['consumer-epg-id']));
-                topoData.nodes.push(createNode(rp['provider-epg-id']));
+                topoData.nodes.push(createNode(rp['consumer-epg-id'], rp['consumer-tenant-id']));
+                topoData.nodes.push(createNode(rp['provider-epg-id'], rp['provider-tenant-id']));
+                // topoData.links.push(createLink(rp['policy-rule-group-with-endpoint-constraints'][0]['policy-rule-group'][0]['contract-id'], rp['consumer-epg-id'], rp['provider-epg-id']));
             });
+
             $scope.topologyData = topoData;
             $scope.topologyLoaded = true;
         }
 
-        function createNode(nodeName) {
+        function createNode(nodeName, tenantId) {
             return {
                 'id': nodeName,
+                'tenantId' : tenantId,
                 'node-id': nodeName,
                 'label': nodeName,
             };
         }
+
+        function createLink(linkName, source, target) {
+            return {
+                'id' : linkName,
+                'source' : source,
+                'target' : target,
+            };
+        }
     }
 
 });
diff --git a/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/rule-sidepanel.tpl.html b/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/rule-sidepanel.tpl.html
new file mode 100644 (file)
index 0000000..c4ce92e
--- /dev/null
@@ -0,0 +1,55 @@
+<md-content>
+       breadcrumb
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Rule info</md-subheader>
+       <div layout="row" class="layout-padding-lr15 layout-row">
+           <span flex="50" class="flex-50"><strong>Rule name</strong></span>
+           <span flex="" class="ng-binding flex">{{sidePanelObject.name}}</span>
+       </div>
+       <div layout="row" class="layout-padding-lr15 layout-row">
+           <span flex="50" class="flex-50"><strong>Order</strong></span>
+           <span flex="" class="ng-binding flex">{{sidePanelObject.order}}</span>
+       </div>
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Action refs ({{sidePanelObject['action-ref'].length}})</md-subheader>
+    <md-list>
+       <ng-repeat ng-repeat="ref in sidePanelObject['action-ref']">
+               <md-list-item ng-click="toggleExpanded(ref)">
+                       {{ref.name}}
+                       <md-content ng-show="ref.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Name</strong></span>
+                                       <span flex class="ng-binding flex">{{ref.name}}</span>
+                               </div>
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Order</strong></span>
+                                       <span flex class="ng-binding flex">{{ref.order}}</span>
+                               </div>
+                       </md-content>
+               </md-list-item>
+       </ng-repeat>
+    </md-list>
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Classifier refs ({{sidePanelObject['classifier-ref'].length}})</md-subheader>
+    <md-list>
+       <ng-repeat ng-repeat="ref in sidePanelObject['classifier-ref']">
+               <md-list-item ng-click="toggleExpanded(ref)">
+                       {{ref.name}}
+                       <md-content ng-show="ref.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Instance name</strong></span>
+                                       <span flex class="ng-binding flex">{{ref['instance-name']}}</span>
+                               </div>
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Connection tracking</strong></span>
+                                       <span flex class="ng-binding flex">{{ref['connection-tracking']}}</span>
+                               </div>
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Direction</strong></span>
+                                       <span flex class="ng-binding flex">{{ref.direction}}</span>
+                               </div>
+                       </md-content>
+               </md-list-item>
+       </ng-repeat>
+    </md-list>
+</md-content>
\ No newline at end of file
diff --git a/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/subject-sidepanel.tpl.html b/groupbasedpolicy-ui/module/src/main/resources/gbp/resolved-policy/subject-sidepanel.tpl.html
new file mode 100644 (file)
index 0000000..3ffefb0
--- /dev/null
@@ -0,0 +1,24 @@
+<md-content>
+       breadcrumb
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Subject info</md-subheader>
+       <div layout="row" class="layout-padding-lr15 layout-row">
+           <span flex="50" class="flex-50"><strong>Subject name</strong></span>
+           <span flex="" class="ng-binding flex">{{sidePanelObject.name}}</span>
+       </div>
+       <md-divider></md-divider>
+       <md-subheader class="md-primary">Rule list ({{sidePanelObject.rule.length}})</md-subheader>
+    <md-list>
+       <ng-repeat ng-repeat="rule in sidePanelObject.rule">
+               <md-list-item ng-click="openSidePanelChild(rule, 'rule')">
+                       {{rule.name}}
+                       <md-content ng-show="rule.expanded" class="md-whiteframe-2dp ng-scope flex layout-margin">
+                               <div layout="row" class="layout-row">
+                               <span flex="50" class="flex-50"><strong>Rule list</strong></span>
+                                       <span flex class="ng-binding flex">{{rule.name}}</span>
+                               </div>
+                       </md-content>
+               </md-list-item>
+       </ng-repeat>
+    </md-list>
+</md-content>
\ No newline at end of file