First Working version. I can add table

This commit is contained in:
2025-05-10 16:55:52 +02:00
parent b708ef2c46
commit 2daff83e67
157 changed files with 17282 additions and 12 deletions

View File

@@ -0,0 +1,17 @@
import logging
from fasthtml.fastapp import fast_app
from components.debugger.constants import Routes
from core.instance_manager import InstanceManager
debugger_app, rt = fast_app()
logger = logging.getLogger("Debugger")
@rt(Routes.DbEngine)
def post(session, _id: str, digest: str = None):
logger.debug(f"Entering {Routes.DbEngine} with args {_id=}, {digest=}")
instance = InstanceManager.get(session, _id)
return instance.add_tab(digest)

View File

View File

@@ -0,0 +1,79 @@
// Import the svelte-jsoneditor module
import {createJSONEditor} from 'https://cdn.jsdelivr.net/npm/vanilla-jsoneditor/standalone.js';
/**
* Initializes and displays a JSON editor using the Svelte JSON Editor.
* https://github.com/josdejong/svelte-jsoneditor
* @param {string} debuggerId - The ID of the container where the editor should be rendered.
* @param {string} targetID - The ID of the component that will receive the response (tab manager)
* @param {Object} data - The JSON data to be rendered in the editor.
*/
function showJson(debuggerId, targetID, data) {
const containerId = `dbengine-${debuggerId}`
const container = document.getElementById(containerId);
if (!container) {
console.error(`Container with ID '${containerId}' not found.`);
return;
}
// Clear previous content (if any)
container.innerHTML = '';
// Create and render the editor
const editor = createJSONEditor({
target: container,
props: {
content: {json: data},
mode: 'view', // Options: 'view', 'tree', 'text'
readOnly: true,
onSelect: (selection) => {
// Access the complete JSON
const jsonContent = editor.get()?.json || {};
const {key, value} = getSelectedNodeValue(selection, jsonContent);
htmx.ajax('POST', '/debugger/dbengine', {
target: `#${targetID}`,
headers: {"Content-Type": "application/x-www-form-urlencoded"},
swap: "outerHTML",
values: {
_id: debuggerId,
digest: value,
}
});
},
},
});
console.log('Svelte JSON Editor initialized with data:', data);
}
/**
* Retrieves the selected key and value based on the editor's selection details and JSON structure.
*
* @param {Object} selection - The editor's selection object.
* @param {Object} jsonContent - The JSON content from the editor.
* @returns {{key: string|null, value: any|null}} - The selected key and value.
*/
function getSelectedNodeValue(selection, jsonContent) {
if (!selection || !jsonContent) {
return {key: null, value: null};
}
if (selection.path) {
// If a full path is provided (e.g., ["items", 0, "value"])
const key = selection.path[selection.path.length - 1]; // The last item is the key
const value = selection.path.reduce((current, segment) => {
return current ? current[segment] : undefined;
}, jsonContent);
return {key, value};
}
// For single key/value selections
return {key: selection.key || null, value: jsonContent[selection.key] || null};
}
window.showJson = showJson;

View File

@@ -0,0 +1,9 @@
from fastcore.basics import NotStr
# DatabaseSearch20Regular
icon_dbengine = NotStr("""<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 20 20">
<g fill="none">
<path d="M4 5c0-1.007.875-1.755 1.904-2.223C6.978 2.289 8.427 2 10 2s3.022.289 4.096.777C15.125 3.245 16 3.993 16 5v4.758a4.485 4.485 0 0 0-1-.502V6.698a4.92 4.92 0 0 1-.904.525C13.022 7.711 11.573 8 10 8s-3.022-.289-4.096-.777A4.92 4.92 0 0 1 5 6.698V15c0 .374.356.875 1.318 1.313c.916.416 2.218.687 3.682.687c.22 0 .437-.006.65-.018c.447.367.966.65 1.534.822c-.68.127-1.417.196-2.184.196c-1.573 0-3.022-.289-4.096-.777C4.875 16.755 4 16.007 4 15V5zm1 0c0 .374.356.875 1.318 1.313C7.234 6.729 8.536 7 10 7s2.766-.27 3.682-.687C14.644 5.875 15 5.373 15 5c0-.374-.356-.875-1.318-1.313C12.766 3.271 11.464 3 10 3s-2.766.27-3.682.687C5.356 4.125 5 4.627 5 5zm8.5 12c.786 0 1.512-.26 2.096-.697l2.55 2.55a.5.5 0 1 0 .708-.707l-2.55-2.55A3.5 3.5 0 1 0 13.5 17zm0-1a2.5 2.5 0 1 1 0-5a2.5 2.5 0 0 1 0 5z" fill="currentColor">
</path>
</g>
</svg>""")

View File

@@ -0,0 +1,16 @@
from components.debugger.constants import ROUTE_ROOT, Routes
class Commands:
def __init__(self, owner):
self._owner = owner
self._id = owner.get_id()
def show_dbengine(self):
return {
"hx-post": f"{ROUTE_ROOT}{Routes.DbEngine}",
"hx-target": f"#{self._owner.tabs_manager.get_id()}",
"hx-swap": "outerHTML",
"hx-vals": f'{{"_id": "{self._id}"}}',
}

View File

@@ -0,0 +1,18 @@
from fasthtml.components import *
from components.BaseComponent import BaseComponent
from core.instance_manager import InstanceManager
class DbEngineDebugger(BaseComponent):
def __init__(self, session, _id, owner, data):
super().__init__(session, _id)
self._owner = owner
self.data = data
def __ft__(self):
return Div(id=f"dbengine-{self._id}")
def on_htmx_after_settle(self):
return f"showJson('{self._id}', '{self._owner.tabs_manager.get_id()}', {self.data});"

View File

@@ -0,0 +1,52 @@
import json
import logging
from fasthtml.components import *
from components.BaseComponent import BaseComponent
from components.debugger.assets.icons import icon_dbengine
from components.debugger.commands import Commands
from components.debugger.components.DbEngineDebugger import DbEngineDebugger
from components.debugger.constants import DBENGINE_DEBUGGER_INSTANCE_ID
from components_helpers import mk_ellipsis, mk_icon
from core.utils import get_unique_id
logger = logging.getLogger("Debugger")
class Debugger(BaseComponent):
def __init__(self, session, _id, settings_manager, tabs_manager):
super().__init__(session, _id)
self.settings_manager = settings_manager
self.db_engine = settings_manager.get_db_engine()
self.tabs_manager = tabs_manager
self.commands = Commands(self)
def add_tab(self, digest):
content = self.mk_db_engine(digest)
tab_key = f"debugger-dbengine-{digest}"
title = f"DBEngine-{digest if digest else 'head'}"
self.tabs_manager.add_tab(title, content, key=tab_key)
return self.tabs_manager.render()
def mk_db_engine(self, digest):
data = self.db_engine.debug_load(digest) if digest else self.db_engine.debug_head()
logger.debug(f"mk_db_engine: {data}")
return DbEngineDebugger(self._session, self._id, self, json.dumps(data))
def __ft__(self):
return Div(
Div(cls="divider"),
mk_ellipsis("Debugger", cls="text-sm font-medium mb-1"),
Div(
mk_icon(icon_dbengine, can_select=False), mk_ellipsis("DbEngine"),
cls="flex truncate",
**self.commands.show_dbengine(),
),
id=self._id,
)
@staticmethod
def create_component_id(session):
prefix = f"{DBENGINE_DEBUGGER_INSTANCE_ID}{session['user_id']}"
return get_unique_id(prefix)

View File

@@ -0,0 +1,6 @@
DBENGINE_DEBUGGER_INSTANCE_ID = "debugger"
ROUTE_ROOT = "/debugger"
class Routes:
DbEngine = "/dbengine" # request the filtering in the grid