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>
