Files
EOS/src/akkudoktoreos/server/dash/admin.py

128 lines
4.1 KiB
Python
Raw Normal View History

"""Admin UI components for EOS Dashboard.
This module provides functions to generate administrative UI components
for the EOS dashboard.
"""
from typing import Any, Optional, Union
import requests
from fasthtml.common import Div
from monsterui.foundations import stringify
from monsterui.franken import (
Button,
ButtonT,
Card,
Details,
DivHStacked,
DividerLine,
Grid,
P,
Summary,
UkIcon,
)
def AdminButton(*c: Any, cls: Optional[Union[str, tuple]] = None, **kwargs: Any) -> Button:
"""Creates a styled button for administrative actions.
Args:
*c (Any): Positional arguments representing the button's content.
cls (Optional[Union[str, tuple]]): Additional CSS classes for styling. Defaults to None.
**kwargs (Any): Additional keyword arguments passed to the `Button`.
Returns:
Button: A styled `Button` component for admin actions.
"""
new_cls = f"{ButtonT.primary}"
if cls:
new_cls += f" {stringify(cls)}"
kwargs["cls"] = new_cls
return Button(*c, submit=False, **kwargs)
def AdminConfig(eos_host: str, eos_port: Union[str, int], data: Optional[dict]) -> Card:
"""Creates a configuration management card with save-to-file functionality.
Args:
eos_host (str): The hostname of the EOS server.
eos_port (Union[str, int]): The port of the EOS server.
data (Optional[dict]): Incoming data containing action and category for processing.
Returns:
tuple[str, Card]: A tuple containing the configuration category label and the `Card` UI component.
"""
server = f"http://{eos_host}:{eos_port}"
category = "configuration"
status = (None,)
if data and data["category"] == category:
# This data is for us
if data["action"] == "save_to_file":
# Safe current configuration to file
try:
result = requests.put(f"{server}/v1/config/file")
result.raise_for_status()
config_file_path = result.json()["general"]["config_file_path"]
status = P(
f"Actual config saved to {config_file_path} on {server}",
cls="text-left",
)
except requests.exceptions.HTTPError as err:
detail = result.json()["detail"]
status = P(
f"Can not save actual config to file on {server}: {err}, {detail}",
cls="text-left",
)
return (
category,
Card(
Details(
Summary(
Grid(
DivHStacked(
UkIcon(icon="play"),
AdminButton(
"Save to file",
hx_post="/eosdash/admin",
hx_target="#page-content",
hx_swap="innerHTML",
hx_vals='{"category": "configuration", "action": "save_to_file"}',
),
),
status,
),
cls="list-none",
),
P(f"Safe actual configuration to config file on {server}."),
),
),
)
def Admin(eos_host: str, eos_port: Union[str, int], data: Optional[dict] = None) -> Div:
"""Generates the administrative dashboard layout.
This includes configuration management and other administrative tools.
Args:
eos_host (str): The hostname of the EOS server.
eos_port (Union[str, int]): The port of the EOS server.
data (Optional[dict], optional): Incoming data to trigger admin actions. Defaults to None.
Returns:
Div: A `Div` component containing the assembled admin interface.
"""
rows = []
last_category = ""
for category, admin in [
AdminConfig(eos_host, eos_port, data),
]:
if category != last_category:
rows.append(P(category))
rows.append(DividerLine())
last_category = category
rows.append(admin)
return Div(*rows, cls="space-y-4")