init
This commit is contained in:
@@ -16,6 +16,13 @@ impl CategoryRepository {
|
|||||||
.await?)
|
.await?)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn get_by_server(&self, server_id: Uuid) -> AnyResult<Vec<category::Model>> {
|
||||||
|
Ok(category::Entity::find()
|
||||||
|
.filter(category::Column::ServerId.eq(server_id))
|
||||||
|
.all(&self.context.db)
|
||||||
|
.await?)
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn get_all(&self) -> AnyResult<Vec<category::Model>> {
|
pub async fn get_all(&self) -> AnyResult<Vec<category::Model>> {
|
||||||
Ok(category::Entity::find().all(&self.context.db).await?)
|
Ok(category::Entity::find().all(&self.context.db).await?)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,16 @@
|
|||||||
use crate::core::state::AppState;
|
use crate::core::state::AppState;
|
||||||
use crate::http::context::Superuser;
|
use crate::http::context::Superuser;
|
||||||
use crate::http::error::HTTPError;
|
use crate::http::error::HTTPError;
|
||||||
|
use crate::repositories::types::{ChannelFilter, ServerTree};
|
||||||
use crate::routes::server::dto::{
|
use crate::routes::server::dto::{
|
||||||
CreateServerRequest, ServerResponse, ServerRolePermissionResponse,
|
CreateServerRequest, ServerResponse, ServerRolePermissionResponse,
|
||||||
ServerUserPermissionResponse, SetServerPermissionRequest, UpdateServerRequest,
|
ServerUserPermissionResponse, SetServerPermissionRequest, UpdateServerRequest,
|
||||||
};
|
};
|
||||||
use crate::routes::server::mapper;
|
use crate::routes::server::mapper;
|
||||||
use axum::{
|
use axum::{
|
||||||
|
Json,
|
||||||
extract::{Path, State},
|
extract::{Path, State},
|
||||||
http::StatusCode,
|
http::StatusCode,
|
||||||
Json,
|
|
||||||
};
|
};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
@@ -362,3 +363,43 @@ pub async fn remove_role_permission(
|
|||||||
|
|
||||||
Ok(StatusCode::NO_CONTENT)
|
Ok(StatusCode::NO_CONTENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[utoipa::path(
|
||||||
|
get,
|
||||||
|
path = "/servers/{id}/tree",
|
||||||
|
responses(
|
||||||
|
(status = 200, description = "Arborescence du serveur récupérée avec succès"),
|
||||||
|
(status = 404, description = "Serveur introuvable"),
|
||||||
|
(status = 500, description = "Erreur interne du serveur")
|
||||||
|
),
|
||||||
|
params(
|
||||||
|
("id" = Uuid, Path, description = "ID du serveur")
|
||||||
|
),
|
||||||
|
tag = "Servers"
|
||||||
|
)]
|
||||||
|
pub async fn get_server_tree(
|
||||||
|
State(state): State<AppState>,
|
||||||
|
Path(id): Path<Uuid>,
|
||||||
|
) -> Result<Json<ServerTree>, HTTPError> {
|
||||||
|
// Vérifier l'existence du serveur
|
||||||
|
state
|
||||||
|
.repositories
|
||||||
|
.server
|
||||||
|
.get_by_id(id)
|
||||||
|
.await?
|
||||||
|
.ok_or(HTTPError::NotFound)?;
|
||||||
|
|
||||||
|
// Exécution parallèle des 3 requêtes via leurs repositories respectifs
|
||||||
|
let (orders, channels, categories) = tokio::try_join!(
|
||||||
|
state.repositories.server_item_order.get_by_server(id),
|
||||||
|
state.repositories.channel.filter(ChannelFilter {
|
||||||
|
server_id: Some(id)
|
||||||
|
}),
|
||||||
|
state.repositories.category.get_by_server(id),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
// Assemblage du ServerTree via le mapper
|
||||||
|
let tree = mapper::build_server_tree(orders, channels, categories);
|
||||||
|
|
||||||
|
Ok(Json(tree))
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,9 +1,13 @@
|
|||||||
use crate::models::{server, server_role_permission, server_user_permission};
|
use crate::models::{
|
||||||
|
category, channel, server, server_item_order, server_role_permission, server_user_permission,
|
||||||
|
};
|
||||||
|
use crate::repositories::types::{ServerExplorerItem, ServerTree};
|
||||||
use crate::routes::server::dto::{
|
use crate::routes::server::dto::{
|
||||||
CreateServerRequest, ServerResponse, ServerRolePermissionResponse,
|
CreateServerRequest, ServerResponse, ServerRolePermissionResponse,
|
||||||
ServerUserPermissionResponse, UpdateServerRequest,
|
ServerUserPermissionResponse, UpdateServerRequest,
|
||||||
};
|
};
|
||||||
use sea_orm::Set;
|
use sea_orm::Set;
|
||||||
|
use std::collections::HashMap;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
pub fn server_model_to_server_response(model: server::Model) -> ServerResponse {
|
pub fn server_model_to_server_response(model: server::Model) -> ServerResponse {
|
||||||
@@ -57,3 +61,54 @@ pub fn server_role_permission_to_response(
|
|||||||
permissions: model.permissions as u64,
|
permissions: model.permissions as u64,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn build_server_tree(
|
||||||
|
orders: Vec<server_item_order::Model>,
|
||||||
|
channels: Vec<channel::Model>,
|
||||||
|
categories: Vec<category::Model>,
|
||||||
|
) -> ServerTree {
|
||||||
|
// Map d'accès rapide : resource_id -> order_key
|
||||||
|
let order_map: HashMap<Uuid, i64> = orders
|
||||||
|
.into_iter()
|
||||||
|
.map(|o| (o.resource_id, o.order_key))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Regrouper les canaux par catégorie ou orphelins
|
||||||
|
let mut category_channels: HashMap<Uuid, Vec<channel::Model>> = HashMap::new();
|
||||||
|
let mut orphan_channels: Vec<channel::Model> = Vec::new();
|
||||||
|
|
||||||
|
for chan in channels {
|
||||||
|
if let Some(cat_id) = chan.category_id {
|
||||||
|
category_channels.entry(cat_id).or_default().push(chan);
|
||||||
|
} else {
|
||||||
|
orphan_channels.push(chan);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Trier les canaux dans chaque catégorie par leur order_key
|
||||||
|
for chans in category_channels.values_mut() {
|
||||||
|
chans.sort_by_key(|c| order_map.get(&c.id).copied().unwrap_or(i64::MAX));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Préparer les éléments racine (catégories & canaux orphelins) avec leur order_key
|
||||||
|
let mut root_items: Vec<(ServerExplorerItem, i64)> = Vec::new();
|
||||||
|
|
||||||
|
for cat in categories {
|
||||||
|
let cat_id = cat.id;
|
||||||
|
let order_key = order_map.get(&cat_id).copied().unwrap_or(i64::MAX);
|
||||||
|
let chans = category_channels.remove(&cat_id).unwrap_or_default();
|
||||||
|
root_items.push((ServerExplorerItem::Category(cat, chans), order_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
for chan in orphan_channels {
|
||||||
|
let order_key = order_map.get(&chan.id).copied().unwrap_or(i64::MAX);
|
||||||
|
root_items.push((ServerExplorerItem::Channel(chan), order_key));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tri du niveau racine par order_key
|
||||||
|
root_items.sort_by_key(|(_, order_key)| *order_key);
|
||||||
|
|
||||||
|
let items = root_items.into_iter().map(|(item, _)| item).collect();
|
||||||
|
|
||||||
|
ServerTree { items }
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user