Rack Editor
Qué es
Interfaz visual principal para diseñar y mantener el contenido físico de un rack de red. Permite arrastrar dispositivos (stencils) desde biblioteca lateral, posicionarlos en unidades U y guardar estado completo automáticamente. Vista servida desde racks/views.py (rack_editor) en racks/editor/<rack_id>/ renderizando editor.html.
Por qué existe
Reemplaza la lógica equivalente en Flask (routes/main.py). Ofrece edición visual en tiempo real sin recargas manteniendo integridad vía transacciones atómicas en backend. Separa explícitamente presentación (canvas Konva en navegador) de negocio (Django Ninja API + RackService), facilitando tests y evolución independiente.
Componentes
Canvas Konva.js (static/js/editor/): frontend inicializa Konva.Stage en #canvas-container (konva_setup.js, initKonvaStage). Cada rack se dibuja como Konva.Group (STATE.rackGroup) con rectángulo de cabinete, líneas separadoras por U y etiquetas de numeración. Dispositivos como nodos Konva con drag-and-drop. Vista ajustada automáticamente con fitView() calculando escala óptima según paneles laterales. Zoom vía wheel event.
PersistenceManager (static/js/state_core/PersistenceManager.js): centraliza operaciones de guardado. scheduleSave(key, config) con debounce configurable. editor_api.js invoca PERSISTENCE.scheduleSave('rack-main', { endpoint: '/api/racks/{id}/devices', method: 'PUT', debounceMs: 1000 }). Si hay pendiente para la misma key, timer se reinicia evitando llamadas redundantes.
API REST (Django Ninja, racks/api/racks.py): CRUD del rack + endpoint clave PUT /{rack_id}/devices que recibe payload completo y delega en RackService.bulk_update_devices. Orden de rutas estáticas (/groups, /templates, /list, /bulk-update) antes de dinámicas (/{rack_id}) es intencional y está documentado para evitar conflictos de matching.
RackService.bulk_update_devices (racks/services/racks.py): decorado con @transaction.atomic, ejecuta reconciliación completa entre estado actual y payload en una sola transacción:
- Caché de IPs de gestión en una query para validar duplicados sin N consultas.
- Dispositivos existentes en payload:
Device.objects.bulk_update. - Nuevos:
Device.objects.bulk_create. - Ausentes: eliminados (sync total).
- Tras crear,
_try_link_device_profilevincula aDeviceProfile(porprofile_ido IP) e inyecta interfaces enriquecidos enmodel_data.ports.
Vista Django (racks/views.py): rack_editor serializa dispositivos del rack a JSON (devices_json) y stencils por categoría (stencil_categories). Inyecta en contexto de editor.html. Frontend lee desde atributos data-* de #rack-data sin llamada inicial a API, minimizando tiempo de carga.
Flujos
Abrir el editor: usuario navega a /racks/editor/<rack_id>/. Django ejecuta rack_editor, recupera rack y dispositivos con query values(), serializa JSON, renderiza. Cliente: DOMContentLoaded dispara initEditor() en main.js, parsea #rack-data, inicializa stage Konva, carga dispositivos pre-renderizando imágenes en paralelo con preloadDeviceImages.
Editar dispositivos: usuario arrastra stencils al canvas. Drop listener en devices.js registra nuevo dispositivo en STATE.devices. Al mover/modificar, triggerAutoSave() activa debounce 500ms (procesamiento) + 1000ms (PersistenceManager) antes de enviar HTTP.
Guardar atómicamente: saveRackState() serializa nodos Konva a objetos planos (calcula u_position desde Y del canvas y altura del rack), construye payload { devices: [...] }, llama PERSISTENCE.scheduleSave. PersistenceManager ejecuta fetch PUT /api/racks/{id}/devices. Servidor: bulk_update_devices procesa en @transaction.atomic. Si falla validación (IP duplicada, datos inválidos), se revierte todo y devuelve 400.
Related
entity--racks--model--rack— modelo contenedor.entity--racks--model--device— sincronizados atómicamente.entity--racks--model--stencil— biblioteca del editor.
Véase también
- [[entity—racks—model—rack]]
- [[entity—racks—model—device]]
- [[entity—racks—model—stencil]]
Referenciado desde
- Agente · dev-rack-editor
- Clonar un rack de la Fila con un clic (v1.78.0)
- Front/Back emparejados en el editor de racks — la trasera es la espalda del mismo aparato (v1.80.0)
- Incidente: el drop en la vista Back moría en un TypeError silencioso (targetU const)
- Map Editor y Auto-Plan AI
- Rack · Modelo racks
- Rack Editor - Documentación Técnica
- Reemplazo manual de la trasera en el editor de racks
- Toggle Stencils/Descriptions en la vista de Fila