First Working version. I can add table
This commit is contained in:
17
src/components/debugger/DebuggerApp.py
Normal file
17
src/components/debugger/DebuggerApp.py
Normal 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)
|
||||
0
src/components/debugger/__init__.py
Normal file
0
src/components/debugger/__init__.py
Normal file
79
src/components/debugger/assets/Debugger.js
Normal file
79
src/components/debugger/assets/Debugger.js
Normal 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;
|
||||
|
||||
0
src/components/debugger/assets/__init__.py
Normal file
0
src/components/debugger/assets/__init__.py
Normal file
9
src/components/debugger/assets/icons.py
Normal file
9
src/components/debugger/assets/icons.py
Normal 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>""")
|
||||
16
src/components/debugger/commands.py
Normal file
16
src/components/debugger/commands.py
Normal 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}"}}',
|
||||
}
|
||||
18
src/components/debugger/components/DbEngineDebugger.py
Normal file
18
src/components/debugger/components/DbEngineDebugger.py
Normal 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});"
|
||||
|
||||
52
src/components/debugger/components/Debugger.py
Normal file
52
src/components/debugger/components/Debugger.py
Normal 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)
|
||||
0
src/components/debugger/components/__init__.py
Normal file
0
src/components/debugger/components/__init__.py
Normal file
6
src/components/debugger/constants.py
Normal file
6
src/components/debugger/constants.py
Normal file
@@ -0,0 +1,6 @@
|
||||
DBENGINE_DEBUGGER_INSTANCE_ID = "debugger"
|
||||
ROUTE_ROOT = "/debugger"
|
||||
|
||||
class Routes:
|
||||
DbEngine = "/dbengine" # request the filtering in the grid
|
||||
|
||||
Reference in New Issue
Block a user