mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
refactoring of sql console into separate widgets
This commit is contained in:
parent
1d64129572
commit
02d9752abf
32
package-lock.json
generated
32
package-lock.json
generated
@ -1792,9 +1792,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001168",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001168.tgz",
|
||||
"integrity": "sha512-P2zmX7swIXKu+GMMR01TWa4csIKELTNnZKc+f1CjebmZJQtTAEXmpQSoKVJVVcvPGAA0TEYTOUp3VehavZSFPQ==",
|
||||
"version": "1.0.30001170",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz",
|
||||
"integrity": "sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==",
|
||||
"dev": true
|
||||
},
|
||||
"caseless": {
|
||||
@ -3209,9 +3209,9 @@
|
||||
}
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.629",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.629.tgz",
|
||||
"integrity": "sha512-iSPPJtPvHrMAvYOt+9cdbDmTasPqwnwz4lkP8Dn200gDNUBQOLQ96xUsWXBwXslAo5XxdoXAoQQ3RAy4uao9IQ==",
|
||||
"version": "1.3.633",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz",
|
||||
"integrity": "sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA==",
|
||||
"dev": true
|
||||
},
|
||||
"electron-window-state": {
|
||||
@ -3250,13 +3250,13 @@
|
||||
}
|
||||
},
|
||||
"enhanced-resolve": {
|
||||
"version": "5.4.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.4.0.tgz",
|
||||
"integrity": "sha512-ZmqfWURB2lConOBM1JdCVfPyMRv5RdKWktLXO6123p97ovVm2CLBgw9t5MBj3jJWA6eHyOeIws9iJQoGFR4euQ==",
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.4.1.tgz",
|
||||
"integrity": "sha512-4GbyIMzYktTFoRSmkbgZ1LU+RXwf4AQ8Z+rSuuh1dC8plp0PPeaWvx6+G4hh4KnUJ48VoxKbNyA1QQQIUpXjYA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.0.0"
|
||||
"tapable": "^2.2.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"graceful-fs": {
|
||||
@ -4142,9 +4142,9 @@
|
||||
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
|
||||
},
|
||||
"helmet": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.2.0.tgz",
|
||||
"integrity": "sha512-aoiSxXMd0ks1ojYpSCFoCRzgv4rY/uB9jKStaw8PkXwsdLYa/Gq+Nc5l0soH0cwBIsLAlujPnx4HLQs+LaXCrQ=="
|
||||
"version": "4.3.1",
|
||||
"resolved": "https://registry.npmjs.org/helmet/-/helmet-4.3.1.tgz",
|
||||
"integrity": "sha512-WsafDyKsIexB0+pUNkq3rL1rB5GVAghR68TP8ssM9DPEMzfBiluEQlVzJ/FEj6Vq2Ag3CNuxf7aYMjXrN0X49Q=="
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.5",
|
||||
@ -7597,9 +7597,9 @@
|
||||
"integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w=="
|
||||
},
|
||||
"webpack": {
|
||||
"version": "5.11.0",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.11.0.tgz",
|
||||
"integrity": "sha512-ubWv7iP54RqAC/VjixgpnLLogCFbAfSOREcSWnnOlZEU8GICC5eKmJSu6YEnph2N2amKqY9rvxSwgyHxVqpaRw==",
|
||||
"version": "5.11.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.11.1.tgz",
|
||||
"integrity": "sha512-tNUIdAmYJv+nupRs/U/gqmADm6fgrf5xE+rSlSsf2PgsGO7j2WG7ccU6AWNlOJlHFl+HnmXlBmHIkiLf+XA9mQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/eslint-scope": "^3.7.0",
|
||||
|
@ -41,7 +41,7 @@
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.17.1",
|
||||
"fs-extra": "9.0.1",
|
||||
"helmet": "4.2.0",
|
||||
"helmet": "4.3.1",
|
||||
"html": "1.0.0",
|
||||
"html2plaintext": "2.1.2",
|
||||
"http-proxy-agent": "4.0.1",
|
||||
@ -86,7 +86,7 @@
|
||||
"jsdoc": "3.6.6",
|
||||
"lorem-ipsum": "2.0.3",
|
||||
"rcedit": "3.0.0",
|
||||
"webpack": "5.11.0",
|
||||
"webpack": "5.11.1",
|
||||
"webpack-cli": "4.3.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@ -5,7 +5,6 @@ import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import TabCachingWidget from "../widgets/tab_caching_widget.js";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
import RunScriptButtonsWidget from "../widgets/run_script_buttons.js";
|
||||
import NoteTypeWidget from "../widgets/note_type.js";
|
||||
import NoteActionsWidget from "../widgets/note_actions.js";
|
||||
import NoteDetailWidget from "../widgets/note_detail.js";
|
||||
@ -35,7 +34,6 @@ export default class DesktopExtraWindowLayout {
|
||||
.overflowing()
|
||||
.cssBlock('.title-row > * { margin: 5px 5px 0 5px; }')
|
||||
.child(new NoteTitleWidget())
|
||||
.child(new RunScriptButtonsWidget().hideInZenMode())
|
||||
.child(new NoteTypeWidget().hideInZenMode())
|
||||
.child(new NoteActionsWidget().hideInZenMode())
|
||||
)
|
||||
|
@ -9,7 +9,6 @@ import TabCachingWidget from "../widgets/tab_caching_widget.js";
|
||||
import NotePathsWidget from "../widgets/note_paths.js";
|
||||
import NoteTitleWidget from "../widgets/note_title.js";
|
||||
import OwnedAttributeListWidget from "../widgets/attribute_widgets/owned_attribute_list.js";
|
||||
import RunScriptButtonsWidget from "../widgets/run_script_buttons.js";
|
||||
import NoteTypeWidget from "../widgets/note_type.js";
|
||||
import NoteActionsWidget from "../widgets/note_actions.js";
|
||||
import NoteDetailWidget from "../widgets/note_detail.js";
|
||||
@ -27,6 +26,8 @@ import InheritedAttributesWidget from "../widgets/inherited_attribute_list.js";
|
||||
import NoteListWidget from "../widgets/note_list.js";
|
||||
import SearchDefinitionWidget from "../widgets/search_definition.js";
|
||||
import Container from "../widgets/container.js";
|
||||
import SqlResultWidget from "../widgets/sql_result.js";
|
||||
import SqlTableSchemasWidget from "../widgets/sql_table_schemas.js";
|
||||
|
||||
const RIGHT_PANE_CSS = `
|
||||
<style>
|
||||
@ -149,7 +150,6 @@ export default class DesktopMainWindowLayout {
|
||||
.cssBlock('.title-row > * { margin: 5px 5px 0 5px; }')
|
||||
.overflowing()
|
||||
.child(new NoteTitleWidget())
|
||||
.child(new RunScriptButtonsWidget().hideInZenMode())
|
||||
.child(new NoteTypeWidget().hideInZenMode())
|
||||
.child(new NoteActionsWidget().hideInZenMode())
|
||||
)
|
||||
@ -163,8 +163,10 @@ export default class DesktopMainWindowLayout {
|
||||
)
|
||||
.child(new Container()
|
||||
.css('height: 100%; overflow: auto;')
|
||||
.child(new TabCachingWidget(() => new SqlTableSchemasWidget()))
|
||||
.child(new TabCachingWidget(() => new NoteDetailWidget()))
|
||||
.child(new TabCachingWidget(() => new NoteListWidget()))
|
||||
.child(new TabCachingWidget(() => new SqlResultWidget()))
|
||||
)
|
||||
.child(new TabCachingWidget(() => new SimilarNotesWidget()))
|
||||
.child(...this.customWidgets.get('center-pane'))
|
||||
|
@ -211,10 +211,12 @@ export default class Entrypoints extends Component {
|
||||
|
||||
if (note.mime.endsWith("env=frontend")) {
|
||||
await bundleService.getAndExecuteBundle(note.noteId);
|
||||
}
|
||||
|
||||
if (note.mime.endsWith("env=backend")) {
|
||||
} else if (note.mime.endsWith("env=backend")) {
|
||||
await server.post('script/run/' + note.noteId);
|
||||
} else if (note.mime === 'text/x-sqlite;schema=trilium') {
|
||||
const result = await server.post("sql/execute/" + note.noteId);
|
||||
|
||||
this.triggerEvent('sqlQueryResults', {results: result.results});
|
||||
}
|
||||
|
||||
toastService.showMessage("Note executed");
|
||||
|
@ -22,10 +22,12 @@ const TPL = `
|
||||
|
||||
export default class NoteListWidget extends TabAwareWidget {
|
||||
isEnabled() {
|
||||
return super.isEnabled() && (
|
||||
['book', 'search'].includes(this.note.type)
|
||||
|| (this.note.type === 'text' && this.note.hasChildren())
|
||||
);
|
||||
return super.isEnabled()
|
||||
&& this.note.mime !== 'text/x-sqlite;schema=trilium'
|
||||
&& (
|
||||
['book', 'search', 'code'].includes(this.note.type)
|
||||
|| (this.note.type === 'text' && this.note.hasChildren())
|
||||
);
|
||||
}
|
||||
|
||||
doRender() {
|
||||
@ -46,10 +48,6 @@ export default class NoteListWidget extends TabAwareWidget {
|
||||
}
|
||||
|
||||
checkRenderStatus() {
|
||||
console.log("this.isIntersecting", this.isIntersecting);
|
||||
console.log("this.noteIdRefreshed === this.noteId", this.noteIdRefreshed === this.noteId);
|
||||
console.log("this.shownNoteId !== this.noteId", this.shownNoteId !== this.noteId);
|
||||
|
||||
if (this.isIntersecting
|
||||
&& this.noteIdRefreshed === this.noteId
|
||||
&& this.shownNoteId !== this.noteId) {
|
||||
|
@ -1,33 +0,0 @@
|
||||
import TabAwareWidget from "./tab_aware_widget.js";
|
||||
|
||||
const TPL = `
|
||||
<div style="display: inline-flex;">
|
||||
<button class="btn btn-sm icon-button bx bx-play-circle render-button"
|
||||
data-trigger-command="renderActiveNote"
|
||||
title="Render"></button>
|
||||
|
||||
<button class="btn btn-sm icon-button bx bx-play-circle execute-script-button"
|
||||
data-trigger-command="runActiveNote"
|
||||
title="Execute"></button>
|
||||
</div>`;
|
||||
|
||||
export default class RunScriptButtonsWidget extends TabAwareWidget {
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.contentSized();
|
||||
|
||||
this.$renderButton = this.$widget.find('.render-button');
|
||||
this.$executeScriptButton = this.$widget.find('.execute-script-button');
|
||||
}
|
||||
|
||||
refreshWithNote(note) {
|
||||
this.$renderButton.toggle(note.type === 'render');
|
||||
this.$executeScriptButton.toggle(note.type === 'code' && note.mime.startsWith('application/javascript'));
|
||||
}
|
||||
|
||||
async entitiesReloadedEvent({loadResults}) {
|
||||
if (loadResults.isNoteReloaded(this.noteId)) {
|
||||
this.refresh();
|
||||
}
|
||||
}
|
||||
}
|
64
src/public/app/widgets/sql_result.js
Normal file
64
src/public/app/widgets/sql_result.js
Normal file
@ -0,0 +1,64 @@
|
||||
import TabAwareWidget from "./tab_aware_widget.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import linkService from "../services/link.js";
|
||||
import hoistedNoteService from "../services/hoisted_note.js";
|
||||
import server from "../services/server.js";
|
||||
import toastService from "../services/toast.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="sql-result-widget">
|
||||
<style>
|
||||
.sql-result-widget {
|
||||
padding: 15px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="sql-console-result-container"></div>
|
||||
</div>`;
|
||||
|
||||
export default class SqlResultWidget extends TabAwareWidget {
|
||||
isEnabled() {
|
||||
return this.note
|
||||
&& this.note.mime === 'text/x-sqlite;schema=trilium'
|
||||
&& super.isEnabled();
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.overflowing();
|
||||
|
||||
this.$sqlConsoleResultContainer = this.$widget.find('.sql-console-result-container');
|
||||
}
|
||||
|
||||
async sqlQueryResultsEvent({results}) {
|
||||
this.$sqlConsoleResultContainer.empty();
|
||||
|
||||
for (const rows of results) {
|
||||
if (rows.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const $table = $('<table class="table table-striped">');
|
||||
this.$sqlConsoleResultContainer.append($table);
|
||||
|
||||
const result = rows[0];
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<th>").html(key));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
|
||||
for (const result of rows) {
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<td>").html(result[key]));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
83
src/public/app/widgets/sql_table_schemas.js
Normal file
83
src/public/app/widgets/sql_table_schemas.js
Normal file
@ -0,0 +1,83 @@
|
||||
import TabAwareWidget from "./tab_aware_widget.js";
|
||||
import treeService from "../services/tree.js";
|
||||
import linkService from "../services/link.js";
|
||||
import hoistedNoteService from "../services/hoisted_note.js";
|
||||
import server from "../services/server.js";
|
||||
import toastService from "../services/toast.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="sql-table-schemas-widget">
|
||||
<style>
|
||||
.sql-table-schemas button {
|
||||
padding: 0.25rem 0.4rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 0.5;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.sql-console-result-container {
|
||||
width: 100%;
|
||||
font-size: smaller;
|
||||
margin-top: 10px;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.table-schema td {
|
||||
padding: 5px;
|
||||
}
|
||||
</style>
|
||||
|
||||
Tables:
|
||||
<span class="sql-table-schemas"></span>
|
||||
</div>`;
|
||||
|
||||
export default class SqlTableSchemasWidget extends TabAwareWidget {
|
||||
isEnabled() {
|
||||
return this.note
|
||||
&& this.note.mime === 'text/x-sqlite;schema=trilium'
|
||||
&& super.isEnabled();
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.overflowing();
|
||||
|
||||
this.$sqlConsoleTableSchemas = this.$widget.find('.sql-table-schemas');
|
||||
}
|
||||
|
||||
async refreshWithNote(note) {
|
||||
if (this.tableSchemasShown) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.tableSchemasShown = true;
|
||||
|
||||
const tableSchema = await server.get('sql/schema');
|
||||
|
||||
for (const table of tableSchema) {
|
||||
const $tableLink = $('<button class="btn">').text(table.name);
|
||||
|
||||
const $table = $('<table class="table-schema">');
|
||||
|
||||
for (const column of table.columns) {
|
||||
$table.append(
|
||||
$("<tr>")
|
||||
.append($("<td>").text(column.name))
|
||||
.append($("<td>").text(column.type))
|
||||
);
|
||||
}
|
||||
|
||||
this.$sqlConsoleTableSchemas.append($tableLink).append(" ");
|
||||
|
||||
$tableLink.tooltip({
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
boundary: 'window',
|
||||
title: $table[0].outerHTML,
|
||||
sanitize: false
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -9,65 +9,24 @@ const TPL = `
|
||||
<div class="note-detail-code note-detail-printable">
|
||||
<style>
|
||||
.note-detail-code {
|
||||
overflow: auto;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.note-detail-code-editor {
|
||||
flex-basis: 200px;
|
||||
min-height: 200px;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.sql-console-table-schemas button {
|
||||
padding: 0.25rem 0.4rem;
|
||||
font-size: 0.875rem;
|
||||
line-height: 0.5;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
|
||||
.sql-console-result-wrapper {
|
||||
flex-grow: 100;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.sql-console-result-container {
|
||||
width: 100%;
|
||||
font-size: smaller;
|
||||
margin-top: 10px;
|
||||
flex-grow: 1;
|
||||
overflow: auto;
|
||||
min-height: 0;
|
||||
}
|
||||
|
||||
.table-schema td {
|
||||
padding: 5px;
|
||||
min-height: 300px;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="sql-console-area">
|
||||
Tables:
|
||||
<span class="sql-console-table-schemas"></span>
|
||||
</div>
|
||||
<button data-trigger-command="runActiveNote"
|
||||
class="no-print execute-button btn btn-sm"
|
||||
style="position: absolute; top: 0px; right: 10px; z-index: 1000;">
|
||||
Execute
|
||||
</button>
|
||||
|
||||
<div class="note-detail-code-editor"></div>
|
||||
|
||||
<div class="sql-console-area sql-console-result-wrapper">
|
||||
<div style="text-align: center">
|
||||
<button class="btn btn-danger sql-console-execute">Execute query <kbd>Ctrl+Enter</kbd></button>
|
||||
</div>
|
||||
|
||||
<div class="sql-console-result-container"></div>
|
||||
</div>
|
||||
</div>`;
|
||||
|
||||
let TABLE_SCHEMA;
|
||||
|
||||
export default class EditableCodeTypeWidget extends TypeWidget {
|
||||
static getType() { return "editable-code"; }
|
||||
|
||||
@ -75,17 +34,10 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
||||
this.$widget = $(TPL);
|
||||
this.contentSized();
|
||||
this.$editor = this.$widget.find('.note-detail-code-editor');
|
||||
this.$sqlConsoleArea = this.$widget.find('.sql-console-area');
|
||||
this.$sqlConsoleTableSchemas = this.$widget.find('.sql-console-table-schemas');
|
||||
this.$sqlConsoleExecuteButton = this.$widget.find('.sql-console-execute');
|
||||
this.$sqlConsoleResultContainer = this.$widget.find('.sql-console-result-container');
|
||||
this.$executeButton = this.$widget.find('.execute-button');
|
||||
|
||||
keyboardActionService.setupActionsForElement('code-detail', this.$widget, this);
|
||||
|
||||
utils.bindElShortcut(this.$editor, 'ctrl+return', () => this.execute());
|
||||
|
||||
this.$sqlConsoleExecuteButton.on('click', () => this.execute());
|
||||
|
||||
this.initialized = this.initEditor();
|
||||
}
|
||||
|
||||
@ -122,6 +74,11 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
||||
}
|
||||
|
||||
async doRefresh(note) {
|
||||
this.$executeButton.toggle(
|
||||
note.mime.startsWith('application/javascript')
|
||||
|| note.mime === 'text/x-sqlite;schema=trilium'
|
||||
);
|
||||
|
||||
const noteComplement = await this.tabContext.getNoteComplement();
|
||||
|
||||
await this.spacedUpdate.allowUpdateWithoutChange(() => {
|
||||
@ -138,104 +95,9 @@ export default class EditableCodeTypeWidget extends TypeWidget {
|
||||
}
|
||||
});
|
||||
|
||||
const isSqlConsole = note.mime === 'text/x-sqlite;schema=trilium';
|
||||
|
||||
this.$sqlConsoleArea.toggle(isSqlConsole);
|
||||
|
||||
if (isSqlConsole) {
|
||||
await this.showTableSchemas();
|
||||
}
|
||||
|
||||
this.show();
|
||||
}
|
||||
|
||||
async showTableSchemas() {
|
||||
if (!TABLE_SCHEMA) {
|
||||
TABLE_SCHEMA = await server.get('sql/schema');
|
||||
}
|
||||
|
||||
this.$sqlConsoleTableSchemas.empty();
|
||||
|
||||
for (const table of TABLE_SCHEMA) {
|
||||
const $tableLink = $('<button class="btn">').text(table.name);
|
||||
|
||||
const $table = $('<table class="table-schema">');
|
||||
|
||||
for (const column of table.columns) {
|
||||
$table.append(
|
||||
$("<tr>")
|
||||
.append($("<td>").text(column.name))
|
||||
.append($("<td>").text(column.type))
|
||||
);
|
||||
}
|
||||
|
||||
this.$sqlConsoleTableSchemas.append($tableLink).append(" ");
|
||||
|
||||
$tableLink
|
||||
.tooltip({
|
||||
html: true,
|
||||
placement: 'bottom',
|
||||
boundary: 'window',
|
||||
title: $table[0].outerHTML,
|
||||
sanitize: false
|
||||
})
|
||||
.on('click', () => this.codeEditor.setValue("SELECT * FROM " + table.name + " LIMIT 100"));
|
||||
}
|
||||
}
|
||||
|
||||
async execute() {
|
||||
// execute the selected text or the whole content if there's no selection
|
||||
let sqlQuery = this.codeEditor.getSelection();
|
||||
|
||||
if (!sqlQuery) {
|
||||
sqlQuery = this.codeEditor.getValue();
|
||||
}
|
||||
|
||||
const result = await server.post("sql/execute", {
|
||||
query: sqlQuery
|
||||
});
|
||||
|
||||
if (!result.success) {
|
||||
toastService.showError(result.error);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
toastService.showMessage("Query was executed successfully.");
|
||||
}
|
||||
|
||||
const results = result.results;
|
||||
|
||||
this.$sqlConsoleResultContainer.empty();
|
||||
|
||||
for (const rows of results) {
|
||||
if (rows.length === 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const $table = $('<table class="table table-striped">');
|
||||
this.$sqlConsoleResultContainer.append($table);
|
||||
|
||||
const result = rows[0];
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<th>").html(key));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
|
||||
for (const result of rows) {
|
||||
const $row = $("<tr>");
|
||||
|
||||
for (const key in result) {
|
||||
$row.append($("<td>").html(result[key]));
|
||||
}
|
||||
|
||||
$table.append($row);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
this.$widget.show();
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
"use strict";
|
||||
|
||||
const sql = require('../../services/sql');
|
||||
const repository = require('../../services/repository');
|
||||
|
||||
function getSchema() {
|
||||
const tableNames = sql.getColumn(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`);
|
||||
@ -17,7 +18,13 @@ function getSchema() {
|
||||
}
|
||||
|
||||
function execute(req) {
|
||||
const queries = req.body.query.split("\n---");
|
||||
const note = repository.getNote(req.params.noteId);
|
||||
|
||||
if (!note) {
|
||||
return [404, `Note ${req.params.noteId} was not found.`];
|
||||
}
|
||||
|
||||
const queries = note.getContent().split("\n---");
|
||||
|
||||
try {
|
||||
const results = [];
|
||||
|
@ -232,7 +232,7 @@ function register(app) {
|
||||
route(POST, '/api/setup/sync-seed', [auth.checkAppNotInitialized], setupApiRoute.saveSyncSeed, apiResultHandler, false);
|
||||
|
||||
apiRoute(GET, '/api/sql/schema', sqlRoute.getSchema);
|
||||
apiRoute(POST, '/api/sql/execute', sqlRoute.execute);
|
||||
apiRoute(POST, '/api/sql/execute/:noteId', sqlRoute.execute);
|
||||
route(POST, '/api/database/anonymize', [auth.checkApiAuthOrElectron, csrfMiddleware], databaseRoute.anonymize, apiResultHandler, false);
|
||||
|
||||
// backup requires execution outside of transaction
|
||||
|
Loading…
x
Reference in New Issue
Block a user