mirror of
				https://github.com/zadam/trilium.git
				synced 2025-11-03 20:06:08 +01:00 
			
		
		
		
	refactoring of sql console into separate widgets
This commit is contained in:
		
							
								
								
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										32
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							@@ -1792,9 +1792,9 @@
 | 
				
			|||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "caniuse-lite": {
 | 
					    "caniuse-lite": {
 | 
				
			||||||
      "version": "1.0.30001168",
 | 
					      "version": "1.0.30001170",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001168.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001170.tgz",
 | 
				
			||||||
      "integrity": "sha512-P2zmX7swIXKu+GMMR01TWa4csIKELTNnZKc+f1CjebmZJQtTAEXmpQSoKVJVVcvPGAA0TEYTOUp3VehavZSFPQ==",
 | 
					      "integrity": "sha512-Dd4d/+0tsK0UNLrZs3CvNukqalnVTRrxb5mcQm8rHL49t7V5ZaTygwXkrq+FB+dVDf++4ri8eJnFEJAB8332PA==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "caseless": {
 | 
					    "caseless": {
 | 
				
			||||||
@@ -3209,9 +3209,9 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "electron-to-chromium": {
 | 
					    "electron-to-chromium": {
 | 
				
			||||||
      "version": "1.3.629",
 | 
					      "version": "1.3.633",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.629.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.633.tgz",
 | 
				
			||||||
      "integrity": "sha512-iSPPJtPvHrMAvYOt+9cdbDmTasPqwnwz4lkP8Dn200gDNUBQOLQ96xUsWXBwXslAo5XxdoXAoQQ3RAy4uao9IQ==",
 | 
					      "integrity": "sha512-bsVCsONiVX1abkWdH7KtpuDAhsQ3N3bjPYhROSAXE78roJKet0Y5wznA14JE9pzbwSZmSMAW6KiKYf1RvbTJkA==",
 | 
				
			||||||
      "dev": true
 | 
					      "dev": true
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "electron-window-state": {
 | 
					    "electron-window-state": {
 | 
				
			||||||
@@ -3250,13 +3250,13 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "enhanced-resolve": {
 | 
					    "enhanced-resolve": {
 | 
				
			||||||
      "version": "5.4.0",
 | 
					      "version": "5.4.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.4.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.4.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-ZmqfWURB2lConOBM1JdCVfPyMRv5RdKWktLXO6123p97ovVm2CLBgw9t5MBj3jJWA6eHyOeIws9iJQoGFR4euQ==",
 | 
					      "integrity": "sha512-4GbyIMzYktTFoRSmkbgZ1LU+RXwf4AQ8Z+rSuuh1dC8plp0PPeaWvx6+G4hh4KnUJ48VoxKbNyA1QQQIUpXjYA==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "graceful-fs": "^4.2.4",
 | 
					        "graceful-fs": "^4.2.4",
 | 
				
			||||||
        "tapable": "^2.0.0"
 | 
					        "tapable": "^2.2.0"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "dependencies": {
 | 
					      "dependencies": {
 | 
				
			||||||
        "graceful-fs": {
 | 
					        "graceful-fs": {
 | 
				
			||||||
@@ -4142,9 +4142,9 @@
 | 
				
			|||||||
      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
 | 
					      "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "helmet": {
 | 
					    "helmet": {
 | 
				
			||||||
      "version": "4.2.0",
 | 
					      "version": "4.3.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.2.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/helmet/-/helmet-4.3.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-aoiSxXMd0ks1ojYpSCFoCRzgv4rY/uB9jKStaw8PkXwsdLYa/Gq+Nc5l0soH0cwBIsLAlujPnx4HLQs+LaXCrQ=="
 | 
					      "integrity": "sha512-WsafDyKsIexB0+pUNkq3rL1rB5GVAghR68TP8ssM9DPEMzfBiluEQlVzJ/FEj6Vq2Ag3CNuxf7aYMjXrN0X49Q=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "hosted-git-info": {
 | 
					    "hosted-git-info": {
 | 
				
			||||||
      "version": "2.8.5",
 | 
					      "version": "2.8.5",
 | 
				
			||||||
@@ -7597,9 +7597,9 @@
 | 
				
			|||||||
      "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w=="
 | 
					      "integrity": "sha512-qBIvFLGiBpLjfwmYAaHPXsn+ho5xZnGvyGvsarywGNc8VyQJUMHJ8OBKGGrPER0okBeMDaan4mNBlgBROxuI8w=="
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "webpack": {
 | 
					    "webpack": {
 | 
				
			||||||
      "version": "5.11.0",
 | 
					      "version": "5.11.1",
 | 
				
			||||||
      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.11.0.tgz",
 | 
					      "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.11.1.tgz",
 | 
				
			||||||
      "integrity": "sha512-ubWv7iP54RqAC/VjixgpnLLogCFbAfSOREcSWnnOlZEU8GICC5eKmJSu6YEnph2N2amKqY9rvxSwgyHxVqpaRw==",
 | 
					      "integrity": "sha512-tNUIdAmYJv+nupRs/U/gqmADm6fgrf5xE+rSlSsf2PgsGO7j2WG7ccU6AWNlOJlHFl+HnmXlBmHIkiLf+XA9mQ==",
 | 
				
			||||||
      "dev": true,
 | 
					      "dev": true,
 | 
				
			||||||
      "requires": {
 | 
					      "requires": {
 | 
				
			||||||
        "@types/eslint-scope": "^3.7.0",
 | 
					        "@types/eslint-scope": "^3.7.0",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,7 +41,7 @@
 | 
				
			|||||||
    "express": "4.17.1",
 | 
					    "express": "4.17.1",
 | 
				
			||||||
    "express-session": "1.17.1",
 | 
					    "express-session": "1.17.1",
 | 
				
			||||||
    "fs-extra": "9.0.1",
 | 
					    "fs-extra": "9.0.1",
 | 
				
			||||||
    "helmet": "4.2.0",
 | 
					    "helmet": "4.3.1",
 | 
				
			||||||
    "html": "1.0.0",
 | 
					    "html": "1.0.0",
 | 
				
			||||||
    "html2plaintext": "2.1.2",
 | 
					    "html2plaintext": "2.1.2",
 | 
				
			||||||
    "http-proxy-agent": "4.0.1",
 | 
					    "http-proxy-agent": "4.0.1",
 | 
				
			||||||
@@ -86,7 +86,7 @@
 | 
				
			|||||||
    "jsdoc": "3.6.6",
 | 
					    "jsdoc": "3.6.6",
 | 
				
			||||||
    "lorem-ipsum": "2.0.3",
 | 
					    "lorem-ipsum": "2.0.3",
 | 
				
			||||||
    "rcedit": "3.0.0",
 | 
					    "rcedit": "3.0.0",
 | 
				
			||||||
    "webpack": "5.11.0",
 | 
					    "webpack": "5.11.1",
 | 
				
			||||||
    "webpack-cli": "4.3.0"
 | 
					    "webpack-cli": "4.3.0"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "optionalDependencies": {
 | 
					  "optionalDependencies": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,6 @@ import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
 | 
				
			|||||||
import NoteTreeWidget from "../widgets/note_tree.js";
 | 
					import NoteTreeWidget from "../widgets/note_tree.js";
 | 
				
			||||||
import TabCachingWidget from "../widgets/tab_caching_widget.js";
 | 
					import TabCachingWidget from "../widgets/tab_caching_widget.js";
 | 
				
			||||||
import NoteTitleWidget from "../widgets/note_title.js";
 | 
					import NoteTitleWidget from "../widgets/note_title.js";
 | 
				
			||||||
import RunScriptButtonsWidget from "../widgets/run_script_buttons.js";
 | 
					 | 
				
			||||||
import NoteTypeWidget from "../widgets/note_type.js";
 | 
					import NoteTypeWidget from "../widgets/note_type.js";
 | 
				
			||||||
import NoteActionsWidget from "../widgets/note_actions.js";
 | 
					import NoteActionsWidget from "../widgets/note_actions.js";
 | 
				
			||||||
import NoteDetailWidget from "../widgets/note_detail.js";
 | 
					import NoteDetailWidget from "../widgets/note_detail.js";
 | 
				
			||||||
@@ -35,7 +34,6 @@ export default class DesktopExtraWindowLayout {
 | 
				
			|||||||
                        .overflowing()
 | 
					                        .overflowing()
 | 
				
			||||||
                        .cssBlock('.title-row > * { margin: 5px 5px 0 5px; }')
 | 
					                        .cssBlock('.title-row > * { margin: 5px 5px 0 5px; }')
 | 
				
			||||||
                        .child(new NoteTitleWidget())
 | 
					                        .child(new NoteTitleWidget())
 | 
				
			||||||
                        .child(new RunScriptButtonsWidget().hideInZenMode())
 | 
					 | 
				
			||||||
                        .child(new NoteTypeWidget().hideInZenMode())
 | 
					                        .child(new NoteTypeWidget().hideInZenMode())
 | 
				
			||||||
                        .child(new NoteActionsWidget().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 NotePathsWidget from "../widgets/note_paths.js";
 | 
				
			||||||
import NoteTitleWidget from "../widgets/note_title.js";
 | 
					import NoteTitleWidget from "../widgets/note_title.js";
 | 
				
			||||||
import OwnedAttributeListWidget from "../widgets/attribute_widgets/owned_attribute_list.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 NoteTypeWidget from "../widgets/note_type.js";
 | 
				
			||||||
import NoteActionsWidget from "../widgets/note_actions.js";
 | 
					import NoteActionsWidget from "../widgets/note_actions.js";
 | 
				
			||||||
import NoteDetailWidget from "../widgets/note_detail.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 NoteListWidget from "../widgets/note_list.js";
 | 
				
			||||||
import SearchDefinitionWidget from "../widgets/search_definition.js";
 | 
					import SearchDefinitionWidget from "../widgets/search_definition.js";
 | 
				
			||||||
import Container from "../widgets/container.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 = `
 | 
					const RIGHT_PANE_CSS = `
 | 
				
			||||||
<style>
 | 
					<style>
 | 
				
			||||||
@@ -149,7 +150,6 @@ export default class DesktopMainWindowLayout {
 | 
				
			|||||||
                        .cssBlock('.title-row > * { margin: 5px 5px 0 5px; }')
 | 
					                        .cssBlock('.title-row > * { margin: 5px 5px 0 5px; }')
 | 
				
			||||||
                        .overflowing()
 | 
					                        .overflowing()
 | 
				
			||||||
                        .child(new NoteTitleWidget())
 | 
					                        .child(new NoteTitleWidget())
 | 
				
			||||||
                        .child(new RunScriptButtonsWidget().hideInZenMode())
 | 
					 | 
				
			||||||
                        .child(new NoteTypeWidget().hideInZenMode())
 | 
					                        .child(new NoteTypeWidget().hideInZenMode())
 | 
				
			||||||
                        .child(new NoteActionsWidget().hideInZenMode())
 | 
					                        .child(new NoteActionsWidget().hideInZenMode())
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
@@ -163,8 +163,10 @@ export default class DesktopMainWindowLayout {
 | 
				
			|||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    .child(new Container()
 | 
					                    .child(new Container()
 | 
				
			||||||
                        .css('height: 100%; overflow: auto;')
 | 
					                        .css('height: 100%; overflow: auto;')
 | 
				
			||||||
 | 
					                        .child(new TabCachingWidget(() => new SqlTableSchemasWidget()))
 | 
				
			||||||
                        .child(new TabCachingWidget(() => new NoteDetailWidget()))
 | 
					                        .child(new TabCachingWidget(() => new NoteDetailWidget()))
 | 
				
			||||||
                        .child(new TabCachingWidget(() => new NoteListWidget()))
 | 
					                        .child(new TabCachingWidget(() => new NoteListWidget()))
 | 
				
			||||||
 | 
					                        .child(new TabCachingWidget(() => new SqlResultWidget()))
 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
                    .child(new TabCachingWidget(() => new SimilarNotesWidget()))
 | 
					                    .child(new TabCachingWidget(() => new SimilarNotesWidget()))
 | 
				
			||||||
                    .child(...this.customWidgets.get('center-pane'))
 | 
					                    .child(...this.customWidgets.get('center-pane'))
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -211,10 +211,12 @@ export default class Entrypoints extends Component {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        if (note.mime.endsWith("env=frontend")) {
 | 
					        if (note.mime.endsWith("env=frontend")) {
 | 
				
			||||||
            await bundleService.getAndExecuteBundle(note.noteId);
 | 
					            await bundleService.getAndExecuteBundle(note.noteId);
 | 
				
			||||||
        }
 | 
					        } else if (note.mime.endsWith("env=backend")) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (note.mime.endsWith("env=backend")) {
 | 
					 | 
				
			||||||
            await server.post('script/run/' + note.noteId);
 | 
					            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");
 | 
					        toastService.showMessage("Note executed");
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -22,8 +22,10 @@ const TPL = `
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
export default class NoteListWidget extends TabAwareWidget {
 | 
					export default class NoteListWidget extends TabAwareWidget {
 | 
				
			||||||
    isEnabled() {
 | 
					    isEnabled() {
 | 
				
			||||||
        return super.isEnabled() && (
 | 
					        return super.isEnabled()
 | 
				
			||||||
            ['book', 'search'].includes(this.note.type)
 | 
					            && this.note.mime !== 'text/x-sqlite;schema=trilium'
 | 
				
			||||||
 | 
					            && (
 | 
				
			||||||
 | 
					                ['book', 'search', 'code'].includes(this.note.type)
 | 
				
			||||||
                || (this.note.type === 'text' && this.note.hasChildren())
 | 
					                || (this.note.type === 'text' && this.note.hasChildren())
 | 
				
			||||||
            );
 | 
					            );
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -46,10 +48,6 @@ export default class NoteListWidget extends TabAwareWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    checkRenderStatus() {
 | 
					    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
 | 
					        if (this.isIntersecting
 | 
				
			||||||
            && this.noteIdRefreshed === this.noteId
 | 
					            && this.noteIdRefreshed === this.noteId
 | 
				
			||||||
            && this.shownNoteId !== 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">
 | 
					<div class="note-detail-code note-detail-printable">
 | 
				
			||||||
    <style>
 | 
					    <style>
 | 
				
			||||||
    .note-detail-code {
 | 
					    .note-detail-code {
 | 
				
			||||||
        overflow: auto;
 | 
					 | 
				
			||||||
        height: 100%;
 | 
					 | 
				
			||||||
        display: flex;
 | 
					        display: flex;
 | 
				
			||||||
        flex-direction: column;
 | 
					        flex-direction: column;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
    .note-detail-code-editor {
 | 
					    .note-detail-code-editor {
 | 
				
			||||||
        flex-basis: 200px;
 | 
					        min-height: 300px;
 | 
				
			||||||
        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;
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    </style>
 | 
					    </style>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="sql-console-area">
 | 
					    <button data-trigger-command="runActiveNote"
 | 
				
			||||||
        Tables:
 | 
					            class="no-print execute-button btn btn-sm"
 | 
				
			||||||
        <span class="sql-console-table-schemas"></span>
 | 
					            style="position: absolute; top: 0px; right: 10px; z-index: 1000;">
 | 
				
			||||||
    </div>
 | 
					        Execute
 | 
				
			||||||
 | 
					    </button>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    <div class="note-detail-code-editor"></div>
 | 
					    <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>`;
 | 
					</div>`;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
let TABLE_SCHEMA;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default class EditableCodeTypeWidget extends TypeWidget {
 | 
					export default class EditableCodeTypeWidget extends TypeWidget {
 | 
				
			||||||
    static getType() { return "editable-code"; }
 | 
					    static getType() { return "editable-code"; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -75,17 +34,10 @@ export default class EditableCodeTypeWidget extends TypeWidget {
 | 
				
			|||||||
        this.$widget = $(TPL);
 | 
					        this.$widget = $(TPL);
 | 
				
			||||||
        this.contentSized();
 | 
					        this.contentSized();
 | 
				
			||||||
        this.$editor = this.$widget.find('.note-detail-code-editor');
 | 
					        this.$editor = this.$widget.find('.note-detail-code-editor');
 | 
				
			||||||
        this.$sqlConsoleArea = this.$widget.find('.sql-console-area');
 | 
					        this.$executeButton = this.$widget.find('.execute-button');
 | 
				
			||||||
        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');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        keyboardActionService.setupActionsForElement('code-detail', this.$widget, this);
 | 
					        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();
 | 
					        this.initialized = this.initEditor();
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -122,6 +74,11 @@ export default class EditableCodeTypeWidget extends TypeWidget {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    async doRefresh(note) {
 | 
					    async doRefresh(note) {
 | 
				
			||||||
 | 
					        this.$executeButton.toggle(
 | 
				
			||||||
 | 
					            note.mime.startsWith('application/javascript')
 | 
				
			||||||
 | 
					            || note.mime === 'text/x-sqlite;schema=trilium'
 | 
				
			||||||
 | 
					        );
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const noteComplement = await this.tabContext.getNoteComplement();
 | 
					        const noteComplement = await this.tabContext.getNoteComplement();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        await this.spacedUpdate.allowUpdateWithoutChange(() => {
 | 
					        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();
 | 
					        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() {
 | 
					    show() {
 | 
				
			||||||
        this.$widget.show();
 | 
					        this.$widget.show();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
"use strict";
 | 
					"use strict";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const sql = require('../../services/sql');
 | 
					const sql = require('../../services/sql');
 | 
				
			||||||
 | 
					const repository = require('../../services/repository');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function getSchema() {
 | 
					function getSchema() {
 | 
				
			||||||
    const tableNames = sql.getColumn(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`);
 | 
					    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) {
 | 
					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 {
 | 
					    try {
 | 
				
			||||||
        const results = [];
 | 
					        const results = [];
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -232,7 +232,7 @@ function register(app) {
 | 
				
			|||||||
    route(POST, '/api/setup/sync-seed', [auth.checkAppNotInitialized], setupApiRoute.saveSyncSeed, apiResultHandler, false);
 | 
					    route(POST, '/api/setup/sync-seed', [auth.checkAppNotInitialized], setupApiRoute.saveSyncSeed, apiResultHandler, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    apiRoute(GET, '/api/sql/schema', sqlRoute.getSchema);
 | 
					    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);
 | 
					    route(POST, '/api/database/anonymize', [auth.checkApiAuthOrElectron, csrfMiddleware], databaseRoute.anonymize, apiResultHandler, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // backup requires execution outside of transaction
 | 
					    // backup requires execution outside of transaction
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user