mirror of
https://github.com/stfrigerio/sqliteDB.git
synced 2026-07-22 05:38:02 +00:00
new add text modal
This commit is contained in:
parent
df2f429049
commit
148c874f02
7 changed files with 338 additions and 52 deletions
6
main.ts
6
main.ts
|
|
@ -19,7 +19,8 @@ import {
|
||||||
registerTextInput,
|
registerTextInput,
|
||||||
registerTimestampUpdaterButton,
|
registerTimestampUpdaterButton,
|
||||||
registerSqlChartRenderer,
|
registerSqlChartRenderer,
|
||||||
registerMoodNoteButtonProcessor
|
registerMoodNoteButtonProcessor,
|
||||||
|
registerAddTextSupport
|
||||||
} from "./src/webcomponents";
|
} from "./src/webcomponents";
|
||||||
import { SQLiteDBSettings, DEFAULT_SETTINGS } from "./src/types";
|
import { SQLiteDBSettings, DEFAULT_SETTINGS } from "./src/types";
|
||||||
import { pluginState } from "src/pluginState";
|
import { pluginState } from "src/pluginState";
|
||||||
|
|
@ -50,7 +51,8 @@ export default class SQLiteDBPlugin extends Plugin {
|
||||||
registerSqlChartRenderer(this, this.dbService);
|
registerSqlChartRenderer(this, this.dbService);
|
||||||
registerTimestampUpdaterButton(this);
|
registerTimestampUpdaterButton(this);
|
||||||
registerMoodNoteButtonProcessor(this, this.dbService);
|
registerMoodNoteButtonProcessor(this, this.dbService);
|
||||||
|
registerAddTextSupport(this, this.dbService);
|
||||||
|
|
||||||
//? Codeblocks
|
//? Codeblocks
|
||||||
this.registerMarkdownCodeBlockProcessor(
|
this.registerMarkdownCodeBlockProcessor(
|
||||||
"sql",
|
"sql",
|
||||||
|
|
|
||||||
|
|
@ -79,10 +79,8 @@ orderDirection: asc`
|
||||||
// --- Choose Renderer based on displayFormat ---
|
// --- Choose Renderer based on displayFormat ---
|
||||||
el.empty(); // Clear loading message or previous content
|
el.empty(); // Clear loading message or previous content
|
||||||
if (params.displayFormat === 'table') {
|
if (params.displayFormat === 'table') {
|
||||||
console.log("Rendering SQL block as table");
|
|
||||||
renderResultsAsTable(resultsToRender, el);
|
renderResultsAsTable(resultsToRender, el);
|
||||||
} else { // Default to 'list'
|
} else { // Default to 'list'
|
||||||
console.log("Rendering SQL block as list");
|
|
||||||
renderResults(resultsToRender, el); // Assuming renderResults is the list renderer
|
renderResults(resultsToRender, el); // Assuming renderResults is the list renderer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,40 +10,84 @@ export async function inspectTableStructure(
|
||||||
editor: Editor,
|
editor: Editor,
|
||||||
app: any
|
app: any
|
||||||
) {
|
) {
|
||||||
const db = dbService.getDB();
|
// Check if we're in local or remote mode
|
||||||
if (!db) {
|
if (dbService.mode === "local") {
|
||||||
new Notice("No DB loaded. Please open the DB first.");
|
const db = dbService.getDB();
|
||||||
return;
|
if (!db) {
|
||||||
}
|
new Notice("No DB loaded. Please open the DB first.");
|
||||||
|
|
||||||
// 1) get all table names
|
|
||||||
const result = db.exec("SELECT name FROM sqlite_master WHERE type='table';");
|
|
||||||
if (!result || result.length === 0) {
|
|
||||||
new Notice("No tables found in the DB.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const tableNames = result[0].values.map((row) => row[0] as string);
|
|
||||||
|
|
||||||
// 2) show a modal to pick one
|
|
||||||
const modal = new TablePickerModal(app, tableNames, (selectedTable) => {
|
|
||||||
// 3) query first 10 rows from that table
|
|
||||||
const rowResult = db.exec(`SELECT * FROM "${selectedTable}" LIMIT 10;`);
|
|
||||||
if (!rowResult || rowResult.length === 0) {
|
|
||||||
editor.replaceSelection(`\nNo rows found in table ${selectedTable}.\n`);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// rowResult[0].columns -> array of column names
|
// 1) get all table names
|
||||||
// rowResult[0].values -> array of row arrays
|
const result = db.exec("SELECT name FROM sqlite_master WHERE type='table';");
|
||||||
const columns = rowResult[0].columns;
|
if (!result || result.length === 0) {
|
||||||
const rows = rowResult[0].values;
|
new Notice("No tables found in the DB.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tableNames = result[0].values.map((row) => row[0] as string);
|
||||||
|
|
||||||
let output = `\n**Columns in "${selectedTable}"**\n`;
|
// 2) show a modal to pick one
|
||||||
output += columns.join(", ");
|
const modal = new TablePickerModal(app, tableNames, (selectedTable) => {
|
||||||
output += "\n\n**First row**\n";
|
// 3) query first 10 rows from that table
|
||||||
output += rows[0].join(", ");
|
const rowResult = db.exec(`SELECT * FROM "${selectedTable}" LIMIT 10;`);
|
||||||
editor.replaceSelection(output + "\n");
|
if (!rowResult || rowResult.length === 0) {
|
||||||
});
|
editor.replaceSelection(`\nNo rows found in table ${selectedTable}.\n`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
modal.open();
|
// rowResult[0].columns -> array of column names
|
||||||
|
// rowResult[0].values -> array of row arrays
|
||||||
|
const columns = rowResult[0].columns;
|
||||||
|
const rows = rowResult[0].values;
|
||||||
|
|
||||||
|
let output = `\n**Columns in "${selectedTable}"**\n`;
|
||||||
|
output += columns.join(", ");
|
||||||
|
output += "\n\n**First row**\n";
|
||||||
|
output += rows[0].join(", ");
|
||||||
|
editor.replaceSelection(output + "\n");
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.open();
|
||||||
|
} else {
|
||||||
|
// Remote mode - Use the DBService methods which handle API calls
|
||||||
|
try {
|
||||||
|
// 1) get all table names using the getQuery method
|
||||||
|
const tables = await dbService.getQuery<{name: string}>("SELECT name FROM sqlite_master WHERE type='table';");
|
||||||
|
if (!tables || tables.length === 0) {
|
||||||
|
new Notice("No tables found in the DB.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const tableNames = tables.map(table => table.name);
|
||||||
|
|
||||||
|
// 2) show a modal to pick one
|
||||||
|
const modal = new TablePickerModal(app, tableNames, async (selectedTable) => {
|
||||||
|
try {
|
||||||
|
// 3) query first 10 rows from that table
|
||||||
|
const rows = await dbService.getQuery(`SELECT * FROM "${selectedTable}" LIMIT 10;`);
|
||||||
|
if (!rows || rows.length === 0) {
|
||||||
|
editor.replaceSelection(`\nNo rows found in table ${selectedTable}.\n`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// For remote results, we get objects directly
|
||||||
|
const columns = Object.keys(rows[0]);
|
||||||
|
|
||||||
|
let output = `\n**Columns in "${selectedTable}"**\n`;
|
||||||
|
output += columns.join(", ");
|
||||||
|
output += "\n\n**First row**\n";
|
||||||
|
output += columns.map(col => rows[0][col]).join(", ");
|
||||||
|
editor.replaceSelection(output + "\n");
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error querying table rows:", error);
|
||||||
|
new Notice(`Error querying table: ${(error as Error).message}`);
|
||||||
|
editor.replaceSelection(`\nError querying table ${selectedTable}.\n`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
modal.open();
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching tables:", error);
|
||||||
|
new Notice(`Error fetching tables: ${(error as Error).message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
146
src/components/AddTextEntryModal.ts
Normal file
146
src/components/AddTextEntryModal.ts
Normal file
|
|
@ -0,0 +1,146 @@
|
||||||
|
import { App, Modal, Notice, TextAreaComponent, Setting } from 'obsidian';
|
||||||
|
import { DBService } from '../DBService'; // Adjust path
|
||||||
|
import { AddTextButtonConfig } from '../webcomponents/AddTextButton/AddTextButton'; // Import config type
|
||||||
|
|
||||||
|
export class AddTextEntryModal extends Modal {
|
||||||
|
private dbService: DBService;
|
||||||
|
private config: AddTextButtonConfig;
|
||||||
|
private inputText: string = '';
|
||||||
|
private textArea: TextAreaComponent | null = null;
|
||||||
|
|
||||||
|
constructor(app: App, dbService: DBService, config: AddTextButtonConfig) {
|
||||||
|
super(app);
|
||||||
|
this.dbService = dbService;
|
||||||
|
this.config = config; // Store the received configuration
|
||||||
|
this.modalEl.addClass('add-text-entry-modal');
|
||||||
|
}
|
||||||
|
|
||||||
|
onOpen() {
|
||||||
|
const { contentEl } = this;
|
||||||
|
contentEl.empty();
|
||||||
|
contentEl.addClass('add-text-modal-content');
|
||||||
|
|
||||||
|
// Use button text or a generic title
|
||||||
|
contentEl.createEl('h2', { text: this.config.buttonText || 'Add Text Entry' });
|
||||||
|
|
||||||
|
// Display the target table/column for clarity (optional)
|
||||||
|
contentEl.createEl('p', {
|
||||||
|
text: `Adding to table "${this.config.dbTable}", column "${this.config.textColumn}".`,
|
||||||
|
cls: 'add-text-modal-info'
|
||||||
|
});
|
||||||
|
// Display extra data being added (optional)
|
||||||
|
if (Object.keys(this.config.extraData).length > 0) {
|
||||||
|
const extraDataStr = Object.entries(this.config.extraData)
|
||||||
|
.map(([key, value]) => `${key}: ${value}`)
|
||||||
|
.join(', ');
|
||||||
|
contentEl.createEl('p', {
|
||||||
|
text: `With fixed data: ${extraDataStr}`,
|
||||||
|
cls: 'add-text-modal-info'
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Text Input Area ---
|
||||||
|
// Create a container div for the text area to center it
|
||||||
|
const textAreaContainer = contentEl.createDiv({ cls: 'text-area-container' });
|
||||||
|
textAreaContainer.style.display = 'flex';
|
||||||
|
textAreaContainer.style.justifyContent = 'center';
|
||||||
|
textAreaContainer.style.width = '100%';
|
||||||
|
textAreaContainer.style.margin = '1rem 0';
|
||||||
|
|
||||||
|
// Create the text area directly instead of using a Setting
|
||||||
|
this.textArea = new TextAreaComponent(textAreaContainer);
|
||||||
|
this.textArea.setPlaceholder("Type your text here...")
|
||||||
|
.setValue(this.inputText)
|
||||||
|
.onChange((value) => {
|
||||||
|
this.inputText = value;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Style the text area
|
||||||
|
this.textArea.inputEl.style.width = '90%';
|
||||||
|
this.textArea.inputEl.style.height = '150px';
|
||||||
|
this.textArea.inputEl.style.margin = '0 auto';
|
||||||
|
this.textArea.inputEl.style.display = 'block';
|
||||||
|
this.textArea.inputEl.addClass('add-text-entry-input');
|
||||||
|
|
||||||
|
// --- Action Buttons ---
|
||||||
|
new Setting(contentEl)
|
||||||
|
.addButton((btn) =>
|
||||||
|
btn
|
||||||
|
.setButtonText('Save Entry')
|
||||||
|
.setCta()
|
||||||
|
.onClick(() => {
|
||||||
|
this.handleSave();
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.addButton((btn) =>
|
||||||
|
btn
|
||||||
|
.setButtonText('Cancel')
|
||||||
|
.onClick(() => {
|
||||||
|
this.close();
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Focus the textarea when the modal opens
|
||||||
|
this.textArea?.inputEl.focus();
|
||||||
|
}
|
||||||
|
|
||||||
|
private async handleSave() {
|
||||||
|
const textToSave = this.inputText.trim();
|
||||||
|
|
||||||
|
if (!textToSave) {
|
||||||
|
new Notice("Please enter some text.");
|
||||||
|
this.textArea?.inputEl.focus(); // Focus back
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Prepare SQL ---
|
||||||
|
const columnsToInsert = [this.config.textColumn];
|
||||||
|
const valuesToInsert = [textToSave];
|
||||||
|
const placeholders = ['?'];
|
||||||
|
|
||||||
|
// Add extra data columns and values
|
||||||
|
for (const [key, value] of Object.entries(this.config.extraData)) {
|
||||||
|
columnsToInsert.push(key); // Use key directly (e.g., 'period', 'key')
|
||||||
|
valuesToInsert.push(value);
|
||||||
|
placeholders.push('?');
|
||||||
|
}
|
||||||
|
|
||||||
|
// generate a random uuid for the entry
|
||||||
|
const uuid = this.dbService.generateUuid();
|
||||||
|
const createdAt = new Date().toISOString();
|
||||||
|
// Add the uuid to the columns and values
|
||||||
|
columnsToInsert.push("uuid");
|
||||||
|
valuesToInsert.push(uuid);
|
||||||
|
placeholders.push('?');
|
||||||
|
columnsToInsert.push("createdAt");
|
||||||
|
columnsToInsert.push("updatedAt");
|
||||||
|
valuesToInsert.push(createdAt);
|
||||||
|
valuesToInsert.push(createdAt);
|
||||||
|
placeholders.push('?');
|
||||||
|
placeholders.push('?');
|
||||||
|
|
||||||
|
// Quote table and column names
|
||||||
|
const quotedTable = `"${this.config.dbTable}"`;
|
||||||
|
const quotedColumns = columnsToInsert.map(col => `"${col}"`).join(', ');
|
||||||
|
const placeholderString = placeholders.join(', ');
|
||||||
|
|
||||||
|
const sql = `INSERT INTO ${quotedTable} (${quotedColumns}) VALUES (${placeholderString});`;
|
||||||
|
const params = valuesToInsert;
|
||||||
|
|
||||||
|
// --- Execute Query ---
|
||||||
|
try {
|
||||||
|
await this.dbService.runQuery(sql, params); // Assumes runQuery for INSERT
|
||||||
|
new Notice(`Entry added to "${this.config.dbTable}"!`);
|
||||||
|
this.close();
|
||||||
|
// Optionally trigger a refresh or callback here if needed
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error saving text entry to ${this.config.dbTable}:`, error);
|
||||||
|
new Notice(`Failed to save entry. Check console. Error: ${error.message}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onClose() {
|
||||||
|
const { contentEl } = this;
|
||||||
|
contentEl.empty();
|
||||||
|
}
|
||||||
|
}
|
||||||
108
src/webcomponents/AddTextButton/AddTextButton.ts
Normal file
108
src/webcomponents/AddTextButton/AddTextButton.ts
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
import { Plugin, Notice, App, ButtonComponent, MarkdownPostProcessorContext } from 'obsidian';
|
||||||
|
import { DBService } from '../../DBService'; // Adjust path
|
||||||
|
import { AddTextEntryModal } from '../../components/AddTextEntryModal'; // Adjust path
|
||||||
|
import { replacePlaceholders } from '../../helpers/replacePlaceholders'; // Import your placeholder function - ADJUST PATH
|
||||||
|
|
||||||
|
// Re-define or import the config interface if not imported from component
|
||||||
|
export interface AddTextButtonConfig {
|
||||||
|
buttonText: string;
|
||||||
|
dbTable: string;
|
||||||
|
textColumn: string;
|
||||||
|
extraData: Record<string, any>;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registers the post-processor for add-text buttons and the global event listener.
|
||||||
|
*/
|
||||||
|
export function registerAddTextSupport(plugin: Plugin, dbService: DBService) {
|
||||||
|
|
||||||
|
// --- 1. Register the Post Processor ---
|
||||||
|
plugin.registerMarkdownPostProcessor((el: HTMLElement, ctx: MarkdownPostProcessorContext) => {
|
||||||
|
const placeholders = el.querySelectorAll<HTMLDivElement>('div.add-text-button-placeholder');
|
||||||
|
|
||||||
|
placeholders.forEach(placeholder => {
|
||||||
|
if (placeholder.dataset.processed) return;
|
||||||
|
placeholder.dataset.processed = 'true';
|
||||||
|
|
||||||
|
// --- Read Raw Configuration from Attributes ---
|
||||||
|
const rawDataTable = placeholder.dataset.table;
|
||||||
|
const rawTextColumn = placeholder.dataset.column;
|
||||||
|
const rawButtonText = placeholder.dataset.buttonText || `Add Entry to ${rawDataTable || 'Table'}`;
|
||||||
|
|
||||||
|
// --- Basic Validation (on raw attributes) ---
|
||||||
|
if (!rawDataTable || !rawTextColumn) {
|
||||||
|
placeholder.textContent = '[Error: add-text-button-placeholder requires data-table and data-column attributes]';
|
||||||
|
placeholder.style.color = 'var(--text-error)';
|
||||||
|
placeholder.style.fontFamily = 'monospace';
|
||||||
|
console.error('AddTextProcessor: Missing required attributes data-table or data-column', placeholder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Collect Raw Extra Data ---
|
||||||
|
const rawExtraData: Record<string, string | undefined> = {};
|
||||||
|
// Iterate over dataset keys
|
||||||
|
for (const key in placeholder.dataset) {
|
||||||
|
// Include keys other than the standard ones and 'processed'
|
||||||
|
if (key !== 'table' && key !== 'column' && key !== 'buttonText' && key !== 'processed') {
|
||||||
|
rawExtraData[key] = placeholder.dataset[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// --- Render the Button ---
|
||||||
|
placeholder.innerHTML = ''; // Clear placeholder content
|
||||||
|
placeholder.addClass('add-text-button-container');
|
||||||
|
|
||||||
|
// Use Obsidian's ButtonComponent for styling
|
||||||
|
const button = new ButtonComponent(placeholder)
|
||||||
|
// Set initial text (placeholders will be resolved onClick)
|
||||||
|
.setButtonText(replacePlaceholders(rawButtonText)) // Resolve button text once for display
|
||||||
|
.setClass('add-text-trigger-button');
|
||||||
|
button.buttonEl.style.margin = '0.5em 0';
|
||||||
|
|
||||||
|
// --- Attach Click Handler ---
|
||||||
|
button.onClick(() => {
|
||||||
|
// --- Apply Placeholders NOW (inside onClick) ---
|
||||||
|
const processedExtraData: Record<string, any> = {};
|
||||||
|
for (const [key, rawValue] of Object.entries(rawExtraData)) {
|
||||||
|
// Only process if the raw value exists
|
||||||
|
processedExtraData[key] = rawValue !== undefined ? replacePlaceholders(rawValue) : undefined;
|
||||||
|
}
|
||||||
|
const processedButtonText = replacePlaceholders(rawButtonText);
|
||||||
|
|
||||||
|
// --- Construct Final Config ---
|
||||||
|
const finalConfig: AddTextButtonConfig = {
|
||||||
|
buttonText: processedButtonText,
|
||||||
|
dbTable: rawDataTable, // Table/Column names usually don't need placeholder replacement
|
||||||
|
textColumn: rawTextColumn,
|
||||||
|
extraData: processedExtraData
|
||||||
|
};
|
||||||
|
|
||||||
|
// --- Dispatch Event with *processed* config ---
|
||||||
|
placeholder.dispatchEvent(new CustomEvent('request-add-text-modal', {
|
||||||
|
bubbles: true,
|
||||||
|
composed: true,
|
||||||
|
detail: finalConfig // Pass the processed config
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- 2. Register the Global Event Listener (Remains the Same) ---
|
||||||
|
plugin.registerDomEvent(
|
||||||
|
document,
|
||||||
|
'request-add-text-modal' as keyof DocumentEventMap,
|
||||||
|
(evt: Event) => {
|
||||||
|
if (!(evt instanceof CustomEvent) || !evt.detail) return;
|
||||||
|
|
||||||
|
const config = evt.detail as AddTextButtonConfig;
|
||||||
|
|
||||||
|
if (!dbService) {
|
||||||
|
new Notice("Database service is not ready.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const appInstance = plugin.app;
|
||||||
|
new AddTextEntryModal(appInstance, dbService, config).open();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import { MarkdownPostProcessorContext, Plugin } from 'obsidian';
|
import { MarkdownPostProcessorContext, Plugin } from 'obsidian';
|
||||||
import { DBService } from '../../DBService'; // Adjust path as needed
|
import { DBService } from '../../DBService';
|
||||||
import { processSqlChartBlock } from '../../codeblocks/processSqlChartBlock'; // Adjust path as needed
|
import { processSqlChartBlock } from '../../codeblocks/processSqlChartBlock';
|
||||||
import { replacePlaceholders } from 'src/helpers/replacePlaceholders';
|
import { replacePlaceholders } from 'src/helpers/replacePlaceholders';
|
||||||
|
|
||||||
// This function sets up the post-processor
|
|
||||||
export function registerSqlChartRenderer(plugin: Plugin, dbService: DBService) {
|
export function registerSqlChartRenderer(plugin: Plugin, dbService: DBService) {
|
||||||
|
|
||||||
plugin.registerMarkdownPostProcessor(
|
plugin.registerMarkdownPostProcessor(
|
||||||
|
|
@ -13,13 +12,10 @@ export function registerSqlChartRenderer(plugin: Plugin, dbService: DBService) {
|
||||||
const chartContainers = el.querySelectorAll<HTMLElement>('div.sql-chart-render');
|
const chartContainers = el.querySelectorAll<HTMLElement>('div.sql-chart-render');
|
||||||
|
|
||||||
if (chartContainers.length === 0) {
|
if (chartContainers.length === 0) {
|
||||||
return; // No charts found in this section
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use Promise.all to process charts potentially in parallel (optional)
|
|
||||||
// Or a simple loop if preferred: for (const container of chartContainers) { ... }
|
|
||||||
await Promise.all(Array.from(chartContainers).map(async (container) => {
|
await Promise.all(Array.from(chartContainers).map(async (container) => {
|
||||||
// Check if already processed (important if post-processor runs multiple times)
|
|
||||||
if (container.dataset.sqlChartProcessed) {
|
if (container.dataset.sqlChartProcessed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -28,8 +24,6 @@ export function registerSqlChartRenderer(plugin: Plugin, dbService: DBService) {
|
||||||
|
|
||||||
const source = container.innerHTML.trim();
|
const source = container.innerHTML.trim();
|
||||||
const parsedSource = replacePlaceholders(source);
|
const parsedSource = replacePlaceholders(source);
|
||||||
|
|
||||||
// Clear the original config text before rendering
|
|
||||||
container.innerHTML = ''; // Clear the container
|
container.innerHTML = ''; // Clear the container
|
||||||
|
|
||||||
if (!source) {
|
if (!source) {
|
||||||
|
|
@ -38,25 +32,18 @@ export function registerSqlChartRenderer(plugin: Plugin, dbService: DBService) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a loading indicator (optional)
|
|
||||||
const loadingEl = container.createEl("p", { text: "Loading chart..." });
|
const loadingEl = container.createEl("p", { text: "Loading chart..." });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Call your existing core logic directly on the container
|
|
||||||
await processSqlChartBlock(dbService, parsedSource, container);
|
await processSqlChartBlock(dbService, parsedSource, container);
|
||||||
// Remove loading indicator if processSqlChartBlock doesn't clear the container itself
|
|
||||||
loadingEl.remove();
|
loadingEl.remove();
|
||||||
} catch (error: any) {
|
} catch (error: any) {
|
||||||
console.error("Error rendering SQL Chart from div:", error);
|
console.error("Error rendering SQL Chart from div:", error);
|
||||||
// Clear potential loading message or partial render
|
|
||||||
container.innerHTML = '';
|
container.innerHTML = '';
|
||||||
container.createEl("p", { text: "Error rendering SQL Chart:" });
|
container.createEl("p", { text: "Error rendering SQL Chart:" });
|
||||||
// Display the error message safely
|
|
||||||
container.createEl("pre", { text: String(error.message || error) });
|
container.createEl("pre", { text: String(error.message || error) });
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
console.log("SQL Chart Renderer registered.");
|
|
||||||
}
|
}
|
||||||
|
|
@ -4,5 +4,6 @@ import { registerTextInput } from "./TextInput/registerTextInput";
|
||||||
import { registerTimestampUpdaterButton } from "./TimestampUpdaterButton/registerTimestampUpdaterButton";
|
import { registerTimestampUpdaterButton } from "./TimestampUpdaterButton/registerTimestampUpdaterButton";
|
||||||
import { registerSqlChartRenderer } from "./SqlChart/registerSqlChart";
|
import { registerSqlChartRenderer } from "./SqlChart/registerSqlChart";
|
||||||
import { registerMoodNoteButtonProcessor } from "./MoodNote/moodButtonProcessor";
|
import { registerMoodNoteButtonProcessor } from "./MoodNote/moodButtonProcessor";
|
||||||
|
import { registerAddTextSupport } from "./AddTextButton/AddTextButton";
|
||||||
|
|
||||||
export { registerHabitCounter, registerBooleanSwitch, registerTextInput, registerTimestampUpdaterButton, registerSqlChartRenderer, registerMoodNoteButtonProcessor };
|
export { registerHabitCounter, registerBooleanSwitch, registerTextInput, registerTimestampUpdaterButton, registerSqlChartRenderer, registerMoodNoteButtonProcessor, registerAddTextSupport };
|
||||||
Loading…
Reference in a new issue