Repository: incubator-blur Updated Branches: refs/heads/apache-blur-0.2 3fed5359f -> c964d85dd
allow typeahead in query field Project: http://git-wip-us.apache.org/repos/asf/incubator-blur/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-blur/commit/1eaf2be8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-blur/tree/1eaf2be8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-blur/diff/1eaf2be8 Branch: refs/heads/apache-blur-0.2 Commit: 1eaf2be8c45b3fb5f99cf69800c388f08f6094b8 Parents: 3fed535 Author: Andrew Avenoso <[email protected]> Authored: Mon Jun 9 13:58:23 2014 -0400 Committer: Chris Rohr <[email protected]> Committed: Mon Jun 9 14:46:24 2014 -0400 ---------------------------------------------------------------------- contrib/blur-console/src/assemble/bin.xml | 1 + contrib/blur-console/src/main/webapp/bower.json | 3 +- contrib/blur-console/src/main/webapp/index.html | 1 + .../src/main/webapp/js/blurconsole.fake.js | 121 ++++++++++++------- .../src/main/webapp/js/blurconsole.model.js | 20 +-- .../src/main/webapp/js/blurconsole.schema.js | 14 +-- .../src/main/webapp/js/blurconsole.search.js | 101 ++++++++++++++++ .../src/main/webapp/sass/blurconsole.scss | 1 + .../main/webapp/sass/blurconsole.search.scss | 8 ++ .../src/main/webapp/sass/blurconsole.shell.scss | 2 +- .../src/main/webapp/sass/typeahead.scss | 48 ++++++++ 11 files changed, 258 insertions(+), 62 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/assemble/bin.xml ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/assemble/bin.xml b/contrib/blur-console/src/assemble/bin.xml index b721234..10b872a 100644 --- a/contrib/blur-console/src/assemble/bin.xml +++ b/contrib/blur-console/src/assemble/bin.xml @@ -73,6 +73,7 @@ under the License. <include>libs/twbs-bootstrap-sass/vendor/assets/javascripts/bootstrap/popover.js</include> <include>libs/twbs-bootstrap-sass/vendor/assets/javascripts/bootstrap/collapse.js</include> <include>libs/twbs-bootstrap-sass/vendor/assets/javascripts/bootstrap/tab.js</include> + <include>libs/typeahead.js/dist/typeahead.jquery.js</include> <include>views/**</include> <include>index.html</include> </includes> http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/bower.json ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/bower.json b/contrib/blur-console/src/main/webapp/bower.json index f9296cb..6c54da7 100644 --- a/contrib/blur-console/src/main/webapp/bower.json +++ b/contrib/blur-console/src/main/webapp/bower.json @@ -6,7 +6,8 @@ "twbs-bootstrap-sass": "3.1.1", "modernizr": "2.7.1", "jquery": "1.11.0", - "flot":"0.8.2" + "flot":"0.8.2", + "typeahead.js":"0.10.2" }, "devDependencies": { "mocha": "~1.18.0", http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/index.html ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/index.html b/contrib/blur-console/src/main/webapp/index.html index af8b454..14ef45f 100644 --- a/contrib/blur-console/src/main/webapp/index.html +++ b/contrib/blur-console/src/main/webapp/index.html @@ -75,6 +75,7 @@ under the License. <script src="libs/flot/jquery.flot.pie.js"></script> <script src="libs/flot/jquery.flot.categories.js"></script> <script src="libs/flot/jquery.flot.stack.js"></script> + <script src="libs/typeahead.js/dist/typeahead.jquery.js"></script> <script src="js/blurconsole.js"></script> <script src="js/blurconsole.utils.js"></script> http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/js/blurconsole.fake.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/js/blurconsole.fake.js b/contrib/blur-console/src/main/webapp/js/blurconsole.fake.js index fc07b1d..91b3be5 100644 --- a/contrib/blur-console/src/main/webapp/js/blurconsole.fake.js +++ b/contrib/blur-console/src/main/webapp/js/blurconsole.fake.js @@ -20,6 +20,8 @@ under the License. /*global blurconsole:false */ blurconsole.fake = (function() { 'use strict'; + var frozen = false; + var tableList, schema, nodeList, queries; //----------------------- Private Methods ---------------------- function _randomNumber(max, includeZero) { @@ -82,67 +84,89 @@ blurconsole.fake = (function() { }, _randomNumber(1000)); } + function _toggleFreeze() { + var button = $('#fake_freeze'); + if(button.html() === 'Freeze'){ + frozen = true; + button.html('Unfreeze'); + console.log('Fake data frozen'); + } else { + frozen = false; + button.html('Freeze'); + console.log('Fake data resumed'); + } + } + //-------------------------- Public API --------------------------- function getTableList(callback) { - console.log('getting fake table list'); - var clusters = ['prodA', 'prodB'], data = []; + //console.log('getting fake table list'); + if(!frozen || !tableList) { + var clusters = ['prodA', 'prodB'], data = []; - for (var i = 0; i < 5; i++) { - var cluster = clusters[_randomNumber(2, true)]; - var rows = _randomNumber(1000); - var records = _randomNumber(10000)+1000; - var enabled = _randomBoolean(); + for (var i = 0; i < 5; i++) { + var cluster = clusters[_randomNumber(2, true)]; + var rows = _randomNumber(1000); + var records = _randomNumber(10000)+1000; + var enabled = _randomBoolean(); - data.push({cluster:cluster, name:'testtable'+i, enabled:enabled, rows:rows, records:records, families: blurconsole.utils.keys(_buildSchema())}); + data.push({cluster:cluster, name:'testtable'+i, enabled:enabled, rows:rows, records:records, families: blurconsole.utils.keys(_buildSchema())}); + } + tableList = {'tables':data, 'clusters':clusters}; } - _sendCallback(callback, {'tables':data, 'clusters':clusters}); + _sendCallback(callback, tableList); } function getNodeList(callback) { - console.log('getting fake node list'); - var controllers = {online:[], offline:[]}, - clusters = [{name:'prodA', online:[], offline:[]}, {name:'prodB', online:[], offline:[]}], - zookeepers = {online: [], offline:[]}; - - for(var i = 0; i < 3; i++) { - var state = _randomBoolean(); - if (state) { - controllers.online.push('controller' + i + '.localhost'); - clusters[0].online.push('prodA.shard' + i + '.localhost'); - clusters[1].online.push('prodB.shard' + i + '.localhost'); - zookeepers.online.push('zookeeper' + i + '.localhost'); - } else { - controllers.offline.push('controller' + i + '.localhost'); - clusters[0].offline.push('prodA.shard' + i + '.localhost'); - clusters[1].offline.push('prodB.shard' + i + '.localhost'); - zookeepers.offline.push('zookeeper' + i + '.localhost'); + //console.log('getting fake node list'); + if(!frozen || !nodeList) { + var controllers = {online:[], offline:[]}, + clusters = [{name:'prodA', online:[], offline:[]}, {name:'prodB', online:[], offline:[]}], + zookeepers = {online: [], offline:[]}; + + for(var i = 0; i < 3; i++) { + var state = _randomBoolean(); + if (state) { + controllers.online.push('controller' + i + '.localhost'); + clusters[0].online.push('prodA.shard' + i + '.localhost'); + clusters[1].online.push('prodB.shard' + i + '.localhost'); + zookeepers.online.push('zookeeper' + i + '.localhost'); + } else { + controllers.offline.push('controller' + i + '.localhost'); + clusters[0].offline.push('prodA.shard' + i + '.localhost'); + clusters[1].offline.push('prodB.shard' + i + '.localhost'); + zookeepers.offline.push('zookeeper' + i + '.localhost'); + } } + nodeList = {controllers: controllers, clusters: clusters, zookeepers: zookeepers}; } - _sendCallback(callback, {controllers: controllers, clusters: clusters, zookeepers: zookeepers}); + _sendCallback(callback, nodeList); } function getQueryPerformance(callback) { - console.log('getting fake query performance'); + //console.log('getting fake query performance'); _sendCallback(callback, _randomNumber(1000, true)); } function getQueries(callback) { - console.log('getting fake queries'); - var queries = []; - - for (var i=0; i < _randomNumber(50); i++) { - queries.push({ - uuid: _randomString(), - user: 'user_' + _randomNumber(10, true), - query: _randomString(), - table: 'testtable' + _randomNumber(5, true), - state: _randomNumber(3, true), - percent: _randomNumber(100, true), - startTime: new Date().getTime() - }); + //console.log('getting fake queries'); + if(!frozen || !queries) { + var randomQueries = []; + + for (var i=0; i < _randomNumber(50); i++) { + randomQueries.push({ + uuid: _randomString(), + user: 'user_' + _randomNumber(10, true), + query: _randomString(), + table: 'testtable' + _randomNumber(5, true), + state: _randomNumber(3, true), + percent: _randomNumber(100, true), + startTime: new Date().getTime() + }); + } + queries = { slowQueries : _randomNumber(10) === 1, queries : randomQueries }; } - _sendCallback(callback, { slowQueries : _randomNumber(10) === 1, queries : queries }); + _sendCallback(callback, queries); } function cancelQuery(table, uuid) { @@ -162,13 +186,15 @@ blurconsole.fake = (function() { } function getSchema(table, callback) { - console.log('getting fake schema for table [' + table + ']'); - _sendCallback(callback, _buildSchema()); + //console.log('getting fake schema for table [' + table + ']'); + if(!frozen || !schema){ + schema = _buildSchema(); + } + _sendCallback(callback, schema); } function findTerms(table, family, column, startsWith, callback) { console.log('getting fake terms from [' + table + '] for family [' + family + '] and column [' + column + '] starting with [' + startsWith + ']'); - var terms = []; for (var i = 0; i < 10; i++) { @@ -233,8 +259,13 @@ blurconsole.fake = (function() { _sendCallback(callback, { families: fams, results: results, total: total }); } } + function initModule() { + $('nav.navbar .pull-right').append('<button type="button" id="fake_freeze" class="btn btn-default btn-sm">Freeze</button>'); + $('#fake_freeze').click(_toggleFreeze); + } return { + initModule: initModule, getTableList : getTableList, getNodeList : getNodeList, getQueryPerformance : getQueryPerformance, http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/js/blurconsole.model.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/js/blurconsole.model.js b/contrib/blur-console/src/main/webapp/js/blurconsole.model.js index 5eca890..a2cddc8 100644 --- a/contrib/blur-console/src/main/webapp/js/blurconsole.model.js +++ b/contrib/blur-console/src/main/webapp/js/blurconsole.model.js @@ -109,14 +109,15 @@ blurconsole.model = (function() { return false; } }); - - return table.families; + if(table) { + return table.families; + } else { + return []; + } } - function findTerms(table, family, column, startsWith) { - configMap.poller.findTerms(table, family, column, startsWith, function(terms) { - $.gevent.publish('terms-updated', terms); - }); + function findTerms(table, family, column, startsWith, callback) { + configMap.poller.findTerms(table, family, column, startsWith, callback); } return { @@ -534,7 +535,12 @@ blurconsole.model = (function() { //----------------------- Public API ------------------------------ function initModule() { - configMap.poller = window.location.href.indexOf('fakeIt=') > -1 ? blurconsole.fake : blurconsole.data; + if(window.location.href.indexOf('fakeIt=') > -1) { + blurconsole.fake.initModule(); + configMap.poller = blurconsole.fake; + } else { + configMap.poller = blurconsole.data; + } setTimeout(function() { _nodePoller(); _tablePoller(); http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/js/blurconsole.schema.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/js/blurconsole.schema.js b/contrib/blur-console/src/main/webapp/js/blurconsole.schema.js index 3006cf0..ebb36dd 100644 --- a/contrib/blur-console/src/main/webapp/js/blurconsole.schema.js +++ b/contrib/blur-console/src/main/webapp/js/blurconsole.schema.js @@ -58,12 +58,12 @@ blurconsole.schema = (function () { stateMap = {}, jqueryMap = {}; - //------------------------------ Private Methods ----------------------------------------------------- - function _findTerms() { - blurconsole.model.tables.findTerms(stateMap.table, stateMap.termFamily, stateMap.termColumn, jqueryMap.termSearch.val()); + //------------------------------ Private Methods ----------------------------------------------------- + function _findTerms() { + blurconsole.model.tables.findTerms(stateMap.table, stateMap.termFamily, stateMap.termColumn, jqueryMap.termSearch.val(), _loadTerms); } - - //------------------------------ Event Handling and DOM Methods -------------------------------------- + + //------------------------------ Event Handling and DOM Methods -------------------------------------- function _showSchema(event, table) { stateMap.table = table; stateMap.modalId = stateMap.table + '_modal'; @@ -160,8 +160,7 @@ blurconsole.schema = (function () { jqueryMap.termSearchButton.trigger('click'); } - function _loadTerms() { - var terms = Array.prototype.slice.call(arguments, 1); + function _loadTerms(terms) { jqueryMap.termList.html(''); $.each(terms, function(i, term){ jqueryMap.termList.append('<li class="list-group-item">' + term + ' <span class="badge badge-success searchTrigger" title="Search for this value" data-value="' + term + '" data-table="' + stateMap.table + '"><i class="glyphicon glyphicon-search"></i></span></li>'); @@ -183,7 +182,6 @@ blurconsole.schema = (function () { //----------------------------- Public API ---------------------------- function initModule() { $.gevent.subscribe($(document), 'schema-show', _showSchema); - $.gevent.subscribe($(document), 'terms-updated', _loadTerms); } return { http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/js/blurconsole.search.js ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/js/blurconsole.search.js b/contrib/blur-console/src/main/webapp/js/blurconsole.search.js index d6c7077..a80d9ff 100644 --- a/contrib/blur-console/src/main/webapp/js/blurconsole.search.js +++ b/contrib/blur-console/src/main/webapp/js/blurconsole.search.js @@ -64,8 +64,108 @@ blurconsole.search = (function () { }; } + function _parseQueryForTypeahead(query) { + var ret = { + family: null, + column: null, + term: null, + mode: null + }; + query = query.toLowerCase(); + var dotIndex = query.lastIndexOf('.'); + var colonIndex = query.lastIndexOf(':'); + var lParenIndex = query.lastIndexOf('('); + var rParenIndex = query.lastIndexOf(')'); + var inParen = lParenIndex > -1 && lParenIndex > rParenIndex; + var spaceIndex = query.lastIndexOf(' '); + var lastIndex = Math.max(0,dotIndex,colonIndex,lParenIndex,rParenIndex,spaceIndex); + if(dotIndex === lastIndex) { // column mode + ret.family = query.substring(spaceIndex+1, dotIndex); + ret.column = query.substring(dotIndex+1); + ret.mode = 'column'; + } else if(colonIndex === lastIndex || (inParen && lParenIndex === colonIndex+1)) { // term mode + var familyStart = query.lastIndexOf(' ', dotIndex); + if(familyStart === -1) { + familyStart = 0; + } + ret.family = query.substring(familyStart, dotIndex); + ret.column = query.substring(dotIndex+1, colonIndex); + ret.term = query.substring(lastIndex+1); + ret.mode = 'term'; + } else if(query.length === 1 || query.length -1 !== lastIndex) { // family mode + ret.family = query.substring(spaceIndex+1); + ret.mode = 'family'; + } + if(ret.family) { + ret.family = ret.family.replace(/[\.\:\(\)\+\- ]/g,''); + } + if(ret.term) { + ret.term = ret.term.replace(/[\+\-]/g,''); + } + return ret; + } + + var _queryTypeaheadDataset = { + name:'query-dataset', + source: function _queryTypeaheadSource(query, cb) { + function buildSuggestionObject(query, hint, value) { + return {value:query.substring(0,query.lastIndexOf(hint)) + value, display:value}; + } + var table = $('#tableChooser').val(); + if(table && table !== '' && blurconsole.model.tables.isDataLoaded()) { + query = query.toLowerCase(); + var parsedQuery = _parseQueryForTypeahead(query); + console.log(parsedQuery.mode); + switch(parsedQuery.mode) { + case 'family': + var families = blurconsole.model.tables.getFamilies(table); + families = $.map(families, function(fam) { + if(fam.indexOf(parsedQuery.family) === 0) { + return buildSuggestionObject(query, parsedQuery.family, fam); + } + }); + cb(families); + break; + case 'column': + blurconsole.model.tables.getSchema(table, function(schema) { + var columnMap = schema[parsedQuery.family]; + if(columnMap) { + var columns = $.map(columnMap, function(data, col) { + if(col.indexOf(parsedQuery.column) === 0) { + return buildSuggestionObject(query, parsedQuery.column, col); + } + }); + cb(columns); + } + }); + break; + case 'term': + if(parsedQuery.term.length > 0) { + blurconsole.model.tables.findTerms(table, parsedQuery.family, parsedQuery.column, parsedQuery.term, function(terms){ + terms = $.map(terms, function(suggestedTerm){ + return buildSuggestionObject(query, parsedQuery.term, suggestedTerm); + }); + cb(terms); + }); + } else { + cb(null); + } + break; + default: + cb(null); + } + } + }, + templates: { + suggestion: function(suggestion) { + return '<p>' + suggestion.display + '</p>'; + } + } + }; + function _registerPageEvents() { $('#searchTrigger').on('click', _sendSearch); + $('#queryField').typeahead({}, _queryTypeaheadDataset); $('#results').on('shown.bs.collapse', '.panel-collapse:not(.loaded)', _getMoreData); $('#results').on('click', '.nextPage', _getMoreData); $('#searchOptionsTrigger').popover({ @@ -82,6 +182,7 @@ blurconsole.search = (function () { function _unregisterPageEvents() { $('#searchTrigger').off('click'); + $('#queryField').typeahead('destroy'); $('#results').off('shown.bs.collapse'); $('#results').off('click'); $('#searchOptionsTrigger').popover('destroy'); http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/sass/blurconsole.scss ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/sass/blurconsole.scss b/contrib/blur-console/src/main/webapp/sass/blurconsole.scss index b7db31b..7996945 100644 --- a/contrib/blur-console/src/main/webapp/sass/blurconsole.scss +++ b/contrib/blur-console/src/main/webapp/sass/blurconsole.scss @@ -27,4 +27,5 @@ $icon-font-path: "../libs/twbs-bootstrap-sass/vendor/assets/fonts/bootstrap/"; @import 'blurconsole.schema'; @import 'blurconsole.queries'; @import 'blurconsole.search'; +@import 'typeahead'; http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/sass/blurconsole.search.scss ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/sass/blurconsole.search.scss b/contrib/blur-console/src/main/webapp/sass/blurconsole.search.scss index 7c57929..cde836d 100644 --- a/contrib/blur-console/src/main/webapp/sass/blurconsole.search.scss +++ b/contrib/blur-console/src/main/webapp/sass/blurconsole.search.scss @@ -41,4 +41,12 @@ tr.row-separator { &:hover th { background-color: $dusty-gray !important; } +} + +.input-group .twitter-typeahead { + float: left; + width: 100%; + .form-control { + border-radius: 4px 0px 0px 4px; + } } \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/sass/blurconsole.shell.scss ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/sass/blurconsole.shell.scss b/contrib/blur-console/src/main/webapp/sass/blurconsole.shell.scss index be169ef..5117f50 100644 --- a/contrib/blur-console/src/main/webapp/sass/blurconsole.shell.scss +++ b/contrib/blur-console/src/main/webapp/sass/blurconsole.shell.scss @@ -33,7 +33,7 @@ nav.navbar-fixed-top { .navbar-brand { color: $white; } - #view_logging_trigger { + .pull-right button.btn { margin-right: 20px; margin-top: 14px; } http://git-wip-us.apache.org/repos/asf/incubator-blur/blob/1eaf2be8/contrib/blur-console/src/main/webapp/sass/typeahead.scss ---------------------------------------------------------------------- diff --git a/contrib/blur-console/src/main/webapp/sass/typeahead.scss b/contrib/blur-console/src/main/webapp/sass/typeahead.scss new file mode 100644 index 0000000..46379dc --- /dev/null +++ b/contrib/blur-console/src/main/webapp/sass/typeahead.scss @@ -0,0 +1,48 @@ +/* + +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. + */ + +.twitter-typeahead { + .tt-hint { + color: #AAA + } + + .tt-dropdown-menu { + width: 422px; + padding: 8px 0; + background-color: #fff; + border: 1px solid #ccc; + border: 1px solid rgba(0, 0, 0, 0.2); + border-radius: 8px; + box-shadow: 0 5px 10px rgba(0,0,0,.2); + } + + .tt-suggestion { + padding: 3px 10px; + } + + .tt-suggestion.tt-cursor { + color: #fff; + background-color: #0097cf; + } + + .tt-suggestion p { + margin: 0; + } +} \ No newline at end of file
