phonograph/phono-server/src/workspace_nav.rs
2025-12-18 20:05:46 +00:00

89 lines
2.4 KiB
Rust

use anyhow::Result;
use askama::Template;
use derive_builder::Builder;
use phono_backends::client::WorkspaceClient;
use phono_models::{client::AppDbClient, workspace::Workspace};
use sqlx::postgres::types::Oid;
use uuid::Uuid;
use crate::{
navigator::Navigator,
workspaces::{RelationPortalSet, fetch_all_accessible_portals},
};
#[derive(Builder, Clone, Debug, Template)]
#[template(path = "workspace_nav.html")]
pub(crate) struct WorkspaceNav {
workspace: Workspace,
relations: Vec<RelationItem>,
#[builder(default, setter(strip_option))]
current: Option<NavLocation>,
navigator: Navigator,
}
impl WorkspaceNav {
pub fn builder() -> WorkspaceNavBuilder {
WorkspaceNavBuilder::default()
}
}
#[derive(Clone, Debug)]
pub struct RelationItem {
pub name: String,
pub oid: Oid,
pub portals: Vec<PortalItem>,
}
#[derive(Clone, Debug)]
pub struct PortalItem {
pub name: String,
pub id: Uuid,
}
#[derive(Clone, Debug, PartialEq)]
pub enum NavLocation {
Rel(Oid, Option<RelLocation>),
}
#[derive(Clone, Debug, PartialEq)]
pub enum RelLocation {
Portal(Uuid),
Sharing,
}
impl WorkspaceNavBuilder {
/// Helper function to populate relations and lenses automatically.
/// [`WorkspaceNavBuilder::workspace()`] must be called first, or else this
/// method will return an error.
///
/// WARNING: This assumes that `workspace_client` is authenticated with
/// [`RoleAssignment::User`] for the current user.
pub async fn populate_rels(
&mut self,
app_db: &mut AppDbClient,
workspace_client: &mut WorkspaceClient,
) -> Result<&mut Self> {
let workspace_id = self
.workspace
.clone()
.ok_or(WorkspaceNavBuilderError::UninitializedField("workspace"))?
.id;
Ok(self.relations(
fetch_all_accessible_portals(workspace_id, app_db, workspace_client)
.await?
.into_iter()
.map(|RelationPortalSet { rel, portals }| RelationItem {
name: rel.relname,
oid: rel.oid,
portals: portals
.into_iter()
.map(|portal| PortalItem {
id: portal.id,
name: portal.name,
})
.collect(),
})
.collect(),
))
}
}