intent_engine/dashboard/
models.rs

1use serde::{Deserialize, Serialize};
2use serde_json::Value;
3
4/// API response wrapper
5#[derive(Serialize)]
6pub struct ApiResponse<T> {
7    pub data: T,
8}
9
10/// API error response
11#[derive(Serialize)]
12pub struct ApiError {
13    pub code: String,
14    pub message: String,
15    #[serde(skip_serializing_if = "Option::is_none")]
16    pub details: Option<Value>,
17}
18
19/// Create task request
20#[derive(Deserialize)]
21pub struct CreateTaskRequest {
22    pub name: String,
23    #[serde(skip_serializing_if = "Option::is_none")]
24    pub spec: Option<String>,
25    #[serde(skip_serializing_if = "Option::is_none")]
26    pub priority: Option<i32>,
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub parent_id: Option<i64>,
29}
30
31/// Update task request
32#[derive(Deserialize)]
33pub struct UpdateTaskRequest {
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub name: Option<String>,
36    #[serde(skip_serializing_if = "Option::is_none")]
37    pub spec: Option<String>,
38    #[serde(skip_serializing_if = "Option::is_none")]
39    pub priority: Option<i32>,
40    #[serde(skip_serializing_if = "Option::is_none")]
41    pub status: Option<String>,
42}
43
44/// Create event request
45#[derive(Deserialize)]
46pub struct CreateEventRequest {
47    #[serde(rename = "type")]
48    pub event_type: String,
49    pub data: String,
50}
51
52/// Update event request
53#[derive(Deserialize)]
54pub struct UpdateEventRequest {
55    #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
56    pub event_type: Option<String>,
57    #[serde(skip_serializing_if = "Option::is_none")]
58    pub data: Option<String>,
59}
60
61/// Spawn subtask request
62#[derive(Deserialize)]
63pub struct SpawnSubtaskRequest {
64    pub name: String,
65    #[serde(skip_serializing_if = "Option::is_none")]
66    pub spec: Option<String>,
67}
68
69/// Query parameters for task list
70#[derive(Deserialize)]
71pub struct TaskListQuery {
72    #[serde(skip_serializing_if = "Option::is_none")]
73    pub status: Option<String>,
74    #[serde(skip_serializing_if = "Option::is_none")]
75    pub parent: Option<String>,
76}
77
78/// Query parameters for event list
79#[derive(Deserialize)]
80pub struct EventListQuery {
81    #[serde(skip_serializing_if = "Option::is_none")]
82    pub event_type: Option<String>,
83    #[serde(skip_serializing_if = "Option::is_none")]
84    pub since: Option<String>,
85    #[serde(skip_serializing_if = "Option::is_none")]
86    pub limit: Option<i32>,
87}
88
89/// Switch project request
90#[derive(Deserialize)]
91pub struct SwitchProjectRequest {
92    pub project_path: String,
93}
94
95/// Query parameters for search
96#[derive(Deserialize)]
97pub struct SearchQuery {
98    pub query: String,
99    #[serde(default = "default_true")]
100    pub include_tasks: bool,
101    #[serde(default = "default_true")]
102    pub include_events: bool,
103    #[serde(skip_serializing_if = "Option::is_none")]
104    pub limit: Option<i32>,
105}
106
107fn default_true() -> bool {
108    true
109}
110
111#[cfg(test)]
112mod tests {
113    use super::*;
114
115    #[test]
116    fn test_create_task_request_deserialization() {
117        let json = r#"{"name":"Test Task","spec":"Test spec","priority":1}"#;
118        let req: CreateTaskRequest = serde_json::from_str(json).unwrap();
119        assert_eq!(req.name, "Test Task");
120        assert_eq!(req.spec, Some("Test spec".to_string()));
121        assert_eq!(req.priority, Some(1));
122    }
123
124    #[test]
125    fn test_api_response_serialization() {
126        let response = ApiResponse { data: "test" };
127        let json = serde_json::to_string(&response).unwrap();
128        assert!(json.contains("\"data\""));
129    }
130
131    #[test]
132    fn test_api_error_serialization() {
133        let error = ApiError {
134            code: "TEST_ERROR".to_string(),
135            message: "Test message".to_string(),
136            details: None,
137        };
138        let json = serde_json::to_string(&error).unwrap();
139        assert!(json.contains("TEST_ERROR"));
140        assert!(!json.contains("details"));
141    }
142
143    #[test]
144    fn test_search_query_defaults() {
145        let json = r#"{"query":"test"}"#;
146        let query: SearchQuery = serde_json::from_str(json).unwrap();
147        assert_eq!(query.query, "test");
148        assert!(query.include_tasks);
149        assert!(query.include_events);
150    }
151}