incubator-blur-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cr...@apache.org
Subject git commit: Got the extra functionality on the tables tab working
Date Mon, 25 Nov 2013 13:15:18 GMT
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 <crohr@nearinfinity.com>
Authored: Mon Nov 25 08:15:12 2013 -0500
Committer: Chris Rohr <crohr@nearinfinity.com>
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>


Mime
View raw message