Refactored Properties component to support grouped structures, updated InstancesDebugger and styles, and upgraded myutils to 0.5.0.
This commit is contained in:
@@ -38,7 +38,7 @@ mdurl==0.1.2
|
|||||||
more-itertools==10.8.0
|
more-itertools==10.8.0
|
||||||
myauth==0.2.1
|
myauth==0.2.1
|
||||||
mydbengine==0.1.0
|
mydbengine==0.1.0
|
||||||
myutils==0.4.0
|
myutils==0.5.0
|
||||||
nh3==0.3.1
|
nh3==0.3.1
|
||||||
numpy==2.3.5
|
numpy==2.3.5
|
||||||
oauthlib==3.3.1
|
oauthlib==3.3.1
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
--font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
--font-sans: ui-sans-serif, system-ui, sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace;
|
||||||
--spacing: 0.25rem;
|
--spacing: 0.25rem;
|
||||||
|
--text-xs: 0.6875rem;
|
||||||
--text-sm: 0.875rem;
|
--text-sm: 0.875rem;
|
||||||
--text-sm--line-height: calc(1.25 / 0.875);
|
--text-sm--line-height: calc(1.25 / 0.875);
|
||||||
--text-xl: 1.25rem;
|
--text-xl: 1.25rem;
|
||||||
@@ -11,6 +12,7 @@
|
|||||||
--radius-md: 0.375rem;
|
--radius-md: 0.375rem;
|
||||||
--default-font-family: var(--font-sans);
|
--default-font-family: var(--font-sans);
|
||||||
--default-mono-font-family: var(--font-mono);
|
--default-mono-font-family: var(--font-mono);
|
||||||
|
--properties-font-size: var(--text-xs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -671,4 +673,79 @@
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
border-left: 1px solid var(--color-border-primary);
|
border-left: 1px solid var(--color-border-primary);
|
||||||
|
padding: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* *********************************************** */
|
||||||
|
/* ************* Properties Component ************ */
|
||||||
|
/* *********************************************** */
|
||||||
|
|
||||||
|
/* Properties container */
|
||||||
|
.mf-properties {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Group card - using DaisyUI card styling */
|
||||||
|
.mf-properties-group-card {
|
||||||
|
background-color: var(--color-base-100);
|
||||||
|
border: 1px solid color-mix(in oklab, var(--color-base-content) 10%, transparent);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
overflow: hidden;
|
||||||
|
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Group header - gradient using DaisyUI primary color */
|
||||||
|
.mf-properties-group-header {
|
||||||
|
background: linear-gradient(135deg, var(--color-primary) 0%, color-mix(in oklab, var(--color-primary) 80%, black) 100%);
|
||||||
|
color: var(--color-primary-content);
|
||||||
|
padding: calc(var(--properties-font-size) * 0.5) calc(var(--properties-font-size) * 0.75);
|
||||||
|
font-weight: 700;
|
||||||
|
font-size: var(--properties-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Group content area */
|
||||||
|
.mf-properties-group-content {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Property row */
|
||||||
|
.mf-properties-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
padding: calc(var(--properties-font-size) * 0.4) calc(var(--properties-font-size) * 0.75);
|
||||||
|
border-bottom: 1px solid color-mix(in oklab, var(--color-base-content) 5%, transparent);
|
||||||
|
transition: background-color 0.15s ease;
|
||||||
|
gap: calc(var(--properties-font-size) * 0.75);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mf-properties-row:last-child {
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mf-properties-row:hover {
|
||||||
|
background-color: color-mix(in oklab, var(--color-base-content) 3%, transparent);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Property key - normal font */
|
||||||
|
.mf-properties-key {
|
||||||
|
font-weight: 600;
|
||||||
|
color: color-mix(in oklab, var(--color-base-content) 70%, transparent);
|
||||||
|
flex: 0 0 40%;
|
||||||
|
font-size: var(--properties-font-size);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Property value - monospace font */
|
||||||
|
.mf-properties-value {
|
||||||
|
font-family: var(--default-mono-font-family);
|
||||||
|
color: var(--color-base-content);
|
||||||
|
flex: 1;
|
||||||
|
text-align: right;
|
||||||
|
font-size: var(--properties-font-size);
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
@@ -21,7 +21,10 @@ class InstancesDebugger(SingleInstance):
|
|||||||
|
|
||||||
def on_network_event(self, event_data: dict):
|
def on_network_event(self, event_data: dict):
|
||||||
session, instance_id = event_data["nodes"][0].split("#")
|
session, instance_id = event_data["nodes"][0].split("#")
|
||||||
properties = {"Id": "_id", "Parent Id": "_parent._id"}
|
properties = {"Main": {"Id": "_id", "Parent Id": "_parent._id"},
|
||||||
|
"State": {"*": "_state"},
|
||||||
|
"Commands": {"*": "commands"},
|
||||||
|
}
|
||||||
return self._panel.set_right(Properties(self,
|
return self._panel.set_right(Properties(self,
|
||||||
InstancesManager.get(session, instance_id),
|
InstancesManager.get(session, instance_id),
|
||||||
properties,
|
properties,
|
||||||
|
|||||||
@@ -1,44 +1,50 @@
|
|||||||
from fasthtml.components import Div
|
from fasthtml.components import Div
|
||||||
from myutils.Expando import Expando
|
from myutils.ProxyObject import ProxyObject
|
||||||
|
|
||||||
from myfasthtml.core.instances import MultipleInstance
|
from myfasthtml.core.instances import MultipleInstance
|
||||||
|
|
||||||
|
|
||||||
class Properties(MultipleInstance):
|
class Properties(MultipleInstance):
|
||||||
def __init__(self, parent, obj=None, properties: dict = None, _id=None):
|
def __init__(self, parent, obj=None, groups: dict = None, _id=None):
|
||||||
super().__init__(parent, _id=_id)
|
super().__init__(parent, _id=_id)
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
self.properties = properties or self._get_default_properties(obj)
|
self.groups = groups
|
||||||
self.expando = self._create_expando()
|
self.properties_by_group = self._create_properties_by_group()
|
||||||
|
|
||||||
def set_obj(self, obj, properties: list[str] = None):
|
def set_obj(self, obj, groups: dict = None):
|
||||||
self.obj = obj
|
self.obj = obj
|
||||||
self.properties = properties or self._get_default_properties(obj)
|
self.groups = groups
|
||||||
|
self.properties_by_group = self._create_properties_by_group()
|
||||||
|
|
||||||
def render(self):
|
def render(self):
|
||||||
return Div(
|
return Div(
|
||||||
*[Div(k, ":", v) for k, v in self.expando.as_dict().items()],
|
*[
|
||||||
|
Div(
|
||||||
|
Div(group_name if group_name is not None else "", cls="mf-properties-group-header"),
|
||||||
|
Div(
|
||||||
|
*[
|
||||||
|
Div(
|
||||||
|
Div(k, cls="mf-properties-key"),
|
||||||
|
Div(str(v), cls="mf-properties-value", title=str(v)),
|
||||||
|
cls="mf-properties-row"
|
||||||
|
)
|
||||||
|
for k, v in proxy.as_dict().items()
|
||||||
|
],
|
||||||
|
cls="mf-properties-group-content"
|
||||||
|
),
|
||||||
|
cls="mf-properties-group-card"
|
||||||
|
)
|
||||||
|
for group_name, proxy in self.properties_by_group.items()
|
||||||
|
],
|
||||||
id=self._id,
|
id=self._id,
|
||||||
|
cls="mf-properties"
|
||||||
)
|
)
|
||||||
|
|
||||||
def _create_expando(self):
|
def _create_properties_by_group(self):
|
||||||
res = {}
|
if self.groups is None:
|
||||||
for attr_name, mapping in self.properties.items():
|
return {None: ProxyObject(self.obj, {"*": ""})}
|
||||||
attrs_path = mapping.split(".")
|
|
||||||
current = self.obj
|
|
||||||
for attr in attrs_path:
|
|
||||||
if hasattr(current, attr):
|
|
||||||
current = getattr(current, attr)
|
|
||||||
else:
|
|
||||||
res[attr_name] = None
|
|
||||||
break
|
|
||||||
res[attr_name] = current
|
|
||||||
|
|
||||||
return Expando(res)
|
return {k: ProxyObject(self.obj, v) for k, v in self.groups.items()}
|
||||||
|
|
||||||
@staticmethod
|
|
||||||
def _get_default_properties(obj):
|
|
||||||
return {k: k for k, v in dir(obj) if not k.startswith("_")} if obj else {}
|
|
||||||
|
|
||||||
def __ft__(self):
|
def __ft__(self):
|
||||||
return self.render()
|
return self.render()
|
||||||
|
|||||||
@@ -176,7 +176,8 @@ class InstancesManager:
|
|||||||
:param instance_id:
|
:param instance_id:
|
||||||
:return:
|
:return:
|
||||||
"""
|
"""
|
||||||
key = (InstancesManager.get_session_id(session), instance_id)
|
session_id = InstancesManager.get_session_id(session) if isinstance(session, dict) else session
|
||||||
|
key = (session_id, instance_id)
|
||||||
return InstancesManager.instances[key]
|
return InstancesManager.instances[key]
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user