112 lines
4.0 KiB
Rust
112 lines
4.0 KiB
Rust
use super::types::{ServerExplorerItem, ServerTree};
|
|
use super::RepositoryContext;
|
|
use crate::models::{category, channel, group, server};
|
|
use crate::utils::permissions::Permission;
|
|
use sea_orm::{ActiveModelTrait, ColumnTrait, DbErr, EntityTrait, QueryFilter, Set};
|
|
use std::sync::Arc;
|
|
use uuid::Uuid;
|
|
|
|
#[derive(Clone)]
|
|
pub struct ServerRepository {
|
|
pub context: Arc<RepositoryContext>,
|
|
}
|
|
|
|
impl ServerRepository {
|
|
pub async fn get_all(&self) -> Result<Vec<server::Model>, DbErr> {
|
|
server::Entity::find().all(&self.context.db).await
|
|
}
|
|
|
|
pub async fn get_by_id(&self, id: uuid::Uuid) -> Result<Option<server::Model>, DbErr> {
|
|
server::Entity::find_by_id(id).one(&self.context.db).await
|
|
}
|
|
|
|
pub async fn update(&self, active: server::ActiveModel) -> Result<server::Model, DbErr> {
|
|
let server = active.update(&self.context.db).await?;
|
|
self.context.events.emit("server_updated", server.clone());
|
|
Ok(server)
|
|
}
|
|
|
|
pub async fn create(&self, active: server::ActiveModel) -> Result<server::Model, DbErr> {
|
|
let server = active.insert(&self.context.db).await?;
|
|
|
|
// Créer le groupe par défaut pour le serveur
|
|
let default_group = group::ActiveModel {
|
|
server_id: Set(server.id),
|
|
name: Set("Membres".to_string()),
|
|
permissions: Set(Permission::default_permissions() as i64),
|
|
is_default: Set(true),
|
|
..Default::default()
|
|
};
|
|
default_group.insert(&self.context.db).await?;
|
|
|
|
self.context.events.emit("server_created", server.clone());
|
|
Ok(server)
|
|
}
|
|
|
|
pub async fn delete(&self, id: uuid::Uuid) -> Result<bool, DbErr> {
|
|
let res = server::Entity::delete_by_id(id)
|
|
.exec(&self.context.db)
|
|
.await?;
|
|
self.context.events.emit("server_deleted", id);
|
|
Ok(res.rows_affected > 0)
|
|
}
|
|
}
|
|
|
|
// Helpers
|
|
impl ServerRepository {
|
|
pub async fn get_tree(&self, server_id: Uuid) -> Result<ServerTree, DbErr> {
|
|
// 1. Récupération des catégories avec leurs channels
|
|
let categories_with_channels = category::Entity::find()
|
|
.filter(category::Column::ServerId.eq(server_id))
|
|
.find_with_related(channel::Entity)
|
|
.all(&self.context.db)
|
|
.await?;
|
|
|
|
// 2. Récupération des channels orphelins (sans catégorie)
|
|
let orphan_channels = channel::Entity::find()
|
|
.filter(channel::Column::ServerId.eq(server_id))
|
|
.filter(channel::Column::CategoryId.is_null())
|
|
.all(&self.context.db)
|
|
.await?;
|
|
|
|
// 3. Transformation et tri des enfants
|
|
let mut items: Vec<ServerExplorerItem> = Vec::new();
|
|
|
|
for (cat, mut channels) in categories_with_channels {
|
|
// On trie les channels internes (obligatoire car SQL ne garantit aucun ordre ici)
|
|
channels.sort_by(|a, b| {
|
|
a.position
|
|
.cmp(&b.position)
|
|
.then(a.created_at.cmp(&b.created_at))
|
|
});
|
|
items.push(ServerExplorerItem::Category(cat, channels));
|
|
}
|
|
|
|
for chan in orphan_channels {
|
|
items.push(ServerExplorerItem::Channel(chan));
|
|
}
|
|
|
|
// 4. Tri final de la liste globale (Mélange catégories et orphelins)
|
|
items.sort_by(|a, b| {
|
|
let pos_cmp = a.position().cmp(&b.position());
|
|
|
|
if pos_cmp == std::cmp::Ordering::Equal {
|
|
// Départage par date si position identique
|
|
let date_a = match a {
|
|
ServerExplorerItem::Category(c, _) => c.created_at,
|
|
ServerExplorerItem::Channel(c) => c.created_at,
|
|
};
|
|
let date_b = match b {
|
|
ServerExplorerItem::Category(c, _) => c.created_at,
|
|
ServerExplorerItem::Channel(c) => c.created_at,
|
|
};
|
|
date_a.cmp(&date_b)
|
|
} else {
|
|
pos_cmp
|
|
}
|
|
});
|
|
|
|
Ok(ServerTree { items })
|
|
}
|
|
}
|