From bb3951db5a18ff3a6c2f38f16979ce3f4a3186e2 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 19 Mar 2014 04:37:46 -0400
Subject: [PATCH] Table refresh improvement for TPS UI.

Currently when a table is refreshed the rows are deleted and recreated,
which makes the UI appear slow. The process has been changed such that
all rows are created initially, then when the refresh happens, it will
simply overwrite the content of the rows and clear the unused ones.

The Table class has been refactored such that operations such as add,
remove, and open can be overriden by the subclass. It also has been
modified to clear the checkboxes on refresh. The ID columns have been
standardized to use "id" attribute name.

The HTML templates have been modified to use a new CSS class for better
control over formatting and to include a default page number.

Ticet #848
---
 base/server/share/webapps/pki/css/pki-ui.css       |   4 +-
 base/server/share/webapps/pki/js/pki-ui.js         | 185 +++++++++++++--------
 .../shared/webapps/tps/ui/activities.html          |   6 +-
 .../shared/webapps/tps/ui/authenticators.html      |   6 +-
 base/tps-tomcat/shared/webapps/tps/ui/certs.html   |   6 +-
 .../shared/webapps/tps/ui/connections.html         |   6 +-
 base/tps-tomcat/shared/webapps/tps/ui/groups.html  |   8 +-
 .../tps-tomcat/shared/webapps/tps/ui/profiles.html |   8 +-
 .../shared/webapps/tps/ui/selftests.html           |   6 +-
 base/tps-tomcat/shared/webapps/tps/ui/tokens.html  |   8 +-
 base/tps-tomcat/shared/webapps/tps/ui/users.html   |   8 +-
 11 files changed, 147 insertions(+), 104 deletions(-)

diff --git a/base/server/share/webapps/pki/css/pki-ui.css b/base/server/share/webapps/pki/css/pki-ui.css
index 8802d41625731ee0fc417f6f968f59b30f2bbc9f..dfab67c4ec4630eccc96996dca73b26634d040cc 100644
--- a/base/server/share/webapps/pki/css/pki-ui.css
+++ b/base/server/share/webapps/pki/css/pki-ui.css
@@ -69,11 +69,11 @@ table tfoot tr th {
   border-bottom: 1px #cedede solid;
 }
 
-table tr th:first-child, table tr td:first-child {
+.pki-select-column {
   width: 13px;
 }
 
-table input[type="checkbox"] + label {
+.pki-select-column input[type='checkbox'] + label {
   margin: 0;
   padding: 0 0 0 13px;
 }
diff --git a/base/server/share/webapps/pki/js/pki-ui.js b/base/server/share/webapps/pki/js/pki-ui.js
index 056607a766957879acd1211eb197dde9f50bc7c0..712379cb78503bb4fbef3df929c2682d106baff0 100644
--- a/base/server/share/webapps/pki/js/pki-ui.js
+++ b/base/server/share/webapps/pki/js/pki-ui.js
@@ -385,65 +385,79 @@ var Dialog = Backbone.View.extend({
     }
 });
 
-var BlankTableItem = Backbone.View.extend({
-    render: function() {
-        var self = this;
-        $("td:first", self.$el).each(function(index) {
-            var item = $(this);
-            item.html("&nbsp;");
-        });
-    }
-});
-
 var TableItem = Backbone.View.extend({
     initialize: function(options) {
         var self = this;
         TableItem.__super__.initialize.call(self, options);
         self.table = options.table;
+        self.reset();
+    },
+    reset: function() {
+        var self = this;
+        $("td", self.$el).each(function(index) {
+            var td = $(this);
+            var name = td.attr("name");
+
+            if (td.hasClass("pki-select-column")) {
+                // uncheck checkbox and reset the value
+                var checkbox = $("input[type='checkbox']", td);
+                checkbox.attr("checked", false);
+                checkbox.val("");
+
+                // hide checkbox by hiding the label
+                $("label", td).hide();
+
+            } else if (name == "id") {
+                // hide the content
+                td.children().hide();
+
+            } else {
+                // empty the content
+                td.html("&nbsp;");
+            }
+        });
     },
     render: function() {
         var self = this;
+        var prefix = self.table.$el.attr("name") + "_select_";
+
         $("td", self.$el).each(function(index) {
-            var item = $(this);
-            var name = item.attr("name");
+            var td = $(this);
+            var name = td.attr("name");
 
-            if (index == 0) {
-                // find the checkbox and label for this item
-                var checkbox = $("input[type='checkbox']", item);
-                var id = checkbox.attr("id");
-                var label = $("label[for='" + id + "']", item);
+            if (td.hasClass("pki-select-column")) {
+                // generate a unique id based on model id
+                var id = prefix + self.model.id;
 
-                // replace checkbox and label id with a unique id
-                id = id + "_" + self.model.id;
+                // set the unique id and value for checkbox
+                var checkbox = $("input[type='checkbox']", td);
                 checkbox.attr("id", id);
-                label.attr("for", id);
-
-                // store item id as checkbox value
+                checkbox.attr("checked", false);
                 checkbox.val(self.model.id);
 
-            } else if (index == 1) {
+                // point the label to the checkbox and make it visible
+                var label = $("label", td);
+                label.attr("for", id);
+                label.show();
+
+            } else if (name == "id") {
                 // setup link to edit dialog
-                item.empty();
+                td.empty();
                 $("<a/>", {
                     href: "#",
-                    text: self.model.get(name),
+                    text: self.model.id,
                     click: function(e) {
-                        var dialog = self.table.editDialog;
-                        dialog.model = self.model;
-                        dialog.once("close", function(event) {
-                            self.render();
-                        });
-                        dialog.open();
+                        self.table.open(self);
                         e.preventDefault();
                     }
-                }).appendTo(item);
+                }).appendTo(td);
 
             } else {
                 // show cell content in plain text
-                item.text(self.model.get(name));
+                td.text(self.model.get(name));
                 // update cell automatically on model change
                 self.model.on("change:" + name, function(event) {
-                    item.text(self.model.get(name));
+                    td.text(self.model.get(name));
                 });
             }
         });
@@ -479,12 +493,7 @@ var Table = Backbone.View.extend({
 
         // setup add button handler
         $("button[name='add']", self.thead).click(function(e) {
-            var dialog = self.addDialog;
-            dialog.model = new self.collection.model();
-            dialog.done(function() {
-                self.render();
-            });
-            dialog.open();
+            self.add();
         });
 
         // setup remove button handler
@@ -496,6 +505,7 @@ var Table = Backbone.View.extend({
             $("input:checked", self.tbody).each(function(index) {
                 var input = $(this);
                 var id = input.val();
+                if (id == "") return;
                 items.push(id);
                 message = message + " - " + id + "\n";
             });
@@ -503,17 +513,12 @@ var Table = Backbone.View.extend({
             if (items.length == 0) return;
             if (!confirm(message)) return;
 
-            _.each(items, function(id, index) {
-                var model = self.collection.get(id);
-                model.destroy({
-                    wait: true
-                });
-            });
-
-            self.render();
+            self.remove(items);
         });
 
-        $("input[type='checkbox']", self.thead).click(function(e) {
+        // setup select all handler
+        self.selectAllCheckbox = $("input[type='checkbox']", self.thead);
+        self.selectAllCheckbox.click(function(e) {
             var checked = $(this).is(":checked");
             $("input[type='checkbox']", self.tbody).prop("checked", checked);
         });
@@ -521,6 +526,18 @@ var Table = Backbone.View.extend({
         self.tbody = $("tbody", self.$el);
         self.template = $("tr", self.tbody).detach();
 
+        // create empty rows
+        self.items = [];
+        for (var i = 0; i < self.pageSize; i++) {
+            var tr = self.template.clone();
+            var item = new TableItem({
+                el: tr,
+                table: self
+            });
+            self.items.push(item);
+            self.tbody.append(tr);
+        }
+
         self.tfoot = $("tfoot", self.$el);
         self.totalEntriesField = $("span[name='totalEntries']", self.tfoot);
         self.pageField = $("input[name='page']", self.tfoot);
@@ -578,42 +595,68 @@ var Table = Backbone.View.extend({
         self.collection.fetch({
             reset: true,
             success: function(collection, response, options) {
-                self.tbody.empty();
+
+                // clear selection
+                self.selectAllCheckbox.attr("checked", false);
 
                 // display total entries
-                self.totalEntriesField.text(self.collection.total);
+                self.totalEntriesField.text(self.totalEntries());
 
                 // display current page number
                 self.pageField.val(self.page);
 
                 // calculate and display total number of pages
-                self.totalPages = Math.floor(Math.max(0, self.collection.total - 1) / self.pageSize) + 1;
+                self.totalPages = Math.floor(Math.max(0, self.totalEntries() - 1) / self.pageSize) + 1;
                 self.totalPagesField.text(self.totalPages);
 
-                // display entries in the current page
-                _(self.collection.models).each(function(model) {
-                    var item = new TableItem({
-                        el: self.template.clone(),
-                        table: self,
-                        model: model
-                    });
-                    item.render();
-                    self.tbody.append(item.$el);
-                }, self);
+                // display entries
+                _(self.items).each(function(item, index) {
+                    if (index < self.collection.length) {
+                        // show entry in existing row
+                        item.model = self.collection.at(index);
+                        item.render();
 
-                // add blank rows to keep page size consistent
-                var blanks = self.pageSize - self.collection.models.length;
-                for (var i = 0; i < blanks; i++) {
-                    var item = new BlankTableItem({
-                        el: self.template.clone()
-                    });
-                    item.render();
-                    self.tbody.append(item.$el);
-                }
+                    } else {
+                        // clear unused row
+                        item.reset();
+                    }
+                });
             },
             error: function(collection, response, options) {
                 alert(response.statusText);
             }
         });
+    },
+    totalEntries: function() {
+        var self = this;
+        return self.collection.total;
+    },
+    open: function(item) {
+        var self = this;
+        var dialog = self.editDialog;
+        dialog.model = item.model;
+        dialog.once("close", function(event) {
+            item.render();
+        });
+        dialog.open();
+    },
+    add: function() {
+        var self = this;
+        var dialog = self.addDialog;
+        dialog.model = new self.collection.model();
+        dialog.done(function() {
+            self.render();
+        });
+        dialog.open();
+    },
+    remove: function(items) {
+        var self = this;
+        _.each(items, function(id, index) {
+            var model = self.collection.get(id);
+            model.destroy({
+                wait: true
+            });
+        });
+        self.render();
     }
 });
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/activities.html b/base/tps-tomcat/shared/webapps/tps/ui/activities.html
index 2e96bb82e7d49dbb6da804b0646471259b360327..3453f81e1e0665d0a44f892e0467eb5e58e7870f 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/activities.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/activities.html
@@ -29,7 +29,7 @@
          </th>
     </tr>
     <tr>
-        <th><input id="activity_selectall" type="checkbox"><label for="activity_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="activity_selectall" type="checkbox"><label for="activity_selectall">&nbsp;</label></th>
         <th>Activity ID</th>
         <th>Token ID</th>
         <th>User ID</th>
@@ -41,7 +41,7 @@
 </thead>
 <tbody>
     <tr>
-        <td><input id="activity_select" type="checkbox"><label for="activity_select">&nbsp;</label></td>
+        <td class="pki-select-column"><input id="activity_select" type="checkbox"><label for="activity_select">&nbsp;</label></td>
         <td name="id">&nbsp;</td>
         <td name="tokenID">&nbsp;</td>
         <td name="userID">&nbsp;</td>
@@ -66,7 +66,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/authenticators.html b/base/tps-tomcat/shared/webapps/tps/ui/authenticators.html
index 771fe2e7b4e8e02b6d63f00d091e79d95c9268fd..29eb8261e815a87f10eb4d8fc02af0a125da46c2 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/authenticators.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/authenticators.html
@@ -31,14 +31,14 @@
          </th>
     </tr>
     <tr>
-        <th><input id="authenticator_selectall" type="checkbox"><label for="authenticator_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="authenticator_selectall" type="checkbox"><label for="authenticator_selectall">&nbsp;</label></th>
         <th>Authenticator ID</th>
         <th>Status</th>
     </tr>
 </thead>
 <tbody>
     <tr>
-        <td><input id="authenticator_select" type="checkbox"><label for="authenticator_select">&nbsp;</label></td>
+        <td class="pki-select-column"><input id="authenticator_select" type="checkbox"><label for="authenticator_select">&nbsp;</label></td>
         <td name="id">&nbsp;</td>
         <td name="status">&nbsp;</td>
     </tr>
@@ -58,7 +58,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/certs.html b/base/tps-tomcat/shared/webapps/tps/ui/certs.html
index 997b7c06c798dac99a632f660e653f2e4da2ce6d..473742d228d615fd0a7ab9a0f01a4ed76f8fbdd4 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/certs.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/certs.html
@@ -29,7 +29,7 @@
          </th>
     </tr>
     <tr>
-        <th><input id="cert_selectall" type="checkbox"><label for="cert_selectall">&nbsp;</label></tdh>
+        <th class="pki-select-column"><input id="cert_selectall" type="checkbox"><label for="cert_selectall">&nbsp;</label></tdh>
         <th>Certificate ID</th>
         <th>Serial Number</th>
         <th>Subject</th>
@@ -43,7 +43,7 @@
 </thead>
 <tbody>
     <tr>
-        <td><input id="cert_select" type="checkbox"><label for="cert_select">&nbsp;</label></td>
+        <td class="pki-select-column"><input id="cert_select" type="checkbox"><label for="cert_select">&nbsp;</label></td>
         <td name="id">&nbsp;</td>
         <td name="serialNumber">&nbsp;</td>
         <td name="subject">&nbsp;</td>
@@ -70,7 +70,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/connections.html b/base/tps-tomcat/shared/webapps/tps/ui/connections.html
index 6f401f56f4b0385e29d7a8ca2bc5ca9da4922a07..404a7234f95eae10b2323bb5d5e98a118fdb4639 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/connections.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/connections.html
@@ -31,14 +31,14 @@
          </th>
     </tr>
     <tr>
-        <th><input id="connection_selectall" type="checkbox"><label for="connection_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="connection_selectall" type="checkbox"><label for="connection_selectall">&nbsp;</label></th>
         <th>Connection ID</th>
         <th>Status</th>
     </tr>
 </thead>
 <tbody>
     <tr>
-        <td><input id="connection_select" type="checkbox"><label for="connection_select">&nbsp;</label></td>
+        <td class="pki-select-column"><input id="connection_select" type="checkbox"><label for="connection_select">&nbsp;</label></td>
         <td name="id">&nbsp;</td>
         <td name="status">&nbsp;</td>
     </tr>
@@ -58,7 +58,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/groups.html b/base/tps-tomcat/shared/webapps/tps/ui/groups.html
index b0e8fedb1a9dd01b6aa95f74912926817cee3378..1c001a029a5c9e755012d6a2a71c4509ab0de034 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/groups.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/groups.html
@@ -31,15 +31,15 @@
          </th>
     </tr>
     <tr>
-        <th><input id="group_selectall" type="checkbox"><label for="group_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="group_selectall" type="checkbox"><label for="group_selectall">&nbsp;</label></th>
         <th>Group ID</th>
         <th>Description</th>
     </tr>
 </thead>
 <tbody>
     <tr>
-        <td><input id="group_select" type="checkbox"><label for="group_select">&nbsp;</label></td>
-        <td name="groupID">&nbsp;</td>
+        <td class="pki-select-column"><input id="group_select" type="checkbox"><label for="group_select">&nbsp;</label></td>
+        <td name="id">&nbsp;</td>
         <td name="description">&nbsp;</td>
     </tr>
 </tbody>
@@ -58,7 +58,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/profiles.html b/base/tps-tomcat/shared/webapps/tps/ui/profiles.html
index 95b556257e9860fbb7a5da085c17d8948b6fe25e..2ea3d48c1b54b20f5d52d2184cfe54843dc7b279 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/profiles.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/profiles.html
@@ -31,15 +31,15 @@
          </th>
     </tr>
     <tr>
-        <th><input id="profile_selectall" type="checkbox"><label for="profile_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="profile_selectall" type="checkbox"><label for="profile_selectall">&nbsp;</label></th>
         <th>Profile ID</th>
         <th>Status</th>
     </tr>
 </thead>
 <tbody>
     <tr>
-        <td><input id="profile_select" type="checkbox"><label for="profile_select">&nbsp;</label></td>
-        <td name="id">&nbsp;</td>
+        <td class="pki-select-column"><input id="profile_select" type="checkbox"><label for="profile_select">&nbsp;</label></td>
+        <td name="id"><a href="profile.html">&nbsp;</a></td>
         <td name="status">&nbsp;</td>
     </tr>
 </tbody>
@@ -58,7 +58,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/selftests.html b/base/tps-tomcat/shared/webapps/tps/ui/selftests.html
index c6771763104f303fbf70b29a8e6dc16e5fc44d8b..978f6cd37a16bf7c728644e27091731c9c109709 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/selftests.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/selftests.html
@@ -29,7 +29,7 @@
          </th>
     </tr>
     <tr>
-        <th><input id="selftest_selectall" type="checkbox"><label for="selftest_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="selftest_selectall" type="checkbox"><label for="selftest_selectall">&nbsp;</label></th>
         <th>Self Test ID</th>
         <th>Enabled at Statup</th>
         <th>Critical at Startup</th>
@@ -39,7 +39,7 @@
 </thead>
 <tbody>
     <tr>
-        <td><input id="selftest_select" type="checkbox"><label for="selftest_select">&nbsp;</label></td>
+        <td class="pki-select-column"><input id="selftest_select" type="checkbox"><label for="selftest_select">&nbsp;</label></td>
         <td name="id">&nbsp;</td>
         <td name="enabledAtStartup">&nbsp;</td>
         <td name="criticalAtStartup">&nbsp;</td>
@@ -62,7 +62,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/tokens.html b/base/tps-tomcat/shared/webapps/tps/ui/tokens.html
index cb8d1a88b58b82c8db67ea46da62076d56126cff..48fc8c285fe826000980cd13d69dd65eef024bae 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/tokens.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/tokens.html
@@ -31,7 +31,7 @@
          </th>
     </tr>
     <tr>
-        <th><input id="token_selectall" type="checkbox"><label for="token_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="token_selectall" type="checkbox"><label for="token_selectall">&nbsp;</label></th>
         <th>Token ID</th>
         <th>User ID</th>
         <th>Status</th>
@@ -44,8 +44,8 @@
 </thead>
 <tbody>
     <tr>
-        <td><input id="token_select" type="checkbox"><label for="token_select">&nbsp;</label></td>
-        <td name="tokenID">&nbsp;</td>
+        <td class="pki-select-column"><input id="token_select" type="checkbox"><label for="token_select">&nbsp;</label></td>
+        <td name="id">&nbsp;</td>
         <td name="userID">&nbsp;</td>
         <td name="status">&nbsp;</td>
         <td name="reason">&nbsp;</td>
@@ -70,7 +70,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/users.html b/base/tps-tomcat/shared/webapps/tps/ui/users.html
index a23fdbb8b2cdd44caf30ba959662c94afa9c54ee..b504d419d3372069e15ecda507df653dd8b9b89a 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/users.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/users.html
@@ -31,15 +31,15 @@
          </th>
     </tr>
     <tr>
-        <th><input id="user_selectall" type="checkbox"><label for="user_selectall">&nbsp;</label></th>
+        <th class="pki-select-column"><input id="user_selectall" type="checkbox"><label for="user_selectall">&nbsp;</label></th>
         <th>User ID</th>
         <th>Full Name</th>
     </tr>
 </thead>
 <tbody>
     <tr>
-        <td><input id="user_select" type="checkbox"><label for="user_select">&nbsp;</label></td>
-        <td name="userID">&nbsp;</td>
+        <td class="pki-select-column"><input id="user_select" type="checkbox"><label for="user_select">&nbsp;</label></td>
+        <td name="id">&nbsp;</td>
         <td name="fullName">&nbsp;</td>
     </tr>
 </tbody>
@@ -58,7 +58,7 @@
                  </ul>
              </span>
              <span name="page-jump">
-                 Page <input name="page" type="text"> of <span name="totalPages">1</span>
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
              </span>
          </th>
     </tr>
-- 
1.8.4.2

