- Add gitignore and prettier configuration files for project scaffolding - Implement room access control service with project member verification - Create user access key management with CRUD operations and activity logging - Add accordion UI component for frontend expandable sections - Implement room AI configuration with list, upsert, and delete operations - Add AI event types for agent join/leave/status change tracking - Create streaming AI processing services for mode and react patterns - Build room AI service with model detection and idempotency handling - Integrate chat service orchestration for AI message processing - Add typing indicators and stream cancellation for AI interactions - Implement mention parsing and context extraction for AI agents
95 lines
3.3 KiB
Rust
95 lines
3.3 KiB
Rust
use crate::error::RoomError;
|
|
use crate::service::RoomService;
|
|
use crate::ws_context::WsUserContext;
|
|
use models::rooms::room_notifications;
|
|
use models::users::user as user_model;
|
|
use sea_orm::*;
|
|
use uuid::Uuid;
|
|
|
|
impl RoomService {
|
|
pub async fn notification_list(
|
|
&self,
|
|
only_unread: Option<bool>,
|
|
archived: Option<bool>,
|
|
limit: Option<u64>,
|
|
ctx: &WsUserContext,
|
|
) -> Result<super::NotificationListResponse, RoomError> {
|
|
let user_id = ctx.user_id;
|
|
|
|
let show_archived = archived.unwrap_or(false);
|
|
let mut query = room_notifications::Entity::find()
|
|
.filter(room_notifications::Column::UserId.eq(user_id))
|
|
.filter(room_notifications::Column::IsArchived.eq(show_archived));
|
|
|
|
if only_unread.unwrap_or(false) {
|
|
query = query.filter(room_notifications::Column::IsRead.eq(false));
|
|
}
|
|
|
|
let unread_count = room_notifications::Entity::find()
|
|
.filter(room_notifications::Column::UserId.eq(user_id))
|
|
.filter(room_notifications::Column::IsArchived.eq(false))
|
|
.filter(room_notifications::Column::IsRead.eq(false))
|
|
.count(&self.db)
|
|
.await? as i64;
|
|
|
|
let total = query.clone().count(&self.db).await? as i64;
|
|
|
|
let models = query
|
|
.order_by_desc(room_notifications::Column::CreatedAt)
|
|
.limit(limit.unwrap_or(50))
|
|
.all(&self.db)
|
|
.await?;
|
|
|
|
let user_ids: Vec<Uuid> = models.iter().filter_map(|m| m.user_id).collect();
|
|
let users: std::collections::HashMap<Uuid, super::UserInfo> = if !user_ids.is_empty() {
|
|
user_model::Entity::find()
|
|
.filter(user_model::Column::Uid.is_in(user_ids))
|
|
.all(&self.db)
|
|
.await?
|
|
.into_iter()
|
|
.map(|u| {
|
|
(
|
|
u.uid,
|
|
super::UserInfo {
|
|
uid: u.uid,
|
|
username: u.username,
|
|
avatar_url: u.avatar_url,
|
|
},
|
|
)
|
|
})
|
|
.collect()
|
|
} else {
|
|
std::collections::HashMap::new()
|
|
};
|
|
|
|
let notifications: Vec<super::NotificationResponse> = models
|
|
.into_iter()
|
|
.map(|m| super::NotificationResponse {
|
|
id: m.id,
|
|
room: m.room,
|
|
project: m.project,
|
|
user_id: m.user_id,
|
|
user_info: m.user_id.and_then(|uid| users.get(&uid).cloned()),
|
|
notification_type: m.notification_type.to_string(),
|
|
title: m.title,
|
|
content: m.content,
|
|
related_message_id: m.related_message_id,
|
|
related_user_id: m.related_user_id,
|
|
related_room_id: m.related_room_id,
|
|
metadata: m.metadata.unwrap_or(serde_json::json!({})),
|
|
is_read: m.is_read,
|
|
is_archived: m.is_archived,
|
|
created_at: m.created_at,
|
|
read_at: m.read_at,
|
|
expires_at: m.expires_at,
|
|
})
|
|
.collect();
|
|
|
|
Ok(super::NotificationListResponse {
|
|
notifications,
|
|
total,
|
|
unread_count,
|
|
})
|
|
}
|
|
}
|