Updated Branches:
  refs/heads/blur-console-v2 f930739a9 -> 4d2f7ccf9

Got the extra functionality on the tables tab working


Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/4d2f7ccf
Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/4d2f7ccf
Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/4d2f7ccf

Branch: refs/heads/blur-console-v2
Commit: 4d2f7ccf914ed081eae51c590fcfd682bcf5a39d
Parents: f930739
Author: Chris Rohr <[email protected]>
Authored: Mon Nov 25 08:15:12 2013 -0500
Committer: Chris Rohr <[email protected]>
Committed: Mon Nov 25 08:15:12 2013 -0500

----------------------------------------------------------------------
 .../org/apache/blur/console/model/Column.java   |  46 ++++
 .../org/apache/blur/console/model/Family.java   |  25 +++
 .../blur/console/servlets/TablesServlet.java    | 118 ++++++++--
 .../org/apache/blur/console/util/TableUtil.java |  56 ++++-
 .../apache/blur/console/webapp/css/console.css  | 132 +++++++++++-
 .../org/apache/blur/console/webapp/js/app.js    |   4 +
 .../apache/blur/console/webapp/js/dashboard.js  | 213 ++++++++++---------
 .../org/apache/blur/console/webapp/js/tables.js |  88 +++++++-
 .../webapp/partials/cluster_table_list.tpl.html |  54 +++++
 .../console/webapp/partials/dashboard.tpl.html  |   5 +-
 .../console/webapp/partials/schema.tpl.html     |  77 +++++++
 .../console/webapp/partials/tables.tpl.html     |  54 +----
 12 files changed, 685 insertions(+), 187 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/java/org/apache/blur/console/model/Column.java
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/java/org/apache/blur/console/model/Column.java 
b/contrib/blur-console/src/main/java/org/apache/blur/console/model/Column.java
new file mode 100644
index 0000000..30297d3
--- /dev/null
+++ 
b/contrib/blur-console/src/main/java/org/apache/blur/console/model/Column.java
@@ -0,0 +1,46 @@
+package org.apache.blur.console.model;
+
+import java.util.Map;
+
+public class Column {
+       private String name;
+       private boolean fullTextIndexed;
+       private String subColumn;
+       private String type;
+       private Map<String, String> props;
+       
+       public Column(String name) {
+               this.name = name;
+       }
+       
+       public String getName() {
+               return name;
+       }
+       public void setName(String name) {
+               this.name = name;
+       }
+       public boolean isFullTextIndexed() {
+               return fullTextIndexed;
+       }
+       public void setFullTextIndexed(boolean fullTextIndexed) {
+               this.fullTextIndexed = fullTextIndexed;
+       }
+       public String getSubColumn() {
+               return subColumn;
+       }
+       public void setSubColumn(String subColumn) {
+               this.subColumn = subColumn;
+       }
+       public String getType() {
+               return type;
+       }
+       public void setType(String type) {
+               this.type = type;
+       }
+       public Map<String, String> getProps() {
+               return props;
+       }
+       public void setProps(Map<String, String> props) {
+               this.props = props;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/java/org/apache/blur/console/model/Family.java
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/java/org/apache/blur/console/model/Family.java 
b/contrib/blur-console/src/main/java/org/apache/blur/console/model/Family.java
new file mode 100644
index 0000000..39affb6
--- /dev/null
+++ 
b/contrib/blur-console/src/main/java/org/apache/blur/console/model/Family.java
@@ -0,0 +1,25 @@
+package org.apache.blur.console.model;
+
+import java.util.List;
+
+public class Family {
+       private String name;
+       private List<Column> columns;
+       
+       public Family(String name) {
+               this.name = name;
+       }
+       
+       public String getName() {
+               return name;
+       }
+       public void setName(String name) {
+               this.name = name;
+       }
+       public List<Column> getColumns() {
+               return columns;
+       }
+       public void setColumns(List<Column> columns) {
+               this.columns = columns;
+       }
+}

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/java/org/apache/blur/console/servlets/TablesServlet.java
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/java/org/apache/blur/console/servlets/TablesServlet.java
 
b/contrib/blur-console/src/main/java/org/apache/blur/console/servlets/TablesServlet.java
index a71e0b8..32ca756 100644
--- 
a/contrib/blur-console/src/main/java/org/apache/blur/console/servlets/TablesServlet.java
+++ 
b/contrib/blur-console/src/main/java/org/apache/blur/console/servlets/TablesServlet.java
@@ -18,7 +18,9 @@ package org.apache.blur.console.servlets;
  */
 
 import java.io.IOException;
+import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
@@ -35,21 +37,30 @@ import org.codehaus.jackson.map.ObjectMapper;
 
 public class TablesServlet extends HttpServlet {
        private static final long serialVersionUID = -5725846390100596115L;
-       private static Pattern tableTermsPattern = 
Pattern.compile("/(.*)/(.*)/terms");
+       private static Pattern tableSchemaPattern = 
Pattern.compile("/(.*)/schema");
+       private static Pattern tableEnablePattern = 
Pattern.compile("/(.*)/enable");
+       private static Pattern tableDisablePattern = 
Pattern.compile("/(.*)/disable");
+       private static Pattern tableDeletePattern = 
Pattern.compile("/(.*)/delete");
+       private static Pattern tableTermsPattern = 
Pattern.compile("/(.*)/(.*)/(.*)/terms");
 
+       @SuppressWarnings("unchecked")
        @Override
        protected void doGet(HttpServletRequest request, HttpServletResponse 
response) throws ServletException, IOException {
                String path = request.getPathInfo();
                Matcher m;
                if ("/summaries".equalsIgnoreCase(path)) {
                        sendSummaries(response);
+               } else if ((m = tableSchemaPattern.matcher(path)).matches()) {
+                       sendSchema(response, m.group(1));
                } else if ((m = tableTermsPattern.matcher(path)).matches()) {
-//                     sendTerms(response, m.group(1), m.group(2));
-               } 
-//             else if ("/query/status".equalsIgnoreCase(path)) {
-//                     sendQueryStatus(response);
-//             } 
-               else {
+                       sendTerms(response, m.group(1), m.group(2), m.group(3), 
request.getParameterMap());
+               } else if ((m = tableEnablePattern.matcher(path)).matches()) {
+                       enableTable(response, m.group(1));
+               } else if ((m = tableDisablePattern.matcher(path)).matches()) {
+                       disableTable(response, m.group(1));
+               } else if ((m = tableDeletePattern.matcher(path)).matches()) {
+                       deleteTable(response, m.group(1), 
request.getParameterMap());
+               } else {
                        response.setStatus(404);
                        IOUtils.write("Route [" + path + "] doesn't exist", 
response.getOutputStream());
                }
@@ -63,6 +74,13 @@ public class TablesServlet extends HttpServlet {
                IOUtils.write(body, response.getOutputStream());
        }
        
+       private void sendGenericOk(HttpServletResponse response) throws 
IOException {
+               response.setContentType("text/plain");
+               response.setContentLength(6);
+               response.setStatus(200);
+               IOUtils.write("success", response.getOutputStream());
+       }
+       
        private void sendSummaries(HttpServletResponse response) throws 
IOException {
                Map<String, Object> tableSummaries = new HashMap<String, 
Object>();
                try {
@@ -77,17 +95,77 @@ public class TablesServlet extends HttpServlet {
                HttpUtil.sendResponse(response, new 
ObjectMapper().writeValueAsString(tableSummaries), HttpUtil.JSON);
        }
        
-//     private void sendTerms(HttpServletResponse response, String cluster, 
String table) {
-//             Map<String, List<Map<String, Object>>> tableSummaries = new 
HashMap<String, List<Map<String,Object>>>();
-//             try {
-//                     tableSummaries = TableUtil.getTableSummaries();
-//             } catch (IOException e) {
-//                     throw new IOException(e);
-//             } catch (Exception e) {
-//                     sendError(response, e);
-//                     return;
-//             }
-//             
-//             HttpUtil.sendResponse(response, new 
ObjectMapper().writeValueAsString(tableSummaries), HttpUtil.JSON);
-//     }
+       private void sendSchema(HttpServletResponse response, String table) 
throws IOException{
+               Object schema;
+               try {
+                       schema = TableUtil.getSchema(table);
+               } catch (IOException e) {
+                       throw new IOException(e);
+               } catch (Exception e) {
+                       sendError(response, e);
+                       return;
+               }
+               
+               HttpUtil.sendResponse(response, new 
ObjectMapper().writeValueAsString(schema), HttpUtil.JSON);
+       }
+       
+       private void sendTerms(HttpServletResponse response, String table, 
String family, String column, Map<String, String[]> params) throws IOException {
+               List<String> terms = new ArrayList<String>();
+               try {
+                       String startWith = null;
+                       if (params.containsKey("startWith")) {
+                               startWith = params.get("startWith")[0];
+                       }
+                       
+                       terms = TableUtil.getTerms(table, family, column, 
startWith);
+               } catch (IOException e) {
+                       throw new IOException(e);
+               } catch (Exception e) {
+                       sendError(response, e);
+                       return;
+               }
+               
+               HttpUtil.sendResponse(response, new 
ObjectMapper().writeValueAsString(terms), HttpUtil.JSON);
+       }
+       
+       private void enableTable(HttpServletResponse response, String table) 
throws IOException {
+               try {
+                       TableUtil.enableTable(table);
+               } catch (IOException e) {
+                       throw new IOException(e);
+               } catch (Exception e) {
+                       sendError(response, e);
+                       return;
+               }
+               sendGenericOk(response);
+       }
+       
+       private void disableTable(HttpServletResponse response, String table) 
throws IOException {
+               try {
+                       TableUtil.disableTable(table);
+               } catch (IOException e) {
+                       throw new IOException(e);
+               } catch (Exception e) {
+                       sendError(response, e);
+                       return;
+               }
+               sendGenericOk(response);
+       }
+       
+       private void deleteTable(HttpServletResponse response, String table, 
Map<String, String[]> params) throws IOException {
+               try {
+                       String includeFiles = null;
+                       if (params.containsKey("includeFiles")) {
+                               includeFiles = params.get("includeFiles")[0];
+                       }
+                       
+                       TableUtil.deleteTable(table, 
Boolean.parseBoolean(includeFiles));
+               } catch (IOException e) {
+                       throw new IOException(e);
+               } catch (Exception e) {
+                       sendError(response, e);
+                       return;
+               }
+               sendGenericOk(response);
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/java/org/apache/blur/console/util/TableUtil.java
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/java/org/apache/blur/console/util/TableUtil.java
 
b/contrib/blur-console/src/main/java/org/apache/blur/console/util/TableUtil.java
index b17e1f3..37b406f 100644
--- 
a/contrib/blur-console/src/main/java/org/apache/blur/console/util/TableUtil.java
+++ 
b/contrib/blur-console/src/main/java/org/apache/blur/console/util/TableUtil.java
@@ -23,10 +23,14 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.blur.console.model.Column;
+import org.apache.blur.console.model.Family;
 import org.apache.blur.thirdparty.thrift_0_9_0.TException;
 import org.apache.blur.thrift.BlurClient;
 import org.apache.blur.thrift.generated.Blur.Iface;
 import org.apache.blur.thrift.generated.BlurException;
+import org.apache.blur.thrift.generated.ColumnDefinition;
+import org.apache.blur.thrift.generated.Schema;
 import org.apache.blur.thrift.generated.TableDescriptor;
 import org.apache.blur.thrift.generated.TableStats;
 
@@ -142,9 +146,51 @@ public class TableUtil {
                return data;
        }
        
-//     public static Object getTerms(String cluster, String table) throws 
IOException {
-//             Iface client = 
BlurClient.getClient(Config.getConnectionString());
-//             
-//             client.terms(arg0, arg1, arg2, arg3, arg4)
-//     }
+       public static Object getSchema(String table) throws IOException, 
BlurException, TException {
+               Iface client = 
BlurClient.getClient(Config.getConnectionString());
+               
+               Schema schema = client.schema(table);
+               
+               List<Family> schemaList = new ArrayList<Family>();
+               for (Map.Entry<String, Map<String, ColumnDefinition>> famEntry 
: schema.getFamilies().entrySet()) {
+                       Family family = new Family(famEntry.getKey());
+                       List<Column> columns = new ArrayList<Column>();
+                       family.setColumns(columns);
+                       for(Map.Entry<String, ColumnDefinition> colEntry : 
famEntry.getValue().entrySet()) {
+                               ColumnDefinition def = colEntry.getValue();
+                               
+                               Column column = new Column(colEntry.getKey());
+                               
column.setFullTextIndexed(def.isFieldLessIndexed());
+                               column.setSubColumn(def.getSubColumnName());
+                               column.setType(def.getFieldType());
+                               column.setProps(def.getProperties());
+                               columns.add(column);
+                       }
+                       schemaList.add(family);
+               }
+               
+               return schemaList;
+       }
+       
+       public static List<String> getTerms(String table, String family, String 
column, String startWith) throws IOException, BlurException, TException {
+               Iface client = 
BlurClient.getClient(Config.getConnectionString());
+               
+               return client.terms(table, family, column, startWith, 
(short)10);
+       }
+       
+       public static void disableTable(String table) throws BlurException, 
TException, IOException {
+               Iface client = 
BlurClient.getClient(Config.getConnectionString());
+               
+               client.disableTable(table);
+       }
+       public static void enableTable(String table) throws BlurException, 
TException, IOException {
+               Iface client = 
BlurClient.getClient(Config.getConnectionString());
+               
+               client.enableTable(table);
+       }
+       public static void deleteTable(String table, boolean includeFiles) 
throws BlurException, TException, IOException {
+               Iface client = 
BlurClient.getClient(Config.getConnectionString());
+               
+               client.removeTable(table, includeFiles);
+       }
 }

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/css/console.css
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/css/console.css
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/css/console.css
index b7bb6b4..2e423a0 100644
--- 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/css/console.css
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/css/console.css
@@ -49,10 +49,6 @@ nav.navbar-inverse .navbar-brand { color: #fff; }
     border: none;
 }
 
-.tab-content {
-    overflow: auto; /* prevent content from running below tabs */
-}
-
 .tabs-left > .tab-content {
     margin-left: 40px;
 }
@@ -65,4 +61,130 @@ nav.navbar-inverse .navbar-brand { color: #fff; }
 
 .dashboard-tile-odd {
     background-color: #EEE;
-}
\ No newline at end of file
+}
+
+.modal.fade.in {
+    display: block;
+}
+
+/* CSS Spinner */
+.spinner {
+    height:60px;
+    width:60px;
+    margin:0px auto;
+    position:relative;
+    -webkit-animation: rotation .6s infinite linear;
+    -moz-animation: rotation .6s infinite linear;
+    -o-animation: rotation .6s infinite linear;
+    animation: rotation .6s infinite linear;
+    border-left:6px solid rgba(0,174,239,.15);
+    border-right:6px solid rgba(0,174,239,.15);
+    border-bottom:6px solid rgba(0,174,239,.15);
+    border-top:6px solid rgba(0,174,239,.8);
+    border-radius:100%;
+}
+
+@-webkit-keyframes rotation {
+    from {-webkit-transform: rotate(0deg);}
+    to {-webkit-transform: rotate(359deg);}
+}
+
+@-moz-keyframes rotation {
+    from {-moz-transform: rotate(0deg);}
+    to {-moz-transform: rotate(359deg);}
+}
+
+@-o-keyframes rotation {
+    from {-o-transform: rotate(0deg);}
+    to {-o-transform: rotate(359deg);}
+}
+
+@keyframes rotation {
+    from {transform: rotate(0deg);}
+    to {transform: rotate(359deg);}
+}
+
+/*  Tree Styles */
+.schema-tree li {
+  list-style:none;
+  margin: 3px;
+  font-size: 12px;
+}
+.schema-tree li i {
+    font-size: 12px;
+}
+.schema-tree li span {
+    cursor: pointer;
+}
+.schema-tree .minimized { display:none; }
+
+/* Term Lookup List */
+.terms {
+    width: 250px;
+    margin: 0 auto 30px;
+    list-style: none;
+    border: 3px solid #ccc;
+    padding-left: 0;
+}
+
+.terms li {
+    position: relative;
+    padding: 5px;
+    font-size: 12px;
+    background: #fff;
+}
+
+.terms li:nth-child(odd) {
+    background:#eee;
+}
+
+.terms li.action {
+    background: #000;
+}
+
+.terms li.action form {
+    margin-bottom: 0;
+}
+
+.terms li.action input {
+    width: 155px;
+}
+
+/*
+.terms {
+    width: 260px;
+    margin: 20px auto;
+    border-radius: 10px;
+    -moz-border-radius: 10px;
+    -webkit-border-radius: 10px;
+    overflow: hidden;
+    -webkit-background-clip: padding-box;
+    list-style: none;
+    border: 1px solid #bbb;
+    background-color: #fff;
+}
+.terms li:first-child {
+    border-radius: 9px 9px 0 0;
+    -moz-border-radius: 9px 9px 0 0;
+    -webkit-border-radius: 9px 9px 0 0;
+    -webkit-background-clip: padding-box;
+}
+.terms li:last-child {
+    border-radius: 0 0 9px 9px;
+    -moz-border-radius: 0 0 9px 9px;
+    -webkit-border-radius: 0 0 9px 9px;
+    -webkit-background-clip: padding-box;
+}
+.terms li {
+    position: relative;
+    height: 42px;
+    background-color: #fff;
+    border-bottom: 1px solid #bbb;
+    padding: 0 10px;
+    line-height: 42px;
+    clear: left;
+}
+.terms li a {
+    color: #000;
+    text-decoration: none;
+} */
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js
index 82dd831..3d7e210 100644
--- 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/app.js
@@ -26,5 +26,9 @@ var Utils = {
                        }
                });
                return result.length == 1 ? result[0] : result;
+       },
+
+       isVisible: function(el) {
+               return el.offsetWidth > 0 || el.offsetHeight > 0;
        }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/dashboard.js
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/dashboard.js
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/dashboard.js
index f126cac..5880284 100644
--- 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/dashboard.js
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/dashboard.js
@@ -30,121 +30,134 @@ blurApp.controller('DashboardCtrl', function($scope, 
$http, $timeout) {
     now.setSeconds(0);
     var nowTime = now.getTime();
 
-
     (function node_tick() {
-        $http.get('/service/dashboard/node/status').success(function (data) {
-            $scope.nodeData = data;
-            $timeout(node_tick, 10000);
-        }).error(function(){
-            console.log("Unable to update nodes");
-            $timeout(node_tick, 10000);
-        });
+        if (Utils.isVisible(document.querySelector('#dashboard-tab-content'))) 
{
+            $http.get('/service/dashboard/node/status').success(function 
(data) {
+                $scope.nodeData = data;
+                $timeout(node_tick, 10000);
+            }).error(function(){
+                console.log("Unable to update nodes");
+                $timeout(node_tick, 10000);
+            });    
+        } else {
+            $timeout(node_tick, 1000);
+        }
+        
     })();
 
     (function table_tick() {
-        $http.get('/service/dashboard/table/status').success(function (data) {
-            $scope.tableData = data;
-            $timeout(table_tick, 10000);
-        }).error(function(){
-            console.log("Unable to update tables");
-            $timeout(table_tick, 10000);
-        });
+        if (Utils.isVisible(document.querySelector('#dashboard-tab-content'))) 
{
+            $http.get('/service/dashboard/table/status').success(function 
(data) {
+                $scope.tableData = data;
+                $timeout(table_tick, 10000);
+            }).error(function(){
+                console.log("Unable to update tables");
+                $timeout(table_tick, 10000);
+            });
+        } else {
+            $timeout(table_tick, 1000);
+        }
     })();
 
     (function query_tick() {
-        $http.get('/service/dashboard/query/status').success(function (data) {
-            $scope.queryData.errMsg = data.errMsg;
-            $scope.hasslowwarnings = data.slowQueries > 0;
-
-            var now = new Date();
-            now.setMilliseconds(0);
-            now.setSeconds(0);
-            var nowTime = now.getTime();
-
-
-            var counterCopy = angular.copy($scope.queryData.counters);
-            angular.forEach(data.clusters, function(cluster) {
-                var clusterData = null;
-                // Find existing cluster's data
-                angular.forEach(counterCopy, function(series){
-                    if (series.label == cluster) {
-                        clusterData = series.data;
-                    }
-                });
-
-                // New cluster add and continue populating
-                if (clusterData == null) {
-                    clusterData = [];
-                    counterCopy.push({data:clusterData, label:cluster});
-                }
-
-                // Update counts for each time tick
-                angular.forEach(data.counts[cluster], function(count, time){
-                    var plot = null;
-                    angular.forEach(clusterData, function(plotterPoint) {
-                        if (plotterPoint[0] == time) {
-                            plot = plotterPoint;
+        if (Utils.isVisible(document.querySelector('#dashboard-tab-content'))) 
{
+            $http.get('/service/dashboard/query/status').success(function 
(data) {
+                $scope.queryData.errMsg = data.errMsg;
+                $scope.hasslowwarnings = data.slowQueries > 0;
+
+                var now = new Date();
+                now.setMilliseconds(0);
+                now.setSeconds(0);
+                var nowTime = now.getTime();
+
+
+                var counterCopy = angular.copy($scope.queryData.counters);
+                angular.forEach(data.clusters, function(cluster) {
+                    var clusterData = null;
+                    // Find existing cluster's data
+                    angular.forEach(counterCopy, function(series){
+                        if (series.label == cluster) {
+                            clusterData = series.data;
                         }
                     });
 
-                    // New time, plot it
-                    if (plot == null) {
-                        clusterData.push([time, count]);
-                    } else if (plot[1] < count) {
-                        plot[1] = count;
+                    // New cluster add and continue populating
+                    if (clusterData == null) {
+                        clusterData = [];
+                        counterCopy.push({data:clusterData, label:cluster});
                     }
-                });
-            });
-            for (var i = 0; i < counterCopy.length; i++) {
-                if (counterCopy[i]['data'].length > 10) {
-                    counterCopy[i]['data'].shift();
-                }
-            }
-            $scope.queryData.counters = counterCopy;
-
-            var perfCopy = angular.copy($scope.queryData.performance);
-            angular.forEach(data.clusters, function(cluster) {
-                var clusterData = null;
-                // Find existing cluster's data
-                angular.forEach(perfCopy, function(series){
-                    if (series.label == cluster) {
-                        clusterData = series.data;
-                    }
-                });
 
-                // New cluster add and continue populating
-                if (clusterData == null) {
-                    clusterData = [];
-                    perfCopy.push({data:clusterData, label:cluster});
-                }
-
-                // Update counts for each time tick
-                angular.forEach(data.performance[cluster], function(perf, 
time){
-                    var plot = null;
-                    angular.forEach(clusterData, function(plotterPoint) {
-                        if (plotterPoint[0] == time) {
-                            plot = plotterPoint;
+                    // Update counts for each time tick
+                    angular.forEach(data.counts[cluster], function(count, 
time){
+                        var plot = null;
+                        angular.forEach(clusterData, function(plotterPoint) {
+                            if (plotterPoint[0] == time) {
+                                plot = plotterPoint;
+                            }
+                        });
+
+                        // New time, plot it
+                        if (plot == null) {
+                            clusterData.push([time, count]);
+                        } else if (plot[1] < count) {
+                            plot[1] = count;
                         }
                     });
-
-                    // New time, plot it
-                    if (plot == null) {
-                        clusterData.push([time, perf]);
-                    }
                 });
-            });
-            for (var i = 0; i < perfCopy.length; i++) {
-                if (perfCopy[i]['data'].length > 10) {
-                    perfCopy[i]['data'].shift();
+                for (var i = 0; i < counterCopy.length; i++) {
+                    if (counterCopy[i]['data'].length > 10) {
+                        counterCopy[i]['data'].shift();
+                    }
                 }
-            }
-            $scope.queryData.performance = perfCopy;
-            $scope.queryData.clusters = data.clusters;
-
-            $timeout(query_tick, 10000);
-        }).error(function(){
-            console.log("Unable to update queries");
-            $timeout(query_tick, 10000);
-        });
+                $scope.queryData.counters = counterCopy;
+
+                // Commented out until Blur gets Query end times!
+                // var perfCopy = angular.copy($scope.queryData.performance);
+                // angular.forEach(data.clusters, function(cluster) {
+                //     var clusterData = null;
+                //     // Find existing cluster's data
+                //     angular.forEach(perfCopy, function(series){
+                //         if (series.label == cluster) {
+                //             clusterData = series.data;
+                //         }
+                //     });
+
+                //     // New cluster add and continue populating
+                //     if (clusterData == null) {
+                //         clusterData = [];
+                //         perfCopy.push({data:clusterData, label:cluster});
+                //     }
+
+                //     // Update counts for each time tick
+                //     angular.forEach(data.performance[cluster], 
function(perf, time){
+                //         var plot = null;
+                //         angular.forEach(clusterData, function(plotterPoint) 
{
+                //             if (plotterPoint[0] == time) {
+                //                 plot = plotterPoint;
+                //             }
+                //         });
+
+                //         // New time, plot it
+                //         if (plot == null) {
+                //             clusterData.push([time, perf]);
+                //         }
+                //     });
+                // });
+                // for (var i = 0; i < perfCopy.length; i++) {
+                //     if (perfCopy[i]['data'].length > 10) {
+                //         perfCopy[i]['data'].shift();
+                //     }
+                // }
+                // $scope.queryData.performance = perfCopy;
+                $scope.queryData.clusters = data.clusters;
+
+                $timeout(query_tick, 10000);
+            }).error(function(){
+                console.log("Unable to update queries");
+                $timeout(query_tick, 10000);
+            });
+        } else {
+            $timeout(query_tick, 1000);
+        }
     })();
 })
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/tables.js
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/tables.js
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/tables.js
index 41ed763..72775df 100644
--- 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/tables.js
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/js/tables.js
@@ -15,9 +15,9 @@
  * limitations under the License.
  */
  
-blurApp.controller('TableCtrl', function($scope, $http, $timeout) {
+blurApp.controller('TableCtrl', function($scope, $http, $timeout, $modal) {
        $scope.summaryData = {};
-       $scope.testMsg = 'This message';
+    $scope.currentSchema = null;
 
     $scope.isEnabled = function(item) {
         return item.enabled;
@@ -27,13 +27,83 @@ blurApp.controller('TableCtrl', function($scope, $http, 
$timeout) {
         return !item.enabled;
     };
 
-       (function table_summary_tick() {
+    $scope.viewInfo = function(table) {
+        $http.get('/service/tables/' + table + 
'/schema').success(function(data){
+            $scope.currentSchema = data;
+            $scope.currentTable = table;
+        });
+        var modalInstance = $modal.open({
+          templateUrl: 'partials/schema.tpl.html',
+          scope: $scope
+        });
+
+        modalInstance.result.then(function() {
+            $scope.currentSchema = null;
+            $scope.currentTable = null;
+        });
+    };
+
+    $scope.enableTable = function(table) {
+        $http.get('/service/tables/' + table + 
'/enable').success(function(data){
+            console.log("enabled");
+            $scope.reload();
+        });
+    }
+
+    $scope.disableTable = function(table) {
+        var ok = confirm('Are you sure you want to disable ' + table + '?');
+        if (ok) {
+            $http.get('/service/tables/' + table + 
'/disable').success(function(data){
+                console.log("disabled");
+                $scope.reload();
+            });
+        }
+    };
+
+    $scope.deleteTable = function(table, includeData) {
+        var ok = confirm('Are you sure you want to delete ' + table + '(' + 
(includeData ? 'with data' : 'table only') + ')?');
+        if (ok) {
+            $http.get('/service/tables/' + table + '/delete?includeFiles=' + 
includeData).success(function(data){
+                $scope.currentTerms = data;
+                $scope.reload();
+            });
+        }
+    };
+
+    $scope.toggleTree = function(el) {
+        var trigger = angular.element(el.target);
+        angular.element(Utils.filterByClassName(trigger.children(), 
'glyphicon')).toggleClass('glyphicon-plus').toggleClass('glyphicon-minus');
+
+        trigger.next().toggleClass('minimized');
+    };
+
+    $scope.viewTerms = function(family, column, startWith) {
+        $scope.currentTermFamily = family;
+        $scope.currentTermColumn = column;
+
+        var params = startWith ? '?startWith=' + startWith : '';
+        $http.get('/service/tables/' + $scope.currentTable + '/' + family + 
'/' + column + '/terms' + params).success(function(data){
+            $scope.currentTerms = data;
+        });
+    };
+
+    $scope.reload = function() {
         $http.get('/service/tables/summaries').success(function (data) {
             $scope.summaryData = data;
-            $timeout(table_summary_tick, 30000);
-        }).error(function(){
-            console.log("Unable to update tables");
-            $timeout(table_summary_tick, 30000);
-        });
+        })
+    };
+
+       (function table_summary_tick() {
+        if (Utils.isVisible(document.querySelector('#table-tab-content'))) {
+            $http.get('/service/tables/summaries').success(function (data) {
+                $scope.summaryData = data;
+                $timeout(table_summary_tick, 30000);
+            }).error(function(){
+                console.log("Unable to update tables");
+                $timeout(table_summary_tick, 30000);
+            });
+        } else {
+            $timeout(table_summary_tick, 1000);
+        }
     })();
-})
\ No newline at end of file
+});
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/cluster_table_list.tpl.html
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/cluster_table_list.tpl.html
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/cluster_table_list.tpl.html
new file mode 100644
index 0000000..4d81859
--- /dev/null
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/cluster_table_list.tpl.html
@@ -0,0 +1,54 @@
+<div class="row">
+       <div class="col-md-12">
+               <h4>Enabled Tables</h4>
+               <table class="table table-hover table-striped table-bordered 
table-condensed">
+                       <thead>
+                               <tr>
+                                       <th>Name</th>
+                                       <th>Row Count</th>
+                                       <th>Record Count</th>
+                                       <th>Actions</th>
+                               </tr>
+                       </thead>
+                       <tbody>
+                               <tr ng-repeat="table in tables | 
filter:isEnabled | orderBy:'name'">
+                                       <td>{{table.name}}</td>
+                                       <td>{{table.rowCount}}</td>
+                                       <td>{{table.recordCount}}</td>
+                                       <td>
+                                               <button type="button" 
class="btn btn-default" ng-click="viewInfo(table.name)"><i class="glyphicon 
glyphicon-eye-open"></i> View</button>
+                                               <button type="button" 
class="btn btn-default" ng-click="disableTable(table.name)"><i class="glyphicon 
glyphicon-cloud-download"></i> Disable</button>
+                                       </td>
+                               </tr>
+                       </tbody>
+               </table>
+       </div>
+       </div>
+       <div class="row">
+       <div class="col-md-12">
+               <h4>Disabled Tables</h4>
+               <table class="table table-hover table-striped table-bordered 
table-condensed">
+                       <thead>
+                               <tr>
+                                       <th>Name</th>
+                                       <th>Actions</th>
+                               </tr>
+                       </thead>
+                       <tbody>
+                               <tr ng-repeat="table in tables | 
filter:isDisabled | orderBy:'name'">
+                                       <td>{{table.name}}</td>
+                                       <td>
+                                               <button type="button" 
class="btn btn-default" ng-click="enableTable(table.name)"><i class="glyphicon 
glyphicon-cloud-upload"></i> Enable</button>
+                                               <div class="btn-group">
+                                                       <button type="button" 
class="btn btn-danger dropdown-toggle"><i class="glyphicon 
glyphicon-trash"></i> Delete <span class="caret"></button>
+                                                       <ul 
class="dropdown-menu">
+                                                               <li><a href="#" 
ng-click="deleteTable(table.name, false)">Table Only</a></li>
+                                                               <li><a href="#" 
ng-click="deleteTable(table.name, true)">Table and Data</a></li>
+                                                       </ul>
+                                               </div>
+                                       </td>
+                               </tr>
+                       </tbody>
+               </table>
+       </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/dashboard.tpl.html
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/dashboard.tpl.html
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/dashboard.tpl.html
index d1b3631..6488eb1 100644
--- 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/dashboard.tpl.html
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/dashboard.tpl.html
@@ -18,7 +18,7 @@ Licensed to the Apache Software Foundation (ASF) under one
 
 -->
 
-<div ng-controller="DashboardCtrl">
+<div ng-controller="DashboardCtrl" id="dashboard-tab-content">
     <div id="slow-query-warnings" class="alert alert-danger" 
ng-show="hasslowwarnings"><strong>Heads Up!</strong>Queries have been running 
for longer than a minute.</div>
     <div class="row">
         <div class="col-md-8">
@@ -53,6 +53,7 @@ Licensed to the Apache Software Foundation (ASF) under one
                     </div>
                 </div>
             </div>
+            <!--  This is commented out until Blur gets query end times!
             <div class="row">
                 <div class="col-md-12">
                     <h4>Query Performance By Cluster</h4>
@@ -63,7 +64,7 @@ Licensed to the Apache Software Foundation (ASF) under one
                         <div class="alert 
alert-danger">{{queryData.errmsg}}</div>
                     </div>
                 </div>
-            </div>
+            </div> -->
         </div>
         <div class="col-md-4">
             <div class="row">

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/schema.tpl.html
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/schema.tpl.html
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/schema.tpl.html
new file mode 100644
index 0000000..93ec5d2
--- /dev/null
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/schema.tpl.html
@@ -0,0 +1,77 @@
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file 
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+
+-->
+
+<div class="modal-dialog">
+       <div class="modal-content">
+               <div class="modal-header">
+                   <h3>Schema</h3>
+               </div>
+               <div class="modal-body">
+                   <div class="spinner" ng-hide="currentSchema"></div>
+                   <div ng-show="currentSchema">
+                       <div class="row">
+                               <div class="col-md-6">
+                                           <div class="schema-tree" 
ng-show="currentSchema">
+                                               <ul>
+                                                       <li ng-repeat="family 
in currentSchema">
+                                                               <span 
ng-click="toggleTree($event)"><i class="glyphicon glyphicon-plus"></i> 
{{family.name}}</span>
+                                                               <ul 
class="minimized">
+                                                                       <li 
ng-repeat="column in family.columns">
+                                                                               
<span ng-click="toggleTree($event)"><i class="glyphicon glyphicon-plus"></i> 
{{column.name}}</span>
+                                                                               
<ul class="minimized">
+                                                                               
        <li>Type: <em>{{column.type}}</em></li>
+                                                                               
        <li ng-show="column.subColumn">Subcolumn Name: 
<em>{{column.subColumn}}</em></li>
+                                                                               
        <li>Full Text?: <em>{{column.fullTextIndexed ? 'Yes' : 'No'}}</em></li>
+                                                                               
        <li ng-repeat="(key, value) in column.props">{{key}}: 
<em>{{value}}</em></li>
+                                                                               
        <li ng-hide="column.type == 'stored'">
+                                                                               
                <a href="#" ng-click="viewTerms(family.name, column.name)">View 
Terms</a>
+                                                                               
        </li>
+                                                                               
</ul>
+                                                                       </li>
+                                                               </ul>
+                                                       </li>
+                                               </ul>
+                                       </div>
+                               </div>
+                               <div class="col-md-6">
+                                       <div ng-show="currentTerms">
+                                               <ul class="terms">
+                                                       <li class="action">
+                                                               <form 
class="form-inline">
+                                                                       <div 
class="form-group">
+                                                                               
<input name="startWith" ng-model="startWith" class="form-control" 
placeholder="Terms start with..."/>
+                                                                               
<button type="button" class="btn btn-primary" 
ng-click="viewTerms(currentTermFamily, currentTermColumn, 
startWith)">Go</button>
+                                                                       </div>
+                                                               </form>
+                                                       </li>
+                                                       <li ng-repeat="term in 
currentTerms">
+                                                               <a 
href="#">{{term}}</a>
+                                                       </li>
+                                               </ul>
+                                       </div>
+                               </div>
+                           </div>
+               </div>
+               </div>
+               <div class="modal-footer">
+                   <button class="btn btn-primary" 
ng-click="$close('close')">Close</button>
+               </div>
+       </div>
+</div>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/4d2f7ccf/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/tables.tpl.html
----------------------------------------------------------------------
diff --git 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/tables.tpl.html
 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/tables.tpl.html
index 89689d2..2b8c7a2 100644
--- 
a/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/tables.tpl.html
+++ 
b/contrib/blur-console/src/main/resources/org/apache/blur/console/webapp/partials/tables.tpl.html
@@ -18,57 +18,19 @@ Licensed to the Apache Software Foundation (ASF) under one
 
 -->
 
-<div ng-controller="TableCtrl">
+<div ng-controller="TableCtrl" id="table-tab-content">
        <div ng-if="summaryData.clusters.length == 0">
                <div class="alert alert-warning">No clusters found</div>
        </div>
-       <div ng-if="summaryData.clusters.length > 0">
+       <div ng-if="summaryData.clusters.length == 1">
+               <div 
ng-init="tables=summaryData.tables[summaryData.clusters[0]]"></div>
+               <ng-include 
src="'partials/cluster_table_list.tpl.html'"></ng-include>
+       </div>
+       <div ng-if="summaryData.clusters.length > 1">
                <tabset>
             <tab ng-repeat="cluster in summaryData.clusters" 
heading="{{cluster}}">
-               <div class="row">
-                       <div class="col-md-12">
-                               <h4>Enabled Tables</h4>
-                               <table class="table table-hover table-striped 
table-bordered table-condensed">
-                                                       <thead>
-                                                               <tr>
-                                                                       
<th>Name</th>
-                                                                       <th>Row 
Count</th>
-                                                                       
<th>Record Count</th>
-                                                                       
<th>Info</th>
-                                                                       
<th>Actions</th>
-                                                               </tr>
-                                                       </thead>
-                                                       <tbody>
-                                                               <tr 
ng-repeat="table in summaryData.tables[cluster] | filter:isEnabled | 
orderBy:'name'">
-                                                                       
<td>{{table.name}}</td>
-                                                                       
<td>{{table.rowCount}}</td>
-                                                                       
<td>{{table.recordCount}}</td>
-                                                                       
<td></td>
-                                                                       
<td></td>
-                                                               </tr>
-                                                       </tbody>
-                                               </table>
-                                       </div>
-                               </div>
-                               <div class="row">
-                       <div class="col-md-12">
-                               <h4>Disabled Tables</h4>
-                               <table class="table table-hover table-striped 
table-bordered table-condensed">
-                                                       <thead>
-                                                               <tr>
-                                                                       
<th>Name</th>
-                                                                       
<th>Actions</th>
-                                                               </tr>
-                                                       </thead>
-                                                       <tbody>
-                                                               <tr 
ng-repeat="table in summaryData.tables[cluster] | filter:isDisabled | 
orderBy:'name'">
-                                                                       
<td>{{table.name}}</td>
-                                                                       
<td></td>
-                                                               </tr>
-                                                       </tbody>
-                                               </table>
-                                       </div>
-                               </div>
+               <div ng-init="tables=summaryData.tables[cluster]"></div>
+               <ng-include 
src="'partials/cluster_table_list.tpl.html'"></ng-include>
             </tab>
                </tabset>
        </div>

Reply via email to