aboutsummaryrefslogtreecommitdiff
path: root/src/app/api/workspaces.rs
diff options
context:
space:
mode:
authorOgulcan Celik <ogulcancelik@gmail.com>2026-06-29 20:39:54 +0300
committerOgulcan Celik <ogulcancelik@gmail.com>2026-06-29 20:39:54 +0300
commit8b74fb8a12716269c76f0b503ee7db5bbec2c921 (patch)
treee5230f94cb1e6eb70d1f00c75cd85dae8b5b9ead /src/app/api/workspaces.rs
parent5fffc59cd8aaea1604abb90e749e58fd97acfac0 (diff)
feat: emit placement mutation events
Diffstat (limited to 'src/app/api/workspaces.rs')
-rw-r--r--src/app/api/workspaces.rs90
1 files changed, 63 insertions, 27 deletions
diff --git a/src/app/api/workspaces.rs b/src/app/api/workspaces.rs
index 56427463..f4189a04 100644
--- a/src/app/api/workspaces.rs
+++ b/src/app/api/workspaces.rs
@@ -13,13 +13,7 @@ impl App {
encode_success(
id,
ResponseResult::WorkspaceList {
- workspaces: self
- .state
- .workspaces
- .iter()
- .enumerate()
- .map(|(idx, _)| self.workspace_info(idx))
- .collect(),
+ workspaces: self.workspace_list_info(),
},
)
}
@@ -140,20 +134,22 @@ impl App {
);
}
- self.state.move_workspace(index, params.insert_index);
+ let workspace_id = self.public_workspace_id(index);
+ let insert_index = params.insert_index;
+ let moved = self.state.move_workspace(index, insert_index);
+ let workspaces = self.workspace_list_info();
+ if moved {
+ self.emit_event(EventEnvelope {
+ event: EventKind::WorkspaceMoved,
+ data: EventData::WorkspaceMoved {
+ workspace_id,
+ insert_index,
+ workspaces: workspaces.clone(),
+ },
+ });
+ }
- encode_success(
- id,
- ResponseResult::WorkspaceList {
- workspaces: self
- .state
- .workspaces
- .iter()
- .enumerate()
- .map(|(idx, _)| self.workspace_info(idx))
- .collect(),
- },
- )
+ encode_success(id, ResponseResult::WorkspaceList { workspaces })
}
pub(super) fn handle_workspace_close(&mut self, id: String, target: WorkspaceTarget) -> String {
@@ -192,6 +188,15 @@ impl App {
encode_success(id, ResponseResult::Ok {})
}
+
+ fn workspace_list_info(&self) -> Vec<crate::api::schema::WorkspaceInfo> {
+ self.state
+ .workspaces
+ .iter()
+ .enumerate()
+ .map(|(idx, _)| self.workspace_info(idx))
+ .collect()
+ }
}
fn workspace_not_found(id: String, workspace_id: &str) -> String {
@@ -279,14 +284,9 @@ mod tests {
#[test]
fn api_workspace_move_reorders_workspaces() {
+ let event_hub = crate::api::EventHub::default();
let (_api_tx, api_rx) = tokio::sync::mpsc::unbounded_channel();
- let mut app = App::new(
- &Config::default(),
- true,
- None,
- api_rx,
- crate::api::EventHub::default(),
- );
+ let mut app = App::new(&Config::default(), true, None, api_rx, event_hub.clone());
app.state.workspaces = vec![
Workspace::test_new("one"),
Workspace::test_new("two"),
@@ -310,5 +310,41 @@ mod tests {
};
assert_eq!(workspaces[2].workspace_id, moved_id);
assert_eq!(app.state.workspaces[2].display_name(), "one");
+ let events = event_hub.events_after(0);
+ assert!(events.iter().any(|(_, event)| {
+ matches!(
+ &event.data,
+ EventData::WorkspaceMoved {
+ workspace_id,
+ insert_index: 3,
+ workspaces,
+ } if workspace_id == &moved_id
+ && workspaces[2].workspace_id == moved_id
+ )
+ }));
+ }
+
+ #[test]
+ fn api_workspace_move_noop_does_not_emit_event() {
+ let event_hub = crate::api::EventHub::default();
+ let (_api_tx, api_rx) = tokio::sync::mpsc::unbounded_channel();
+ let mut app = App::new(&Config::default(), true, None, api_rx, event_hub.clone());
+ app.state.workspaces = vec![Workspace::test_new("one"), Workspace::test_new("two")];
+ let moved_id = app.public_workspace_id(0);
+
+ let response = app.handle_workspace_move(
+ "req".into(),
+ WorkspaceMoveParams {
+ workspace_id: moved_id.clone(),
+ insert_index: 1,
+ },
+ );
+
+ let success: SuccessResponse = serde_json::from_str(&response).unwrap();
+ let ResponseResult::WorkspaceList { workspaces } = success.result else {
+ panic!("expected workspace list");
+ };
+ assert_eq!(workspaces[0].workspace_id, moved_id);
+ assert!(event_hub.events_after(0).is_empty());
}
}