This commit is contained in:
2026-01-03 18:00:01 +01:00
parent 26e0400f50
commit 96765342d1
10 changed files with 121 additions and 7 deletions

View File

@@ -1,6 +1,7 @@
use std::sync::Arc;
use sea_orm::{DbErr, EntityTrait, ActiveModelTrait};
use crate::models::server;
use sea_orm::{DbErr, EntityTrait, ActiveModelTrait, QueryFilter, ColumnTrait, QueryOrder};
use uuid::Uuid;
use crate::models::{category, channel, server};
use crate::repositories::RepositoryContext;
#[derive(Clone)]
@@ -34,4 +35,79 @@ impl ServerRepository {
self.context.events.emit("server_deleted", id);
Ok(res.rows_affected > 0)
}
}
pub enum ServerExplorerItem {
Category(category::Model, Vec<channel::Model>),
Channel(channel::Model),
}
// Pour pouvoir trier facilement
impl ServerExplorerItem {
fn position(&self) -> i32 {
match self {
ServerExplorerItem::Category(cat, _) => cat.position,
ServerExplorerItem::Channel(chan) => chan.position,
}
}
}
pub struct ServerLayout {
pub items: Vec<ServerExplorerItem>,
}
// Helpers
impl ServerRepository {
pub async fn get_channels_tree(&self, server_id: Uuid) -> Result<ServerLayout, 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(ServerLayout { items })
}
}