");
-
- for (const key in result) {
- $row.append($("").text(result[key]));
- }
-
- $table.append($row);
- }
- }
- }
-}
diff --git a/apps/client/src/widgets/sql_result.tsx b/apps/client/src/widgets/sql_result.tsx
new file mode 100644
index 000000000..760651774
--- /dev/null
+++ b/apps/client/src/widgets/sql_result.tsx
@@ -0,0 +1,62 @@
+import { SqlExecuteResults } from "@triliumnext/commons";
+import { useNoteContext, useTriliumEvent } from "./react/hooks";
+import "./sql_result.css";
+import { useState } from "preact/hooks";
+import Alert from "./react/Alert";
+import { t } from "../services/i18n";
+
+export default function SqlResults() {
+ const { note, ntxId } = useNoteContext();
+ const [ results, setResults ] = useState();
+
+ useTriliumEvent("sqlQueryResults", ({ ntxId: eventNtxId, results }) => {
+ if (eventNtxId !== ntxId) return;
+ setResults(results);
+ })
+
+ return (
+
+ {note?.mime === "text/x-sqlite;schema=trilium" && (
+ results?.length === 1 && Array.isArray(results[0]) && results[0].length === 0 ? (
+
+ {t("sql_result.no_rows")}
+
+ ) : (
+
+ {results?.map(rows => {
+ // inserts, updates
+ if (typeof rows === "object" && !Array.isArray(rows)) {
+ return {JSON.stringify(rows, null, "\t")}
+ }
+
+ // selects
+ return
+ })}
+
+ )
+ )}
+
+ )
+}
+
+function SqlResultTable({ rows }: { rows: object[] }) {
+ if (!rows.length) return;
+
+ return (
+
+
+
+ {Object.keys(rows[0]).map(key => | {key} | )}
+
+
+
+
+ {rows.map(row => (
+
+ {Object.values(row).map(cell => | {cell} | )}
+
+ ))}
+
+
+ )
+}
\ No newline at end of file
diff --git a/apps/client/src/widgets/sql_table_schemas.css b/apps/client/src/widgets/sql_table_schemas.css
new file mode 100644
index 000000000..d13a71dfd
--- /dev/null
+++ b/apps/client/src/widgets/sql_table_schemas.css
@@ -0,0 +1,43 @@
+.sql-table-schemas-widget {
+ padding: 12px;
+ padding-right: 10%;
+ contain: none !important;
+}
+
+.sql-table-schemas > .dropdown {
+ display: inline-block !important;
+}
+
+.sql-table-schemas button.btn {
+ padding: 0.25rem 0.4rem;
+ font-size: 0.875rem;
+ line-height: 0.5;
+ border: 1px solid var(--button-border-color);
+ border-radius: var(--button-border-radius);
+ background: var(--button-background-color);
+ color: var(--button-text-color);
+ cursor: pointer;
+}
+
+.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;
+}
+
+.dropdown .table-schema {
+ font-family: var(--monospace-font-family);
+ font-size: .85em;
+}
+
+/* Data type */
+.dropdown .table-schema td:nth-child(2) {
+ color: var(--muted-text-color);
+}
\ No newline at end of file
diff --git a/apps/client/src/widgets/sql_table_schemas.ts b/apps/client/src/widgets/sql_table_schemas.ts
deleted file mode 100644
index 5a15881c4..000000000
--- a/apps/client/src/widgets/sql_table_schemas.ts
+++ /dev/null
@@ -1,94 +0,0 @@
-import { t } from "../services/i18n.js";
-import NoteContextAwareWidget from "./note_context_aware_widget.js";
-import server from "../services/server.js";
-import type FNote from "../entities/fnote.js";
-
-const TPL = /*html*/`
-
-
-
- ${t("sql_table_schemas.tables")}:
-
- `;
-
-interface SchemaResponse {
- name: string;
- columns: {
- name: string;
- type: string;
- }[];
-}
-
-export default class SqlTableSchemasWidget extends NoteContextAwareWidget {
-
- private tableSchemasShown?: boolean;
- private $sqlConsoleTableSchemas!: JQuery;
-
- isEnabled() {
- return this.note && this.note.mime === "text/x-sqlite;schema=trilium" && super.isEnabled();
- }
-
- doRender() {
- this.$widget = $(TPL);
- this.contentSized();
-
- this.$sqlConsoleTableSchemas = this.$widget.find(".sql-table-schemas");
- }
-
- async refreshWithNote(note: FNote) {
- if (this.tableSchemasShown) {
- return;
- }
-
- this.tableSchemasShown = true;
-
- const tableSchema = await server.get("sql/schema");
-
- for (const table of tableSchema) {
- const $tableLink = $(' |