diff --git a/crates/modelrelay-cloud/src/routes/dashboard.rs b/crates/modelrelay-cloud/src/routes/dashboard.rs index aa309fb..a56cdec 100644 --- a/crates/modelrelay-cloud/src/routes/dashboard.rs +++ b/crates/modelrelay-cloud/src/routes/dashboard.rs @@ -107,10 +107,12 @@ pub async fn page(session: Session, State(state): State>) -> Res .unwrap_or_default(); let html = admin_dashboard_html(&user.email, &keys, &csrf_field); - Html(modelrelay_web::templates::page_shell( + Html(modelrelay_web::templates::page_shell_custom( "Dashboard", &html, true, + "", + "", )) .into_response() } else { @@ -154,10 +156,12 @@ pub async fn page(session: Session, State(state): State>) -> Res api_key_display.as_deref(), &csrf_field, ); - Html(modelrelay_web::templates::page_shell( + Html(modelrelay_web::templates::page_shell_custom( "Dashboard", &html, true, + "", + "", )) .into_response() } @@ -605,109 +609,193 @@ fn status_badge(status: &str) -> &'static str { } } +#[allow(clippy::too_many_lines)] +fn dashboard_css() -> &'static str { + "" +} + #[allow(clippy::too_many_lines)] fn admin_dashboard_html(email: &str, keys: &[ApiKeyRow], csrf_field: &str) -> String { let email_escaped = html_escape(email); + let mut out = String::from(dashboard_css()); - // ── Admin dashboard-specific styles ── - let admin_css = "\ -"; - - // ── Welcome header ── - let header = format!( - "{admin_css}\ -
\ -
\ + // ── Header ── + let _ = write!( + out, + "
\ +

Dashboard

\

Signed in as {email_escaped} \ Admin

\
" ); // ── Section: API Keys ── - let mut keys_html = String::from( - "\ -
", + out.push_str( + "\ +
", ); if keys.is_empty() { - keys_html.push_str("

No active API keys. Generate one below.

"); + out.push_str("

No active API keys. Generate one to get started.

"); } else { - keys_html.push_str( - "\ - ", + out.push_str( + "
NameKeyCreated
\ + ", ); for key in keys { let name_escaped = html_escape(&key.name); let key_escaped = html_escape(&key.raw_key); - let created = key.created_at.format("%Y-%m-%d %H:%M UTC").to_string(); + let created = key.created_at.format("%b %d, %Y").to_string(); let _ = write!( - keys_html, + out, "\ \ - \ - \ - \ + \ +
NameKeyCreated
{name_escaped}{key_escaped}{created}\ -
\ +
{key_escaped}{created}\ + \ {csrf_field}\
"); + out.push_str(""); } let _ = write!( - keys_html, - "
\ + out, + "
\ \ {csrf_field}\ - \ + \ \
\ -
", +
" ); - // ── Section: Status grid (workers + info) ── - let workers_card = format!( - "\ -
\ -
\ -

Workers

\ -
\ -
\ -
\ -
\ -
\ -
\ - \ -
\ -
\ -

Account

\ - \ - \ - \ -
Email{email_escaped}
RoleAdministrator
\ -
\ -
" - ); - - let onboarding_card = if keys.is_empty() { - "
\ -

🚀 Get Started

\ -

Generate an API key above, then connect your first worker machine.

\ -

Set Up a Worker →

\ + // ── Section: System ── + let _ = write!( + out, + "\ +
\ +
\ +

Workers

\ +
\ +
\ +
\ +
\ + \ +
\ +
\ +

Account

\ + \ + \ + \ +
Email{email_escaped}
RoleAdministrator
\ +
\
" - .to_string() - } else { - String::new() - }; + ); - let close = "
"; // close .admin-container + // ── Onboarding CTA (only when no keys) ── + if keys.is_empty() { + out.push_str( + "
\ +

Get Started

\ +

Generate an API key above, then connect your first worker machine.

\ +

Set Up a Worker →

\ +
", + ); + } - format!("{header}\n{keys_html}\n{workers_card}\n{onboarding_card}\n{close}") + out } #[allow(clippy::too_many_lines)] @@ -814,181 +899,91 @@ fn subscriber_dashboard_html( csrf_field: &str, ) -> String { let email_escaped = html_escape(email); + let mut out = String::from(dashboard_css()); - // ── Dashboard-specific styles ── - let dashboard_css = "\ -"; - - // ── Welcome header ── - let welcome = format!( - "{dashboard_css}\ -
\ -
\ + // ── Header ── + let _ = write!( + out, + "
\ +

Dashboard

\

Signed in as {email_escaped}

\
" ); - // ── Section: API Key (hero card) ── - let api_key_section = { - let label = ""; - let card = if let Some(s) = sub { - if let Some(key) = api_key { - format!( - "
\ -

API Key Active

\ -
\ - {}\ - \ -
\ - \ -
\ - ", - html_escape(key), - ) - } else if s.api_key_id.is_some() { - "
\ + // ── Section: API Key ── + out.push_str(""); + + if let Some(s) = sub { + if let Some(key) = api_key { + let _ = write!( + out, + "
\ +

API Key Active

\ +
\ +
{}
\ + \ +
\ + \ +
\ + ", + html_escape(key), + ); + } else if s.api_key_id.is_some() { + out.push_str( + "
\

API Key Provisioned

\

Your API key has been provisioned. \ The raw key was shown once at creation and is stored securely.

\ \ -
" - .to_string() - } else if s.status == "active" { - "
\ +
", + ); + } else if s.status == "active" { + out.push_str( + "
\

API Key Provisioning…

\ -
\ -
\ -
\ +
\ +
\ +
\
\

Your subscription is active. \ Your API key is being provisioned and will appear here shortly.

\ -
" - .to_string() - } else { - "
\ +
", + ); + } else { + out.push_str( + "
\

Get Your API Key

\

An active subscription is required for API key access.

\ View Pricing →\ -
" - .to_string() - } - } else { - "
\ +
", + ); + } + } else { + out.push_str( + "
\

Start Routing Inference Requests

\

Subscribe to get your relay API key and connect your own GPU workers.

\ View Pricing →\ -
" - .to_string() - }; - format!("{label}{card}") - }; +
", + ); + } - // ── Section: Status grid ── + // ── Section: Status ── let sub_badge = if let Some(s) = sub { format!( - "{}\ + "{}
\ \ \
Status{}
Updated{}
", @@ -998,7 +993,7 @@ fn subscriber_dashboard_html( ) } else { "No Active Subscription\ -

View pricing →

" +

View pricing →

" .to_string() }; @@ -1013,16 +1008,15 @@ fn subscriber_dashboard_html( String::new() }; - let status_section = format!( + let _ = write!( + out, "\
\
\ -

Relay Status

\ +

Relay

\
\ -
\ -
\ -
\ -
\ +
\ +
\
\