| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016 |
- // Licensed to Cloudera, Inc. under one
- // or more contributor license agreements. See the NOTICE file
- // distributed with this work for additional information
- // regarding copyright ownership. Cloudera, Inc. 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.
- var searchRenderers = {
- 'rowkey': { //class to tag selection
- select: /[^\,\{\[]+(([\{\[][^\}\]]+[\}\]])+|)([^\,]+|)/g, //select the substring to process, useful as JS has no lookbehinds old: ([^,]+\[([^,]+(,|)+)+\]|[^,]+)
- tag: /.+/g, //select the matches to wrap with tags
- nested: {
- 'scan': { select: /(([^\\]|\b)\+[0-9]+)/g, tag: /\+[0-9]+/g },
- 'columns': {
- select: /\[.+\]/g,
- tag: /[^,\[\]]+/g, //forced to do this select due to lack of lookbehinds /[\[\]]/g
- nested: {
- 'range': {
- select: /\sto\s/g,
- tag: /.+/g
- }
- }
- },
- 'prefix': { select: /[^\*\\]+\*/g, tag: /\*/g},
- 'filter': {
- select: /\{[^\{\}]+\}/,
- tag:/[^\{\}]+/g,
- nested: {
- 'linker': {
- select: /\ (AND|OR|SKIP|WHILE)\ /g,
- tag: /.+/g
- }/*,
- 'compare_op': {
- select: /[\<\=\!\>]{1,2}/g,
- tag: /.+/g
- }*/ //will be added eventually after html bug is figured out
- }
- }
- }
- }
- };
- var DataTableViewModel = function(options) {
- var self = this, _defaults = {
- name: '',
- columns: [],
- items: [],
- reload: function() {
- },
- el:''
- };
- options = ko.utils.extend(_defaults,options);
- ListViewModel.apply(this, [options]);
- self.name = ko.observable(options.name);
- self.searchQuery.subscribe(function(value) {
- self._table.fnFilter(value);
- });
- self.columns = ko.observableArray(options.columns);
- self._el = $('table[data-datasource="' + options.el + '"]');
- self._table = null;
- self._initTable = function() {
- if(!self._table) {
- self._table = self._el.dataTable({
- "aoColumnDefs": [ { "bSortable": false, "aTargets": [ 0 ] }
- ],
- "sDom": 'tr',//this has to be in, change to sDom so you can call filter()
- 'bAutoWidth':false,
- "iDisplayLength": -1});
- return self._table;
- }
- };
- self.sort = function(viewModel, event) {
- var el = $(event.currentTarget);
- };
- var _reload = self.reload;
- self.reload = function(callback) {
- if(self._table) {
- self._table.fnClearTable();
- self._table.fnDestroy();
- self._table = null;
- }
- _reload(function() {
- self._initTable();
- if(callback!=null)
- callback();
- });
- };
- self.canDrop = ko.computed(function() {
- var selected = self.selected();
- if(selected.length <= 0) return false;
- for(var i=0; i<selected.length; i++) {
- if(selected[i].enabled()) return false;
- }
- return true;
- });
- self.canDisable = ko.computed(function() {
- var selected = self.selected();
- if(selected.length <= 0) return false;
- for(var i=0; i<selected.length; i++) {
- if(!selected[i].enabled()) return false;
- }
- return true;
- });
- self.canEnable = ko.computed(function() {
- var selected = self.selected();
- if(selected.length <= 0) return false;
- for(var i=0; i<selected.length; i++) {
- if(selected[i].enabled()) return false;
- }
- return true;
- });
- };
- //a Listview of Listviews
- var SmartViewModel = function(options) {
- var self = this;
- options = ko.utils.extend({
- name: '',
- items: [],
- reload: function() {
- },
- el:'',
- sortFields: {
- 'Row Key': function(a, b) {
- return a.row.localeCompare(b.row);
- },
- 'Column Count': function(a, b) {
- a = a.items().length;
- b = b.items().length;
- if(a > b)
- return 1;
- if(a < b)
- return -1;
- return 0;
- },
- 'Row Key Length': function(a, b) {
- a = a.row.length;
- b = b.row.length;
- if(a > b)
- return 1;
- if(a < b)
- return -1;
- return 0;
- }
- }
- }, options);
- ListViewModel.apply(this, [options]); //items: [ListView.items[],ListView.items[]]
- self.columnFamilies = ko.observableArray();
- self.name = ko.observable(options.name);
- self.name.subscribe(function(val){
- if(!val) return;
- self.columnFamilies([]);
- self._reloadcfs();
- if(app.station() == 'table' && app.search.cur_input())
- return;
- self.querySet.removeAll();
- self.evaluateQuery();
- }); //fix and decouple
- self.lastReloadTime = ko.observable(1);
- self.searchQuery.subscribe(function(value) //make this as nice as the render function and split into two, also fire not down on keyup events
- {
- if(app.station() != 'table')
- return;
- if(value.replace(/\s/g, "") == '' || value == null)
- routie(app.cluster() + '/' + app.views.tabledata.name());
- var inputs = value.match(searchRenderers['rowkey']['select']);
- self.querySet.removeAll();
- if(inputs) {
- for(var i=0; i<inputs.length; i++) {
- if(inputs[i].trim() != "" && inputs[i].trim() != ',') {
- //pull out filters
- var filter = inputs[i].match(searchRenderers['rowkey']['nested']['filter']['select']) || "";
- filter = filter != null && filter.length > 0 ? escape(filter[0].trim().slice(1, -1)) : "";
- function filterPostfix(postfix) {
- return (filter != null && filter.length > 0 ? ' AND ' : ' ' ) + postfix;
- }
- //pull out columns
- var extract = inputs[i].match(searchRenderers['rowkey']['nested']['columns']['select']);
- var columns = extract != null ? extract[0].match(searchRenderers['rowkey']['nested']['columns']['tag']) : [];
- inputs[i] = inputs[i].replace(extract, '');
- //pull out scan
- var p = pullFromRenderer(inputs[i], searchRenderers['rowkey']['nested']['scan']);
- inputs[i] = inputs[i].replace(p, '');
- p = p.split('+');
- var scan = p.length > 1 ? parseInt(p[1].trim()) : 0;
- //pull out column filters
- var toRemove = [];
- var cfs = [];
- for(var n = 0; n < columns.length; n++) {
- var o = columns[n];
- if(columns[n].match(searchRenderers['rowkey']['nested']['columns']['nested']['range']['select'])) {
- var partitions = columns[n].split(searchRenderers['rowkey']['nested']['columns']['nested']['range']['select']);
- filter += filterPostfix("ColumnRangeFilter('" + partitions[0] + "', false, '" + partitions[1] + "', true)");
- toRemove.push(n);
- } else {
- if(o.indexOf(':') == -1) {
- toRemove.push(n);
- //for each column family push cf and then column
- $(self.columnFamilies()).each(function(i, item) {
- columns.push(item.name + o);
- });
- continue;
- } else {
- o = o.slice(o.indexOf(':') + 1);
- }
- var colscan = pullFromRenderer(o, searchRenderers['rowkey']['nested']['scan']);
- if(colscan) {
- colscan = parseInt(colscan.split('+')[1]) + 1;
- filter += filterPostfix("ColumnPaginationFilter(" + colscan + ", 0)");
- }
- var fc = o.replace(pullFromRenderer(o, searchRenderers['rowkey']['nested']['prefix']), '');
- if(fc != o) {
- filter += filterPostfix("ColumnPrefixFilter('" + o.match(/[^:*]+/g)[0] + "')");
- columns[n] = columns[n].split(':')[0] + ':';
- }
- }
- }
- for(var n = toRemove.length - 1; n>=0; n--) {
- columns.splice(toRemove[n], 1);
- };
- self.querySet.push(new QuerySetPiece({
- 'row_key': inputs[i].replace(/\\(\+|\*|\,)/g, '$1').replace(/[\[\{].+[\]\}]|\*/g,'').trim(), //clean up with column regex selectors instead
- 'scan_length': scan ? scan + 1 : 1,
- 'columns': columns,
- 'prefix': inputs[i].match(searchRenderers['rowkey']['nested']['prefix']['select']) != null,
- 'filter': filter.length > 0 ? filter : null
- }));
- }
- }
- }
- self.evaluateQuery();
- });
- self._reloadcfs = function(callback) {
- return API.queryTable("getColumnDescriptors").done(function(data) {
- self.columnFamilies.removeAll();
- var keys = Object.keys(data);
- for(var i=0;i<keys.length;i++) {
- self.columnFamilies.push(new ColumnFamily({name:keys[i], enabled:false}));
- }
- if(callback!=null)
- callback();
- });
- };
- self.columnQuery = ko.observable("");
- self.columnQuery.subscribe(function(query) {
- var dataRowFilter = function(index, data_row) {
- data_row.searchQuery(query);
- };
- if (self.selected().length > 0) {
- $.each(self.selected(), dataRowFilter);
- } else {
- $.each(self.items(), dataRowFilter);
- }
- });
- self.rows = ko.computed(function() {
- var a = [];
- var items = this.items();
- for(var i=0; i<items.length; i++) {
- a.push(items[i].row);
- }
- return a;
- }, self);
- self.querySet = ko.observableArray();
- self.validateQuery = function() {
- if(self.querySet().length == 0) {
- self.querySet.push(new QuerySetPiece({
- 'row_key': 'null',
- 'scan_length': 10,
- 'prefix': 'false'
- }));
- } else {
- $(self.querySet()).each(function() {
- this.validate();
- this.editing(false);
- });
- }
- };
- self.addQuery = function() {
- self.validateQuery();
- self.querySet.push(new QuerySetPiece({onValidate: function() {
- //self.reload();
- }}))
- };
- self.evaluateQuery = function(callback) {
- self.validateQuery();
- self.reload(callback);
- };
- var _reload = self.reload;
- self.reload = function(callback) {
- var queryStart = new Date();
- _reload(function() {
- self.lastReloadTime((new Date() - queryStart)/1000);
- if(callback!=null)
- callback();
- self.isLoading(false);
- });
- };
- self.showGrid = ko.observable(false);
- self.showGrid.subscribe(function(val) {
- if(val) {
- var rows = self.items();
- var columns = {};
- //build full lookup hash of columns
- for(var i=0; i<rows.length; i++) {
- var cols = rows[i].items();
- for(var q=0; q<cols.length; q++) {
- if(!columns[cols[q].name])
- columns[cols[q].name] = "";
- }
- }
- for(var i=0; i<rows.length; i++) {
- //clone blank template from hash
- var new_row = $.extend({}, columns);
- var cols = rows[i].items();
- var col_list = [];
- //set existing values
- for(var q=0; q<cols.length; q++) {
- new_row[cols[q].name] = cols[q];
- }
- //build actual row from hash
- var keys = Object.keys(new_row);
- for(var r=0; r<keys.length; r++) {
- if(!new_row[keys[r]]) new_row[keys[r]] = new ColumnRow({ name: keys[r], value: '', parent: rows[i] });
- col_list.push(new_row[keys[r]]);
- }
- //set and sort
- rows[i].items(col_list);
- rows[i].sortDropDown.sort();
- }
- } else {
- self.reload();
- }
- });
- self.truncateLimit = ko.observable(1500);
- self.reachedLimit = ko.computed(function() {
- var items = self.items();
- for(var i=0; i<items.length; i++) {
- if(self.truncateLimit() < items[i].items().length) return true;
- }
- return false;
- });
- };
- var SmartViewDataRow = function(options) {
- var self = this;
- options = ko.utils.extend({
- sortFields: {
- 'Column Family': function(a, b) {
- return a.name.localeCompare(b.name);
- },
- 'Column Name': function(a, b) {
- return a.name.split(':')[1].localeCompare(b.name.split(':')[1]);
- },
- 'Cell Size': function(a, b) {
- a = a.value().length;
- b = b.value().length;
- if(a > b)
- return 1;
- if(a < b)
- return -1;
- return 0;
- },
- 'Cell Value': function(a, b) {
- return a.value().localeCompare(b.value());
- },
- 'Timestamp': function(a, b) {
- a = parseInt(a.timestamp);
- b = parseInt(b.timestamp);
- if(a > b)
- return 1;
- if(a < b)
- return -1;
- return 0;
- },
- 'Column Name Length': function(a, b) {
- a = a.name.split(':')[1].length;
- b = b.name.split(':')[1].length;
- if(a > b)
- return 1;
- if(a < b)
- return -1;
- return 0;
- }
- }
- }, options);
- DataRow.apply(self,[options]);
- ListViewModel.apply(self,[options]);
- self.displayedItems = ko.observableArray();
- self.displayRangeStart = 0;
- self.displayRangeLength = 20;
- self.items.subscribe(function() {
- self.displayedItems([]);
- self.updateDisplayedItems();
- });
- self.searchQuery.subscribe(function(searchValue) {
- self.scrollLoadSource = ko.computed(function(){
- return self.items().filter(function(column) {
- return column.name.toLowerCase().indexOf(searchValue.toLowerCase()) != -1;
- });
- });
- self.displayRangeLength = 20;
- self.updateDisplayedItems();
- });
- self.scrollLoadSource = self.items;
- self.updateDisplayedItems = function() {
- var x = self.displayRangeStart;
- self.displayedItems(self.scrollLoadSource().slice(x, x + self.displayRangeLength));
- };
- self.resetScrollLoad = function() {
- self.scrollLoadSource = self.items;
- self.updateDisplayedItems();
- };
- self.isCollapsed = ko.observable(false);
- self.toggleSelectedCollapse = function() {
- if(!self.isCollapsed()) {
- self.displayedItems(self.displayedItems().filter(function(item) {
- return item.isSelected();
- }));
- self.scrollLoadSource = self.displayedItems;
- self.isCollapsed(true);
- }
- else {
- self.isCollapsed(false);
- self.resetScrollLoad();
- }
- };
- self.onScroll = function(target, ev) {
- var displayRangeDelta = 15;
- if($(ev.target).scrollLeft() == ev.target.scrollWidth - ev.target.clientWidth) {
- if(self.displayedItems().length < self.scrollLoadSource().length) {
- self.displayRangeLength += displayRangeDelta;
- self.updateDisplayedItems();
- } else {
- self.displayRangeLength = self.items().length + displayRangeDelta;
- var validate = self.items().length;
- API.queryTable('getRowPartial' , prepForTransport(self.row), self.items().length, 100).done(function(data) {
- if(self.items().length != validate) return false;
- var cols = data[0].columns;
- var keys = Object.keys(cols);
- var temp = [];
- for(var i=0; i<keys.length; i++) {
- var col = cols[keys[i]];
- temp.push(new ColumnRow({name: keys[i],
- timestamp: col.timestamp,
- value: col.value,
- parent: self}));
- }
- self.items(self.items().concat(temp));
- });
- }
- }
- };
- self.drop = function(cont) {
- function doDrop() {
- self.isLoading(true);
- return API.queryTable('deleteAllRow', self.row, "{}").complete(function() {
- app.views.tabledata.items.remove(self); //decouple later
- self.isLoading(false);
- });
- }
- (cont === true) ? doDrop() : confirm(i18n("Confirm Delete"), i18n('Delete row ') + self.row + i18n('? (This cannot be undone)'), doDrop);
- };
- self.setItems = function(cols) {
- var colKeys = Object.keys(cols);
- var items = [];
- for(var q=0; q<colKeys.length; q++) {
- items.push(new ColumnRow({name: colKeys[q],
- timestamp: cols[colKeys[q]].timestamp,
- value: cols[colKeys[q]].value,
- parent: self}));
- }
- self.items(items);
- return self.items();
- };
- self.selectAllVisible = function(){
- for(t=0; t<self.displayedItems().length; t++)
- self.displayedItems()[t].isSelected(true);
- return self;
- };
- self.deselectAllVisible = function(){
- for(t=0; t<self.displayedItems().length; t++)
- self.displayedItems()[t].isSelected(false);
- return self;
- };
- self.toggleSelectAllVisible = function() {
- if(self.selected().length != self.displayedItems().length)
- return self.selectAllVisible();
- return self.deselectAllVisible();
- };
- self.push = function(item) {
- var column = new ColumnRow(item);
- self.items.push(column);
- };
- var _reload = self.reload;
- self.reload = function(callback) {
- logGA('get_row');
- _reload(function() {
- if(callback!=null)
- callback();
- self.isLoading(false);
- });
- };
- };
- var ColumnRow = function(options) {
- var self = this;
- ko.utils.extend(self,options);
- DataRow.apply(self,[options]);
- self.value = ko.observable(self.value);
- self.history = new CellHistoryPage({row: self.parent.row, column: self.name, timestamp: self.timestamp, items: []});
- self.drop = function(cont) {
- function doDrop() {
- logGA('filter_columns');
- self.parent.isLoading(true);
- return API.queryTable('deleteColumn', prepForTransport(self.parent.row), prepForTransport(self.name)).done(function(data) {
- self.parent.items.remove(self);
- if(self.parent.items().length > 0)
- self.parent.reload(); //change later
- self.parent.isLoading(false);
- });
- }
- (cont === true) ? doDrop() : confirm(i18n("Confirm Delete"), i18n("Are you sure you want to drop this column?"), doDrop);
- };
- self.reload = function(callback, skipPut) {
- self.isLoading(true);
- API.queryTable('get', prepForTransport(self.parent.row), prepForTransport(self.name), 'null').done(function(data) {
- if(data.length > 0 && !skipPut)
- self.value(data[0].value);
- if(typeof callback !== "undefined" && callback != null)
- callback();
- self.isLoading(false);
- });
- };
- self.value.subscribe(function(value) {
- //change transport prep to object wrapper
- logGA('put_column');
- API.queryTable('putColumn', prepForTransport(self.parent.row), prepForTransport(self.name), "hbase-post-key-" + JSON.stringify(value)).done(function(data) {
- self.reload(function(){}, true);
- });
- self.editing(false);
- });
- self.editing = ko.observable(false);
- self.isLoading = ko.observable(false); //move to baseclass
- };
- var SortDropDownView = function(options) {
- var self = this;
- options = ko.utils.extend({
- sortFields: {},
- target: null
- }, options);
- BaseModel.apply(self,[options]);
- self.target = options.target;
- self.sortAsc = ko.observable(true);
- self.sortAsc.subscribe(function(){self.sort()});
- self.sortField = ko.observable("");
- self.sortField.subscribe(function(){self.sort()});
- self.sortFields = ko.observableArray(Object.keys(options.sortFields)); // change to ko.computed?
- self.sortFunctionHash = ko.observable(options.sortFields);
- self.toggleSortMode = function() {
- self.sortAsc(!self.sortAsc());
- };
- self.sort = function() {
- if (!self.target || !(self.sortFields().length > 0)) return;
- self.target.sort(function(a, b) {
- return (self.sortAsc() ? 1 : -1) * self.sortFunctionHash()[self.sortField() ? self.sortField() : self.sortFields()[0]](a,b); //all sort functions must sort by ASC for default
- });
- };
- };
- var TableDataRow = function(options) {
- var self = this;
- options = ko.utils.extend({
- name:"",
- enabled:true
- }, options);
- DataRow.apply(self,[options]);
- self.name = options['name'];
- self.enabled = ko.observable(options['enabled']);
- self.toggle = function(viewModel,event){
- var action = [i18n('enable'), i18n('disable')][self.enabled() << 0], el = $(event.currentTarget);
- confirm(i18n("Confirm") + " " + action, i18n("Are you sure you want to") + " " + action + " " + i18n("this table?"), function()
- {
- el.showIndicator();
- return self[action](el).complete(function() {
- el.hideIndicator();
- });
- });
- };
- self.enable = function(el) {
- return API.queryCluster('enableTable',self.name).complete(function() {
- self.enabled(true);
- });
- };
- self.disable = function(callback) {
- return API.queryCluster('disableTable',self.name).complete(function() {
- self.enabled(false);
- if($.isFunction(callback)) callback();
- });
- };
- self.drop = function(el) {
- return API.queryCluster('deleteTable',self.name);
- };
- };
- var QuerySetPiece = function(options) {
- var self = this;
- options = ko.utils.extend({
- row_key: "null",
- scan_length: 1,
- prefix: false,
- columns: [],
- filter: null,
- onValidate: function(){}
- }, options);
- BaseModel.apply(self,[options]);
- self.row_key = ko.observable(options.row_key);
- self.scan_length = ko.observable(options.scan_length);
- self.columns = ko.observableArray(options.columns);
- self.prefix = ko.observable(options.prefix);
- self.filter = ko.observable(options.filter);
- self.editing = ko.observable(true);
- self.validate = function() {
- if(self.scan_length() <= 0 || self.row_key() == "")
- return app.views.tabledata.querySet.remove(self); //change later
- return options.onValidate();
- };
- self.row_key.subscribe(self.validate.bind());
- self.scan_length.subscribe(self.validate.bind());
- };
- var ColumnFamily = function(options) {
- this.name = options.name;
- this.enabled = ko.observable(options.enabled);
- this.toggle = function() {
- this.enabled(!this.enabled());
- app.views.tabledata.reload();
- };
- }
- //tagsearch
- var tagsearch = function() {
- var self = this;
- self.tags = ko.observableArray();
- self.mode = ko.observable('idle');
- self.cur_input = ko.observable('');
- self.submitted = ko.observable(false);
- self.filters = ["KeyOnlyFilter ()", "FirstKeyOnlyFilter ()", "PrefixFilter ('row_prefix')", "ColumnPrefixFilter('column_prefix')", "MultipleColumnPrefixFilter('column_prefix', 'column_prefix', …, 'column_prefix')", "ColumnCountGetFilter (limit)", "PageFilter (page_size)", "ColumnPaginationFilter(limit, offset)", "InclusiveStopFilter('stop_row_key')", "TimeStampsFilter (timestamp, timestamp, ... ,timestamp)", "RowFilter (compareOp, 'row_comparator')", "QualifierFilter (compareOp, 'qualifier_comparator')", "QualifierFilter (compareOp,'qualifier_comparator')", "ValueFilter (compareOp,'value_comparator')", "DependentColumnFilter ('family', 'qualifier', boolean, compare operator, 'value comparator')", "DependentColumnFilter ('family', 'qualifier', boolean)", "DependentColumnFilter ('family', 'qualifier')", "SingleColumnValueFilter('family', 'qualifier', compare operator, 'comparator', filterIfColumnMissing_boolean, latest_version_boolean)", "SingleColumnValueFilter('family', 'qualifier', compare operator, 'comparator')", "SingleColumnValueExcludeFilter('family', 'qualifier', compare operator, 'comparator', latest_version_boolean, filterIfColumnMissing_boolean)", "SingleColumnValueExcludeFilter('family', 'qualifier', compare operator, 'comparator')", "ColumnRangeFilter ('minColumn', minColumnInclusive_bool, 'maxColumn', maxColumnInclusive_bool)"];
- self.hints = ko.observableArray([ {
- hint: i18n('End Query'),
- shortcut: ',',
- mode: ['rowkey', 'prefix', 'scan'],
- selected: false
- }, {
- hint: i18n('Prefix Scan'),
- shortcut: '*',
- mode: ['rowkey', 'columns'],
- selected: false
- }, {
- hint: i18n('Start Scan'),
- shortcut: '+',
- mode: ['rowkey', 'prefix', 'columns'],
- selected: false
- }, {
- hint: i18n('Start Select Columns'),
- shortcut: '[',
- mode: ['rowkey', 'prefix'],
- selected: false
- }, {
- hint: i18n('End Column/Family'),
- shortcut: ',',
- mode: ['columns'],
- selected: false
- }, {
- hint: i18n('End Select Columns'),
- shortcut: ']',
- mode: ['columns'],
- selected: false
- }, {
- hint: i18n('Column Range'),
- shortcut: ' to ',
- mode: ['columns'],
- selected: false
- },
- {
- hint: i18n('Start FilterString'),
- shortcut: '{',
- mode: ['rowkey'],
- selected: false
- },
- {
- hint: i18n('End FilterString'),
- shortcut: '}',
- mode: ['filter'],
- selected: false
- }
- ]);
- self.activeHints = ko.computed(function() {
- var ret = [];
- $(self.hints()).each(function(i, hint) {
- if (hint.mode.indexOf(self.mode()) > -1)
- ret.push(hint);
- });
- return ret;
- });
- self.activeHint = ko.observable(-1);
- self.modes = {
- 'rowkey': {
- hint: i18n('Row Key Value'),
- type: i18n('String')
- },
- 'scan': {
- hint: i18n('Length of Scan or Row Key'),
- type: i18n('Integer')
- },
- 'columns': {
- hint: i18n('Column Family: Column Name'),
- type: i18n('String')
- },
- 'prefix': {
- hint: i18n('Rows starting with'),
- type: i18n('String')
- },
- 'filter': {
- hint: i18n('Thrift FilterString'),
- type: i18n('String')
- }
- }
- self.modeQueue = ['idle'];
- self.focused = ko.observable(false);
- self.activeSuggestions = ko.observableArray();
- self.activeSuggestion = ko.observable(-1);
- self.insertTag = function(tag) {
- var mode = tag.indexOf('+') != -1 ? 'scan' : 'rowkey';
- var tag = {value: tag, tag: mode} //parse mode
- self.tags.push(tag);
- }
- self.render = function(input, renderers) {
- var keys = Object.keys(renderers);
- for(var i=0; i<keys.length; i++) {
- input = input.replace(renderers[keys[i]].select, function(selected) {
- var hasMatched = false;
- var processed = selected.replace(renderers[keys[i]].tag, function(tagged) {
- hasMatched = true;
- return "<span class='" + keys[i] + " tagsearchTag' title='" + keys[i] + "' data-toggle='tooltip'>" + ('nested' in renderers[keys[i]] ? self.render(tagged, renderers[keys[i]].nested) : tagged) + "</span>";
- });
- if(hasMatched && renderers[keys[i]]['strip'])
- processed = processed.replace(renderers[keys[i]].strip, '');
- return processed;
- });
- }
- return input;
- };
- self.updateMode = function(value) {
- self.submitted(false);
- var selection = value.slice(0, self.selectionEnd());
- var endindex = selection.slice(selection.lastIndexOf(',')).indexOf(',');
- if(endindex == -1) endindex = selection.length;
- var lastbit = value.substring(selection.lastIndexOf(','), endindex).trim();
- if(lastbit == "," || lastbit == "") {
- self.mode('idle');
- return;
- }
- var tokens = "[]+*{}";
- var m = 'rowkey';
- for(var i=selection.length - 1; i>=0; i--) {
- if(tokens.indexOf(selection[i]) != -1) {
- if(selection[i] == '{')
- m = 'filter';
- else if(selection[i] == '[')
- m = 'columns';
- else if(selection[i] == ']' || selection[i] == '}')
- m = 'rowkey';
- else if(selection[i] == '+')
- m = 'scan';
- else if(selection[i] == '-')
- m = 'prefix';
- break;
- }
- }
- self.mode(m.trim());
- };
- self.selectionStart = ko.observable(0);
- self.selectionEnd = ko.observable(0);
- self.hintText = ko.computed(function() {
- var pre, s, e;
- try {
- var r = window.getSelection().getRangeAt(0);
- pre = r.startContainer.nodeValue;
- s = r.startOffset;
- e = r.endOffset;
- return pre.slice(0, s) + "<span class='selection'>" + pre.slice(s, e) + "</span>" + pre.slice(e);
- } catch (e) {
- var value = self.cur_input();
- var selection = value.slice(0, self.selectionEnd());
- var index = selection.lastIndexOf(',') + 1;
- var endindex = value.slice(index).indexOf(',');
- endindex = endindex == -1 ? value.length : endindex;
- pre = value.substring(index, index + endindex);
- s = self.selectionStart() - index;
- e = self.selectionEnd() - index;
- if(s == e)
- e += 1;
- s = s < 0 ? 0 : s;
- e = e > pre.length ? pre.length : e;
- }
- return pre.slice(0, s) + "<span class='selection'>" + pre.slice(s, e) + "</span>" + pre.slice(e);
- });
- self.onKeyDown = function(target, ev) {
- if(ev.keyCode == 13 && self.cur_input().slice(self.cur_input().lastIndexOf(',')).trim() != ",") {
- if(self.activeSuggestion() > -1) {
- self.replaceFocusNode(self.activeSuggestions()[self.activeSuggestion()]);
- self.activeSuggestion(-1);
- setTimeout(function() {
- var s = self.cur_input(), r;
- if(s.lastIndexOf('(') != -1 && s.lastIndexOf(')') != -1) {
- r = setCursor($('#search-tags')[0], s.lastIndexOf('(') + 1);
- r.setEnd(r.endContainer, r.startOffset + (s.lastIndexOf(')') - s.lastIndexOf('(') - 1));
- } else {
- r = setCursor($('#search-tags')[0], s.length);
- }
- var sel = window.getSelection();
- sel.removeAllRanges();
- sel.addRange(r);
- }, 1);
- } else {
- self.evaluate();
- }
- return false;
- } else if (ev.keyCode == 219) {
- setTimeout(function() {
- var ep = getEditablePosition($('#search-tags')[0], true);
- self.cur_input(self.cur_input().slice(0, ep) + (ev.shiftKey ? '}' : ']') + self.cur_input().slice(ep));
- }, 1);
- } else if (ev.keyCode == 40) {
- if(self.activeSuggestion() < self.activeSuggestions().length - 1)
- self.activeSuggestion(self.activeSuggestion() + 1);
- return false;
- } else if(ev.keyCode == 38) {
- if(self.activeSuggestion() > 0)
- self.activeSuggestion(self.activeSuggestion() - 1);
- return false;
- }
- setTimeout(self.updateMenu, 1);
- return true;
- };
- self.updateMenu = function() {
- self.activeSuggestion(-1);
- try{
- var pos = getEditablePosition(document.getElementById('search-tags'));
- self.selectionStart(pos);
- self.selectionEnd(pos);
- } catch (err) {}
- self.updateMode(self.cur_input());
- self.updateSuggestions();
- };
- self.replaceFocusNode = function(text) {
- window.getSelection().getRangeAt(0).startContainer.nodeValue = text;
- };
- self.updateSuggestions = function() {
- var val = window.getSelection().getRangeAt(0).startContainer.nodeValue;
- switch(self.mode()) {
- case 'filter':
- var focus = val.replace(/\{|\}|\s|&[^;]+?;/g,"").split(searchRenderers.rowkey.nested.filter.nested.linker.select).slice(-1)[0];
- if(focus != "") {
- self.activeSuggestions(self.filters.filter(function(a) {
- return a.toLowerCase().replace(" ","").indexOf(focus.toLowerCase()) != -1;
- }));
- } else {
- self.activeSuggestions([]);
- }
- return;
- case 'rowkey':
- var validate = window.getSelection().getRangeAt(0).startContainer.nodeValue;
- function cancel() {
- return window.getSelection().getRangeAt(0).startContainer.nodeValue != validate;
- }
- function callback() {
- if(cancel()) return false;
- if(validate.trim() != "") {
- API.queryTable('getAutocompleteRows', 10, prepForTransport(validate.trim())).done(function(data) {
- if(cancel()) return false;
- self.activeSuggestions(data);
- });
- }
- }
- setTimeout(callback, 200);
- return;
- default:
- self.activeSuggestions([]);
- return;
- }
- }
- self.evaluate = function() {
- table_search(self.cur_input());
- self.submitted(true);
- self.mode('idle');
- };
- $('#search-tags').blur(function(){
- self.focused(false);
- });
- self.doBlur = function() {
- if(self.cur_input().trim() == "") {
- function doClick() {
- if(self.cur_input().trim() != "") return false;
- setTimeout(function() {
- $('#search-tags').focus();
- }, 1);
- }
- $('#search-tags').html('<small>' + $('#search-tags').data("placeholder") + '</small>').one('click', doClick).find('small').on('mousedown', doClick);
- }
- }
- $('#search-tags').focus(function(){
- self.focused(true);
- });
- };
- var CellHistoryPage = function(options) {
- var self = this;
- self.items = ko.observableArray(options.items);
- self.loading = ko.observable(false);
- self.reload = function(timestamp, append) {
- if(!timestamp)
- timestamp = options.timestamp
- API.queryTable("getVerTs", prepForTransport(options.row), prepForTransport(options.column), timestamp, 10, 'null').done(function(res) {
- self.loading = ko.observable(true);
- if(!append)
- self.items(res);
- else
- self.items(self.items() + res);
- self.loading = ko.observable(false);
- });
- };
- self.pickHistory = function(data) {
- data.history = self;
- if(!ko.isObservable(data.value))
- data.value = ko.observable(data.value);
- launchModal('cell_edit_modal',{ content: data, mime: detectMimeType(data.value()), readonly: true })
- };
- };
|