You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by bf...@apache.org on 2012/10/10 20:18:11 UTC

[2/3] git commit: UI: Add quick view to table list

UI: Add quick view to table list

For any list view that has a corresponding detail view, adds a tooltip
to display the compact overview of the detail view contents, including
all available actions. This avoids a user from having to click into a
new panel to see more details and actions for an item.

This will happen automatically for any list view with a 'detailView'
sub-option, and will append a new column to the end of each item
row. If 'noCompact: true' is specified in the detailView's options,
then the quick view will not be rendered.

** Note: This also removes the existing list actions for the instances
         and zones tables.

Example, to show a quick view:

listView: {
  detailView: {
    // Specify noCompact: true to not render a quick view
    //
    // noCompact: true
    ...
  },
  ...
}

Conflicts:
	ui/scripts/ui/widgets/detailView.js


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/991557bf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/991557bf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/991557bf

Branch: refs/heads/master
Commit: 991557bfb6c253017954c07722344c78c805bb51
Parents: a5edef0
Author: Brian Federle <br...@citrix.com>
Authored: Tue Oct 9 11:19:12 2012 -0700
Committer: Brian Federle <br...@citrix.com>
Committed: Wed Oct 10 11:18:02 2012 -0700

----------------------------------------------------------------------
 .../WEB-INF/classes/resources/messages.properties  |    6 +
 ui/css/cloudstack3.css                             |  307 ++++++++++++++-
 ui/dictionary.jsp                                  |    6 +
 ui/scripts/accounts.js                             |    1 +
 ui/scripts/instances.js                            |  195 +---------
 ui/scripts/network.js                              |    2 +-
 ui/scripts/system.js                               |  223 ++++++-----
 ui/scripts/ui-custom/zoneChart.js                  |    1 +
 ui/scripts/ui/widgets/detailView.js                |   84 +++-
 ui/scripts/ui/widgets/listView.js                  |  166 +++++++-
 10 files changed, 649 insertions(+), 342 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/client/WEB-INF/classes/resources/messages.properties
----------------------------------------------------------------------
diff --git a/client/WEB-INF/classes/resources/messages.properties b/client/WEB-INF/classes/resources/messages.properties
index b40fce4..73465fc 100644
--- a/client/WEB-INF/classes/resources/messages.properties
+++ b/client/WEB-INF/classes/resources/messages.properties
@@ -17,6 +17,12 @@
 
 
 #new labels (begin) **********************************************************************************************
+label.migrate.to.host=Migrate to host
+label.migrate.to.storage=Migrate to storage
+label.stop=Stop
+label.reboot=Reboot
+label.destroy=Destroy
+label.restore=Restore
 label.isolation.uri=Isolation URI
 label.broadcast.uri=Broadcast URI
 #new labels (end) ************************************************************************************************

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/css/cloudstack3.css
----------------------------------------------------------------------
diff --git a/ui/css/cloudstack3.css b/ui/css/cloudstack3.css
index 19b0aee..7a8d066 100644
--- a/ui/css/cloudstack3.css
+++ b/ui/css/cloudstack3.css
@@ -74,6 +74,7 @@ body.install-wizard {
   display: none;
 }
 
+/*Table*/
 table {
   width: 740px;
   max-width: 777px;
@@ -140,10 +141,11 @@ table tbody td.loading {
   border-top: 1px solid #FBFBFB;
 }
 
+/** Actions table cell*/
 table tbody td.actions {
-  width: 155px;
-  max-width: 155px !important;
-  min-width: 155px !important;
+  width: 130px;
+  max-width: 130px !important;
+  min-width: 130px !important;
   vertical-align: middle;
 }
 
@@ -155,6 +157,44 @@ table tbody td.actions input {
   margin: 11px 0 0px;
 }
 
+/** Quick view table cell*/
+table tbody td.quick-view,
+table thead th.quick-view {
+  min-width: 58px;
+  max-width: 58px !important;
+  width: 58px !important;
+  height: 14px !important;
+  text-indent: 7px;
+}
+
+table tbody td.quick-view {
+  cursor: pointer;
+}
+
+table tbody td.quick-view .icon {
+  margin-left: 22px;
+  margin-top: 3px;
+  padding: 0px 0px 6px 12px;
+  background: url(../images/sprites.png) no-repeat -44px -62px;
+}
+
+table tbody td.quick-view:hover .icon {
+  background-position: -44px -644px;
+}
+
+table tbody tr.loading td.quick-view .icon {
+  display: none;
+}
+
+table tbody tr.loading td.quick-view {
+  cursor: default;
+}
+
+table tbody tr.loading td.quick-view .loading {
+  background-position: center center;
+}
+
+/** Row styling*/
 table tbody tr {
   border-left: 1px solid #C4C5C5;
   border-right: 1px solid #C4C5C5;
@@ -220,6 +260,7 @@ table th div.ui-resizable-handle {
   float: right;
 }
 
+/** Header, misc*/
 #header,
 #navigation {
   /*+text-shadow:0px -1px 1px #000000;*/
@@ -1229,7 +1270,9 @@ div.panel div.list-view div.fixed-header table {
 }
 
 div.list-view td.state {
-  width: 129px;
+  width: 120px;
+  min-width: 120px;
+  max-width: 120px;
 }
 
 div.list-view td.first {
@@ -1241,7 +1284,7 @@ div.list-view td.first:hover {
 }
 
 div.list-view td.state span {
-  padding: 0 0 0 26px;
+  padding: 1px 0 0 18px;
   text-align: center;
   width: 80px;
   /*+text-shadow:0px 1px 1px #FFFFFF;*/
@@ -1266,6 +1309,241 @@ div.list-view td.state.off span {
   background-position: 1px -496px;
 }
 
+/** Quick view tooltip*/
+.quick-view-tooltip {
+  width: 400px;
+  display: inline-block;
+  margin-left: -359px;
+  padding-top: 50px;
+}
+
+.quick-view-tooltip > div.title {
+  width: 376px;
+  position: absolute;
+  top: 71px;
+  left: 10px;
+  color: #5A6977;
+  /*+text-shadow:0px 1px #EAEAEA;*/
+  -moz-text-shadow: 0px 1px #EAEAEA;
+  -webkit-text-shadow: 0px 1px #EAEAEA;
+  -o-text-shadow: 0px 1px #EAEAEA;
+  text-shadow: 0px 1px #EAEAEA;
+}
+
+.quick-view-tooltip > div.title .icon {
+  position: relative;
+  top: -3px;
+  background: url(../images/sprites.png) no-repeat -42px -67px;
+  float: right;
+  padding: 5px 21px 0 1px;
+}
+
+.quick-view-tooltip .loading-overlay {
+  top: 94px;
+  height: 57px;
+  left: 1px;
+  /*+opacity:35%;*/
+  filter: alpha(opacity=35);
+  -ms-filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=35);
+  -moz-opacity: 0.35;
+  opacity: 0.35;
+}
+
+.quick-view-tooltip > div.title span.title {
+}
+
+.quick-view-tooltip .container {
+  border: 1px solid #9EA2A5;
+  background: #CCCFD6;
+  width: 400px;
+  min-height: 100px;
+  height: auto;
+  overflow: auto;
+  display: inline-block;
+  /*+box-shadow:0px 7px 9px #676F76;*/
+  -moz-box-shadow: 0px 7px 9px #676F76;
+  -webkit-box-shadow: 0px 7px 9px #676F76;
+  -o-box-shadow: 0px 7px 9px #676F76;
+  box-shadow: 0px 7px 9px #676F76;
+}
+
+/*** Quick view detail view*/
+.quick-view-tooltip .detail-view {
+}
+
+.quick-view-tooltip .detail-view .main-groups {
+  width: 394px;
+  height: 132px;
+  position: absolute;
+  top: 55px;
+  padding-top: 7px;
+  border: 1px solid #808080;
+  border-left: none;
+  border-right: none;
+  overflow: hidden;
+  /*+box-shadow:0px 1px #E6E6E6;*/
+  -moz-box-shadow: 0px 1px #E6E6E6;
+  -webkit-box-shadow: 0px 1px #E6E6E6;
+  -o-box-shadow: 0px 1px #E6E6E6;
+  box-shadow: 0px 1px #E6E6E6;
+}
+
+.quick-view-tooltip .detail-view .actions {
+}
+
+.quick-view-tooltip .detail-view .tagger {
+  display: none;
+}
+
+.quick-view-tooltip .detail-view ul {
+  display: none !important;
+}
+
+.quick-view-tooltip .detail-view .ui-tabs-panel {
+  display: inline-block;
+  width: 100% !important;
+  float: left;
+  height: auto;
+  overflow: hidden;
+}
+
+.quick-view-tooltip .detail-view .details {
+  display: inline-block;
+  height: auto;
+  padding-bottom: 209px;
+}
+
+.quick-view-tooltip .detail-view .detail-group {
+  width: 365px;
+  margin: 0;
+  padding: 0;
+  left: -9px;
+  background: none;
+  border: none;
+}
+
+.quick-view-tooltip .detail-view .detail-group table {
+  margin: 0;
+  border: none;
+  background: none;
+}
+
+.quick-view-tooltip .detail-view .detail-group table tr {
+  background: none;
+}
+
+.quick-view-tooltip .detail-view .detail-group table td.name {
+  color: #3E5F7F !important;
+  padding: 0px 29px 0px 5px !important;
+  font-size: 13px;
+  /*+text-shadow:0px 1px #DBDBDB;*/
+  -moz-text-shadow: 0px 1px #DBDBDB;
+  -webkit-text-shadow: 0px 1px #DBDBDB;
+  -o-text-shadow: 0px 1px #DBDBDB;
+  text-shadow: 0px 1px #DBDBDB;
+}
+
+.quick-view-tooltip .detail-view .detail-group table td.value {
+  font-size: 12px;
+  /*+text-shadow:0px 1px #EAEAEA;*/
+  -moz-text-shadow: 0px 1px #EAEAEA;
+  -webkit-text-shadow: 0px 1px #EAEAEA;
+  -o-text-shadow: 0px 1px #EAEAEA;
+  text-shadow: 0px 1px #EAEAEA;
+}
+
+.quick-view-tooltip .detail-view .detail-group table td.value input[type=text] {
+  width: 258px;
+  height: 10px;
+  margin-left: 0px;
+}
+
+.quick-view-tooltip .detail-view .detail-group .main-groups table td.value span {
+  height: 15px;
+  top: 0px;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions {
+  position: relative;
+  top: 202px;
+  float: left;
+  width: 100%;
+  height: auto;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions .button {
+  top: 160px;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions .action.text {
+  width: 112px;
+  height: 41px;
+  background: none;
+  border: none;
+  float: left;
+  margin-left: 5px;
+  display: inline-block;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions .action.text:hover {
+  /*+box-shadow:none;*/
+  -moz-box-shadow: none;
+  -webkit-box-shadow: none;
+  -o-box-shadow: none;
+  box-shadow: none;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions .action.text .icon {
+  display: block;
+  float: left;
+  width: 4px;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions .action.text .label {
+  width: 81px;
+  display: block;
+  float: right;
+  font-size: 11px;
+  color: #454C53;
+  /*+text-shadow:0px 1px #FFFFFF;*/
+  -moz-text-shadow: 0px 1px #FFFFFF;
+  -webkit-text-shadow: 0px 1px #FFFFFF;
+  -o-text-shadow: 0px 1px #FFFFFF;
+  text-shadow: 0px 1px #FFFFFF;
+  text-indent: 0px;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions .action.text:hover .label {
+  color: #000000;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions .detail-actions {
+  width: 400px;
+  height: auto;
+  background: none;
+  vertical-align: top;
+  float: left;
+}
+
+.quick-view-tooltip .detail-view .detail-group.actions td.view-all {
+  position: relative;
+  left: 0px;
+  float: left;
+  width: 394px;
+  height: 22px;
+  border-top: 1px solid #808080;
+  /*+box-shadow:inset 0px 1px #FFFFFF;*/
+  -moz-box-shadow: inset 0px 1px #FFFFFF;
+  -webkit-box-shadow: inset 0px 1px #FFFFFF;
+  -o-box-shadow: inset 0px 1px #FFFFFF;
+  box-shadow: inset 0px 1px #FFFFFF;
+}
+
+.quick-view-tooltip .detail-view .detail-actions a {
+  background: none;
+  width: 30px;
+}
+
 /*Details page*/
 .detail-view {
   padding: 0 0 0 14px;
@@ -2844,7 +3122,7 @@ table td.actions span {
 table td.actions .action span.icon {
   background-image: url(../images/sprites.png);
   cursor: pointer;
-  width: 28px;
+  width: 23px;
   height: 21px;
   float: left;
 }
@@ -10018,6 +10296,23 @@ div.ui-dialog div.autoscaler div.field-group div.form-container form div.form-it
   top: 31px;
 }
 
+/*List state BG colors*/
+.list-view .body td.item-state-on {
+  background: #C0FFC0;
+  border-bottom: 1px solid #09BC09;
+}
+
+.list-view .body td.item-state-off {
+  background: #FFD8CF;
+  border-bottom: 1px solid #FF9F9F;
+}
+
+.list-view .body tr.selected td.item-state-on,
+.list-view .body tr.selected td.item-state-off {
+  background-color: inherit;
+  border-color: inherit;
+}
+
 /*Action icons*/
 .action.edit .icon {
   background-position: 1px -1px;

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/dictionary.jsp
----------------------------------------------------------------------
diff --git a/ui/dictionary.jsp b/ui/dictionary.jsp
index 9457e30..c62bf28 100644
--- a/ui/dictionary.jsp
+++ b/ui/dictionary.jsp
@@ -25,6 +25,12 @@ under the License.
 <% long now = System.currentTimeMillis(); %>
 <script language="javascript">
 dictionary = {
+'label.migrate.to.host': '<fmt:message key="label.migrate.to.host"/>',
+'label.migrate.to.storage': '<fmt:message key="label.migrate.to.storage"/>',
+'label.stop': '<fmt:message key="label.stop"/>',
+'label.reboot': '<fmt:message key="label.reboot"/>',
+'label.destroy': '<fmt:message key="label.destroy"/>',
+'label.restore': '<fmt:message key="label.restore"/>',
 'label.broadcast.uri': '<fmt:message key="label.broadcast.uri"/>',
 'label.isolation.uri': '<fmt:message key="label.isolation.uri"/>',
 'message.zoneWizard.enable.local.storage': '<fmt:message key="message.zoneWizard.enable.local.storage"/>',

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/scripts/accounts.js
----------------------------------------------------------------------
diff --git a/ui/scripts/accounts.js b/ui/scripts/accounts.js
index 15da521..5158eb0 100644
--- a/ui/scripts/accounts.js
+++ b/ui/scripts/accounts.js
@@ -261,6 +261,7 @@
             actions: {
               edit: {
                 label: 'message.edit.account',
+                compactLabel: 'label.edit',
                 action: function(args) {
                   var errorMsg = "";
                   var accountObj = args.context.accounts[0];

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/scripts/instances.js
----------------------------------------------------------------------
diff --git a/ui/scripts/instances.js b/ui/scripts/instances.js
index e86e688..4f8ff3d 100644
--- a/ui/scripts/instances.js
+++ b/ui/scripts/instances.js
@@ -152,193 +152,6 @@
           notification: {
             poll: pollAsyncJobResult
           }
-        },
-        start: {
-          label: 'label.action.start.instance' ,
-          action: function(args) {
-            $.ajax({
-              url: createURL("startVirtualMachine&id=" + args.context.instances[0].id),
-              dataType: "json",
-              async: true,
-              success: function(json) {
-                var jid = json.startvirtualmachineresponse.jobid;
-                args.response.success(
-                  {_custom:
-                   {jobId: jid,
-                    getUpdatedItem: function(json) {
-                      return json.queryasyncjobresultresponse.jobresult.virtualmachine;
-                    },
-                    getActionFilter: function() {
-                      return vmActionfilter;
-                    }
-                   }
-                  }
-                );
-              }
-            });
-          },
-          messages: {
-            confirm: function(args) {
-              return 'message.action.start.instance';
-            },
-            notification: function(args) {
-              return 'label.action.start.instance';
-            },
-						complete: function(args) {						  
-							if(args.password != null) {
-								alert('Password of the VM is ' + args.password);
-							}
-							return 'label.action.start.instance';
-						}			
-          },
-          notification: {
-            poll: pollAsyncJobResult
-          }
-        },
-        stop: {
-          label: 'label.action.stop.instance',
-          addRow: 'false',
-          createForm: {
-            title: 'label.action.stop.instance',
-            desc: 'message.action.stop.instance',
-            fields: {
-              forced: {
-                label: 'force.stop',
-                isBoolean: true,
-                isChecked: false
-              }
-            }
-          },
-          action: function(args) {
-            var array1 = [];
-            array1.push("&forced=" + (args.data.forced == "on"));
-            $.ajax({
-              url: createURL("stopVirtualMachine&id=" + args.context.instances[0].id + array1.join("")),
-              dataType: "json",
-              async: true,
-              success: function(json) {
-                var jid = json.stopvirtualmachineresponse.jobid;
-                args.response.success(
-                  {_custom:
-                   {jobId: jid,
-                    getUpdatedItem: function(json) {
-                      return json.queryasyncjobresultresponse.jobresult.virtualmachine;
-                    },
-                    getActionFilter: function() {
-                      return vmActionfilter;
-                    }
-                   }
-                  }
-                );
-              }
-            });
-          },
-          messages: {
-            confirm: function(args) {
-              return 'message.action.stop.instance';
-            },
-
-            notification: function(args) {
-              return 'label.action.stop.instance';
-            }
-          },
-          notification: {
-            poll: pollAsyncJobResult
-          }
-        },
-        restart: {
-          label: 'instances.actions.reboot.label',
-          action: function(args) {
-            $.ajax({
-              url: createURL("rebootVirtualMachine&id=" + args.context.instances[0].id),
-              dataType: "json",
-              async: true,
-              success: function(json) {
-                var jid = json.rebootvirtualmachineresponse.jobid;
-                args.response.success(
-                  {_custom:
-                   {jobId: jid,
-                    getUpdatedItem: function(json) {
-                      return json.queryasyncjobresultresponse.jobresult.virtualmachine;
-                    },
-                    getActionFilter: function() {
-                      return vmActionfilter;
-                    }
-                   }
-                  }
-                );
-              }
-            });
-          },
-          messages: {
-            confirm: function(args) {
-              return 'message.action.reboot.instance';
-            },
-            notification: function(args) {
-              return 'instances.actions.reboot.label';
-            }
-          },
-          notification: {
-            poll: pollAsyncJobResult
-          }
-        },
-        destroy: {
-          label: 'label.action.destroy.instance',
-          messages: {
-            confirm: function(args) {
-              return 'message.action.destroy.instance';
-            },            
-            notification: function(args) {
-              return 'label.action.destroy.instance';
-            }
-          },
-          action: function(args) {
-            $.ajax({
-              url: createURL("destroyVirtualMachine&id=" + args.context.instances[0].id),
-              dataType: "json",
-              async: true,
-              success: function(json) {
-                var jid = json.destroyvirtualmachineresponse.jobid;
-                args.response.success(
-                  {_custom:
-                   {jobId: jid,
-                    getUpdatedItem: function(json) {
-                      return json.queryasyncjobresultresponse.jobresult.virtualmachine;
-                    },
-                    getActionFilter: function() {
-                      return vmActionfilter;
-                    }
-                   }
-                  }
-                );
-              }
-            });
-          },
-          notification: {
-            poll: pollAsyncJobResult
-          }
-        },
-        restore: {     
-					label: 'label.action.restore.instance',
-					messages: {
-						confirm: function(args) {
-							return 'message.action.restore.instance';
-						},
-						notification: function(args) {
-							return 'label.action.restore.instance';
-						}
-					},					
-          action: function(args) {
-            $.ajax({
-              url: createURL("recoverVirtualMachine&id=" + args.context.instances[0].id),
-              dataType: "json",
-              async: true,
-              success: function(json) {
-                var item = json.recovervirtualmachineresponse.virtualmachine;
-                args.response.success({data:item});
-              }
-            });
-          }
         }
       },
 
@@ -487,6 +300,7 @@
           },
           stop: {
             label: 'label.action.stop.instance',
+            compactLabel: 'label.stop',
             createForm: {
               title: 'Stop instance',
               desc: 'message.action.stop.instance',
@@ -536,6 +350,7 @@
           },
           restart: {
             label: 'label.action.reboot.instance',
+            compactLabel: 'label.reboot',
             action: function(args) {
               $.ajax({
                 url: createURL("rebootVirtualMachine&id=" + args.context.instances[0].id),
@@ -572,6 +387,7 @@
           },
           destroy: {
             label: 'label.action.destroy.instance',
+            compactLabel: 'label.destroy',
             messages: {
               confirm: function(args) {
                 return 'message.action.destroy.instance';
@@ -608,6 +424,7 @@
           },
           restore: {
             label: 'label.action.restore.instance',
+            compactLabel: 'label.restore',
             messages: {
               confirm: function(args) {
                 return 'message.action.restore.instance';
@@ -635,7 +452,7 @@
           },
 
           edit: {
-            label: 'Edit',
+            label: 'label.edit',
             action: function(args) {
               var array1 = [];							
 							if(args.data.displayname != args.context.instances[0].displayname)
@@ -982,6 +799,7 @@
 
           migrate: {
             label: 'label.migrate.instance.to.host',
+            compactLabel: 'label.migrate.to.host',
             messages: {
               confirm: function(args) {
                 return 'message.migrate.instance.to.host';
@@ -1060,6 +878,7 @@
 
           migrateToAnotherStorage: {
             label: 'label.migrate.instance.to.ps',
+            compactLabel: 'label.migrate.to.storage',
             messages: {
               confirm: function(args) {
                 return 'message.migrate.instance.to.ps';

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/scripts/network.js
----------------------------------------------------------------------
diff --git a/ui/scripts/network.js b/ui/scripts/network.js
index 520998a..65adf66 100644
--- a/ui/scripts/network.js
+++ b/ui/scripts/network.js
@@ -3880,7 +3880,7 @@
             name: 'label.details',											
 						actions: {
               configureVpc: {
-                label: 'label.edit.vpc',
+                label: 'label.configure',
                 textLabel: 'label.configure',
                 action: {
                   custom: cloudStack.uiCustom.vpc(cloudStack.vpc)

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/scripts/system.js
----------------------------------------------------------------------
diff --git a/ui/scripts/system.js b/ui/scripts/system.js
index 5a718fc..7611853 100644
--- a/ui/scripts/system.js
+++ b/ui/scripts/system.js
@@ -3828,6 +3828,34 @@
                   }
                 }
               },
+
+              dataProvider: function(args) {
+                var array1 = [];
+                if(args.filterBy != null) {
+                  if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
+                    switch(args.filterBy.search.by) {
+                      case "name":
+                        if(args.filterBy.search.value.length > 0)
+                          array1.push("&keyword=" + args.filterBy.search.value);
+                        break;
+                    }
+                  }
+                }
+
+                $.ajax({
+                  url: createURL("listZones&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
+                  dataType: "json",
+                  async: true,
+                  success: function(json) {
+                    zoneObjs = json.listzonesresponse.zone;
+                    args.response.success({
+                      actionFilter: zoneActionfilter,
+                      data:zoneObjs
+                    });
+                  }
+                });
+              },
+
               actions: {
                 add: {
                   label: 'label.add.zone',
@@ -3912,127 +3940,98 @@
                       }
                     });
                   }
-                },
+                }
+              },
 
-                enable: {
-                  label: 'label.action.enable.zone',
-                  messages: {
-                    confirm: function(args) {
-                      return 'message.action.enable.zone';
+              detailView: {
+                isMaximized: true,
+                actions: {
+                  enable: {
+                    label: 'label.action.enable.zone',
+                    messages: {
+                      confirm: function(args) {
+                        return 'message.action.enable.zone';
+                      },
+                      notification: function(args) {
+                        return 'label.action.enable.zone';
+                      }
                     },
-                    notification: function(args) {
-                      return 'label.action.enable.zone';
-                    }
-                  },
-                  action: function(args) {
-                    $.ajax({
-                      url: createURL("updateZone&id=" + args.context.physicalResources[0].id + "&allocationstate=Enabled"),  //embedded objects in listView is called physicalResources while embedded objects in detailView is called zones
-                      dataType: "json",
-                      async: true,
-                      success: function(json) {
-                        var item = json.updatezoneresponse.zone;
-                        args.response.success({
-                          actionFilter: zoneActionfilter,
-                          data:item
-                        });
+                    action: function(args) {
+                      $.ajax({
+                        url: createURL("updateZone&id=" + args.context.physicalResources[0].id + "&allocationstate=Enabled"),  //embedded objects in listView is called physicalResources while embedded objects in detailView is called zones
+                        dataType: "json",
+                        async: true,
+                        success: function(json) {
+                          var item = json.updatezoneresponse.zone;
+                          args.response.success({
+                            actionFilter: zoneActionfilter,
+                            data:item
+                          });
+                        }
+                      });
+                    },
+                    notification: {
+                      poll: function(args) {
+                        args.complete();
                       }
-                    });
-                  },
-                  notification: {
-                    poll: function(args) {
-                      args.complete();
                     }
-                  }
-                },
+                  },
 
-                disable: {
-                  label: 'label.action.disable.zone',
-                  messages: {
-                    confirm: function(args) {
-                      return 'message.action.disable.zone';
+                  disable: {
+                    label: 'label.action.disable.zone',
+                    messages: {
+                      confirm: function(args) {
+                        return 'message.action.disable.zone';
+                      },
+                      notification: function(args) {
+                        return 'label.action.disable.zone';
+                      }
                     },
-                    notification: function(args) {
-                      return 'label.action.disable.zone';
-                    }
-                  },
-                  action: function(args) {
-                    $.ajax({
-                      url: createURL("updateZone&id=" + args.context.physicalResources[0].id + "&allocationstate=Disabled"),  //embedded objects in listView is called physicalResources while embedded objects in detailView is called zones
-                      dataType: "json",
-                      async: true,
-                      success: function(json) {
-                        var item = json.updatezoneresponse.zone;
-                        args.response.success({
-                          actionFilter: zoneActionfilter,
-                          data:item
-                        });
+                    action: function(args) {
+                      $.ajax({
+                        url: createURL("updateZone&id=" + args.context.physicalResources[0].id + "&allocationstate=Disabled"),  //embedded objects in listView is called physicalResources while embedded objects in detailView is called zones
+                        dataType: "json",
+                        async: true,
+                        success: function(json) {
+                          var item = json.updatezoneresponse.zone;
+                          args.response.success({
+                            actionFilter: zoneActionfilter,
+                            data:item
+                          });
+                        }
+                      });
+                    },
+                    notification: {
+                      poll: function(args) {
+                        args.complete();
                       }
-                    });
-                  },
-                  notification: {
-                    poll: function(args) {
-                      args.complete();
                     }
-                  }
-                },
+                  },
 
-                'remove': {
-                  label: 'label.action.delete.zone',
-                  messages: {
-                    confirm: function(args) {
-                      return 'message.action.delete.zone';
+                  'remove': {
+                    label: 'label.action.delete.zone',
+                    messages: {
+                      confirm: function(args) {
+                        return 'message.action.delete.zone';
+                      },
+                      notification: function(args) {
+                        return 'label.action.delete.zone';
+                      }
                     },
-                    notification: function(args) {
-                      return 'label.action.delete.zone';
+                    action: function(args) {
+                      $.ajax({
+                        url: createURL("deleteZone&id=" + args.context.physicalResources[0].id),  //embedded objects in listView is called physicalResources while embedded objects in detailView is called zones
+                        dataType: "json",
+                        async: true,
+                        success: function(json) {
+                          args.response.success({data:{}});
+                        }
+                      });
+                    },
+                    notification: {
+                      poll: function(args) { args.complete(); }
                     }
                   },
-                  action: function(args) {
-                    $.ajax({
-                      url: createURL("deleteZone&id=" + args.context.physicalResources[0].id),  //embedded objects in listView is called physicalResources while embedded objects in detailView is called zones
-                      dataType: "json",
-                      async: true,
-                      success: function(json) {
-                        args.response.success({data:{}});
-                      }
-                    });
-                  },
-                  notification: {
-                    poll: function(args) { args.complete(); }
-                  }
-                }
-
-              },
-
-              dataProvider: function(args) {
-                var array1 = [];
-                if(args.filterBy != null) {
-                  if(args.filterBy.search != null && args.filterBy.search.by != null && args.filterBy.search.value != null) {
-                    switch(args.filterBy.search.by) {
-                      case "name":
-                        if(args.filterBy.search.value.length > 0)
-                          array1.push("&keyword=" + args.filterBy.search.value);
-                        break;
-                    }
-                  }
-                }
-
-                $.ajax({
-                  url: createURL("listZones&page=" + args.page + "&pagesize=" + pageSize + array1.join("")),
-                  dataType: "json",
-                  async: true,
-                  success: function(json) {
-                    zoneObjs = json.listzonesresponse.zone;
-                    args.response.success({
-                      actionFilter: zoneActionfilter,
-                      data:zoneObjs
-                    });
-                  }
-                });
-              },
-
-              detailView: {
-                isMaximized: true,
-                actions: {
                   edit: {
                     label: 'label.edit',
                     action: function(args) {
@@ -4106,7 +4105,10 @@
                         },
                         success: function(json) {
                           selectedZoneObj = json.listzonesresponse.zone[0];
-                          args.response.success({ data: json.listzonesresponse.zone[0] });
+                          args.response.success({
+                            data: json.listzonesresponse.zone[0],
+                            actionFilter: zoneActionfilter
+                          });
                         }
                       });
                     }
@@ -4187,6 +4189,7 @@
                       },
 
                       detailView: {
+                        noCompact: true,
                         name: 'System VM details',
                         actions: {
                           start: {

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/scripts/ui-custom/zoneChart.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui-custom/zoneChart.js b/ui/scripts/ui-custom/zoneChart.js
index dcc6dac..12ba6aa 100644
--- a/ui/scripts/ui-custom/zoneChart.js
+++ b/ui/scripts/ui-custom/zoneChart.js
@@ -307,6 +307,7 @@
                     args.response.success({ actionFilter: actionFilter, data: data });
                   },
                   detailView: {
+                    noCompact: true,
                     tabs: {
                       network: {
                         title: 'Network',

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/scripts/ui/widgets/detailView.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/detailView.js b/ui/scripts/ui/widgets/detailView.js
index a51cfcc..362b5c1 100644
--- a/ui/scripts/ui/widgets/detailView.js
+++ b/ui/scripts/ui/widgets/detailView.js
@@ -21,6 +21,9 @@
     if (!$row) return;
 
     var $listView = $row.closest('.list-view');
+
+    if (!$listView.parents('html').size()) return;
+
     var $newRow;
     var jsonObj = $row.data('json-obj');
 
@@ -94,6 +97,7 @@
         if (!options) options = {};
 
         var $form = options.$form;
+        var viewArgs = $detailView.data('view-args');
 
         if (customAction && !noAdd) {
           customAction({
@@ -119,7 +123,7 @@
 
                 // Success
                 function(args) {
-                  if (!$detailView.is(':visible')) return;
+                  if (!$detailView.parents('html').size()) return;
 
                   $loading.remove();
                   replaceListViewItem($detailView, args.data);
@@ -162,10 +166,10 @@
                 cloudStack.ui.notifications.add(
                   notification,
                   function(args2) { //name parameter as "args2" instead of "args" to avoid override "args" from success: function(args) {
-                    if ($detailView.is(':visible')) {
+                    if ($detailView.parents('html').size()) {
                       $loading.remove();
 
-                      if (!noRefresh) {
+                      if (!noRefresh && !viewArgs.compact) {
                         updateTabContent(args.data? args.data : args2.data);
                       }
                     }
@@ -180,6 +184,10 @@
                     }));
 
                     replaceListViewItem($detailView, args.data ? args.data : args2.data);
+
+                    if (viewArgs && viewArgs.onActionComplete) {
+                      viewArgs.onActionComplete();
+                    }
                   },
 
                   {},
@@ -202,6 +210,10 @@
               }
             }
           });
+
+          if (viewArgs && viewArgs.onPerformAction) {
+            viewArgs.onPerformAction();
+          }
         }
       };
 
@@ -646,11 +658,16 @@
         });
 
       $.each(actions, function(key, value) {
-        if ($.inArray(key, allowedActions) == -1) return true;
+        if ($.inArray(key, allowedActions) == -1 ||
+           (key == 'edit' && options.compact)) return true;
 
         var $action = $('<div></div>')
               .addClass('action').addClass(key)
-              .appendTo($actions.find('div.buttons'));
+              .appendTo($actions.find('div.buttons'))
+              .attr({
+                title: _l(value.label),
+                alt: _l(value.label)
+              });
         var $actionLink = $('<a></a>')
               .attr({
                 href: '#',
@@ -664,11 +681,17 @@
               )
               .appendTo($action);
 
-        if (value.textLabel) {
+        if (value.textLabel || options.compact) {
           $action
             .addClass('single text')
             .prepend(
-              $('<span>').addClass('label').html(_l(value.textLabel))
+              $('<span>').addClass('label').html(
+                _l(
+                  options.compact ?
+                    (value.compactLabel ?
+                     value.compactLabel : value.label) : value.textLabel
+                )
+              )
             );
         }
 
@@ -835,8 +858,9 @@
         $actions = makeActionButtons(detailViewArgs.actions, {
           actionFilter: actionFilter,
           data: data,
-          context: $detailView.data('view-args').context
-        });
+          context: $detailView.data('view-args').context,
+          compact: detailViewArgs.compact
+        }).prependTo($firstRow.closest('div.detail-group').closest('.details'));
 
       // 'View all' button
       var showViewAll = detailViewArgs.viewAll ?
@@ -912,9 +936,11 @@
       { activeTab: targetTabID }
     );
 
-    $tabContent.append(
-      $('<div>').addClass('loading-overlay')
-    );
+    if (!$detailView.data('view-args').compact) {
+      $tabContent.append(
+        $('<div>').addClass('loading-overlay')
+      );
+    }
 
     return dataProvider({
       tab: targetTabID,
@@ -968,6 +994,10 @@
             ).appendTo($detailView.find('.main-groups'));
           }
 
+          if ($detailView.data('view-args').onLoad) {
+            $detailView.data('view-args').onLoad($detailView);
+          }
+
           return true;
         },
         error: function() {
@@ -986,6 +1016,8 @@
     var tabFilter = options.tabFilter;
     var context = options.context ? options.context : {};
     var updateContext = $detailView.data('view-args').updateContext;
+    var compact = options.compact;
+    var tabTotal = 0;
 
     if (updateContext) {
       $.extend($detailView.data('view-args').context, updateContext({
@@ -1010,6 +1042,7 @@
     $.each(tabs, function(key, value) {
       // Don't render tab, if filtered out
       if ($.inArray(key, removedTabs) > -1) return true;
+      if (compact && tabTotal) return true;
 
       var propGroup = key;
       var prop = value;
@@ -1027,6 +1060,8 @@
       $tabContent.data('detail-view-tab-id', key);
       $tabContent.data('detail-view-tab-data', value);
 
+      tabTotal++;
+
       return true;
     });
 
@@ -1059,9 +1094,12 @@
 
   $.fn.detailView = function(args, options) {
     var $detailView = this;
-    
+    var compact = args.compact;
+    var $toolbar = makeToolbar();
+    var $tabs;
+
     if (options == 'refresh') {
-      var $tabs = replaceTabs($detailView, args.tabs, {
+      $tabs = replaceTabs($detailView, args.tabs, {
         context: args.context,
         tabFilter: args.tabFilter
       });
@@ -1073,18 +1111,22 @@
         $detailView.data('list-view-row', args.$listViewRow);
       }
 
-      // Create toolbar
-      var $toolbar = makeToolbar().appendTo($detailView);
-
-      // Create tabs
-      var $tabs = makeTabs($detailView, args.tabs, {
+      $tabs = makeTabs($detailView, args.tabs, {
+        compact: compact,
         context: args.context,
         tabFilter: args.tabFilter
-      }).appendTo($detailView);
+      });
+
+      $tabs.appendTo($detailView);
+      
+      // Create toolbar
+      if (!compact) {
+        $toolbar.appendTo($detailView);
+      }
     }
 
     $detailView.tabs();
-
+    
     return $detailView;
   };
 

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/991557bf/ui/scripts/ui/widgets/listView.js
----------------------------------------------------------------------
diff --git a/ui/scripts/ui/widgets/listView.js b/ui/scripts/ui/widgets/listView.js
index a6d2113..369a1ca 100644
--- a/ui/scripts/ui/widgets/listView.js
+++ b/ui/scripts/ui/widgets/listView.js
@@ -614,9 +614,12 @@
 
     var $thead = $('<thead>').prependTo($table).append($('<tr>'));
     var reorder = options.reorder;
-
+    var detailView = options.detailView;
+    var viewArgs = $table.closest('.list-view').data('view-args');
+    var uiCustom = viewArgs.uiCustom;
     var hiddenFields = [];
-    if(preFilter != null)
+    
+    if (preFilter != null)
       hiddenFields = preFilter();
 
     $.each(fields, function(key) {
@@ -628,14 +631,18 @@
       if ($th.index()) $th.addClass('reduced-hide');
 
       $th.html(_l(field.label));
+
+      return true;
     });
 
+    // Re-order row buttons
     if (reorder) {
       $thead.find('tr').append(
         $('<th>').html(_l('label.order')).addClass('reorder-actions reduced-hide')
       );
     }
 
+    // Actions column
     if (actions && renderActionCol(actions)) {
       $thead.find('tr').append(
         $('<th></th>')
@@ -644,6 +651,15 @@
       );
     }
 
+    // Quick view
+    if (detailView && !detailView.noCompact && !uiCustom) {
+      $thead.find('tr').append(
+        $('<th></th>')
+          .html('Quickview')
+          .addClass('quick-view reduced-hide')
+      );
+    }
+
     return $thead;
   };
 
@@ -665,6 +681,8 @@
         }).html(_l(this.label));
 
         $option.appendTo($filterSelect);
+
+        return true;
       });
 
     return $filters.appendTo($toolbar);
@@ -765,7 +783,7 @@
   /**
    * Initialize detail view for specific ID from list view
    */
-  var createDetailView = function(args, complete, $row) {
+  var createDetailView = function(args, complete, $row, options) {
     var $panel = args.$panel;
     var title = args.title;
     var id = args.id;
@@ -775,9 +793,11 @@
       jsonObj: args.jsonObj,
       section: args.section,
       context: args.context,
-      $listViewRow: $row
+      $listViewRow: $row,
+      compact: options ? options.compact : false
     });
 
+    var noPanel = options ? options.noPanel : false;
     var $detailView, $detailsPanel;
     var panelArgs = {
       title: title,
@@ -798,14 +818,19 @@
       }
     };
 
-    // Create panel
-    $detailsPanel = data.$browser.cloudBrowser('addPanel', panelArgs);
+    if (noPanel) {
+      return $('<div>').detailView(data);
+    } else {
+      $detailsPanel = data.$browser.cloudBrowser('addPanel', panelArgs);
+    }
   };
 
   var addTableRows = function(preFilter, fields, data, $tbody, actions, options) {
     if (!options) options = {};
     var rows = [];
     var reorder = options.reorder;
+    var detailView = options.detailView;
+    var uiCustom = $tbody.closest('.list-view').data('view-args').uiCustom;
 
     if (!data || ($.isArray(data) && !data.length)) {
       if (!$tbody.find('tr').size()) {
@@ -824,6 +849,7 @@
     $(data).each(function() {
       var dataItem = this;
       var id = dataItem.id;
+      var $quickView;
 
       var $tr = $('<tr>');
       rows.push($tr);
@@ -851,7 +877,11 @@
 
         if (field.indicator) {
           $td.addClass('state').addClass(field.indicator[content]);
+
+          // Disabling indicator for now per new design
+          //$tr.find('td:first').addClass('item-state-' + field.indicator[content]);
         }
+        
         if (field.id == true) id = field.id;
         if ($td.index()) $td.addClass('reduced-hide');
         if (field.action) {
@@ -992,6 +1022,95 @@
           }
         );
       }
+
+      // Add quick view
+      if (detailView && !detailView.noCompact && !uiCustom) {
+        $quickView = $('<td>').addClass('quick-view reduced-hide')
+          .append(
+            $('<span>').addClass('icon').html('&nbsp;')
+          )
+          .appendTo($tr);
+        $quickView.mouseover(
+          // Show quick view
+          function() {
+            var $quickViewTooltip = $('<div>').addClass('quick-view-tooltip');
+            var $tr = $quickView.closest('tr');
+            var $listView = $tr.closest('.list-view');
+            var $title = $('<div>').addClass('title');
+            var $detailsContainer = $('<div>').addClass('container').appendTo($quickViewTooltip);
+            var context = $.extend(true, {}, options.context);
+            var activeSection = $listView.data('view-args').activeSection;
+            var itemID = $tr.data('list-view-item-id');
+            var jsonObj = $tr.data('json-obj');
+            var $loading = $('<div>').addClass('loading-overlay').appendTo($detailsContainer);
+
+            if ($tr.hasClass('loading')) return;
+
+            // Title
+            $title.append(
+              $('<span>').html('Quickview: '),
+              $('<span>').addClass('title').html(
+                cloudStack.concat(
+                  $tr.find('td:first span').html(), 30
+                )
+              ),
+              $('<span>').addClass('icon').html('&nbsp;')
+            );
+            $quickViewTooltip.append($title);
+
+            // Setup positioning
+            $quickViewTooltip.hide().appendTo('#container').fadeIn(200, function() {
+              if (!$quickViewTooltip.is(':visible')) return;
+              
+              // Init detail view
+              context[activeSection] = [jsonObj];
+              createDetailView(
+                {
+                  data: $.extend(true, {}, detailView, {
+                    onLoad: function($detailView) {
+                      $loading.remove();
+                      $detailView.slideToggle('fast');
+                    },
+                    onPerformAction: function() {
+                      $tr.addClass('loading').find('td:last').prepend($('<div>').addClass('loading'));
+                      $quickViewTooltip.hide();
+                    },
+                    onActionComplete: function() {
+                      $tr.removeClass('loading').find('td:last .loading').remove();
+                      $quickViewTooltip.remove();
+                    }
+                  }),
+                  id: itemID,
+                  jsonObj: jsonObj,
+                  section: activeSection,
+                  context: context,
+                  $listViewRow: $tr
+                },
+                function($detailView) { //complete(), callback funcion
+                  $detailView.data('list-view', $listView);
+                }, $tr,
+                {
+                  compact: true,
+                  noPanel: true
+                }
+              ).appendTo($detailsContainer).hide();
+            });
+            $quickViewTooltip.css({
+              position: 'absolute',
+              left: $tr.width() + ($quickViewTooltip.width() -
+                                   ($quickViewTooltip.width() / 2)),
+              top: $quickView.offset().top - 50,
+              zIndex: $tr.closest('.panel').zIndex() + 1
+            });
+            
+            $quickViewTooltip.mouseleave(function() {
+              if (!$('.overlay:visible').size()) {
+                $quickViewTooltip.remove();
+              }
+            });
+          }
+        );
+      }
     });
 
     return rows;
@@ -1051,7 +1170,8 @@
             addTableRows(preFilter, fields, args.data, $tbody, actions, {
               actionFilter: args.actionFilter,
               context: context,
-              reorder: reorder
+              reorder: reorder,
+              detailView: options.detailView
             });
             $table.dataTable(null, { noSelect: uiCustom });
 
@@ -1272,7 +1392,10 @@
                  listViewData.fields,
                  $table,
                  listViewData.actions,
-                 { reorder: reorder });
+                 {
+                   reorder: reorder,
+                   detailView: listViewData.detailView
+                 });
     createFilters($toolbar, listViewData.filters);
     createSearchBar($toolbar, listViewData);
 
@@ -1296,7 +1419,8 @@
       listViewData.actions,
       {
         context: args.context,
-        reorder: reorder
+        reorder: reorder,
+        detailView: listViewData.detailView
       }
     );
 
@@ -1348,7 +1472,8 @@
         listViewData.actions,
         {
           context: $listView.data('view-args').context,
-          reorder: listViewData.reorder
+          reorder: listViewData.reorder,
+          detailView: listViewData.detailView
         }
       );
     };
@@ -1397,7 +1522,8 @@
         listViewData.actions,
         {
           context: $listView.data('view-args').context,
-          reorder: listViewData.reorder
+          reorder: listViewData.reorder,
+          detailView: listViewData.detailView
         }
       );
     };
@@ -1443,12 +1569,17 @@
 					  filterBy.advSearch = $listView.data('advSearch');
 					}
 					
-          loadBody($table, listViewData.dataProvider, listViewData.preFilter, listViewData.fields, true, {
+          loadBody(
+            $table,
+            listViewData.dataProvider,
+            listViewData.preFilter,
+            listViewData.fields, true, {
             context: context,
             page: page,
             filterBy: filterBy
           }, actions, {
-            reorder: listViewData.reorder
+            reorder: listViewData.reorder,
+            detailView: listViewData.detailView
           });
         }
       }, 500);
@@ -1608,7 +1739,8 @@
       {
         prepend: true,
         actionFilter: actionFilter,
-        reorder: reorder
+        reorder: reorder,
+        detailView: targetArgs.detailView
       }
     )[0];
     listView.find('table').dataTable('refresh');
@@ -1639,7 +1771,8 @@
       targetArgs.actions,
       {
         actionFilter: actionFilter ? actionFilter : defaultActionFilter,
-        reorder: reorder
+        reorder: reorder,
+        detailView: targetArgs.detailView
       }
     )[0];
 
@@ -1680,7 +1813,8 @@
         null,
         listViewArgs.actions,
         {
-          context: this.data('view-args').context
+          context: this.data('view-args').context,
+          detailView: listViewArgs.detailView
         }
       );
     } else {