Ubicación
POST /api/blueprints/reorder
blueprints/api/blueprints.py :: reorder_blueprints(request, payload)
Descripción
Endpoint que persiste el orden manual de las secciones del Dashboard después de un arrastre (drag&drop). Consumido exclusivamente por el cliente web (static/js/dashboard.js).
Permisos: blueprints:edit (solo administradores y operadores).
Versión: Introducido en v1.50.0 (2026-07-13, solo blueprints). Evolucionado en v1.51.0 para incluir secciones fijas (Rooms, No Map).
Contrato
Request
{
"section_keys": [
"nomap",
"1",
"rooms",
"2"
]
}
- Campo:
section_keys: list[str] - Tokens:
"rooms"— Sección de Salas (DCIM Fase 3)"<blueprint_id>"(string entero) — Blueprint (Map o Row)"nomap"— Racks sin blueprint
Semántica: Orden visual del Dashboard en el momento del POST. El índice de cada token en la lista determina su posición final.
Scoping: La organización se obtiene de request.org (middleware). Solo se aplican cambios a blueprints de esa organización; ids foráneos o borrados se ignoran silenciosamente.
Response (200 OK)
{
"ok": true,
"count": 3
}
count: Número de entidades actualizadas (suma de blueprints cuyosort_ordercambió + secciones fijas cuya posición se fijó en ui_pref).
Response (403 Forbidden)
Si el usuario no tiene permiso blueprints:edit.
Response (400 Bad Request)
Si section_keys no es una lista o contiene valores inválidos.
Lógica de persistencia
Blueprints → Blueprint.sort_order
Cada token que sea un entero válido y corresponda a un Blueprint de la organización actual:
bp = Blueprint.objects.get(id=token, organization=org, deleted_at__isnull=True)
bp.sort_order = index
Blueprints cuyo id NO aparezca en section_keys conservan su sort_order anterior.
Secciones fijas → OrgUIPreference
- Token
"rooms"→set_ui_pref(org.id, "dashboard_rooms_sort", str(index)) - Token
"nomap"→set_ui_pref(org.id, "dashboard_nomap_sort", str(index))
Estas preferencias son de organización (no de usuario individual).
Fuentes de datos
| Recurso | Origen |
|---|---|
| Blueprints de la org | Blueprint.objects.filter(organization=org, deleted_at__isnull=True) |
| Ui-prefs de Rooms/NoMap | OrgUIPreference con claves dashboard_rooms_sort, dashboard_nomap_sort |
Cambios en v1.51.0
v1.50.0 (contrato inicial):
{ "blueprint_ids": [1, 2, 3] }
Solo aceptaba IDs de blueprints numéricos. Rooms y No Map no eran reordenables.
v1.51.0 (cambio breaking):
{ "section_keys": ["rooms", "1", "nomap", "2"] }
- Campo renombrado:
blueprint_ids→section_keys. - Tokens mixtos: además de IDs de blueprints, soporta
"rooms"y"nomap". - Persistencia: Rooms/NoMap se guardan en
OrgUIPreference(no en Blueprint).
Consumidor: Solo el cliente web (dashboard.js) consume este endpoint. Cambio interno, sin API pública documentada.
Ejemplo de flujo
- Usuario arrastra “No Map” a la posición 0 (primera), “Alpha” (id=5) a posición 1, y “Rooms” a posición 2.
- JavaScript recolecta el DOM (
[...document.querySelectorAll('.blueprint-section[data-section-key]')].map(s => s.dataset.sectionKey)). - Envía
POST /api/blueprints/reordercon{"section_keys": ["nomap", "5", "rooms", ...]}. - El endpoint:
- Lee la org del request.
- Actualiza
Blueprint(id=5).sort_order = 1en la org. - Escribe
OrgUIPreference(..., key="dashboard_nomap_sort", value="0"). - Escribe
OrgUIPreference(..., key="dashboard_rooms_sort", value="2"). - Retorna
{"ok": true, "count": 3}.
- El dashboard se re-renderiza (
HTMXo recarga) con el nuevo orden.
Validación y seguridad
- Permiso: Requiere
blueprints:edit. - Scoping: Solo blueprints de la organización actual son modificados.
- Blindaje: Ids foráneos, papeleras (soft-deleted) e inválidos se ignoran sin error.
- Atomicidad: Toda la operación ocurre en un
transaction.atomic()— si falla, se revierte todo.
Mocking / Testing
Tests en tests/api/test_blueprints_reorder.py:
- Reorden de índices con verificación de
sort_order. - Persistencia de Rooms/NoMap en ui_prefs (leyendo directo de PostgreSQL, no caché).
- Ignora ids foráneos y deletreados.
- Viewer (readonly) no puede reordenar → 403.
Véase también
- [[entity—racks—service—dashboard-sections]]
- [[entity—blueprints—model—blueprint]]
- [[entity—core—service—ui-pref]]
- [[feature—dashboard—reorder-todas-secciones]]
- [[entity—blueprints—model—room]]