mirror of
https://github.com/ruvnet/RuView
synced 2026-07-28 18:21:42 +00:00
feat(homecore iter 3): DELETE /api/states/<id> + confirm modal in UI
CRUD increment 3/6. Full delete path lands end-to-end.
Backend (homecore-api):
rest.rs +18 LOC — new `delete_state` handler. Idempotent (matches HA's
removal semantics): returns 204 No Content whether the entity existed
or not. 4xx only for malformed entity_id or auth failure.
app.rs +6 LOC — adds `.delete(rest::delete_state)` to the
/api/states/:entity_id route alongside existing GET + POST.
Backend curl smoke:
POST /api/states/sensor.test_delete 201
DELETE /api/states/sensor.test_delete 204
GET /api/states/sensor.test_delete 404
Frontend:
components/StateCard.ts +25 LOC — small `×` delete button in the
card's top-right corner. opacity 0 by default, fades in on hover
or keyboard focus. dispatches `hc-state-card-delete` (NOT
`hc-state-card-click`) with stopPropagation so the card's own
click-to-edit handler doesn't also fire.
pages/Dashboard.ts +45 LOC — deletingState (StateView | null), a
confirm modal that names the entity_id in the body, Cancel /
Delete buttons in the footer (Delete styled in muted red),
`_confirmDelete()` dispatches DELETE with bearer, toast on
success, grid refresh.
Browser-verified end-to-end on real homecore-server :8123:
- Hover card → × button visible
- Click × → DELETE confirm modal (NOT edit modal — stopPropagation works)
- Modal names entity_id in code block
- Cancel: entity preserved, modal closes
- Delete: backend GET-after-DELETE returns 404, grid card vanishes,
toast "Deleted sensor.delete_target"
- 0 unexpected console errors (1 expected 404 from verification fetch)
Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
@@ -28,7 +28,12 @@ pub fn router(state: SharedState) -> Router {
|
||||
.route("/api/", get(rest::api_root))
|
||||
.route("/api/config", get(rest::get_config))
|
||||
.route("/api/states", get(rest::get_states))
|
||||
.route("/api/states/:entity_id", get(rest::get_state).post(rest::set_state))
|
||||
.route(
|
||||
"/api/states/:entity_id",
|
||||
get(rest::get_state)
|
||||
.post(rest::set_state)
|
||||
.delete(rest::delete_state),
|
||||
)
|
||||
.route("/api/services", get(rest::get_services))
|
||||
.route("/api/services/:domain/:service", post(rest::call_service))
|
||||
.route("/api/websocket", get(ws::websocket_handler))
|
||||
|
||||
@@ -92,6 +92,21 @@ pub struct SetStateRequest {
|
||||
pub attributes: serde_json::Value,
|
||||
}
|
||||
|
||||
/// DELETE /api/states/:entity_id — remove an entity from the state
|
||||
/// machine. Idempotent: returns 204 whether or not the entity existed,
|
||||
/// matching HA's removal semantics. 4xx only for malformed entity_id or
|
||||
/// auth failure.
|
||||
pub async fn delete_state(
|
||||
headers: HeaderMap,
|
||||
State(s): State<SharedState>,
|
||||
Path(entity_id): Path<String>,
|
||||
) -> ApiResult<StatusCode> {
|
||||
let _ = BearerAuth::from_headers(&headers, s.tokens()).await?;
|
||||
let id = EntityId::parse(entity_id).map_err(|e| ApiError::BadRequest(e.to_string()))?;
|
||||
s.homecore().states().remove(&id);
|
||||
Ok(StatusCode::NO_CONTENT)
|
||||
}
|
||||
|
||||
pub async fn set_state(
|
||||
headers: HeaderMap,
|
||||
State(s): State<SharedState>,
|
||||
|
||||
Reference in New Issue
Block a user