diff --git a/public/javascripts/dialogs/sql_console.js b/public/javascripts/dialogs/sql_console.js
new file mode 100644
index 000000000..0f4792bde
--- /dev/null
+++ b/public/javascripts/dialogs/sql_console.js
@@ -0,0 +1,59 @@
+"use strict";
+
+const sqlConsole = (function() {
+ const dialogEl = $("#sql-console-dialog");
+ const queryEl = $('#sql-console-query');
+ const executeButton = $('#sql-console-execute');
+ const resultHeadEl = $('#sql-console-results thead');
+ const resultBodyEl = $('#sql-console-results tbody');
+
+ function showDialog() {
+ glob.activeDialog = dialogEl;
+
+ dialogEl.dialog({
+ modal: true,
+ width: $(window).width(),
+ height: $(window).height()
+ });
+ }
+
+ async function execute() {
+ const sqlQuery = queryEl.val();
+
+ const results = await server.post("sql/execute", {
+ query: sqlQuery
+ });
+
+ resultHeadEl.empty();
+ resultBodyEl.empty();
+
+ if (results.length > 0) {
+ const result = results[0];
+ const rowEl = $("
");
+
+ for (const key in result) {
+ rowEl.append($("").html(key));
+ }
+
+ resultHeadEl.append(rowEl);
+ }
+
+ for (const result of results) {
+ const rowEl = $(" |
");
+
+ for (const key in result) {
+ rowEl.append($("").html(result[key]));
+ }
+
+ resultBodyEl.append(rowEl);
+ }
+ }
+
+ $(document).bind('keydown', 'alt+o', showDialog);
+
+ executeButton.click(execute);
+
+ return {
+ showDialog
+ };
+})();
\ No newline at end of file
diff --git a/routes/api/sql.js b/routes/api/sql.js
new file mode 100644
index 000000000..b4c735fd7
--- /dev/null
+++ b/routes/api/sql.js
@@ -0,0 +1,14 @@
+"use strict";
+
+const express = require('express');
+const router = express.Router();
+const auth = require('../../services/auth');
+const sql = require('../../services/sql');
+
+router.post('/execute', auth.checkApiAuth, async (req, res, next) => {
+ const query = req.body.query;
+
+ res.send(await sql.getResults(query));
+});
+
+module.exports = router;
\ No newline at end of file
diff --git a/routes/routes.js b/routes/routes.js
index 888dbfc0a..d7e7b5513 100644
--- a/routes/routes.js
+++ b/routes/routes.js
@@ -21,6 +21,7 @@ const appInfoRoute = require('./api/app_info');
const exportRoute = require('./api/export');
const importRoute = require('./api/import');
const setupApiRoute = require('./api/setup');
+const sqlRoute = require('./api/sql');
function register(app) {
app.use('/', indexRoute);
@@ -45,6 +46,7 @@ function register(app) {
app.use('/api/export', exportRoute);
app.use('/api/import', importRoute);
app.use('/api/setup', setupApiRoute);
+ app.use('/api/sql', sqlRoute);
}
module.exports = {
diff --git a/services/build.js b/services/build.js
index d274a49c9..46f071326 100644
--- a/services/build.js
+++ b/services/build.js
@@ -1 +1 @@
-module.exports = { build_date:"2017-12-13T23:36:38-05:00", build_revision: "180a7432caa0ca43986a24e7f911a64c48f8a134" };
+module.exports = { build_date:"2017-12-14T20:10:49-05:00", build_revision: "45fba6d7f8a53d4ebbd48b1205442410b6f1dc46" };
diff --git a/views/index.ejs b/views/index.ejs
index 262f1be48..975eea52c 100644
--- a/views/index.ejs
+++ b/views/index.ejs
@@ -273,6 +273,16 @@
+
+
+
|