Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 19 additions & 2 deletions dashboard/components/batch.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,16 @@
from monsterui.all import *
from dashboard.app import app


def create_batches_dropdown(batch_name: str) -> DropDownNavContainer:
"""Create the metric batches dropdown menu."""
"""Create the metric batches dropdown menu.

Args:
batch_name (str): The name of the batch to display.

Returns:
DropDownNavContainer: The metric batches dropdown menu.
"""
return DropDownNavContainer(
NavHeaderLi("metric batches"),
*[
Expand All @@ -28,8 +36,17 @@ def create_batches_dropdown(batch_name: str) -> DropDownNavContainer:
],
uk_dropdown="pos: bottom-right; boundary: window; shift: true; flip: true;")


def create_batch_card(batch_name: str, stats: dict) -> Card:
"""Create a card displaying batch information."""
"""Create a card displaying batch information.

Args:
batch_name (str): The name of the batch to display.
stats (dict): The stats for the batch.

Returns:
Card: The batch card.
"""
metric_info = [
(UkIcon("activity", cls="text-blue-500"), f"{stats['unique_metrics']} metrics"),
(UkIcon("clock", cls="text-green-500"), f"{stats['latest_timestamp']}"),
Expand Down
9 changes: 8 additions & 1 deletion dashboard/components/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@


def create_controls(batch_name: str) -> Card:
"""Create the main controls for the dashboard."""
"""Create the main controls for the dashboard.

Args:
batch_name (str): The name of the batch to display.

Returns:
Card: The main controls for the dashboard.
"""
return Card(
DivFullySpaced(
Div(
Expand Down
9 changes: 7 additions & 2 deletions dashboard/components/header.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,13 @@
from fasthtml.common import *
from monsterui.all import *


def create_header() -> Div:
"""Create the dashboard header."""
"""Create the dashboard header.

Returns:
Div: The dashboard header.
"""
return DivLAligned(
H2(
"Anomstack",
Expand All @@ -30,4 +35,4 @@ def create_header() -> Div:
),
style="justify-content: space-between;",
cls="mb-6",
)
)
23 changes: 19 additions & 4 deletions dashboard/components/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,17 @@
from monsterui.all import *
from dashboard.app import app


def create_search_form(batch_name: str) -> Form:
"""Create the search form."""
"""Create the search form.

Args:
batch_name (str): The name of the batch to display.

Returns:
Form: The search form.
"""
current_search = app.state.search_term.get(batch_name, "")

return Form(
Input(
type="search",
Expand All @@ -35,8 +42,16 @@ def create_search_form(batch_name: str) -> Form:
cls="w-full md:w-auto",
)


def create_last_n_form(batch_name: str) -> Form:
"""Create the last n number form."""
"""Create the last n number form.

Args:
batch_name (str): The name of the batch to display.

Returns:
Form: The last n number form.
"""
return Form(
DivLAligned(
Input(
Expand All @@ -52,4 +67,4 @@ def create_last_n_form(batch_name: str) -> Form:
),
hx_post=f"/batch/{batch_name}/update-n",
hx_target="#main-content",
)
)
22 changes: 19 additions & 3 deletions dashboard/components/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,21 @@

from fasthtml.common import *
from monsterui.all import *
from dashboard.state import get_state
from dashboard.app import app


def create_settings_button(text: str, batch_name: str, action: str, tooltip: str) -> Li:
"""Create a settings dropdown button."""
"""Create a settings dropdown button.

Args:
text (str): The text to display on the button.
batch_name (str): The name of the batch to update.
action (str): The action to perform when the button is clicked.
tooltip (str): The tooltip to display when the button is hovered over.

Returns:
Li: The settings dropdown button.
"""
return Li(
A(
text,
Expand All @@ -25,7 +34,14 @@ def create_settings_button(text: str, batch_name: str, action: str, tooltip: str
)

def create_settings_dropdown(batch_name: str) -> DropDownNavContainer:
"""Create the settings dropdown menu."""
"""Create the settings dropdown menu.

Args:
batch_name (str): The name of the batch to update.

Returns:
DropDownNavContainer: The settings dropdown menu.
"""
buttons = [
(
"large charts" if app.state.small_charts else "small charts",
Expand Down
9 changes: 8 additions & 1 deletion dashboard/components/toolbar.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,14 @@


def create_toolbar_buttons(batch_name: str) -> Div:
"""Create the toolbar buttons."""
"""Create the toolbar buttons.

Args:
batch_name (str): The name of the batch to display.

Returns:
Div: The toolbar buttons.
"""
return Div(
Button(
DivLAligned(UkIcon("home")),
Expand Down
34 changes: 28 additions & 6 deletions dashboard/routes/batch_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,14 @@


def get_batch_data(batch_name: str):
"""Get batch data, either from cache or by fetching."""
"""Get batch data, either from cache or by fetching.

Args:
batch_name (str): The name of the batch to display.

Returns:
pd.DataFrame: The batch data.
"""
try:
return get_data(app.state.specs_enabled[batch_name],
last_n=app.state.last_n.get(batch_name,
Expand All @@ -33,12 +40,19 @@ def get_batch_data(batch_name: str):

@rt("/batch/{batch_name}")
def get_batch_view(batch_name: str,
initial_load: int = DEFAULT_LOAD_N_CHARTS):
"""Get the batch view."""
initial_load: int = DEFAULT_LOAD_N_CHARTS) -> Div:
"""Get the batch view.

Args:
batch_name (str): The name of the batch to display.
initial_load (int): The number of metrics to load initially.

Returns:
Div: The batch view.
"""
if batch_name not in app.state.df_cache or batch_name not in app.state.stats_cache:
app.state.df_cache[batch_name] = get_batch_data(batch_name)
app.state.calculate_metric_stats(batch_name)

metric_stats = app.state.stats_cache[batch_name]
remaining_metrics = len(metric_stats) - initial_load

Expand Down Expand Up @@ -82,8 +96,16 @@ def get_batch_view(batch_name: str,


@rt("/batch/{batch_name}/chart/{chart_index}")
def get(batch_name: str, chart_index: int):
"""Get chart for a batch and index."""
def get(batch_name: str, chart_index: int) -> Card:
"""Get chart for a batch and index.

Args:
batch_name (str): The name of the batch to display.
chart_index (int): The index of the chart to display.

Returns:
Card: The chart.
"""
df = app.state.df_cache[batch_name]
metric_stats = app.state.stats_cache[batch_name]
metric_name = metric_stats[chart_index]["metric_name"]
Expand Down
57 changes: 45 additions & 12 deletions dashboard/routes/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,15 @@
log = logging.getLogger("anomstack")


def _get_batch_data(batch_name: str) -> pd.DataFrame:
"""Get batch data, either from cache or by fetching."""
def get_batch_data(batch_name: str) -> pd.DataFrame:
"""Get batch data, either from cache or by fetching.

Args:
batch_name (str): The name of the batch to display.

Returns:
pd.DataFrame: The batch data.
"""
if batch_name not in app.state.df_cache:
try:
df = get_data(app.state.specs_enabled[batch_name],
Expand All @@ -38,11 +45,15 @@ def _get_batch_data(batch_name: str) -> pd.DataFrame:
return app.state.df_cache[batch_name]


def _get_sorted_batch_stats() -> tuple:
"""Calculate and sort batch statistics."""
def get_sorted_batch_stats() -> tuple:
"""Calculate and sort batch statistics.

Returns:
tuple: A tuple containing the batch statistics and sorted batch names.
"""
batch_stats = {}
for batch_name in app.state.metric_batches:
df = _get_batch_data(batch_name)
df = get_batch_data(batch_name)
batch_stats[batch_name] = calculate_batch_stats(df, batch_name)

filtered_batches = {
Expand All @@ -62,8 +73,16 @@ def _get_sorted_batch_stats() -> tuple:
return batch_stats, sorted_batch_names


def _create_main_content(batch_stats: dict, sorted_batch_names: list) -> Div:
"""Create the main dashboard content."""
def create_main_content(batch_stats: dict, sorted_batch_names: list) -> Div:
"""Create the main dashboard content.

Args:
batch_stats (dict): The batch statistics.
sorted_batch_names (list): The sorted batch names.

Returns:
Div: The main dashboard content.
"""
return Div(
Card(
DivLAligned(
Expand Down Expand Up @@ -119,8 +138,15 @@ def _create_main_content(batch_stats: dict, sorted_batch_names: list) -> Div:


@rt("/refresh-all")
def post(request: Request):
"""Refresh all batch data."""
def post(request: Request) -> list:
"""Refresh all batch data.

Args:
request (Request): The request object.

Returns:
list: A list of the main dashboard content.
"""
try:
app.state.df_cache.clear()
app.state.stats_cache.clear()
Expand All @@ -133,7 +159,14 @@ def post(request: Request):

@rt
def index(request: Request):
"""Index route for the dashboard."""
"""Index route for the dashboard.

Args:
request (Request): The request object.

Returns:
list: A list of the main dashboard content.
"""
is_htmx = request.headers.get("HX-Request") == "true"

script = Script(f"""
Expand All @@ -142,8 +175,8 @@ def index(request: Request):
}}
""")

batch_stats, sorted_batch_names = _get_sorted_batch_stats()
main_content = _create_main_content(batch_stats, sorted_batch_names)
batch_stats, sorted_batch_names = get_sorted_batch_stats()
main_content = create_main_content(batch_stats, sorted_batch_names)

if is_htmx:
return main_content
Expand Down
34 changes: 29 additions & 5 deletions dashboard/routes/search.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,17 @@

@rt("/batch/{batch_name}/search")
def get(batch_name: str, search: str = ""):
"""Search metrics."""
"""Search metrics.

Args:
batch_name (str): The name of the batch to display.
search (str): The search term.

Returns:
list: A list of the main dashboard content.
"""
import re
app.state.search_term[batch_name] = search

if batch_name not in app.state.stats_cache:
app.state.calculate_metric_stats(batch_name)

Expand Down Expand Up @@ -56,8 +63,16 @@ def get(batch_name: str, search: str = ""):


@rt("/batch/{batch_name}/load-more/{start_index}")
def get(batch_name: str, start_index: int):
"""Load more charts."""
def get(batch_name: str, start_index: int) -> list:
"""Load more charts.

Args:
batch_name (str): The name of the batch to display.
start_index (int): The index of the first chart to load.

Returns:
list: A list of the main dashboard content.
"""
metric_stats = app.state.stats_cache[batch_name]
remaining_metrics = len(metric_stats) - (start_index + 10)
load_next = min(10, remaining_metrics)
Expand Down Expand Up @@ -87,9 +102,18 @@ def get(batch_name: str, start_index: int):
),
]


@rt("/batch/{batch_name}/update-n")
def post(batch_name: str, last_n: str = "30n", session=None):
"""Update time window."""
"""Update time window.

Args:
batch_name (str): The name of the batch to display.
last_n (str): The last n number.

Returns:
list: A list of the main dashboard content.
"""
try:
app.state.last_n[batch_name] = last_n
app.state.clear_batch_cache(batch_name)
Expand Down