leptos_forms_rs/error/
context.rs1use std::collections::HashMap;
8
9#[derive(Debug, Clone)]
11pub struct ErrorContext {
12 pub form_name: Option<String>,
13 pub field_name: Option<String>,
14 pub operation: Option<String>,
15 pub timestamp: Option<chrono::DateTime<chrono::Utc>>,
16 pub user_agent: Option<String>,
17 pub additional_data: HashMap<String, String>,
18}
19
20impl ErrorContext {
21 pub fn new() -> Self {
23 Self {
24 form_name: None,
25 field_name: None,
26 operation: None,
27 timestamp: Some(chrono::Utc::now()),
28 user_agent: None,
29 additional_data: HashMap::new(),
30 }
31 }
32
33 pub fn with_form_name(mut self, form_name: impl Into<String>) -> Self {
35 self.form_name = Some(form_name.into());
36 self
37 }
38
39 pub fn with_field_name(mut self, field_name: impl Into<String>) -> Self {
41 self.field_name = Some(field_name.into());
42 self
43 }
44
45 pub fn with_operation(mut self, operation: impl Into<String>) -> Self {
47 self.operation = Some(operation.into());
48 self
49 }
50
51 pub fn with_user_agent(mut self, user_agent: impl Into<String>) -> Self {
53 self.user_agent = Some(user_agent.into());
54 self
55 }
56
57 pub fn with_data(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
59 self.additional_data.insert(key.into(), value.into());
60 self
61 }
62
63 pub fn form_name(&self) -> Option<&str> {
65 self.form_name.as_deref()
66 }
67
68 pub fn field_name(&self) -> Option<&str> {
70 self.field_name.as_deref()
71 }
72
73 pub fn operation(&self) -> Option<&str> {
75 self.operation.as_deref()
76 }
77
78 pub fn timestamp(&self) -> Option<chrono::DateTime<chrono::Utc>> {
80 self.timestamp
81 }
82
83 pub fn user_agent(&self) -> Option<&str> {
85 self.user_agent.as_deref()
86 }
87
88 pub fn get_data(&self, key: &str) -> Option<&String> {
90 self.additional_data.get(key)
91 }
92
93 pub fn all_data(&self) -> &HashMap<String, String> {
95 &self.additional_data
96 }
97
98 pub fn has_form_name(&self) -> bool {
100 self.form_name.is_some()
101 }
102
103 pub fn has_field_name(&self) -> bool {
105 self.field_name.is_some()
106 }
107
108 pub fn has_operation(&self) -> bool {
110 self.operation.is_some()
111 }
112
113 pub fn has_timestamp(&self) -> bool {
115 self.timestamp.is_some()
116 }
117
118 pub fn has_user_agent(&self) -> bool {
120 self.user_agent.is_some()
121 }
122
123 pub fn has_additional_data(&self) -> bool {
125 !self.additional_data.is_empty()
126 }
127
128 pub fn additional_data_count(&self) -> usize {
130 self.additional_data.len()
131 }
132
133 pub fn clear_additional_data(&mut self) {
135 self.additional_data.clear();
136 }
137
138 pub fn remove_data(&mut self, key: &str) -> Option<String> {
140 self.additional_data.remove(key)
141 }
142
143 pub fn update_timestamp(&mut self) {
145 self.timestamp = Some(chrono::Utc::now());
146 }
147
148 pub fn for_form(form_name: impl Into<String>) -> Self {
150 Self::new().with_form_name(form_name)
151 }
152
153 pub fn for_field(field_name: impl Into<String>) -> Self {
155 Self::new().with_field_name(field_name)
156 }
157
158 pub fn for_operation(operation: impl Into<String>) -> Self {
160 Self::new().with_operation(operation)
161 }
162}
163
164impl Default for ErrorContext {
165 fn default() -> Self {
166 Self::new()
167 }
168}
169
170impl std::fmt::Display for ErrorContext {
171 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172 write!(f, "ErrorContext(")?;
173
174 let mut parts = Vec::new();
175
176 if let Some(form_name) = &self.form_name {
177 parts.push(format!("form: {}", form_name));
178 }
179
180 if let Some(field_name) = &self.field_name {
181 parts.push(format!("field: {}", field_name));
182 }
183
184 if let Some(operation) = &self.operation {
185 parts.push(format!("operation: {}", operation));
186 }
187
188 if let Some(timestamp) = &self.timestamp {
189 parts.push(format!(
190 "timestamp: {}",
191 timestamp.format("%Y-%m-%d %H:%M:%S UTC")
192 ));
193 }
194
195 if let Some(user_agent) = &self.user_agent {
196 parts.push(format!("user_agent: {}", user_agent));
197 }
198
199 if !self.additional_data.is_empty() {
200 parts.push(format!("data: {} entries", self.additional_data.len()));
201 }
202
203 write!(f, "{}", parts.join(", "))?;
204 write!(f, ")")
205 }
206}