Skip to content

Commit

Permalink
Restructure UI Component Code (#808)
Browse files Browse the repository at this point in the history
* Move card components to CardComponents class

Add docstrings for CardComponents

* Move input components to InputComponents class

And add proper docstring and type hints

* Move navigation components to NavigationComponents class
  • Loading branch information
proy30 authored Jan 22, 2025
1 parent dd79d2f commit d7667fe
Show file tree
Hide file tree
Showing 9 changed files with 228 additions and 160 deletions.
6 changes: 4 additions & 2 deletions src/python/impactx/dashboard/Input/__init__.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
from trame.widgets import vuetify as vuetify

from ..trame_setup import setup_server
from .components import CardComponents, InputComponents, NavigationComponents
from .defaults import DashboardDefaults
from .generalFunctions import generalFunctions
from .trameFunctions import TrameFunctions

__all__ = [
"InputComponents",
"CardComponents",
"vuetify",
"DashboardDefaults",
"TrameFunctions",
"NavigationComponents",
"generalFunctions",
"setup_server",
]
172 changes: 172 additions & 0 deletions src/python/impactx/dashboard/Input/components.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
from typing import Optional

from . import setup_server, vuetify
from .generalFunctions import generalFunctions

server, state, ctrl = setup_server()


class CardComponents:
"""
Class contains staticmethods to build
card components using Vuetify's VCard.
"""

@staticmethod
def input_header(section_name: str, additional_components=None) -> None:
"""
Creates a standardized header look for inputs.
:param section_name: The name for the input section.
"""

documentation_name = section_name.lower().replace(" ", "_")
with vuetify.VCardTitle(section_name):
vuetify.VSpacer()
if additional_components:
additional_components()
CardComponents.refresh_icon(documentation_name)
CardComponents.documentation_icon(documentation_name)
vuetify.VDivider()

@staticmethod
def documentation_icon(section_name: str) -> vuetify.VIcon:
"""
Takes user to input section's documentation.
:param section_name: The name for the input section.
"""

return vuetify.VIcon(
"mdi-information",
style="color: #00313C;",
click=lambda: generalFunctions.documentation(section_name),
)

@staticmethod
def refresh_icon(section_name: str) -> vuetify.VIcon:
"""
Resets input values to default.
:param section_name: The name for the input section.
"""

return vuetify.VIcon(
"mdi-refresh",
style="color: #00313C;",
click=lambda: generalFunctions.reset_inputs(section_name),
)


class InputComponents:
"""
Class contains staticmethod to create
input-related Vuetify components.
"""

DENSE = True

@staticmethod
def select(
label: str,
v_model_name: Optional[str] = None,
items: Optional[list] = None,
**kwargs,
) -> vuetify.VSelect:
"""
Creates a Vuetify VSelect component with
pre-filled components.
:param label: Display label
:param v_model_name: v_model binding name. Optional, as default name
created otherwise with label name.
:param items: Items list override
"""

if v_model_name is None:
v_model_name = label.lower().replace(" ", "_")

if items is None:
items = (
generalFunctions.get_default(f"{v_model_name}_list", "default_values"),
)

return vuetify.VSelect(
label=label,
v_model=(v_model_name,),
items=items,
dense=True,
**kwargs,
)

@staticmethod
def text_field(
label: str, v_model_name: Optional[str] = None, **kwargs
) -> vuetify.VTextField:
"""
Creates a Vuetify VTextField component with
pre-filled components.
:param label: Display label
:param v_model_name: v_model binding name. Optional, as default name
created otherwise with label name.
"""

if v_model_name is None:
v_model_name = label.lower().replace(" ", "_")

return vuetify.VTextField(
label=label,
v_model=(v_model_name,),
error_messages=(f"{v_model_name}_error_message", []),
type="number",
step=generalFunctions.get_default(f"{v_model_name}", "steps"),
suffix=generalFunctions.get_default(f"{v_model_name}", "units"),
__properties=["step"],
dense=True,
**kwargs,
)


class NavigationComponents:
"""
Class contains staticmethods to create
navigation-related Vuetify components.
"""

@staticmethod
def create_route(route_title: str, mdi_icon: str) -> None:
"""
Creates a route with specified title and icon.
:param route_title: The title for the route
:param mdi_icon: The MDI icon name to display
"""
state[route_title] = False # Does not display route by default

to = f"/{route_title}"
click = f"{route_title} = true"

with vuetify.VListItem(to=to, click=click):
with vuetify.VListItemIcon():
vuetify.VIcon(mdi_icon)
with vuetify.VListItemContent():
vuetify.VListItemTitle(route_title)

@staticmethod
def create_dialog_tabs(name: str, num_tabs: int, tab_names: list[str]) -> None:
"""
Creates a tabbed dialog interface.
:param name: The base name for the tab group
:param num_tabs: Number of tabs to create
:param tab_names: List of names for each tab
"""
if len(tab_names) != num_tabs:
raise ValueError("Number of tab names must match number of tabs_names")

with vuetify.VCard():
with vuetify.VTabs(v_model=(f"{name}", 0)):
for tab_name in tab_names:
vuetify.VTab(tab_name)
vuetify.VDivider()
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from .. import TrameFunctions, setup_server, vuetify
from .. import CardComponents, InputComponents, setup_server, vuetify

server, state, ctrl = setup_server()

Expand All @@ -11,16 +11,16 @@ def card():
"""

with vuetify.VCard(v_show="csr", style="width: 170px;"):
TrameFunctions.input_section_header("CSR")
CardComponents.input_header("CSR")
with vuetify.VCardText():
with vuetify.VRow(classes="my-0"):
with vuetify.VCol(classes="py-0"):
TrameFunctions.select(
InputComponents.select(
label="Particle Shape",
)
with vuetify.VRow(classes="my-0"):
with vuetify.VCol(classes="py-0"):
TrameFunctions.text_field(
InputComponents.text_field(
label="CSR Bins",
input=(ctrl.input_change, "['csr_bins']"),
)
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@
from impactx import distribution

from .. import (
CardComponents,
DashboardDefaults,
TrameFunctions,
InputComponents,
generalFunctions,
setup_server,
vuetify,
Expand Down Expand Up @@ -173,17 +174,17 @@ def card():
"""

with vuetify.VCard(style="width: 340px; height: 300px"):
TrameFunctions.input_section_header("Distribution Parameters")
CardComponents.input_header("Distribution Parameters")
with vuetify.VCardText():
with vuetify.VRow():
with vuetify.VCol(cols=6):
TrameFunctions.select(
InputComponents.select(
label="Select Distribution",
v_model_name="distribution",
items=(DISTRIBUTION_LIST,),
)
with vuetify.VCol(cols=6):
TrameFunctions.select(
InputComponents.select(
label="Type",
v_model_name="distribution_type",
disabled=("distribution_type_disable",),
Expand Down
17 changes: 9 additions & 8 deletions src/python/impactx/dashboard/Input/inputParameters/inputMain.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
"""

from .. import (
CardComponents,
DashboardDefaults,
TrameFunctions,
InputComponents,
generalFunctions,
setup_server,
vuetify,
Expand Down Expand Up @@ -66,7 +67,7 @@ def card(self):
"""

with vuetify.VCard(style="width: 340px; height: 350px"):
TrameFunctions.input_section_header("Input Parameters")
CardComponents.input_header("Input Parameters")
with vuetify.VCardText():
with vuetify.VRow(classes="py-2"):
with vuetify.VCol(cols=6, classes="py-0"):
Expand All @@ -83,40 +84,40 @@ def card(self):
)
with vuetify.VRow(classes="my-2"):
with vuetify.VCol(cols=6, classes="py-0"):
TrameFunctions.text_field(
InputComponents.text_field(
label="Ref. Particle Charge",
v_model_name="charge_qe",
input=(ctrl.input_change, "['charge_qe']"),
)
with vuetify.VCol(cols=6, classes="py-0"):
TrameFunctions.text_field(
InputComponents.text_field(
label="Ref. Particle Mass",
v_model_name="mass_MeV",
input=(ctrl.input_change, "['mass_MeV']"),
)
with vuetify.VRow(classes="my-0"):
with vuetify.VCol(cols=12, classes="py-0"):
TrameFunctions.text_field(
InputComponents.text_field(
label="Number of Particles",
v_model_name="npart",
input=(ctrl.input_change, "['npart']"),
)
with vuetify.VRow(classes="my-2"):
with vuetify.VCol(cols=8, classes="py-0"):
TrameFunctions.text_field(
InputComponents.text_field(
label="Kinetic Energy",
v_model_name="kin_energy_on_ui",
input=(ctrl.input_change, "['kin_energy_on_ui']"),
classes="mr-2",
)
with vuetify.VCol(cols=4, classes="py-0"):
TrameFunctions.select(
InputComponents.select(
label="Unit",
v_model_name="kin_energy_unit",
)
with vuetify.VRow(classes="my-2"):
with vuetify.VCol(cols=12, classes="py-0"):
TrameFunctions.text_field(
InputComponents.text_field(
label="Bunch Charge",
v_model_name="bunch_charge_C",
input=(ctrl.input_change, "['bunch_charge_C']"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,14 @@

from impactx import elements

from .. import TrameFunctions, generalFunctions, setup_server, vuetify
from .. import (
CardComponents,
InputComponents,
NavigationComponents,
generalFunctions,
setup_server,
vuetify,
)

server, state, ctrl = setup_server()

Expand Down Expand Up @@ -237,7 +244,7 @@ def card():
LatticeConfiguration.dialog_settings()

with vuetify.VCard(style="width: 696px;"):
TrameFunctions.input_section_header("Lattice Configuration")
CardComponents.input_header("Lattice Configuration")
with vuetify.VCardText():
with vuetify.VRow(align="center", no_gutters=True):
with vuetify.VCol(cols=10):
Expand Down Expand Up @@ -306,13 +313,13 @@ def dialog_settings():
"""
dialog_name = "lattice_configuration_dialog_tab_settings"

TrameFunctions.create_dialog_tabs(dialog_name, 1, ["Defaults"])
NavigationComponents.create_dialog_tabs(dialog_name, 1, ["Defaults"])
with vuetify.VTabsItems(v_model=(dialog_name, 0)):
with vuetify.VTabItem():
with vuetify.VCardText():
with vuetify.VRow():
with vuetify.VCol(cols=3):
TrameFunctions.text_field(
InputComponents.text_field(
label="nslice",
v_model_name="nslice",
change=(
Expand Down
Loading

0 comments on commit d7667fe

Please sign in to comment.