From 8b47daba8bd315639fa49d8608e8985af16e5fe4 Mon Sep 17 00:00:00 2001 From: Travis Vasceannie Date: Mon, 26 Jan 2026 09:56:35 +0000 Subject: [PATCH] feat(tauri): add delete_meetings bulk delete command - Add DeleteMeetingsRequest/Response types to core.rs - Implement delete_meetings method in gRPC client - Add delete_meetings Tauri command in meeting.rs - Register command in app handler Enables frontend to bulk delete meetings via single IPC call. Refs: mass-delete-meetings plan tasks 3-4 --- client/src-tauri/src/commands/meeting.rs | 9 ++++ client/src-tauri/src/grpc/client/meetings.rs | 21 +++++++++ client/src-tauri/src/grpc/noteflow.rs | 48 ++++++++++++++++++++ client/src-tauri/src/grpc/types/core.rs | 20 ++++++++ client/src-tauri/src/lib.rs | 1 + 5 files changed, 99 insertions(+) diff --git a/client/src-tauri/src/commands/meeting.rs b/client/src-tauri/src/commands/meeting.rs index c28a759..ad20b77 100644 --- a/client/src-tauri/src/commands/meeting.rs +++ b/client/src-tauri/src/commands/meeting.rs @@ -90,3 +90,12 @@ pub async fn stop_meeting(state: State<'_, Arc>, meeting_id: String) - pub async fn delete_meeting(state: State<'_, Arc>, meeting_id: String) -> Result { state.grpc_client.delete_meeting(&meeting_id).await } + +/// Delete multiple meetings in bulk. +#[tauri::command(rename_all = "snake_case")] +pub async fn delete_meetings( + state: State<'_, Arc>, + meeting_ids: Vec, +) -> Result { + state.grpc_client.delete_meetings(meeting_ids).await +} diff --git a/client/src-tauri/src/grpc/client/meetings.rs b/client/src-tauri/src/grpc/client/meetings.rs index 454bef8..4de90fc 100644 --- a/client/src-tauri/src/grpc/client/meetings.rs +++ b/client/src-tauri/src/grpc/client/meetings.rs @@ -15,6 +15,7 @@ use crate::grpc::types::core::{ SummarizationTemplate, SummarizationTemplateMutationResult, Summary, + DeleteMeetingsResponse, }; use super::converters::{ @@ -131,6 +132,26 @@ impl GrpcClient { Ok(response.success) } + /// Delete multiple meetings in bulk. + #[instrument(skip(self))] + pub async fn delete_meetings(&self, meeting_ids: Vec) -> Result { + let mut client = self.get_client()?; + let response = client + .delete_meetings(pb::DeleteMeetingsRequest { + meeting_ids, + }) + .await? + .into_inner(); + + Ok(DeleteMeetingsResponse { + deleted_count: response.deleted_count, + succeeded_ids: response.succeeded_ids, + failed_ids: response.failed_ids, + skipped_ids: response.skipped_ids, + error_message: response.error_message, + }) + } + /// Generate a summary for a meeting. #[instrument(skip(self, options))] pub async fn generate_summary( diff --git a/client/src-tauri/src/grpc/noteflow.rs b/client/src-tauri/src/grpc/noteflow.rs index 680e39f..56ecd17 100644 --- a/client/src-tauri/src/grpc/noteflow.rs +++ b/client/src-tauri/src/grpc/noteflow.rs @@ -230,6 +230,30 @@ pub struct DeleteMeetingResponse { pub success: bool, } #[derive(Clone, PartialEq, ::prost::Message)] +pub struct DeleteMeetingsRequest { + /// Meeting IDs to delete + #[prost(string, repeated, tag = "1")] + pub meeting_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, +} +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct DeleteMeetingsResponse { + /// Number of meetings successfully deleted + #[prost(int32, tag = "1")] + pub deleted_count: i32, + /// Meeting IDs that were successfully deleted + #[prost(string, repeated, tag = "2")] + pub succeeded_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// Meeting IDs that failed to delete + #[prost(string, repeated, tag = "3")] + pub failed_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// Meeting IDs that were skipped (e.g., active recordings) + #[prost(string, repeated, tag = "4")] + pub skipped_ids: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + /// Error message if batch operation failed + #[prost(string, tag = "5")] + pub error_message: ::prost::alloc::string::String, +} +#[derive(Clone, PartialEq, ::prost::Message)] pub struct Summary { /// Meeting this summary belongs to #[prost(string, tag = "1")] @@ -3511,6 +3535,30 @@ pub mod note_flow_service_client { .insert(GrpcMethod::new("noteflow.NoteFlowService", "DeleteMeeting")); self.inner.unary(req, path, codec).await } + pub async fn delete_meetings( + &mut self, + request: impl tonic::IntoRequest, + ) -> std::result::Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::unknown( + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/noteflow.NoteFlowService/DeleteMeetings", + ); + let mut req = request.into_request(); + req.extensions_mut() + .insert(GrpcMethod::new("noteflow.NoteFlowService", "DeleteMeetings")); + self.inner.unary(req, path, codec).await + } /// Summary generation pub async fn generate_summary( &mut self, diff --git a/client/src-tauri/src/grpc/types/core.rs b/client/src-tauri/src/grpc/types/core.rs index 28ef25e..b87a9b5 100644 --- a/client/src-tauri/src/grpc/types/core.rs +++ b/client/src-tauri/src/grpc/types/core.rs @@ -348,3 +348,23 @@ pub struct CloudConsentStatus { pub summary_consent: bool, pub embedding_consent: bool, } + +// ============================================================================ +// Bulk Delete Meetings +// ============================================================================ + +/// Request to delete multiple meetings +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DeleteMeetingsRequest { + pub meeting_ids: Vec, +} + +/// Response from bulk delete operation +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct DeleteMeetingsResponse { + pub deleted_count: i32, + pub succeeded_ids: Vec, + pub failed_ids: Vec, + pub skipped_ids: Vec, + pub error_message: String, +} diff --git a/client/src-tauri/src/lib.rs b/client/src-tauri/src/lib.rs index 26b3935..486ed6e 100644 --- a/client/src-tauri/src/lib.rs +++ b/client/src-tauri/src/lib.rs @@ -71,6 +71,7 @@ macro_rules! app_invoke_handler { commands::get_meeting, commands::stop_meeting, commands::delete_meeting, + commands::delete_meetings, // Recording (5 commands) commands::recording::session::start::start_recording, commands::recording::session::stop::stop_recording,