From 2327e4e536e3be29ffd7af54ebba6ae24265c692 Mon Sep 17 00:00:00 2001 From: James Barnett Date: Sat, 17 Feb 2018 18:03:34 +0000 Subject: WIP - Add basic unstyled static tabs. IPC needs work --- editor-instance.html | 45 ++++++++++ editor-instance.js | 245 +++++++++++++++++++++++++++++++++++++++++++++++++++ index.html | 38 +++----- instance-manager.js | 29 ++++++ main.js | 16 +++- package-lock.json | 6 ++ package.json | 3 +- renderer.js | 245 --------------------------------------------------- 8 files changed, 352 insertions(+), 275 deletions(-) create mode 100644 editor-instance.html create mode 100644 editor-instance.js create mode 100644 instance-manager.js delete mode 100644 renderer.js diff --git a/editor-instance.html b/editor-instance.html new file mode 100644 index 0000000..1983bfe --- /dev/null +++ b/editor-instance.html @@ -0,0 +1,45 @@ + + + + + + SQL++ + + + + + + + + + + + + +
+
+ +
+ + +
+
+ +
+
+
+
+
+ + +
+ + + + \ No newline at end of file diff --git a/editor-instance.js b/editor-instance.js new file mode 100644 index 0000000..3ec123a --- /dev/null +++ b/editor-instance.js @@ -0,0 +1,245 @@ +"use strict"; + +const { ipcRenderer } = require('electron'); +const $ = window.jQuery = require("jquery"); +require("jquery-ui"); +require("jquery.tabulator"); +const cm = require("codemirror"); +require("codemirror/mode/sql/sql"); +require("codemirror/addon/hint/show-hint.js") +require("codemirror/addon/hint/sql-hint.js") +const Split = require("split.js"); + +const editorContext = cm(document.getElementById("editor"), { + value: "select *\nfrom information_schema.tables\n/\nselect now()\n/\nselect *\nfrom foo", + mode: "text/x-sql", + theme: "dracula", + lineNumbers: true, + gutters: ["CodeMirror-linenumbers", "statement-pointer"], + extraKeys: { "Ctrl-Space": "autocomplete" } +}); + +editorContext.on("cursorActivity", (instance) => { + let coords = instance.getCursor(); + $("#cursor-coords").text("Ln " + (parseInt(coords.line) + 1) + ", Col " + (parseInt(coords.ch) + 1)); +}); + +ipcRenderer.send("queryExecutor.queryTableMetadata"); +ipcRenderer.on("queryExecutor.queryTableMetadataComplete", (event, response) => { + console.log(response); + cm.commands.autocomplete = function (cmInstance) { + cm.showHint(cmInstance, cm.hint.sql, { + tables: response.result + }); + } +}); + +const statementDelimiter = "/"; + +let dataTable; +let execStartTime; +let execTimerInterval; +let execElapsedTime; +let queryMark; + +function runQuery() { + + _setExecutionStatusIndicator("RUNNING"); + _startExecTimer(); + + let query = findQuery(); + + ipcRenderer.send("queryExecutor.runQuery", query); +} + +/** + * If there's selected text, return it. Otherwise find the statement nearest the cursor. + * Statements are delimited by lines containing only a "/" character. + */ +function findQuery() { + let selectedText = editorContext.getSelection(); + + if (selectedText !== "") { + _clearQueryMarks(); + return selectedText; + } + else { + let cursorLine = editorContext.getCursor().line; + + let statementStartLine = editorContext.firstLine(); + + // lineCount rather than lastLine here, since lineCount is index 1 based. + // getRange(from, to) below is 0 based, but the range is exclusive, so if we need to include the last line we need the +1 + let statementEndLine = editorContext.lineCount(); + + // if the current line is a delimiter, thats the end of the statement + if (editorContext.getLine(cursorLine) === statementDelimiter) { + statementEndLine = cursorLine; + } + else { + // move down the document until a delimiter or the end of the document is reached + for (let i = cursorLine + 1; i <= editorContext.lastLine(); i++) { + if (editorContext.getLine(i) === statementDelimiter) { + statementEndLine = i; + break; + } + } + } + + // mode up the document until a previous statements delimiter is found or the start of the document is reached + for (let i = cursorLine - 1; i >= editorContext.firstLine(); i--) { + if (editorContext.getLine(i) === statementDelimiter) { + statementStartLine = i + 1; + break; + } + } + + let query = editorContext.getRange( + { line: statementStartLine, ch: 0 }, + { line: statementEndLine, ch: 0 } + ); + + console.log(query); + + _clearQueryMarks(); + + queryMark = editorContext.markText( + { line: statementStartLine, ch: 0 }, + { line: statementEndLine, ch: 0 }, + { className: "selected-statement" } + ); + + editorContext.setGutterMarker(statementStartLine, "statement-pointer", _createGutterMarkerDom()); + + return query; + } +} + +function _createGutterMarkerDom() { + return $("
>
").get(0); +} + +function _clearQueryMarks() { + if (queryMark) { + queryMark.clear(); + } + editorContext.clearGutter("statement-pointer"); +} + +ipcRenderer.on("queryExecutor.runQueryComplete", (event, response) => { + _stopExecTimer(); + if (response.error === undefined) { + handleResult(response.result); + } + else { + handleError(response.error); + } + +}); + +function _startExecTimer() { + execStartTime = new Date; + execElapsedTime = 0; + execTimerInterval = setInterval(() => { + execElapsedTime = Date.now() - execStartTime; + $("#execution-time").text("exec time: " + execElapsedTime + "ms"); + }, 10); +} + +function _stopExecTimer() { + clearInterval(execTimerInterval); + execStartTime = null; +} + +function handleError(err) { + _stopExecTimer(); + _destroyDataTable(); + $("#result-error").removeAttr("style").text("Error (" + err.code + ") - " + err.message); + _setExecutionStatusIndicator("ERROR"); + $("#execution-time").text("failed after " + execElapsedTime + " ms"); +} + +function handleResult(results) { + _stopExecTimer(); + _clearErrors(); + _destroyDataTable(); + + dataTable = $("#result-table").tabulator({ + height: "100%", + columns: _mapColumnProperties(results), + data: results.rows + }); + + _setExecutionStatusIndicator("OK"); + $("#execution-time").text("returned " + results.rowCount + " rows in " + execElapsedTime + " ms"); +} + +function _mapColumnProperties(results) { + return results.fields.map((column) => { + return { + field: column.name, + title: column.name + }; + }); +} + +function _resultTable() { + return $("#result-table"); +} + +function _setExecutionStatusIndicator(status) { + switch (status) { + case "RUNNING": + $("#execution-status").removeClass().addClass("exec-running").text("Running"); + break; + case "OK": + $("#execution-status").removeClass().addClass("exec-ok").text("Ok"); + break; + case "ERROR": + $("#execution-status").removeClass().addClass("exec-error").text("Error"); + break; + } +} + +function _destroyDataTable() { + if (dataTable) { + _resultTable().tabulator("destroy"); + _resultTable().removeAttr("style").empty(); + dataTable = undefined; + } +} + +function _clearErrors() { + $("#result-error").attr("style", "display:none;").empty(); +} + +function _onKeyUp(event) { + if (event.ctrlKey && event.keyCode == 13) { + runQuery(); + } +} + +$(document).ready(() => { + + // Event handlers + $("#run-query").click(runQuery); + $(document).keyup(_onKeyUp); + + Split([".editor-row", ".results-row"], { + sizes: [50, 50], + direction: "vertical", + gutterSize: 10, + elementStyle: (dimension, size, gutterSize) => { + return { + "flex-basis": "calc(" + size + "% - " + gutterSize + "px" + } + }, + gutterStyle: (dimension, gutterSize) => { + return { + "flex-basis": gutterSize + "px" + } + } + }); + +}) + diff --git a/index.html b/index.html index 0de4296..217c363 100644 --- a/index.html +++ b/index.html @@ -4,37 +4,23 @@ SQL++ - - - - - - + + -
-
- -
- -
-
- -
-
-
-
-
- - +
+
+
+
+ \ No newline at end of file diff --git a/instance-manager.js b/instance-manager.js new file mode 100644 index 0000000..e8b803e --- /dev/null +++ b/instance-manager.js @@ -0,0 +1,29 @@ +"use strict"; + +const { ipcRenderer } = require('electron'); +const TabGroup = require("electron-tabs"); + +let tabGroup = new TabGroup(); +let tab = tabGroup.addTab({ + title: "Electron", + src: 'file://' + __dirname + '/editor-instance.html', + visible: true, + active: true, + webviewAttributes: {"nodeintegration":true}, + // ready: tab => { + // let webview = tab.webview; + // if (!!webview) { + // webview.addEventListener('dom-ready', () => { + // webview.openDevTools(); + // }) + // } + // } +}); + +let tab2 = tabGroup.addTab({ + title: "Electron", + src: 'file://' + __dirname + '/editor-instance.html', + visible: true, + active: true, + webviewAttributes: { "nodeintegration": true }, +}); \ No newline at end of file diff --git a/main.js b/main.js index cc89b11..6c19d99 100644 --- a/main.js +++ b/main.js @@ -25,7 +25,7 @@ function createMainWindow() { function createQueryExecutorProcess() { queryExecutorProcess = new BrowserWindow({ - show: false + show: true }); queryExecutorProcess.loadURL(url.format({ @@ -57,8 +57,18 @@ app.on("activate", () => { } }); -ipcMain.on("queryExecutor.runQueryComplete", (event, payload) => uiWindow.webContents.send("queryExecutor.runQueryComplete", payload)); +const { webContents } = require('electron'); + +ipcMain.on("queryExecutor.runQueryComplete", (event, payload) => { + webContents.getAllWebContents().forEach((w) => { + w.send("queryExecutor.runQueryComplete", payload); + }) +}); ipcMain.on("queryExecutor.runQuery", (event, payload) => queryExecutorProcess.webContents.send("queryExecutor.runQuery", payload)); -ipcMain.on("queryExecutor.queryTableMetadataComplete", (event, payload) => uiWindow.webContents.send("queryExecutor.queryTableMetadataComplete", payload)); +ipcMain.on("queryExecutor.queryTableMetadataComplete", (event, payload) => { + webContents.getAllWebContents().forEach((w) => { + w.send("queryExecutor.queryTableMetadataComplete", payload); + }) +}); ipcMain.on("queryExecutor.queryTableMetadata", (event, payload) => queryExecutorProcess.webContents.send("queryExecutor.queryTableMetadata", payload)); \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 04cec7a..7d59e86 100644 --- a/package-lock.json +++ b/package-lock.json @@ -318,6 +318,12 @@ "sumchecker": "1.3.1" } }, + "electron-tabs": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/electron-tabs/-/electron-tabs-0.9.0.tgz", + "integrity": "sha1-kb+L66dftJjp0vjf5WHhH6cLm34=", + "dev": true + }, "error-ex": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.1.tgz", diff --git a/package.json b/package.json index ae1958c..f0ab1d3 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "pg": "7.4.1", "split.js": "1.3.5", "jquery-ui": "1.12.1", - "jquery.tabulator": "3.4.2" + "jquery.tabulator": "3.4.2", + "electron-tabs": "0.9.0" } } diff --git a/renderer.js b/renderer.js deleted file mode 100644 index 9fe1be7..0000000 --- a/renderer.js +++ /dev/null @@ -1,245 +0,0 @@ -"use strict"; - -const { ipcRenderer } = require('electron'); -const $ = window.jQuery = require("jquery"); -require("jquery-ui"); -require("jquery.tabulator"); -const cm = require("codemirror"); -require("codemirror/mode/sql/sql"); -require("codemirror/addon/hint/show-hint.js") -require("codemirror/addon/hint/sql-hint.js") -const Split = require("split.js"); - -const editorContext = cm(document.getElementById("editor"), { - value: "select *\nfrom information_schema.tables\n/\nselect now()\n/\nselect *\nfrom foo", - mode: "text/x-sql", - theme: "dracula", - lineNumbers: true, - gutters: ["CodeMirror-linenumbers", "statement-pointer"], - extraKeys: { "Ctrl-Space": "autocomplete" } -}); - -editorContext.on("cursorActivity", (instance) => { - let coords = instance.getCursor(); - $("#cursor-coords").text("Ln " + (parseInt(coords.line) + 1) + ", Col " + (parseInt(coords.ch) + 1)); -}); - -ipcRenderer.send("queryExecutor.queryTableMetadata"); -ipcRenderer.on("queryExecutor.queryTableMetadataComplete", (event, response) => { - console.log(response); - cm.commands.autocomplete = function (cmInstance) { - cm.showHint(cmInstance, cm.hint.sql, { - tables: response.result - }); - } -}); - -const statementDelimiter = "/"; - -let dataTable; -let execStartTime; -let execTimerInterval; -let execElapsedTime; -let queryMark; - -function runQuery() { - - _setExecutionStatusIndicator("RUNNING"); - _startExecTimer(); - - let query = findQuery(); - - ipcRenderer.send("queryExecutor.runQuery", query); -} - -/** - * If there's selected text, return it. Otherwise find the statement nearest the cursor. - * Statements are delimited by lines containing only a "/" character. - */ -function findQuery() { - let selectedText = editorContext.getSelection(); - - if (selectedText !== "") { - _clearQueryMarks(); - return selectedText; - } - else { - let cursorLine = editorContext.getCursor().line; - - let statementStartLine = editorContext.firstLine(); - - // lineCount rather than lastLine here, since lineCount is index 1 based. - // getRange(from, to) below is 0 based, but the range is exclusive, so if we need to include the last line we need the +1 - let statementEndLine = editorContext.lineCount(); - - // if the current line is a delimiter, thats the end of the statement - if (editorContext.getLine(cursorLine) === statementDelimiter) { - statementEndLine = cursorLine; - } - else { - // move down the document until a delimiter or the end of the document is reached - for (let i = cursorLine + 1; i <= editorContext.lastLine(); i++) { - if (editorContext.getLine(i) === statementDelimiter) { - statementEndLine = i; - break; - } - } - } - - // mode up the document until a previous statements delimiter is found or the start of the document is reached - for (let i = cursorLine - 1; i >= editorContext.firstLine(); i--) { - if (editorContext.getLine(i) === statementDelimiter) { - statementStartLine = i + 1; - break; - } - } - - let query = editorContext.getRange( - { line: statementStartLine, ch: 0 }, - { line: statementEndLine, ch: 0 } - ); - - console.log(query); - - _clearQueryMarks(); - - queryMark = editorContext.markText( - { line: statementStartLine, ch: 0 }, - { line: statementEndLine, ch: 0 }, - { className: "selected-statement" } - ); - - editorContext.setGutterMarker(statementStartLine, "statement-pointer", _createGutterMarkerDom()); - - return query; - } -} - -function _createGutterMarkerDom() { - return $("
>
").get(0); -} - -function _clearQueryMarks() { - if (queryMark) { - queryMark.clear(); - } - editorContext.clearGutter("statement-pointer"); -} - -ipcRenderer.on("queryExecutor.runQueryComplete", (event, response) => { - _stopExecTimer(); - if (response.error === undefined) { - handleResult(response.result); - } - else { - handleError(response.error); - } - -}); - -function _startExecTimer() { - execStartTime = new Date; - execElapsedTime = 0; - execTimerInterval = setInterval(() => { - execElapsedTime = Date.now() - execStartTime; - $("#execution-time").text("exec time: " + execElapsedTime + "ms"); - }, 10); -} - -function _stopExecTimer() { - clearInterval(execTimerInterval); - execStartTime = null; -} - -function handleError(err) { - _stopExecTimer(); - _destroyDataTable(); - $("#result-error").removeAttr("style").text("Error (" + err.code + ") - " + err.message); - _setExecutionStatusIndicator("ERROR"); - $("#execution-time").text("failed after " + execElapsedTime + " ms"); -} - -function handleResult(results) { - _stopExecTimer(); - _clearErrors(); - _destroyDataTable(); - - dataTable = $("#result-table").tabulator({ - height: "100%", - columns: _mapColumnProperties(results), - data: results.rows - }); - - _setExecutionStatusIndicator("OK"); - $("#execution-time").text("returned " + results.rowCount + " rows in " + execElapsedTime + " ms"); -} - -function _mapColumnProperties(results) { - return results.fields.map((column) => { - return { - field: column.name, - title: column.name - }; - }); -} - -function _resultTable() { - return $("#result-table"); -} - -function _setExecutionStatusIndicator(status) { - switch (status) { - case "RUNNING": - $("#execution-status").removeClass().addClass("exec-running").text("Running"); - break; - case "OK": - $("#execution-status").removeClass().addClass("exec-ok").text("Ok"); - break; - case "ERROR": - $("#execution-status").removeClass().addClass("exec-error").text("Error"); - break; - } -} - -function _destroyDataTable() { - if(dataTable) { - _resultTable().tabulator("destroy"); - _resultTable().removeAttr("style").empty(); - dataTable = undefined; - } -} - -function _clearErrors() { - $("#result-error").attr("style", "display:none;").empty(); -} - -function _onKeyUp(event) { - if (event.ctrlKey && event.keyCode == 13) { - runQuery(); - } -} - -$(document).ready(() => { - - // Event handlers - $("#run-query").click(runQuery); - $(document).keyup(_onKeyUp); - - Split([".editor-row", ".results-row"], { - sizes: [50, 50], - direction: "vertical", - gutterSize: 10, - elementStyle: (dimension, size, gutterSize) => { - return { - "flex-basis": "calc(" + size + "% - " + gutterSize + "px" - } - }, - gutterStyle: (dimension, gutterSize) => { - return { - "flex-basis": gutterSize + "px" - } - } - }); - -}) - -- cgit v1.2.3