From 4c07d06794bd0c2825c63ead32dc571b0600b056 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Mon, 24 Mar 2014 13:37:46 -0400
Subject: [PATCH] Added details page for TPS profiles.

A new page has been added to view TPS profile details. The properties
are displayed in a table which provides pagination and search
functionality. Currently the page is read-only. The edit functionality
will be added separately later.

Previously the ProfileData had a problem with JSON mapping because it
incorrectly included a PropertyNames attribute. To fix the problem the
class has been modified to require explicit JAXB mapping by setting the
@XmlAccessorType to NONE.

New CSS classes have been added to format the details page.

Ticket #654
---
 .../netscape/certsrv/tps/profile/ProfileData.java  |  3 +
 base/server/share/webapps/pki/css/pki-ui.css       |  9 +++
 base/server/share/webapps/pki/js/pki-ui.js         | 67 +++++++++++++++++++
 base/tps-tomcat/shared/webapps/tps/js/profile.js   | 52 +++++++++++++--
 base/tps-tomcat/shared/webapps/tps/ui/index.html   |  2 +-
 base/tps-tomcat/shared/webapps/tps/ui/profile.html | 77 ++++++++++++++++++++++
 6 files changed, 204 insertions(+), 6 deletions(-)
 create mode 100644 base/tps-tomcat/shared/webapps/tps/ui/profile.html

diff --git a/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java b/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java
index c4bbc037e189bd689d528e928e1d5515be49836c..d733777aa3af6e854b8c6ea9a4beb0c59507b6d4 100644
--- a/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java
+++ b/base/common/src/com/netscape/certsrv/tps/profile/ProfileData.java
@@ -29,6 +29,8 @@ import java.util.Map;
 import javax.xml.bind.JAXBContext;
 import javax.xml.bind.Marshaller;
 import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
 import javax.xml.bind.annotation.XmlAttribute;
 import javax.xml.bind.annotation.XmlElement;
 import javax.xml.bind.annotation.XmlRootElement;
@@ -42,6 +44,7 @@ import org.jboss.resteasy.plugins.providers.atom.Link;
  * @author Endi S. Dewata
  */
 @XmlRootElement(name="Profile")
+@XmlAccessorType(XmlAccessType.NONE)
 public class ProfileData {
 
     public static Marshaller marshaller;
diff --git a/base/server/share/webapps/pki/css/pki-ui.css b/base/server/share/webapps/pki/css/pki-ui.css
index dfab67c4ec4630eccc96996dca73b26634d040cc..ee82aca245358bd1a347ada37ee1282a0833b350 100644
--- a/base/server/share/webapps/pki/css/pki-ui.css
+++ b/base/server/share/webapps/pki/css/pki-ui.css
@@ -78,10 +78,19 @@ table tfoot tr th {
   padding: 0 0 0 13px;
 }
 
+.pki-property-name-column {
+  width: 500px;
+}
+
 .pagination {
   margin: 4px;
 }
 
+.pki-fields fieldset label {
+  min-width: 100px;
+  display: inline-block;
+}
+
 .pki-table-actions {
   padding: 1px;
   border-top: none;
diff --git a/base/server/share/webapps/pki/js/pki-ui.js b/base/server/share/webapps/pki/js/pki-ui.js
index 6b12ca010a98e4b5736e0cbc7872130123cc7abb..e649382063a8567ac6590d8fd2505dad81b26ba4 100644
--- a/base/server/share/webapps/pki/js/pki-ui.js
+++ b/base/server/share/webapps/pki/js/pki-ui.js
@@ -680,3 +680,70 @@ var Table = Backbone.View.extend({
         self.render();
     }
 });
+
+var PropertiesTableItem = TableItem.extend({
+    initialize: function(options) {
+        var self = this;
+        PropertiesTableItem.__super__.initialize.call(self, options);
+    },
+    id: function() {
+        var self = this;
+        return self.property.name;
+    },
+    renderColumn: function(td) {
+        var self = this;
+        td.text(self.property.value);
+    }
+});
+
+var PropertiesTable = Table.extend({
+    initialize: function(options) {
+        var self = this;
+        options.tableItem = options.tableItem || PropertiesTableItem;
+        PropertiesTable.__super__.initialize.call(self, options);
+        self.properties = options.properties;
+    },
+    render: function() {
+        var self = this;
+
+        // perform manual filter
+        var filter = self.searchField.val();
+        if (filter === "") {
+            self.entries = self.properties;
+
+        } else {
+            self.entries = [];
+            _(self.properties).each(function(item, index) {
+                // select properties whose names or values contain the filter
+                if (item.name.indexOf(filter) >= 0 || item.value.indexOf(filter) >= 0) {
+                    self.entries.push(item);
+                }
+            });
+        }
+
+        self.renderControls();
+
+        _(self.items).each(function(item, index) {
+            self.renderRow(item, index);
+        });
+    },
+    totalEntries: function() {
+        var self = this;
+        return self.entries.length;
+    },
+    open: function(item) {
+    },
+    renderRow: function(item, index) {
+        var self = this;
+        var i = (self.page - 1) * self.pageSize + index;
+        if (i < self.entries.length) {
+            // show entry in existing row
+            item.property = self.entries[i];
+            item.render();
+
+        } else {
+            // clear unused row
+            item.reset();
+        }
+    }
+});
diff --git a/base/tps-tomcat/shared/webapps/tps/js/profile.js b/base/tps-tomcat/shared/webapps/tps/js/profile.js
index fbba2c9ec8cbd5112c2e3ab87d22284389ba6593..6e44b4378db294fcde7be09be260d318f525934f 100644
--- a/base/tps-tomcat/shared/webapps/tps/js/profile.js
+++ b/base/tps-tomcat/shared/webapps/tps/js/profile.js
@@ -24,7 +24,8 @@ var ProfileModel = Model.extend({
     parseResponse: function(response) {
         return {
             id: response.id,
-            status: response.Status
+            status: response.Status,
+            properties: response.Properties.Property
         };
     },
     parseXML: function(data) {
@@ -124,18 +125,59 @@ var ProfileDialog = Dialog.extend({
     }
 });
 
-var ProfilePage = Page.extend({
-    load: function() {
+var ProfilesTable = Table.extend({
+    initialize: function(options) {
+        var self = this;
+        ProfilesTable.__super__.initialize.call(self, options);
+        self.url = options.url;
+        self.container = options.container;
+    },
+    open: function(item) {
+        var self = this;
+
+        // load entry properties
+        item.model.fetch({
+            success: function(model, response, options) {
+                self.container.load(self.url, function(response, status, xhr) {
+                    $("h1 span[name='id']", self.container).text(model.id);
+
+                    var fields = $("div[name='profile']", self.container);
+                    $("input[name='id']", fields).val(model.id);
+                    $("input[name='status']", fields).val(model.get("status"));
+
+                    var properties = new PropertiesTable({
+                        el: $("table[name='profile-properties']"),
+                        properties: model.get("properties"),
+                        pageSize: 10
+                    });
+                    properties.render();
+                });
+            }
+        });
+    }
+});
+
+var ProfilesPage = Page.extend({
+    initialize: function(options) {
+        var self = this;
+        ProfilesPage.__super__.initialize.call(self, options);
+        self.container = options.container;
+    },
+    load: function(container) {
+        var self = this;
+
         var editDialog = new ProfileDialog({
             el: $("#profile-dialog"),
             title: "Edit Profile",
             readonly: ["id", "status"]
         });
 
-        var table = new Table({
+        var table = new ProfilesTable({
+            url: "profile.html",
             el: $("table[name='profiles']"),
             collection: new ProfileCollection(),
-            editDialog: editDialog
+            editDialog: editDialog,
+            container: container
         });
         table.render();
     }
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/index.html b/base/tps-tomcat/shared/webapps/tps/ui/index.html
index 7fc48b60fc18d3133a69cbdeab556c380e654901..2cfee922890417d1139ccf0747b182d665f30420 100644
--- a/base/tps-tomcat/shared/webapps/tps/ui/index.html
+++ b/base/tps-tomcat/shared/webapps/tps/ui/index.html
@@ -47,7 +47,7 @@ $(function() {
             certs: new CertificatePage({ url: "certs.html" }),
             connections: new ConnectionPage({ url: "connections.html" }),
             groups: new GroupPage({ url: "groups.html" }),
-            profiles: new ProfilePage({ url: "profiles.html" }),
+            profiles: new ProfilesPage({ url: "profiles.html" }),
             selftests: new SelfTestPage({ url: "selftests.html" }),
             tokens: new TokenPage({ url: "tokens.html" }),
             users: new UserPage({ url: "users.html" })
diff --git a/base/tps-tomcat/shared/webapps/tps/ui/profile.html b/base/tps-tomcat/shared/webapps/tps/ui/profile.html
new file mode 100644
index 0000000000000000000000000000000000000000..81d7b7f3f58592f3e40e76f7d4f648001a83a4d8
--- /dev/null
+++ b/base/tps-tomcat/shared/webapps/tps/ui/profile.html
@@ -0,0 +1,77 @@
+<!-- --- BEGIN COPYRIGHT BLOCK ---
+     This program is free software; you can redistribute it and/or modify
+     it under the terms of the GNU General Public License as published by
+     the Free Software Foundation; version 2 of the License.
+
+     This program is distributed in the hope that it will be useful,
+     but WITHOUT ANY WARRANTY; without even the implied warranty of
+     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+     GNU General Public License for more details.
+
+     You should have received a copy of the GNU General Public License along
+     with this program; if not, write to the Free Software Foundation, Inc.,
+     51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+     Copyright (C) 2014 Red Hat, Inc.
+     All rights reserved.
+     --- END COPYRIGHT BLOCK --- -->
+<h1>Profile <span name="id"></span></h1>
+
+<div name="profile" class="pki-fields">
+<fieldset>
+    <label>Profile ID</label>
+    <input name="id" readonly>
+    <br>
+    <label>Status</label>
+    <input name="status" readonly>
+    <br>
+</fieldset>
+</div>
+
+<h2>Properties</h2>
+
+<table name="profile-properties">
+<thead>
+    <tr>
+         <th class="pki-table-actions" colspan="3">
+             <span name="search">
+                 <input name="search" type="text" placeholder="Search...">
+             </span>
+             <span name="actions">
+             </span>
+         </th>
+    </tr>
+    <tr>
+        <th class="pki-select-column"><input id="profile_selectall" type="checkbox"><label for="profile_selectall">&nbsp;</label></th>
+        <th class="pki-property-name-column">Name</th>
+        <th>Value</th>
+    </tr>
+</thead>
+<tbody>
+    <tr>
+        <td class="pki-select-column"><input id="profile_select" type="checkbox"><label for="profile_select">&nbsp;</label></td>
+        <td name="id" class="pki-property-name-column"><a href="profile.html">&nbsp;</a></td>
+        <td name="status">&nbsp;</td>
+    </tr>
+</tbody>
+<tfoot>
+    <tr>
+         <th class="pki-table-actions" colspan="3">
+             <span name="info">
+                 Total: <span name="totalEntries">0</span> entries
+             </span>
+             <span name="page-controls">
+                 <ul class="pagination">
+                     <li><a href="#" name="first"><span class="i fa fa-angle-double-left"></span></a></li>
+                     <li><a href="#" name="prev"><span class="i fa fa-angle-left"></span></a></li>
+                     <li><a href="#" name="next"><span class="i fa fa-angle-right"></span></a></li>
+                     <li><a href="#" name="last"><span class="i fa fa-angle-double-right"></span></a></li>
+                 </ul>
+             </span>
+             <span name="page-jump">
+                 Page <input name="page" type="text" value="1"> of <span name="totalPages">1</span>
+             </span>
+         </th>
+    </tr>
+</tfoot>
+</table>
-- 
1.8.4.2

