data_loader.rs 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. use crate::api::ApiClient;
  2. use serde_json::Value;
  3. /// Loading state management for UI views
  4. #[derive(Default)]
  5. pub struct LoadingState {
  6. pub is_loading: bool,
  7. pub last_error: Option<String>,
  8. pub last_load_time: Option<std::time::Instant>,
  9. }
  10. impl LoadingState {
  11. pub fn new() -> Self {
  12. Self::default()
  13. }
  14. pub fn start_loading(&mut self) {
  15. self.is_loading = true;
  16. self.last_error = None;
  17. self.last_load_time = Some(std::time::Instant::now());
  18. }
  19. pub fn finish_loading(&mut self, error: Option<String>) {
  20. self.is_loading = false;
  21. self.last_error = error;
  22. }
  23. pub fn finish_success(&mut self) {
  24. self.finish_loading(None);
  25. }
  26. pub fn finish_error(&mut self, error: String) {
  27. self.finish_loading(Some(error));
  28. }
  29. #[allow(dead_code)]
  30. pub fn has_error(&self) -> bool {
  31. self.last_error.is_some()
  32. }
  33. pub fn get_error(&self) -> Option<&str> {
  34. self.last_error.as_deref()
  35. }
  36. #[allow(dead_code)]
  37. pub fn should_auto_retry(&self, retry_after_seconds: u64) -> bool {
  38. if let (Some(error), Some(load_time)) = (&self.last_error, self.last_load_time) {
  39. !error.is_empty() && load_time.elapsed().as_secs() > retry_after_seconds
  40. } else {
  41. false
  42. }
  43. }
  44. }
  45. /// Data loader for assets
  46. pub struct DataLoader;
  47. impl DataLoader {
  48. pub fn load_assets(
  49. api_client: &ApiClient,
  50. limit: Option<u32>,
  51. where_clause: Option<Value>,
  52. filter: Option<Value>,
  53. ) -> Result<Vec<Value>, String> {
  54. log::info!(
  55. "Loading inventory assets (limit={:?}, where={:?}, filter={:?})...",
  56. limit,
  57. where_clause,
  58. filter
  59. );
  60. // Use select_with_joins to load assets with zone and category data
  61. let response = api_client
  62. .select_with_joins(
  63. "assets",
  64. None, // columns (None = all)
  65. where_clause,
  66. filter,
  67. None, // order_by
  68. limit,
  69. None, // joins (None = use default joins)
  70. )
  71. .map_err(|e| format!("Failed to load assets: {}", e))?;
  72. if !response.success {
  73. // Check if this is a database timeout error
  74. if ApiClient::is_database_timeout_error(&response.error) {
  75. log::warn!("Database timeout detected while loading assets");
  76. }
  77. let error_msg = format!("API error: {:?}", response.error);
  78. log::error!("{}", error_msg);
  79. return Err(error_msg);
  80. }
  81. let assets = response.data.unwrap_or_default();
  82. log::info!("Loaded {} assets successfully (with JOINs)", assets.len());
  83. Ok(assets)
  84. }
  85. }