From a62751ca4f011362829df7366a1c4c5d06f24f9e Mon Sep 17 00:00:00 2001
From: Tatiana Ovchinnikova <t.v.ovtchinnikova@gmail.com>
Date: Mon, 13 Jan 2020 12:01:09 +0100
Subject: [PATCH] Add pagination to Security Groups table in Launch Instance
 wizard

The most elegant way to add pagination is to refactor the table using
<hz-dynamic-table> which already contains pagination instead of wiring
it to the existing table framework.
This solution adds the pagination and makes the code more readable.

Partial-Bug: #1859423

Change-Id: Iaff9e1f3c834a2bdb5823249de632ce472811a7d
---
 .../security-group-details.html               |   4 +-
 .../security-groups.controller.js             |  20 +++-
 .../security-groups/security-groups.html      | 109 ++----------------
 .../security-groups/security-groups.spec.js   |  13 ++-
 4 files changed, 31 insertions(+), 115 deletions(-)

diff --git a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-group-details.html b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-group-details.html
index 58012e5ced..74bdb654cc 100644
--- a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-group-details.html
+++ b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-group-details.html
@@ -1,4 +1,4 @@
-<table st-table="row.security_group_rules" class="table table-condensed table-rsp security-group-details">
+<table st-table="item.security_group_rules" class="table table-condensed table-rsp security-group-details">
   <thead>
     <tr>
       <th st-sort="direction" st-sort-default translate>Direction</th>
@@ -10,7 +10,7 @@
     </tr>
   </thead>
   <tbody>
-    <tr ng-repeat="d in row.security_group_rules">
+    <tr ng-repeat="d in item.security_group_rules">
       <td>{$ d.direction | noValue $}</td>
       <td>{$ d.ethertype | noValue $}</td>
       <td>{$ d.protocol | noValue $}</td>
diff --git a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.controller.js b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.controller.js
index 9df1a082f8..e91216cda3 100644
--- a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.controller.js
+++ b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.controller.js
@@ -37,16 +37,24 @@
 
     ctrl.tableData = {
       available: launchInstanceModel.securityGroups,
-      allocated: launchInstanceModel.newInstanceSpec.security_groups,
-      displayedAvailable: [],
-      displayedAllocated: []
+      allocated: launchInstanceModel.newInstanceSpec.security_groups
     };
 
-    ctrl.tableDetails = basePath + 'security-groups/security-group-details.html';
+    ctrl.availableTableConfig = {
+      selectAll: false,
+      trackId: 'id',
+      detailsTemplateUrl: basePath + 'security-groups/security-group-details.html',
+      columns: [
+        {id: 'name', title: gettext('Name'), priority: 1},
+        {id: 'description', title: gettext('Description'), priority: 2}
+      ]
+    };
+
+    ctrl.allocatedTableConfig = angular.copy(ctrl.availableTableConfig);
+    ctrl.allocatedTableConfig.noItemsMessage = gettext(
+      'Select one or more security groups from the available groups below.');
 
     ctrl.tableHelp = {
-      /*eslint-disable max-len */
-      noneAllocText: gettext('Select one or more security groups from the available groups below.'),
       /*eslint-enable max-len */
       availHelpText: gettext('Select one or more')
     };
diff --git a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.html b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.html
index 108c0ba374..ab7f56e6f2 100644
--- a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.html
+++ b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.html
@@ -1,106 +1,13 @@
 <div ng-controller="LaunchInstanceSecurityGroupsController as ctrl">
   <p class="step-description" translate>Select the security groups to launch the instance in.</p>
 
-  <transfer-table tr-model="ctrl.tableData"
-                  help-text="ctrl.tableHelp"
-                  limits="ctrl.tableLimits">
-
-    <!-- Security Groups Allocated -->
-    <allocated>
-      <table st-table="ctrl.tableData.displayedAllocated"
-             st-safe-src="ctrl.tableData.allocated" hz-table
-             class="table table-striped table-rsp table-detail">
-        <thead>
-        <tr>
-          <th class="expander"></th>
-          <th st-sort="name" st-sort-default class="rsp-p1" translate>Name</th>
-          <th st-sort="description" class="rsp-p2" translate>Description</th>
-          <th></th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-if="ctrl.tableData.allocated.length === 0">
-          <td colspan="8">
-            <div class="no-rows-help">
-              {$ ::trCtrl.helpText.noneAllocText $}
-            </div>
-          </td>
-        </tr>
-        <tr ng-repeat-start="row in ctrl.tableData.displayedAllocated track by row.id">
-          <td class="expander">
-              <span class="fa fa-chevron-right" hz-expand-detail
-                    title="{$ ::trCtrl.helpText.expandDetailsText $}"></span>
-          </td>
-          <td class="rsp-p1 word-break">{$ row.name $}</td>
-          <td class="rsp-p2">{$ row.description $}</td>
-          <td class="actions_column">
-            <action-list>
-              <action action-classes="'btn btn-default'"
-                      callback="trCtrl.deallocate" item="row">
-                <span class="fa fa-arrow-down"></span>
-              </action>
-            </action-list>
-          </td>
-        </tr>
-        <tr ng-repeat-end class="detail-row">
-          <td></td>
-            <td class="detail" colspan="3" ng-include="ctrl.tableDetails">
-            </td>
-        </tr>
-        </tbody>
-      </table>
-    </allocated>
-
-    <!-- Security Groups Available -->
-    <available>
-      <hz-magic-search-context filter-facets="ctrl.filterFacets">
-        <hz-magic-search-bar></hz-magic-search-bar>
-      <table st-table="ctrl.tableData.displayedAvailable"
-             st-magic-search
-             st-safe-src="ctrl.tableData.available"
-             hz-table class="table table-striped table-rsp table-detail">
-        <thead>
-        <tr>
-          <th class="expander"></th>
-          <th st-sort="name" st-sort-default class="rsp-p1" translate>Name</th>
-          <th st-sort="description" class="rsp-p1" translate>Description</th>
-          <th></th>
-        </tr>
-        </thead>
-        <tbody>
-        <tr ng-if="trCtrl.numAvailable() === 0">
-          <td colspan="8">
-            <div class="no-rows-help">
-              {$ ::trCtrl.helpText.noneAvailText $}
-            </div>
-          </td>
-        </tr>
-        <tr ng-repeat-start="row in ctrl.tableData.displayedAvailable track by row.id"
-            ng-if="!trCtrl.allocatedIds[row.id]">
-          <td class="expander">
-              <span class="fa fa-chevron-right" hz-expand-detail
-                    title="{$ ::trCtrl.helpText.expandDetailsText $}"></span>
-          </td>
-          <td class="rsp-p1 word-break">{$ row.name$}</td>
-          <td class="rsp-p1">{$ row.description $}</td>
-          <td class="actions_column">
-            <action-list>
-              <action action-classes="'btn btn-default'"
-                                      callback="trCtrl.allocate" item="row">
-                <span class="fa fa-arrow-up"></span>
-              </action>
-            </action-list>
-          </td>
-        </tr>
-        <tr ng-repeat-end class="detail-row" ng-if="!trCtrl.allocatedIds[row.id]">
-          <td class="detail" colspan="4" ng-include="ctrl.tableDetails">
-          </td>
-        </tr>
-        </tbody>
-      </table>
-      </hz-magic-search-context>
-    </available>
-
+  <transfer-table tr-model="ctrl.tableData" help-text="ctrl.tableHelp" limits="ctrl.tableLimits" clone-content>
+    <hz-dynamic-table
+        config="$isAvailableTable ? ctrl.availableTableConfig : ctrl.allocatedTableConfig"
+        items="$isAvailableTable ? ($sourceItems | filterAvailable:trCtrl.allocatedIds) : $sourceItems"
+        item-actions="trCtrl.itemActions"
+        filter-facets="$isAvailableTable && ctrl.filterFacets"
+        table="ctrl">
+    </hz-dynamic-table>
   </transfer-table> <!-- End Security Groups Transfer Table -->
-
 </div> <!-- End Controller -->
diff --git a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.spec.js b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.spec.js
index d68cb42d35..df0cfd4e6a 100644
--- a/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.spec.js
+++ b/openstack_dashboard/dashboards/project/static/dashboard/project/workflow/launch-instance/security-groups/security-groups.spec.js
@@ -45,21 +45,22 @@
 
       it('sets table data to appropriate scoped items', function() {
         expect(ctrl.tableData).toBeDefined();
-        expect(Object.keys(ctrl.tableData).length).toBe(4);
+        expect(Object.keys(ctrl.tableData).length).toBe(2);
         expect(ctrl.tableData.available).toEqual([ 'group 1', 'group 2' ]);
         expect(ctrl.tableData.allocated).toEqual([ 'group 1' ]);
-        expect(ctrl.tableData.displayedAvailable).toEqual([]);
-        expect(ctrl.tableData.displayedAllocated).toEqual([]);
       });
 
       it('defines table details template', function() {
-        expect(ctrl.tableDetails).toBeDefined();
+        expect(ctrl.availableTableConfig.detailsTemplateUrl).toBeDefined();
+      });
+
+      it('defines a custom no items message for allocated table', function() {
+        expect(ctrl.allocatedTableConfig.noItemsMessage).toBeDefined();
       });
 
       it('defines table help', function() {
         expect(ctrl.tableHelp).toBeDefined();
-        expect(Object.keys(ctrl.tableHelp).length).toBe(2);
-        expect(ctrl.tableHelp.noneAllocText).toBeDefined();
+        expect(Object.keys(ctrl.tableHelp).length).toBe(1);
         expect(ctrl.tableHelp.availHelpText).toBeDefined();
       });