feat(admin/models): delete an added model with inline confirm

Backend: AiModelRepository.delete() + DELETE /api/admin/models/{id} (owner-only,
audited) in the RPC-served admin router; session commits per request.
Frontend: api.adminDeleteModel() (WebSocket RPC DELETE) and a per-row حذف
action with a two-step inline confirm (تأیید حذف / انصراف) that removes the
row from state on success. tsc clean, py_compile clean.
This commit is contained in:
mjalmoudy94
2026-10-13 17:40:16 +03:30
parent f2983afaec
commit d5c9917371
4 changed files with 85 additions and 0 deletions
@@ -281,6 +281,14 @@ class AiModelRepository:
await self.session.flush()
return _model_to_domain(row)
async def delete(self, model_id: str) -> bool:
row = await self.session.get(AiModelRow, model_id)
if row is None:
return False
await self.session.delete(row)
await self.session.flush()
return True
async def pick_for_mode(self, mode: RoutingMode) -> AiModel | None:
"""Choose a model for a routing mode.
@@ -215,6 +215,28 @@ async def create_model(
return _model_out(model)
@router.delete("/models/{model_id}", status_code=status.HTTP_200_OK)
async def delete_model(
model_id: str,
request: Request,
owner: User = Depends(require_platform_owner),
session: AsyncSession = Depends(get_session),
) -> dict:
repo = AiModelRepository(session)
existing = await repo.get(model_id)
if existing is None:
raise NotFoundError("مدلی با این شناسه یافت نشد.")
await repo.delete(model_id)
ip, ua = client_meta(request)
await record_audit(
session, action=AuditAction.MODEL_CHANGE, actor_user_id=owner.id,
target_type="model", target_id=model_id,
metadata={"internal_name": existing.internal_name, "deleted": True},
ip=ip, user_agent=ua,
)
return {"ok": True}
# ---------------------------------------------------------------------------
# Routing policies
# ---------------------------------------------------------------------------