1+ use super :: * ;
2+ use crate :: data_export:: service:: DataExportService ;
3+ use tauri:: State ;
4+ use std:: sync:: Arc ;
5+ use tokio:: sync:: Mutex ;
6+ use anyhow:: Result ;
7+
8+ #[ tauri:: command]
9+ pub async fn get_data_export_config (
10+ export_service : State < ' _ , Arc < Mutex < DataExportService > > > ,
11+ ) -> Result < DataExportConfig , String > {
12+ let service = export_service. lock ( ) . await ;
13+ Ok ( service. get_config ( ) . await )
14+ }
15+
16+ #[ tauri:: command]
17+ pub async fn update_data_export_config (
18+ export_service : State < ' _ , Arc < Mutex < DataExportService > > > ,
19+ config : DataExportConfig ,
20+ ) -> Result < ( ) , String > {
21+ let service = export_service. lock ( ) . await ;
22+ service. update_config ( config) . await
23+ . map_err ( |e| e. to_string ( ) )
24+ }
25+
26+ #[ tauri:: command]
27+ pub async fn export_data (
28+ export_service : State < ' _ , Arc < Mutex < DataExportService > > > ,
29+ request : ExportRequest ,
30+ ) -> Result < ExportResult , String > {
31+ let service = export_service. lock ( ) . await ;
32+ service. export_data ( request, None ) . await
33+ . map_err ( |e| e. to_string ( ) )
34+ }
35+
36+ #[ tauri:: command]
37+ pub async fn export_data_with_progress (
38+ export_service : State < ' _ , Arc < Mutex < DataExportService > > > ,
39+ request : ExportRequest ,
40+ window : tauri:: Window ,
41+ ) -> Result < ExportResult , String > {
42+ let service = export_service. lock ( ) . await ;
43+
44+ // Create progress callback that emits events to frontend
45+ let progress_callback = Box :: new ( move |progress : ExportProgress | {
46+ let _ = window. emit ( "export-progress" , & progress) ;
47+ } ) ;
48+
49+ service. export_data ( request, Some ( progress_callback) ) . await
50+ . map_err ( |e| e. to_string ( ) )
51+ }
52+
53+ #[ tauri:: command]
54+ pub async fn get_export_formats ( ) -> Result < Vec < ExportFormatInfo > , String > {
55+ Ok ( vec ! [
56+ ExportFormatInfo {
57+ format: ExportFormat :: Archive ( ArchiveFormat :: Zip ) ,
58+ display_name: "ZIP Archive" . to_string( ) ,
59+ description: "Standard ZIP archive with all content and metadata" . to_string( ) ,
60+ extension: "zip" . to_string( ) ,
61+ supports_compression: true ,
62+ supports_encryption: true ,
63+ recommended_for: vec![ "General sharing" . to_string( ) , "Cross-platform compatibility" . to_string( ) ] ,
64+ } ,
65+ ExportFormatInfo {
66+ format: ExportFormat :: Archive ( ArchiveFormat :: TarGz ) ,
67+ display_name: "TAR.GZ Archive" . to_string( ) ,
68+ description: "Compressed TAR archive for efficient storage" . to_string( ) ,
69+ extension: "tar.gz" . to_string( ) ,
70+ supports_compression: true ,
71+ supports_encryption: false ,
72+ recommended_for: vec![ "Unix/Linux systems" . to_string( ) , "Efficient compression" . to_string( ) ] ,
73+ } ,
74+ ExportFormatInfo {
75+ format: ExportFormat :: Database ( DatabaseFormat :: JsonExport ) ,
76+ display_name: "JSON Export" . to_string( ) ,
77+ description: "Human-readable JSON format for data analysis" . to_string( ) ,
78+ extension: "json" . to_string( ) ,
79+ supports_compression: false ,
80+ supports_encryption: false ,
81+ recommended_for: vec![ "Data analysis" . to_string( ) , "Integration with other tools" . to_string( ) ] ,
82+ } ,
83+ ExportFormatInfo {
84+ format: ExportFormat :: Portable ( PortableFormat :: CurriculumPack ) ,
85+ display_name: "Curriculum Pack" . to_string( ) ,
86+ description: "Self-contained package for sharing curricula" . to_string( ) ,
87+ extension: "ccpack" . to_string( ) ,
88+ supports_compression: true ,
89+ supports_encryption: true ,
90+ recommended_for: vec![ "Educator sharing" . to_string( ) , "Complete curriculum distribution" . to_string( ) ] ,
91+ } ,
92+ ExportFormatInfo {
93+ format: ExportFormat :: Portable ( PortableFormat :: EducatorBundle ) ,
94+ display_name: "Educator Bundle" . to_string( ) ,
95+ description: "Educator-friendly bundle with documentation" . to_string( ) ,
96+ extension: "edubundle" . to_string( ) ,
97+ supports_compression: true ,
98+ supports_encryption: false ,
99+ recommended_for: vec![ "Educational institutions" . to_string( ) , "Teaching resource sharing" . to_string( ) ] ,
100+ } ,
101+ ExportFormatInfo {
102+ format: ExportFormat :: Portable ( PortableFormat :: MinimalExport ) ,
103+ display_name: "Minimal Export" . to_string( ) ,
104+ description: "Lightweight export without media files" . to_string( ) ,
105+ extension: "ccmin" . to_string( ) ,
106+ supports_compression: true ,
107+ supports_encryption: false ,
108+ recommended_for: vec![ "Quick sharing" . to_string( ) , "Text-only content" . to_string( ) ] ,
109+ } ,
110+ ] )
111+ }
112+
113+ #[ tauri:: command]
114+ pub async fn validate_export_request (
115+ request : ExportRequest ,
116+ ) -> Result < ExportValidation , String > {
117+ let mut validation = ExportValidation {
118+ is_valid : true ,
119+ warnings : vec ! [ ] ,
120+ errors : vec ! [ ] ,
121+ estimated_size_mb : 0 ,
122+ estimated_time_minutes : 0 ,
123+ } ;
124+
125+ // Check output path
126+ if !request. output_path . exists ( ) {
127+ validation. errors . push ( "Output directory does not exist" . to_string ( ) ) ;
128+ validation. is_valid = false ;
129+ }
130+
131+ // Check if output path is writable
132+ if request. output_path . exists ( ) && request. output_path . metadata ( ) . map_or ( true , |m| m. permissions ( ) . readonly ( ) ) {
133+ validation. errors . push ( "Output directory is not writable" . to_string ( ) ) ;
134+ validation. is_valid = false ;
135+ }
136+
137+ // Validate session filter
138+ match & request. sessions {
139+ ExportSessionFilter :: SelectedSessions ( sessions) if sessions. is_empty ( ) => {
140+ validation. errors . push ( "No sessions selected for export" . to_string ( ) ) ;
141+ validation. is_valid = false ;
142+ }
143+ ExportSessionFilter :: DateRange { start, end } if start >= end => {
144+ validation. errors . push ( "Invalid date range: start date must be before end date" . to_string ( ) ) ;
145+ validation. is_valid = false ;
146+ }
147+ ExportSessionFilter :: RecentSessions ( count) if * count == 0 => {
148+ validation. errors . push ( "Recent sessions count must be greater than 0" . to_string ( ) ) ;
149+ validation. is_valid = false ;
150+ }
151+ _ => { }
152+ }
153+
154+ // Check for encryption requirements
155+ if request. options . encrypt && request. options . password . is_none ( ) {
156+ validation. errors . push ( "Password required for encrypted exports" . to_string ( ) ) ;
157+ validation. is_valid = false ;
158+ }
159+
160+ // Estimate size and time (simplified)
161+ validation. estimated_size_mb = match & request. sessions {
162+ ExportSessionFilter :: All => 50 , // Rough estimate
163+ ExportSessionFilter :: SelectedSessions ( sessions) => sessions. len ( ) as u64 * 5 ,
164+ ExportSessionFilter :: DateRange { .. } => 30 ,
165+ ExportSessionFilter :: RecentSessions ( count) => * count as u64 * 5 ,
166+ } ;
167+
168+ validation. estimated_time_minutes = match request. format {
169+ ExportFormat :: Archive ( _) => ( validation. estimated_size_mb / 10 ) . max ( 1 ) ,
170+ ExportFormat :: Database ( _) => ( validation. estimated_size_mb / 20 ) . max ( 1 ) ,
171+ ExportFormat :: Portable ( _) => ( validation. estimated_size_mb / 15 ) . max ( 1 ) ,
172+ } ;
173+
174+ // Add warnings for large exports
175+ if validation. estimated_size_mb > 100 {
176+ validation. warnings . push ( format ! (
177+ "Large export estimated: {} MB. Consider using compression or splitting the export." ,
178+ validation. estimated_size_mb
179+ ) ) ;
180+ }
181+
182+ if validation. estimated_time_minutes > 10 {
183+ validation. warnings . push ( format ! (
184+ "Long export estimated: {} minutes. Consider exporting in smaller batches." ,
185+ validation. estimated_time_minutes
186+ ) ) ;
187+ }
188+
189+ Ok ( validation)
190+ }
191+
192+ #[ tauri:: command]
193+ pub async fn preview_export_contents (
194+ export_service : State < ' _ , Arc < Mutex < DataExportService > > > ,
195+ session_filter : ExportSessionFilter ,
196+ ) -> Result < ExportPreview , String > {
197+ // This would provide a preview of what will be exported
198+ // For now, return a basic preview structure
199+
200+ let preview = ExportPreview {
201+ session_count : match & session_filter {
202+ ExportSessionFilter :: All => 0 , // Would need to count actual sessions
203+ ExportSessionFilter :: SelectedSessions ( sessions) => sessions. len ( ) as u32 ,
204+ ExportSessionFilter :: DateRange { .. } => 0 , // Would need to query by date
205+ ExportSessionFilter :: RecentSessions ( count) => * count,
206+ } ,
207+ content_types : vec ! [ "Slides" . to_string( ) , "InstructorNotes" . to_string( ) , "Worksheets" . to_string( ) ] ,
208+ estimated_files : 10 , // Would be calculated based on actual content
209+ estimated_size_bytes : 1024 * 1024 , // 1MB estimate
210+ sessions_summary : vec ! [ ] , // Would contain actual session info
211+ } ;
212+
213+ Ok ( preview)
214+ }
215+
216+ #[ tauri:: command]
217+ pub async fn get_recent_exports ( ) -> Result < Vec < RecentExport > , String > {
218+ // This would return a list of recent exports
219+ // For now, return an empty list
220+ Ok ( vec ! [ ] )
221+ }
222+
223+ #[ tauri:: command]
224+ pub async fn cleanup_old_exports (
225+ days_old : u32 ,
226+ ) -> Result < CleanupResult , String > {
227+ // This would clean up old export files
228+ // For now, return a basic result
229+ Ok ( CleanupResult {
230+ files_removed : 0 ,
231+ space_freed_bytes : 0 ,
232+ errors : vec ! [ ] ,
233+ } )
234+ }
235+
236+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
237+ pub struct ExportFormatInfo {
238+ pub format : ExportFormat ,
239+ pub display_name : String ,
240+ pub description : String ,
241+ pub extension : String ,
242+ pub supports_compression : bool ,
243+ pub supports_encryption : bool ,
244+ pub recommended_for : Vec < String > ,
245+ }
246+
247+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
248+ pub struct ExportValidation {
249+ pub is_valid : bool ,
250+ pub warnings : Vec < String > ,
251+ pub errors : Vec < String > ,
252+ pub estimated_size_mb : u64 ,
253+ pub estimated_time_minutes : u64 ,
254+ }
255+
256+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
257+ pub struct ExportPreview {
258+ pub session_count : u32 ,
259+ pub content_types : Vec < String > ,
260+ pub estimated_files : u32 ,
261+ pub estimated_size_bytes : u64 ,
262+ pub sessions_summary : Vec < SessionSummary > ,
263+ }
264+
265+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
266+ pub struct RecentExport {
267+ pub export_id : String ,
268+ pub created_at : chrono:: DateTime < chrono:: Utc > ,
269+ pub format : ExportFormat ,
270+ pub file_path : PathBuf ,
271+ pub file_size : u64 ,
272+ pub sessions_count : u32 ,
273+ }
274+
275+ #[ derive( Debug , Clone , serde:: Serialize , serde:: Deserialize ) ]
276+ pub struct CleanupResult {
277+ pub files_removed : u32 ,
278+ pub space_freed_bytes : u64 ,
279+ pub errors : Vec < String > ,
280+ }
0 commit comments