提交 15cb7e57 编写于 作者: V Vlad Ilyushchenko

grid vertical navigation via keyboard

上级 8da6024f
......@@ -29,4 +29,4 @@
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--><!--suppress HtmlUnknownTag --><html><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1"><title>QuestDB - Console</title><link rel="apple-touch-icon" href="apple-touch-icon.png"><!-- Place favicon.ico in the root directory --><link rel="stylesheet" href="styles/qdb.css"><script type="text/javascript">history.pushState(null, null, 'index.html');
window.addEventListener('popstate', function () {
history.pushState(null, null, 'index.html');
});</script></head><body class="pace-done"><div id="wrapper"><nav class="navbar-default navbar-static-side" role="navigation"><div class="sidebar-collapse"><ul class="nav metismenu" id="side-menu"><li class="nav-header"><div class="dropdown profile-element"><a data-toggle="dropdown" class="dropdown-toggle" href="#"><span class="clear"><h3>QuestDB</h3></span></a></div><div class="logo-element">QDB</div></li><li><a id="sql-editor" href="#"><i class="fa fa-table"></i> <span class="nav-label">SQL Console</span></a></li><li><a id="file-upload" href="#"><i class="fa fa-upload"></i> <span class="nav-label">Data import</span></a></li><li><a href="#"><i class="fa fa-pie-chart"></i> <span class="nav-label">Analytics</span></a></li></ul></div></nav><div id="page-wrapper" class="gray-bg"><div class="row border-bottom"><nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0"><div class="navbar-header"><a class="navbar-minimalize minimalize-styl-2 btn btn-primary" href="#"><i class="fa fa-bars"></i></a></div><ul class="nav navbar-top-links navbar-right"><li><span class="m-r-sm text-muted welcome-message">Welcome to QuestDB Console</span></li><li><a href="#"><i class="fa fa-sign-out"></i> Log out</a></li></ul></nav></div><div class="row wrapper border-bottom white-bg page-heading js-sql-panel"><div class="col-lg-10"><h3>SQL Console</h3></div></div><div class="wrapper wrapper-content js-sql-panel"><div class="row"><div class="col-lg-12"><div class="ibox"><div class="ibox-content"><div class="m-b-sm"><div class="btn-group pull-right"><button class="btn btn-white btn-sm"><i class="fa fa-arrow-left"></i></button></div><button class="btn btn-white btn-sm m-r-sm js-query-run"><i class="fa fa-play"></i>&nbsp;&nbsp;Run</button> <button class="btn btn-white btn-sm"><i class="fa fa-copy"></i></button> <button class="btn btn-white btn-sm"><i class="fa fa-scissors"></i></button> <button class="btn btn-white btn-sm m-r-sm"><i class="fa fa-clipboard"></i></button> <button class="btn btn-white btn-sm"><i class="fa fa-paragraph"></i></button></div><div id="sqlEditor" class="editor border-rounded-top-half"></div><div class="query-progress-spinner js-query-spinner"></div><div class="query-message query-message-ok js-query-message-panel"><div class="col-lg-2 query-time"><i class="fa fa-clock-o"></i><div class="js-query-time">-</div></div><div class="col-lg-10 js-query-message-text"></div></div></div></div></div></div><div class="row"><div class="col-lg-12"><div class="ibox"><div class="ibox-content"><div id="grid"><div class="qg-header-row"></div><div class="qg-viewport"><div class="qg-canvas"></div></div></div></div></div></div></div></div><div class="row wrapper border-bottom white-bg page-heading js-import-panel"><div class="col-lg-10"><h3>Data import</h3></div></div><div class="wrapper wrapper-content js-import-panel"><div class="row"><div class="col-lg-12"><div class="ibox"><div class="ibox-content"><div id="dragTarget" class="drag-target drag-idle"><h2>Drag files here to import</h2></div><div class="m-b-sm"><button id="btnImportClearSelected" class="btn btn-white btn-sm" disabled="disabled"><i class="fa fa-remove"></i>Clear</button> <button id="btnRetry" class="btn btn-white btn-sm" title disabled="disabled"><i class="fa fa-upload"></i></button> <button id="btnImportCancel" class="btn btn-white btn-sm" title disabled="disabled"><i class="fa fa-stop"></i></button></div><div id="import-file-list"></div></div></div></div></div><div class="row" id="import-detail"><div class="col-lg-12"><div class="js-import-editor"><div class="ibox"><div class="ibox-content"><div class="row"><div class="col-lg-12"><div class="stats-switcher-viewport"><div class="stats-switcher"><div class="row vertical-align import-imported-table"><div class="col-xs-3"><i class="fa fa-table fa-2x"></i></div><div class="col-xs-9 text-right"><h3 class="font-bold js-import-tab-name">ABCD</h3></div></div><div class="import-stats"><div class="import-imported-stats pull-right"><i class="fa fa-thumbs-o-down"></i>&nbsp;<span class="js-rejected-row-count">1023003</span> rows</div><div class="import-imported-stats"><i class="fa fa-thumbs-o-up"></i>&nbsp;<span class="js-imported-row-count">15000000</span> rows</div></div></div></div></div><div class="row"><div class="col-lg-12"><div class="import-stats-chart"><div class="import-rejected pull-right"></div><div class="import-imported"></div></div></div></div><div class="row"><div class="col-lg-12"><div class="grid"><div class="ud-header-row"><div class="ud-header gh-1"><i class="fa fa-hashtag"></i></div><div class="ud-header gh-2">Column name</div><div class="ud-header gh-3">Type</div><div class="ud-header gh-4">Errors</div></div><div class="ud-canvas"><!--<div class="ud-row" style="top: 0">--><!--<div class="ud-cell gc-1 g-other js-g-row">1</div>--><!--<div class="ud-cell gc-2 g-other">location</div>--><!--<div class="ud-cell gc-3 g-type">STRING</div>--><!--<div class="ud-cell gc-4 g-other">10</div>--><!--<div class="ud-cell gc-5 g-other">0</div>--><!--</div>--><!--<div class="ud-row" style="top: 35px">--><!--<div class="ud-cell gc-1 g-other">2</div>--><!--<div class="ud-cell gc-2 g-other"><i--><!--class="fa fa-exclamation-triangle g-warning"></i>price--><!--</div>--><!--<div class="ud-cell gc-3 g-type">DOUBLE</div>--><!--<div class="ud-cell gc-4 g-other">8</div>--><!--<div class="ud-cell gc-5 g-other">1400</div>--><!--</div>--></div></div></div></div></div></div></div></div><div class="panel panel-danger js-import-error"><div class="panel-heading">Import failed</div><div class="panel-body"><div class="col-sm-7 js-message">Server rejected file due to unsupported file format.</div><div class="col-sm-5 ud-btn-group js-import-error-btn-group"><form method="get"><label><input type="radio" name="importAction" value="append" class="js-btn-append"> Append</label><label><input type="radio" name="importAction" value="overwrite" class="js-btn-overwrite"> Overwrite</label><label><input type="radio" name="importAction" value="cancel" class="js-btn-cancel"> Cancel</label></form></div></div></div></div></div></div><div class="footer"><div><strong>Copyright</strong> Appsicle Ltd. &copy; 2014-2016</div></div></div></div><script src="scripts/qdb.js"></script></body></html>
\ No newline at end of file
});</script></head><body class="pace-done"><div id="wrapper"><nav class="navbar-default navbar-static-side" role="navigation"><div class="sidebar-collapse"><ul class="nav metismenu" id="side-menu"><li class="nav-header"><div class="dropdown profile-element"><a data-toggle="dropdown" class="dropdown-toggle" href="#"><span class="clear"><h3>QuestDB</h3></span></a></div><div class="logo-element">QDB</div></li><li><a id="sql-editor" href="#"><i class="fa fa-table"></i> <span class="nav-label">SQL Console</span></a></li><li><a id="file-upload" href="#"><i class="fa fa-upload"></i> <span class="nav-label">Data import</span></a></li><li><a href="#"><i class="fa fa-pie-chart"></i> <span class="nav-label">Analytics</span></a></li></ul></div></nav><div id="page-wrapper" class="gray-bg"><div class="row border-bottom"><nav class="navbar navbar-static-top" role="navigation" style="margin-bottom: 0"><div class="navbar-header"><a class="navbar-minimalize minimalize-styl-2 btn btn-primary" href="#"><i class="fa fa-bars"></i></a></div><ul class="nav navbar-top-links navbar-right"><li><span class="m-r-sm text-muted welcome-message">Welcome to QuestDB Console</span></li><li><a href="#"><i class="fa fa-sign-out"></i> Log out</a></li></ul></nav></div><div class="row wrapper border-bottom white-bg page-heading js-sql-panel"><div class="col-lg-10"><h3>SQL Console</h3></div></div><div class="wrapper wrapper-content js-sql-panel"><div class="row"><div class="col-lg-12"><div class="ibox"><div class="ibox-content"><div class="m-b-sm"><div class="btn-group pull-right"><button class="btn btn-white btn-sm"><i class="fa fa-arrow-left"></i></button></div><button class="btn btn-white btn-sm m-r-sm js-query-run"><i class="fa fa-play"></i>&nbsp;&nbsp;Run</button> <button class="btn btn-white btn-sm js-editor-copy"><i class="fa fa-copy"></i></button> <button class="btn btn-white btn-sm"><i class="fa fa-scissors"></i></button> <button class="btn btn-white btn-sm m-r-sm"><i class="fa fa-clipboard"></i></button> <button data-toggle="button" type="button" class="btn btn-white btn-sm js-editor-toggle-invisible"><i class="fa fa-paragraph"></i></button></div><div id="sqlEditor" class="editor border-rounded-top-half"></div><div class="query-progress-spinner js-query-spinner"></div><div class="query-message query-message-ok js-query-message-panel"><div class="col-lg-2 query-time"><i class="fa fa-clock-o"></i><div class="js-query-time">-</div></div><div class="col-lg-10 js-query-message-text"></div></div></div></div></div></div><div class="row"><div class="col-lg-12"><div class="ibox"><div class="ibox-content"><div id="grid"><div class="qg-header-row"></div><div class="qg-viewport"><div class="qg-canvas"></div></div></div></div></div></div></div></div><div class="row wrapper border-bottom white-bg page-heading js-import-panel"><div class="col-lg-10"><h3>Data import</h3></div></div><div class="wrapper wrapper-content js-import-panel"><div class="row"><div class="col-lg-12"><div class="ibox"><div class="ibox-content"><div id="dragTarget" class="drag-target drag-idle"><h2>Drag files here to import</h2></div><div class="m-b-sm"><button id="btnImportClearSelected" class="btn btn-white btn-sm" disabled="disabled"><i class="fa fa-remove"></i>Clear</button> <button id="btnRetry" class="btn btn-white btn-sm" title disabled="disabled"><i class="fa fa-upload"></i></button> <button id="btnImportCancel" class="btn btn-white btn-sm" title disabled="disabled"><i class="fa fa-stop"></i></button></div><div id="import-file-list"></div></div></div></div></div><div class="row" id="import-detail"><div class="col-lg-12"><div class="js-import-editor"><div class="ibox"><div class="ibox-content"><div class="row"><div class="col-lg-12"><div class="stats-switcher-viewport"><div class="stats-switcher"><div class="row vertical-align import-imported-table"><div class="col-xs-3"><i class="fa fa-table fa-2x"></i></div><div class="col-xs-9 text-right"><h3 class="font-bold js-import-tab-name">ABCD</h3></div></div><div class="import-stats"><div class="import-imported-stats pull-right"><i class="fa fa-thumbs-o-down"></i>&nbsp;<span class="js-rejected-row-count">1023003</span> rows</div><div class="import-imported-stats"><i class="fa fa-thumbs-o-up"></i>&nbsp;<span class="js-imported-row-count">15000000</span> rows</div></div></div></div></div><div class="row"><div class="col-lg-12"><div class="import-stats-chart"><div class="import-rejected pull-right"></div><div class="import-imported"></div></div></div></div><div class="row"><div class="col-lg-12"><div class="grid"><div class="ud-header-row"><div class="ud-header gh-1"><i class="fa fa-hashtag"></i></div><div class="ud-header gh-2">Column name</div><div class="ud-header gh-3">Type</div><div class="ud-header gh-4">Errors</div></div><div class="ud-canvas"></div></div></div></div></div></div></div></div><div class="panel panel-danger js-import-error"><div class="panel-heading">Import failed</div><div class="panel-body"><div class="col-sm-7 js-message">Server rejected file due to unsupported file format.</div><div class="col-sm-5 ud-btn-group js-import-error-btn-group"><form method="get"><label><input type="radio" name="importAction" value="append" class="js-btn-append"> Append</label><label><input type="radio" name="importAction" value="overwrite" class="js-btn-overwrite"> Overwrite</label><label><input type="radio" name="importAction" value="cancel" class="js-btn-cancel"> Cancel</label></form></div></div></div></div></div></div><div class="footer"><div><strong>Copyright</strong> Appsicle Ltd. &copy; 2014-2016</div></div></div></div><script src="scripts/qdb.js"></script></body></html>
\ No newline at end of file
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -126,10 +126,12 @@
</div>
<button class="btn btn-white btn-sm m-r-sm js-query-run"><i class="fa fa-play"></i>&nbsp;&nbsp;Run
</button>
<button class="btn btn-white btn-sm"><i class="fa fa-copy"></i></button>
<button class="btn btn-white btn-sm js-editor-copy"><i class="fa fa-copy"></i></button>
<button class="btn btn-white btn-sm"><i class="fa fa-scissors"></i></button>
<button class="btn btn-white btn-sm m-r-sm"><i class="fa fa-clipboard"></i></button>
<button class="btn btn-white btn-sm"><i class="fa fa-paragraph"></i>
<button data-toggle="button" type="button"
class="btn btn-white btn-sm js-editor-toggle-invisible"><i
class="fa fa-paragraph"></i>
</button>
</div>
<div id="sqlEditor" class="editor border-rounded-top-half">
......@@ -237,22 +239,6 @@
<div class="ud-header gh-4">Errors</div>
</div>
<div class="ud-canvas">
<!--<div class="ud-row" style="top: 0">-->
<!--<div class="ud-cell gc-1 g-other js-g-row">1</div>-->
<!--<div class="ud-cell gc-2 g-other">location</div>-->
<!--<div class="ud-cell gc-3 g-type">STRING</div>-->
<!--<div class="ud-cell gc-4 g-other">10</div>-->
<!--<div class="ud-cell gc-5 g-other">0</div>-->
<!--</div>-->
<!--<div class="ud-row" style="top: 35px">-->
<!--<div class="ud-cell gc-1 g-other">2</div>-->
<!--<div class="ud-cell gc-2 g-other"><i-->
<!--class="fa fa-exclamation-triangle g-warning"></i>price-->
<!--</div>-->
<!--<div class="ud-cell gc-3 g-type">DOUBLE</div>-->
<!--<div class="ud-cell gc-4 g-other">8</div>-->
<!--<div class="ud-cell gc-5 g-other">1400</div>-->
<!--</div>-->
</div>
</div>
</div>
......@@ -302,6 +288,7 @@
<!-- build:js scripts/qdb.js -->
<!-- bower:js -->
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/bootstrap/dist/js/bootstrap.min.js"></script>
<script src="/bower_components/metisMenu/dist/metisMenu.min.js"></script>
<script src="/bower_components/PACE/pace.min.js"></script>
<script src="/bower_components/ace-builds/src-noconflict/ace.js"></script>
......
......@@ -86,6 +86,9 @@
var o;
// row div cache
var rows = [];
// active (highlighted) row
var activeRow = -1;
var activeContainer;
function addRows(n) {
r += n;
......@@ -99,23 +102,30 @@
canvas.css('height', h === 0 ? 1 : h);
}
function renderRow(row, n) {
if (row.questIndex !== n) {
function renderRow(rowContainer, n) {
if (rowContainer.questIndex !== n) {
var rowData = data[Math.floor(n / pageSize)];
var offset = n % pageSize;
var k;
if (rowData) {
var d = rowData[offset];
for (k = 0; k < columns.length; k++) {
row.childNodes[k].innerHTML = d[k] !== null ? d[k].toString() : 'null';
rowContainer.childNodes[k].innerHTML = d[k] !== null ? d[k].toString() : 'null';
}
row.questIndex = n;
rowContainer.questIndex = n;
} else {
for (k = 0; k < columns.length; k++) {
row.childNodes[k].innerHTML = '';
rowContainer.childNodes[k].innerHTML = '';
}
}
rowContainer.style.top = (n * rh - o) + 'px';
if (rowContainer === activeContainer) {
if (n === activeRow) {
rowContainer.className = 'qg-r qg-r-active';
} else {
rowContainer.className = 'qg-r';
}
}
row.style.top = (n * rh - o) + 'px';
}
}
......@@ -408,11 +418,67 @@
viewportScroll(true);
}
function rowClick() {
if (activeContainer) {
activeContainer.className = 'qg-r';
}
this.focus();
activeContainer = this.parentElement;
activeContainer.className += ' qg-r-active';
activeRow = activeContainer.questIndex;
}
function activeRowUp(n) {
if (activeRow > 0) {
activeRow = Math.max(0, activeRow - n);
activeContainer.className = 'qg-r';
activeContainer = rows[activeRow & dcn];
activeContainer.className = 'qg-r qg-r-active';
var scrollTop = activeRow * rh;
if (scrollTop < viewport.scrollTop) {
viewport.scrollTop = Math.max(0, scrollTop);
}
}
}
function activeRowDown(n) {
if (activeRow > -1 && activeRow < r) {
activeRow = Math.min(r, activeRow + n);
activeContainer.className = 'qg-r';
activeContainer = rows[activeRow & dcn];
activeContainer.className = 'qg-r qg-r-active';
var scrollTop = activeRow * rh - vp + rh;
if (scrollTop > viewport.scrollTop) {
viewport.scrollTop = scrollTop;
}
}
}
function onKeyDown(e) {
var keyCode = ('which' in event) ? event.which : event.keyCode;
switch (keyCode) {
case 33: // page up
activeRowUp(Math.floor(vp / rh));
break;
case 38: // arrow up
activeRowUp(1);
break;
case 40: // arrow down
activeRowDown(1);
break;
case 34: // arrow down
activeRowDown(Math.floor(vp / rh));
break;
}
// console.log('key: ' + keyCode);
e.preventDefault();
}
function addColumns() {
for (var i = 0; i < dc; i++) {
var rowDiv = $('<div class="qg-r"/>');
var rowDiv = $('<div class="qg-r" tabindex="' + i + '"/>');
for (var k = 0; k < columns.length; k++) {
$('<div class="qg-c qg-w' + k + '"/>').appendTo(rowDiv);
$('<div class="qg-c qg-w' + k + '"/>').click(rowClick).appendTo(rowDiv);
}
rowDiv.css({top: -100, height: rh}).appendTo(canvas);
rows.push(rowDiv[0]);
......@@ -440,6 +506,7 @@
viewport = div.find('.qg-viewport')[0];
viewport.onscroll = viewportScroll;
canvas = div.find('.qg-canvas');
canvas.bind('keydown', onKeyDown);
$(document).on('query.ok', update);
$(window).resize(resize);
}
......
......@@ -144,6 +144,10 @@
function error(x, m) {
clearTimeout(timer);
if (m.statusText === 'abort') {
return;
}
div.removeClass('query-progress-animated');
divMsg.removeClass('query-message-ok').addClass('query-message-error');
divTime.html('failed after <strong>' + (m.delta / 1000) + 's</strong>');
......@@ -246,9 +250,15 @@
edit.focus();
}
function toggleInvisibles() {
console.log('about to ask');
edit.renderer.setShowInvisibles(!edit.renderer.getShowInvisibles());
}
function bind() {
$(document).on('editor.execute', submitQuery);
$(document).on('editor.show.error', showError);
$(document).on('editor.toggle.invisibles', toggleInvisibles);
edit.commands.addCommand({
name: 'editor.execute',
......@@ -281,5 +291,9 @@ $(document).ready(function () {
$('.js-query-run').click(function () {
$(document).trigger('editor.execute');
});
$('.js-editor-toggle-invisible').click(function () {
$(document).trigger('editor.toggle.invisibles');
});
});
......@@ -48,6 +48,20 @@
background-color: #f6f6f6;
}
.qg-r:focus {
outline: none;
}
.qg-r-active:hover {
background-color: #8ED0C2;
color: white;
}
.qg-r-active {
background-color: #6caea0;
color: white;
}
.qg-header {
display: inline-block;
padding: 5px 3px 7px;
......
{
"name": "questdb-console",
"authors": [
"Vlad Ilyushchenko"
"Vlad Ilyushchenko (Appsicle Ltd.)"
],
"description": "QuestDB Web Console",
"license": "The MIT License",
......@@ -21,7 +21,8 @@
"metisMenu": "^2.4.3",
"PACE": "pace#^1.0.2",
"ace-builds": "^1.2.3",
"iCheck": "^1.0.2"
"iCheck": "^1.0.2",
"bootstrap": "^3.3.6"
},
"overrides": {
"bootstrap-sass": {
......@@ -41,8 +42,5 @@
"devDependencies": {
"chai": "^3.5.0",
"mocha": "^2.4.5"
},
"resolutions": {
"mocha": "^2.4.5"
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册