admin_tabs.rs 78 lignes · 2730 octets
//! Tab navigation DTO shared by every `/admin/fediverse/*` screen.
//!
//! Exposes `AdminTabDTO` (one entry rendered into the tab bar) and the
//! `admin_tabs` async factory that builds the six tabs with labels
//! resolved against the i18n service. Each handler then passes the
//! `tabs` vector to its template plus an `active_tab` slug so the
//! current entry gets the `tab-active` class.

use rustwarden_core::i18n::service::I18nService;

/// One entry rendered into the federation admin tab bar.
///
/// `slug` is the stable identifier matched against the active page; the
/// template adds `tab-active` to the entry whose slug equals
/// `active_tab`. `label` carries the already-translated text (no key
/// resolution at template render time).
#[derive(Clone, serde::Serialize)]
pub struct AdminTabDTO {
    /// Translated label rendered as the tab text.
    pub label: String,
    /// Absolute URL the tab links to.
    pub href: String,
    /// Logical identifier matched against `active_tab` to flag the
    /// currently displayed tab. Stable across translations.
    pub slug: String,
}

/// Build the six federation admin tabs with localized labels.
///
/// The order mirrors the ANSSI / RFC 0021 visual hierarchy: settings →
/// trust list → queue → remote sessions → nodeinfo → invites. The
/// invites tab points at the federation hub (`/admin/fediverse`)
/// because invitations are scoped per team — the admin picks the team
/// from the hub before reaching the per-team invites screen.
pub async fn admin_tabs(i18n: &I18nService, locale: &str) -> Vec<AdminTabDTO> {
    let entries: &[(&str, &str, &str)] = &[
        (
            "settings",
            "/admin/fediverse/settings",
            "fediverse.admin.tabs.settings",
        ),
        (
            "trust_list",
            "/admin/fediverse/trust_list",
            "fediverse.admin.tabs.trust_list",
        ),
        (
            "queue",
            "/admin/fediverse/queue",
            "fediverse.admin.tabs.queue",
        ),
        (
            "sessions_remote",
            "/admin/fediverse/sessions_remote",
            "fediverse.admin.tabs.sessions_remote",
        ),
        (
            "nodeinfo",
            "/admin/fediverse/nodeinfo",
            "fediverse.admin.tabs.nodeinfo",
        ),
        (
            "invites",
            "/admin/fediverse",
            "fediverse.admin.tabs.invites",
        ),
    ];

    let mut tabs = Vec::with_capacity(entries.len());
    for (slug, href, key) in entries {
        tabs.push(AdminTabDTO {
            label: i18n.translate(key, locale).await,
            href: (*href).to_string(),
            slug: (*slug).to_string(),
        });
    }
    tabs
}