feat(react/widgets): sql table schemas

This commit is contained in:
Elian Doran 2025-08-29 17:14:27 +03:00
parent f2ce8b9f3c
commit 753f1dc7b6
No known key found for this signature in database
7 changed files with 99 additions and 111 deletions

View File

@ -7,8 +7,6 @@ import NoteTitleWidget from "../widgets/note_title.jsx";
import NoteDetailWidget from "../widgets/note_detail.js";
import PromotedAttributesWidget from "../widgets/promoted_attributes.js";
import NoteListWidget from "../widgets/note_list.js";
import SqlResultWidget from "../widgets/sql_result.js";
import SqlTableSchemasWidget from "../widgets/sql_table_schemas.js";
import NoteIconWidget from "../widgets/note_icon.jsx";
import ScrollingContainer from "../widgets/containers/scrolling_container.js";
import RootContainer from "../widgets/containers/root_container.js";
@ -43,6 +41,7 @@ import { DESKTOP_FLOATING_BUTTONS } from "../widgets/FloatingButtonsDefinitions.
import SearchResult from "../widgets/search_result.jsx";
import GlobalMenu from "../widgets/buttons/global_menu.jsx";
import SqlResults from "../widgets/sql_result.js";
import SqlTableSchemas from "../widgets/sql_table_schemas.js";
export default class DesktopLayout {
@ -137,7 +136,7 @@ export default class DesktopLayout {
new ScrollingContainer()
.filling()
.child(new PromotedAttributesWidget())
.child(new SqlTableSchemasWidget())
.child(<SqlTableSchemas />)
.child(new NoteDetailWidget())
.child(new NoteListWidget(false))
.child(<SearchResult />)

View File

@ -96,7 +96,6 @@
background: var(--background) !important;
color: var(--color) !important;
line-height: unset;
cursor: help;
}
.sql-table-schemas-widget .sql-table-schemas button:hover,
@ -106,18 +105,6 @@
--color: var(--main-text-color);
}
/* Tooltip */
.tooltip .table-schema {
font-family: var(--monospace-font-family);
font-size: .85em;
}
/* Data type */
.tooltip .table-schema td:nth-child(2) {
color: var(--muted-text-color);
}
/*
* NOTE MAP
*/

View File

@ -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);
}

View File

@ -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*/`
<div class="sql-table-schemas-widget">
<style>
.sql-table-schemas-widget {
padding: 12px;
padding-right: 10%;
}
.sql-table-schemas button {
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);
}
.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>
${t("sql_table_schemas.tables")}:
<span class="sql-table-schemas"></span>
</div>`;
interface SchemaResponse {
name: string;
columns: {
name: string;
type: string;
}[];
}
export default class SqlTableSchemasWidget extends NoteContextAwareWidget {
private tableSchemasShown?: boolean;
private $sqlConsoleTableSchemas!: JQuery<HTMLElement>;
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<SchemaResponse[]>("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",
title: $table[0].outerHTML,
sanitize: false
});
}
}
}

View File

@ -0,0 +1,45 @@
import { useEffect, useState } from "preact/hooks";
import { t } from "../services/i18n";
import { useNoteContext } from "./react/hooks";
import "./sql_table_schemas.css";
import { SchemaResponse } from "@triliumnext/commons";
import server from "../services/server";
import Dropdown from "./react/Dropdown";
export default function SqlTableSchemas() {
const { note } = useNoteContext();
const [ schemas, setSchemas ] = useState<SchemaResponse[]>();
useEffect(() => {
server.get<SchemaResponse[]>("sql/schema").then(setSchemas);
}, []);
return (
<div className="sql-table-schemas-widget">
{note?.mime === "text/x-sqlite;schema=trilium" && schemas && (
<>
{t("sql_table_schemas.tables")}{": "}
<span class="sql-table-schemas">
{schemas.map(({ name, columns }) => (
<>
<Dropdown text={name} noSelectButtonStyle hideToggleArrow
>
<table className="table-schema">
{columns.map(column => (
<tr>
<td>{column.name}</td>
<td>{column.type}</td>
</tr>
))}
</table>
</Dropdown>
{" "}
</>
))}
</span>
</>
)}
</div>
)
}

View File

@ -18,7 +18,7 @@ function getSchema() {
for (const tableName of tableNames) {
tables.push({
name: tableName,
columns: sql.getRows(`PRAGMA table_info(${tableName})`)
columns: sql.getRows<{ name: string; type: string; }>(`PRAGMA table_info(${tableName})`)
});
}

View File

@ -234,3 +234,11 @@ export interface CreateChildrenResponse {
note: NoteRow;
branch: BranchRow;
}
export interface SchemaResponse {
name: string;
columns: {
name: string;
type: string;
}[];
}