feat: chat conversation list titles, sorting, etc

This commit is contained in:
Per Stark
2025-04-15 16:34:44 +02:00
parent fbd534ff39
commit 6950009675
9 changed files with 309 additions and 7 deletions
@@ -224,3 +224,110 @@ pub async fn new_chat_user_message(
Ok(response.into_response())
}
#[derive(Deserialize)]
pub struct PatchConversationTitle {
title: String,
}
#[derive(Serialize)]
pub struct DrawerContext {
user: User,
conversation_archive: Vec<Conversation>,
#[serde(skip_serializing_if = "Option::is_none")]
edit_conversation_id: Option<String>,
}
pub async fn show_conversation_editing_title(
State(state): State<HtmlState>,
RequireUser(user): RequireUser,
Path(conversation_id): Path<String>,
) -> Result<impl IntoResponse, HtmlError> {
let conversation_archive = User::get_user_conversations(&user.id, &state.db).await?;
let owns = conversation_archive
.iter()
.any(|c| c.id == conversation_id && c.user_id == user.id);
if !owns {
return Ok(TemplateResponse::unauthorized().into_response());
}
Ok(TemplateResponse::new_template(
"chat/drawer.html",
DrawerContext {
user,
conversation_archive,
edit_conversation_id: Some(conversation_id),
},
)
.into_response())
}
pub async fn patch_conversation_title(
State(state): State<HtmlState>,
RequireUser(user): RequireUser,
Path(conversation_id): Path<String>,
Form(form): Form<PatchConversationTitle>,
) -> Result<impl IntoResponse, HtmlError> {
Conversation::patch_title(&conversation_id, &user.id, &form.title, &state.db).await?;
let updated_conversations = User::get_user_conversations(&user.id, &state.db).await?;
Ok(TemplateResponse::new_template(
"chat/drawer.html",
DrawerContext {
user,
conversation_archive: updated_conversations,
edit_conversation_id: None,
},
)
.into_response())
}
pub async fn delete_conversation(
State(state): State<HtmlState>,
RequireUser(user): RequireUser,
Path(conversation_id): Path<String>,
) -> Result<impl IntoResponse, HtmlError> {
let conversation: Conversation = state
.db
.get_item(&conversation_id)
.await?
.ok_or_else(|| AppError::NotFound("Conversation not found".to_string()))?;
if conversation.user_id != user.id {
return Ok(TemplateResponse::unauthorized().into_response());
}
state
.db
.delete_item::<Conversation>(&conversation_id)
.await?;
let conversation_archive = User::get_user_conversations(&user.id, &state.db).await?;
Ok(TemplateResponse::new_template(
"chat/drawer.html",
DrawerContext {
user,
conversation_archive,
edit_conversation_id: None,
},
)
.into_response())
}
pub async fn reload_sidebar(
State(state): State<HtmlState>,
RequireUser(user): RequireUser,
) -> Result<impl IntoResponse, HtmlError> {
let conversation_archive = User::get_user_conversations(&user.id, &state.db).await?;
Ok(TemplateResponse::new_template(
"chat/drawer.html",
DrawerContext {
user,
conversation_archive,
edit_conversation_id: None,
},
)
.into_response())
}
+13 -2
View File
@@ -8,7 +8,8 @@ use axum::{
Router,
};
use chat_handlers::{
new_chat_user_message, new_user_message, show_chat_base, show_existing_chat,
delete_conversation, new_chat_user_message, new_user_message, patch_conversation_title,
reload_sidebar, show_chat_base, show_conversation_editing_title, show_existing_chat,
show_initialized_chat,
};
use message_response_stream::get_response_stream;
@@ -23,7 +24,17 @@ where
{
Router::new()
.route("/chat", get(show_chat_base).post(new_chat_user_message))
.route("/chat/:id", get(show_existing_chat).post(new_user_message))
.route(
"/chat/:id",
get(show_existing_chat)
.post(new_user_message)
.delete(delete_conversation),
)
.route(
"/chat/:id/title",
get(show_conversation_editing_title).patch(patch_conversation_title),
)
.route("/chat/sidebar", get(reload_sidebar))
.route("/initialized-chat", post(show_initialized_chat))
.route("/chat/response-stream", get(get_response_stream))
.route("/chat/reference/:id", get(show_reference_tooltip))