Skip to content
Merged
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
2 changes: 1 addition & 1 deletion comprl-web-reflex/comprl_web/components.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ def links() -> rx.Component:
"""Render the links for the demo."""
return rx.fragment(
rx.stack(
rx.link("Home", href="/"),
rx.link("User Info", href="/dashboard"),
rx.link("Leaderboard", href="/leaderboard"),
rx.link("Games", href="/games"),
rx.link("Settings", href="/settings"),
rx.cond(
LocalAuthState.is_authenticated,
rx.link(
Expand Down
9 changes: 7 additions & 2 deletions comprl-web-reflex/comprl_web/comprl_web.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from .components import standard_layout
from . import config, reflex_local_auth
from .pages import user_dashboard, leaderboard, games
from .pages import user_dashboard, leaderboard, games, settings
from .reflex_local_auth.local_auth import LocalAuthState
from .protected_state import UserDashboardState

Expand Down Expand Up @@ -33,7 +33,7 @@ def _load_comprl_configuration() -> None:
print("Configuration loaded.")


@rx.page()
@rx.page(on_load=rx.redirect("/dashboard"))
def index() -> rx.Component:
"""Render the index page.

Expand Down Expand Up @@ -80,5 +80,10 @@ def registration() -> rx.Component:
route="/games",
title="Games",
)
app.add_page(
settings.settings,
route="/settings",
title="User Settings",
)

app.register_lifespan_task(_load_comprl_configuration)
134 changes: 134 additions & 0 deletions comprl-web-reflex/comprl_web/pages/settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
"""User settings page to change username and password."""

import reflex as rx

from ..components import standard_layout
from ..protected_state import SettingsState
from .. import reflex_local_auth


def change_username_card() -> rx.Component:
return rx.card(
rx.heading("Change Login Name", as_="h2", size="4"),
rx.cond(
SettingsState.username_error_message != "",
rx.callout(
SettingsState.username_error_message,
icon="triangle_alert",
color_scheme="red",
role="alert",
width="100%",
),
),
rx.cond(
SettingsState.username_status_message != "",
rx.callout(
SettingsState.username_status_message,
icon="check",
color_scheme="green",
role="status",
width="100%",
),
),
rx.form(
rx.hstack(
rx.input(
name="username",
value=SettingsState.username,
on_change=SettingsState.set_username,
width="100%",
),
rx.hstack(
rx.spacer(),
rx.button(
"Save",
type="submit",
),
),
align_items="stretch",
spacing="3",
),
on_submit=SettingsState.save_username,
),
width="100%",
)


def change_password_card() -> rx.Component:
return rx.card(
rx.heading("Change Password", as_="h2", size="4"),
rx.spacer(height="0.5rem"),
rx.cond(
SettingsState.password_error_message != "",
rx.callout(
SettingsState.password_error_message,
icon="triangle_alert",
color_scheme="red",
role="alert",
width="100%",
),
),
rx.cond(
SettingsState.password_status_message != "",
rx.callout(
SettingsState.password_status_message,
icon="check",
color_scheme="green",
role="status",
width="100%",
),
),
rx.form(
rx.vstack(
rx.text("Current Password:"),
rx.input(
name="current_password",
value=SettingsState.current_password,
on_change=SettingsState.set_current_password,
type="password",
width="100%",
),
rx.text("New Password:"),
rx.input(
name="new_password",
value=SettingsState.new_password,
on_change=SettingsState.set_new_password,
type="password",
placeholder="min. 8 characters",
width="100%",
),
rx.text("Confirm New Password:"),
rx.input(
name="confirm_password",
value=SettingsState.confirm_password,
on_change=SettingsState.set_confirm_password,
type="password",
width="100%",
),
rx.button(
"Update password",
type="submit",
),
spacing="1",
),
on_submit=SettingsState.save_password,
),
width="100%",
)


@reflex_local_auth.require_login
def settings() -> rx.Component:
return standard_layout(
rx.center(
rx.vstack(
change_username_card(),
change_password_card(),
spacing="4",
width="100%",
max_width="36rem",
),
on_mount=SettingsState.on_load,
),
heading="User Settings",
)
106 changes: 53 additions & 53 deletions comprl-web-reflex/comprl_web/pages/user_dashboard.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,67 +8,67 @@
from ..reflex_local_auth.local_auth import LocalAuthState


@reflex_local_auth.require_login
def dashboard() -> rx.Component:
def user_info_card() -> rx.Component:
win_rate = round(
UserDashboardState.game_statistics.num_games_won
/ UserDashboardState.game_statistics.num_games_played
* 100
)

return standard_layout(
rx.hstack(
rx.card(
rx.heading("User Information", style={"margin-bottom": "1rem"}),
rx.data_list.root(
rx.data_list.item(
rx.data_list.label("username"),
rx.data_list.value(LocalAuthState.authenticated_user.username),
),
rx.data_list.item(
rx.data_list.label("Access Token"),
rx.data_list.value(LocalAuthState.authenticated_user.token),
),
rx.data_list.item(
rx.data_list.label("Ranking"),
rx.data_list.value(
f"{UserDashboardState.ranking_position}. place"
),
),
rx.data_list.item(
rx.data_list.label("Games Played"),
rx.data_list.value(
UserDashboardState.game_statistics.num_games_played
),
),
rx.data_list.item(
rx.data_list.label("Games Won"),
rx.data_list.value(
UserDashboardState.game_statistics.num_games_won
),
),
rx.data_list.item(
rx.data_list.label("Win rate"),
rx.data_list.value(f"{win_rate} %"),
),
rx.data_list.item(
rx.data_list.label("Disconnects"),
rx.data_list.value(
UserDashboardState.game_statistics.num_disconnects
),
),
),
return rx.card(
rx.heading("User Information", style={"margin-bottom": "1rem"}),
rx.data_list.root(
rx.data_list.item(
rx.data_list.label("username"),
rx.data_list.value(LocalAuthState.authenticated_user.username),
),
rx.data_list.item(
rx.data_list.label("Access Token"),
rx.data_list.value(LocalAuthState.authenticated_user.token),
),
rx.data_list.item(
rx.data_list.label("Ranking"),
rx.data_list.value(f"{UserDashboardState.ranking_position}. place"),
),
rx.card(
rx.heading("Client Configuration", style={"margin-bottom": "1rem"}),
rx.spacer(),
rx.code_block(UserDashboardState.client_config, language="bash"),
rx.text("The client code can be found here: "),
rx.link(
"GitHub: martius-lab/comprl-hockey-agent",
href="https://github.com/martius-lab/comprl-hockey-agent",
),
rx.data_list.item(
rx.data_list.label("Games Played"),
rx.data_list.value(UserDashboardState.game_statistics.num_games_played),
),
rx.data_list.item(
rx.data_list.label("Games Won"),
rx.data_list.value(UserDashboardState.game_statistics.num_games_won),
),
rx.data_list.item(
rx.data_list.label("Win rate"),
rx.data_list.value(f"{win_rate} %"),
),
rx.data_list.item(
rx.data_list.label("Disconnects"),
rx.data_list.value(UserDashboardState.game_statistics.num_disconnects),
),
),
)


def client_config_card() -> rx.Component:
return rx.card(
rx.heading("Client Configuration", style={"margin-bottom": "1rem"}),
rx.spacer(),
rx.code_block(UserDashboardState.client_config, language="bash"),
rx.text("The client code can be found here: "),
rx.link(
"GitHub: martius-lab/comprl-hockey-agent",
href="https://github.com/martius-lab/comprl-hockey-agent",
),
)


@reflex_local_auth.require_login
def dashboard() -> rx.Component:
return standard_layout(
rx.hstack(
user_info_card(),
client_config_card(),
),
heading="Dashboard",
)
Loading