datos invocados correctamente, falta que se hagan visibles
This commit is contained in:
@@ -23,6 +23,7 @@ class Componente {
|
|||||||
this.ubicacion,
|
this.ubicacion,
|
||||||
this.imagenUrl,
|
this.imagenUrl,
|
||||||
required this.fechaRegistro,
|
required this.fechaRegistro,
|
||||||
|
String? distribucionId,
|
||||||
});
|
});
|
||||||
|
|
||||||
factory Componente.fromMap(Map<String, dynamic> map) {
|
factory Componente.fromMap(Map<String, dynamic> map) {
|
||||||
|
|||||||
141
lib/models/nethive/vista_conexiones_por_cables_model.dart
Normal file
141
lib/models/nethive/vista_conexiones_por_cables_model.dart
Normal file
@@ -0,0 +1,141 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class VistaConexionesPorCables {
|
||||||
|
final String conexionId;
|
||||||
|
final String? descripcion;
|
||||||
|
final bool activo;
|
||||||
|
final String origenId;
|
||||||
|
final String componenteOrigen;
|
||||||
|
final String destinoId;
|
||||||
|
final String componenteDestino;
|
||||||
|
final String? cableId;
|
||||||
|
final String? cableUsado;
|
||||||
|
final String? tipoCable;
|
||||||
|
final String? color;
|
||||||
|
final double? tamano;
|
||||||
|
final String? tipoConector;
|
||||||
|
|
||||||
|
VistaConexionesPorCables({
|
||||||
|
required this.conexionId,
|
||||||
|
this.descripcion,
|
||||||
|
required this.activo,
|
||||||
|
required this.origenId,
|
||||||
|
required this.componenteOrigen,
|
||||||
|
required this.destinoId,
|
||||||
|
required this.componenteDestino,
|
||||||
|
this.cableId,
|
||||||
|
this.cableUsado,
|
||||||
|
this.tipoCable,
|
||||||
|
this.color,
|
||||||
|
this.tamano,
|
||||||
|
this.tipoConector,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory VistaConexionesPorCables.fromMap(Map<String, dynamic> map) {
|
||||||
|
return VistaConexionesPorCables(
|
||||||
|
conexionId: map['conexion_id']?.toString() ?? '',
|
||||||
|
descripcion: map['descripcion']?.toString(),
|
||||||
|
activo: map['activo'] == true,
|
||||||
|
origenId: map['origen_id']?.toString() ?? '',
|
||||||
|
componenteOrigen: map['componente_origen']?.toString() ?? '',
|
||||||
|
destinoId: map['destino_id']?.toString() ?? '',
|
||||||
|
componenteDestino: map['componente_destino']?.toString() ?? '',
|
||||||
|
cableId: map['cable_id']?.toString(),
|
||||||
|
cableUsado: map['cable_usado']?.toString(),
|
||||||
|
tipoCable: map['tipo_cable']?.toString(),
|
||||||
|
color: map['color']?.toString(),
|
||||||
|
tamano: map['tamaño']?.toDouble(),
|
||||||
|
tipoConector: map['tipo_conector']?.toString(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'conexion_id': conexionId,
|
||||||
|
'descripcion': descripcion,
|
||||||
|
'activo': activo,
|
||||||
|
'origen_id': origenId,
|
||||||
|
'componente_origen': componenteOrigen,
|
||||||
|
'destino_id': destinoId,
|
||||||
|
'componente_destino': componenteDestino,
|
||||||
|
'cable_id': cableId,
|
||||||
|
'cable_usado': cableUsado,
|
||||||
|
'tipo_cable': tipoCable,
|
||||||
|
'color': color,
|
||||||
|
'tamaño': tamano,
|
||||||
|
'tipo_conector': tipoConector,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory VistaConexionesPorCables.fromJson(String source) =>
|
||||||
|
VistaConexionesPorCables.fromMap(json.decode(source));
|
||||||
|
|
||||||
|
String toJson() => json.encode(toMap());
|
||||||
|
|
||||||
|
// Método para obtener el color del cable para visualización
|
||||||
|
String getColorForVisualization() {
|
||||||
|
if (color == null || color!.isEmpty) {
|
||||||
|
// Color por defecto basado en tipo de cable
|
||||||
|
switch (tipoCable?.toLowerCase()) {
|
||||||
|
case 'fibra':
|
||||||
|
case 'fibra optica':
|
||||||
|
return '#00BCD4'; // Cyan
|
||||||
|
case 'utp':
|
||||||
|
case 'cat6':
|
||||||
|
case 'cat5e':
|
||||||
|
return '#FFEB3B'; // Yellow
|
||||||
|
case 'coaxial':
|
||||||
|
return '#FF9800'; // Orange
|
||||||
|
default:
|
||||||
|
return '#2196F3'; // Blue por defecto
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Convertir nombre de color a código hex
|
||||||
|
switch (color!.toLowerCase()) {
|
||||||
|
case 'azul':
|
||||||
|
case 'blue':
|
||||||
|
return '#2196F3';
|
||||||
|
case 'rojo':
|
||||||
|
case 'red':
|
||||||
|
return '#F44336';
|
||||||
|
case 'verde':
|
||||||
|
case 'green':
|
||||||
|
return '#4CAF50';
|
||||||
|
case 'amarillo':
|
||||||
|
case 'yellow':
|
||||||
|
return '#FFEB3B';
|
||||||
|
case 'naranja':
|
||||||
|
case 'orange':
|
||||||
|
return '#FF9800';
|
||||||
|
case 'morado':
|
||||||
|
case 'purple':
|
||||||
|
return '#9C27B0';
|
||||||
|
case 'cyan':
|
||||||
|
return '#00BCD4';
|
||||||
|
case 'gris':
|
||||||
|
case 'gray':
|
||||||
|
return '#757575';
|
||||||
|
default:
|
||||||
|
return '#2196F3';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método para determinar el grosor de línea basado en el tipo de cable
|
||||||
|
double getThicknessForVisualization() {
|
||||||
|
switch (tipoCable?.toLowerCase()) {
|
||||||
|
case 'fibra':
|
||||||
|
case 'fibra optica':
|
||||||
|
return 5.0; // Más grueso para backbone
|
||||||
|
case 'utp':
|
||||||
|
case 'cat6':
|
||||||
|
return 4.0;
|
||||||
|
case 'cat5e':
|
||||||
|
return 3.0;
|
||||||
|
case 'coaxial':
|
||||||
|
return 3.5;
|
||||||
|
default:
|
||||||
|
return 3.0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
183
lib/models/nethive/vista_topologia_por_negocio_model.dart
Normal file
183
lib/models/nethive/vista_topologia_por_negocio_model.dart
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
|
class VistaTopologiaPorNegocio {
|
||||||
|
final String negocioId;
|
||||||
|
final String nombreNegocio;
|
||||||
|
final String? distribucionId;
|
||||||
|
final String? tipoDistribucion;
|
||||||
|
final String? distribucionNombre;
|
||||||
|
final String componenteId;
|
||||||
|
final String componenteNombre;
|
||||||
|
final String? descripcion;
|
||||||
|
final String categoriaComponente;
|
||||||
|
final bool enUso;
|
||||||
|
final bool activo;
|
||||||
|
final String? ubicacion;
|
||||||
|
final String? imagenUrl;
|
||||||
|
final DateTime fechaRegistro;
|
||||||
|
|
||||||
|
VistaTopologiaPorNegocio({
|
||||||
|
required this.negocioId,
|
||||||
|
required this.nombreNegocio,
|
||||||
|
this.distribucionId,
|
||||||
|
this.tipoDistribucion,
|
||||||
|
this.distribucionNombre,
|
||||||
|
required this.componenteId,
|
||||||
|
required this.componenteNombre,
|
||||||
|
this.descripcion,
|
||||||
|
required this.categoriaComponente,
|
||||||
|
required this.enUso,
|
||||||
|
required this.activo,
|
||||||
|
this.ubicacion,
|
||||||
|
this.imagenUrl,
|
||||||
|
required this.fechaRegistro,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory VistaTopologiaPorNegocio.fromMap(Map<String, dynamic> map) {
|
||||||
|
return VistaTopologiaPorNegocio(
|
||||||
|
negocioId: map['negocio_id']?.toString() ?? '',
|
||||||
|
nombreNegocio: map['nombre_negocio']?.toString() ?? '',
|
||||||
|
distribucionId: map['distribucion_id']?.toString(),
|
||||||
|
tipoDistribucion: map['tipo_distribucion']?.toString(),
|
||||||
|
distribucionNombre: map['distribucion_nombre']?.toString(),
|
||||||
|
componenteId: map['componente_id']?.toString() ?? '',
|
||||||
|
componenteNombre: map['componente_nombre']?.toString() ?? '',
|
||||||
|
descripcion: map['descripcion']?.toString(),
|
||||||
|
categoriaComponente: map['categoria_componente']?.toString() ?? '',
|
||||||
|
enUso: map['en_uso'] == true,
|
||||||
|
activo: map['activo'] == true,
|
||||||
|
ubicacion: map['ubicacion']?.toString(),
|
||||||
|
imagenUrl: map['imagen_url']?.toString(),
|
||||||
|
fechaRegistro:
|
||||||
|
DateTime.tryParse(map['fecha_registro']?.toString() ?? '') ??
|
||||||
|
DateTime.now(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'negocio_id': negocioId,
|
||||||
|
'nombre_negocio': nombreNegocio,
|
||||||
|
'distribucion_id': distribucionId,
|
||||||
|
'tipo_distribucion': tipoDistribucion,
|
||||||
|
'distribucion_nombre': distribucionNombre,
|
||||||
|
'componente_id': componenteId,
|
||||||
|
'componente_nombre': componenteNombre,
|
||||||
|
'descripcion': descripcion,
|
||||||
|
'categoria_componente': categoriaComponente,
|
||||||
|
'en_uso': enUso,
|
||||||
|
'activo': activo,
|
||||||
|
'ubicacion': ubicacion,
|
||||||
|
'imagen_url': imagenUrl,
|
||||||
|
'fecha_registro': fechaRegistro.toIso8601String(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory VistaTopologiaPorNegocio.fromJson(String source) =>
|
||||||
|
VistaTopologiaPorNegocio.fromMap(json.decode(source));
|
||||||
|
|
||||||
|
String toJson() => json.encode(toMap());
|
||||||
|
|
||||||
|
// Método para obtener el tipo de componente principal basado en IDs
|
||||||
|
String get tipoComponentePrincipal {
|
||||||
|
final categoria = categoriaComponente.toLowerCase();
|
||||||
|
|
||||||
|
// Clasificación basada en los nombres de categorías exactos
|
||||||
|
if (categoria == 'cable') return 'cable';
|
||||||
|
if (categoria == 'switch') return 'switch';
|
||||||
|
if (categoria == 'patch panel') return 'patch_panel';
|
||||||
|
if (categoria == 'rack') return 'rack';
|
||||||
|
if (categoria == 'ups') return 'ups';
|
||||||
|
if (categoria == 'mdf') return 'mdf';
|
||||||
|
if (categoria == 'idf') return 'idf';
|
||||||
|
|
||||||
|
// Clasificación por contenido para compatibilidad
|
||||||
|
if (categoria.contains('switch')) return 'switch';
|
||||||
|
if (categoria.contains('router') || categoria.contains('firewall'))
|
||||||
|
return 'router';
|
||||||
|
if (categoria.contains('servidor') || categoria.contains('server'))
|
||||||
|
return 'servidor';
|
||||||
|
if (categoria.contains('cable')) return 'cable';
|
||||||
|
if (categoria.contains('patch') || categoria.contains('panel'))
|
||||||
|
return 'patch_panel';
|
||||||
|
if (categoria.contains('rack')) return 'rack';
|
||||||
|
if (categoria.contains('ups')) return 'ups';
|
||||||
|
if (categoria.contains('organizador')) return 'organizador';
|
||||||
|
|
||||||
|
return 'otro';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método mejorado para determinar si es MDF
|
||||||
|
bool get esMDF {
|
||||||
|
final categoria = categoriaComponente.toLowerCase();
|
||||||
|
return categoria == 'mdf' ||
|
||||||
|
tipoDistribucion?.toUpperCase() == 'MDF' ||
|
||||||
|
ubicacion?.toLowerCase().contains('mdf') == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método mejorado para determinar si es IDF
|
||||||
|
bool get esIDF {
|
||||||
|
final categoria = categoriaComponente.toLowerCase();
|
||||||
|
return categoria == 'idf' ||
|
||||||
|
tipoDistribucion?.toUpperCase() == 'IDF' ||
|
||||||
|
ubicacion?.toLowerCase().contains('idf') == true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método para obtener el nivel de prioridad del componente (para ordenamiento en topología)
|
||||||
|
int get prioridadTopologia {
|
||||||
|
if (esMDF) return 1; // Máxima prioridad para MDF
|
||||||
|
if (esIDF) return 2; // Segunda prioridad para IDF
|
||||||
|
|
||||||
|
switch (tipoComponentePrincipal) {
|
||||||
|
case 'router':
|
||||||
|
return 3;
|
||||||
|
case 'switch':
|
||||||
|
return 4;
|
||||||
|
case 'servidor':
|
||||||
|
return 5;
|
||||||
|
case 'patch_panel':
|
||||||
|
return 6;
|
||||||
|
case 'rack':
|
||||||
|
return 7;
|
||||||
|
case 'ups':
|
||||||
|
return 8;
|
||||||
|
case 'cable':
|
||||||
|
return 9;
|
||||||
|
case 'organizador':
|
||||||
|
return 10;
|
||||||
|
default:
|
||||||
|
return 11;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método para determinar el color del componente en el diagrama
|
||||||
|
String getColorForDiagram() {
|
||||||
|
if (esMDF) return '#2196F3'; // Azul para MDF
|
||||||
|
if (esIDF) {
|
||||||
|
return enUso
|
||||||
|
? '#4CAF50'
|
||||||
|
: '#FF9800'; // Verde si está en uso, naranja si no
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (tipoComponentePrincipal) {
|
||||||
|
case 'router':
|
||||||
|
return '#FF5722'; // Naranja rojizo
|
||||||
|
case 'switch':
|
||||||
|
return '#9C27B0'; // Morado
|
||||||
|
case 'servidor':
|
||||||
|
return '#E91E63'; // Rosa
|
||||||
|
case 'patch_panel':
|
||||||
|
return '#607D8B'; // Azul gris
|
||||||
|
case 'rack':
|
||||||
|
return '#795548'; // Marrón
|
||||||
|
case 'ups':
|
||||||
|
return '#FFC107'; // Ámbar
|
||||||
|
case 'cable':
|
||||||
|
return '#4CAF50'; // Verde
|
||||||
|
case 'organizador':
|
||||||
|
return '#9E9E9E'; // Gris
|
||||||
|
default:
|
||||||
|
return activo ? '#2196F3' : '#757575';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,13 +1,11 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
import 'package:flutter_flow_chart/flutter_flow_chart.dart';
|
||||||
import 'package:flutter_animate/flutter_animate.dart';
|
import 'package:flutter_animate/flutter_animate.dart';
|
||||||
import 'package:nethive_neo/theme/theme.dart';
|
import 'package:nethive_neo/theme/theme.dart';
|
||||||
import 'package:nethive_neo/providers/nethive/componentes_provider.dart';
|
import 'package:nethive_neo/providers/nethive/componentes_provider.dart';
|
||||||
import 'package:nethive_neo/providers/nethive/empresas_negocios_provider.dart';
|
import 'package:nethive_neo/models/nethive/vista_topologia_por_negocio_model.dart';
|
||||||
import 'package:nethive_neo/models/nethive/componente_model.dart';
|
import 'package:nethive_neo/models/nethive/vista_conexiones_por_cables_model.dart';
|
||||||
import 'package:nethive_neo/models/nethive/conexion_componente_model.dart';
|
|
||||||
|
|
||||||
class TopologiaPage extends StatefulWidget {
|
class TopologiaPage extends StatefulWidget {
|
||||||
const TopologiaPage({Key? key}) : super(key: key);
|
const TopologiaPage({Key? key}) : super(key: key);
|
||||||
@@ -306,8 +304,7 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
];
|
];
|
||||||
|
|
||||||
// MDF -> IDF2 (Fibra)
|
// MDF -> IDF2 (Fibra)
|
||||||
mdfElement.next = [
|
mdfElement.next!.add(
|
||||||
...mdfElement.next ?? [],
|
|
||||||
ConnectionParams(
|
ConnectionParams(
|
||||||
destElementId: idf2Element.id,
|
destElementId: idf2Element.id,
|
||||||
arrowParams: ArrowParams(
|
arrowParams: ArrowParams(
|
||||||
@@ -315,7 +312,7 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
thickness: 4,
|
thickness: 4,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
);
|
||||||
|
|
||||||
// IDF1 -> Switch A1 (UTP)
|
// IDF1 -> Switch A1 (UTP)
|
||||||
idf1Element.next = [
|
idf1Element.next = [
|
||||||
@@ -329,8 +326,7 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
];
|
];
|
||||||
|
|
||||||
// IDF1 -> Switch A2 (UTP)
|
// IDF1 -> Switch A2 (UTP)
|
||||||
idf1Element.next = [
|
idf1Element.next!.add(
|
||||||
...idf1Element.next ?? [],
|
|
||||||
ConnectionParams(
|
ConnectionParams(
|
||||||
destElementId: switch2Element.id,
|
destElementId: switch2Element.id,
|
||||||
arrowParams: ArrowParams(
|
arrowParams: ArrowParams(
|
||||||
@@ -338,7 +334,7 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
thickness: 3,
|
thickness: 3,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
);
|
||||||
|
|
||||||
// IDF2 -> Switch B1 (UTP)
|
// IDF2 -> Switch B1 (UTP)
|
||||||
idf2Element.next = [
|
idf2Element.next = [
|
||||||
@@ -352,8 +348,7 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
];
|
];
|
||||||
|
|
||||||
// IDF2 -> Switch B2 (UTP - Desconectado)
|
// IDF2 -> Switch B2 (UTP - Desconectado)
|
||||||
idf2Element.next = [
|
idf2Element.next!.add(
|
||||||
...idf2Element.next ?? [],
|
|
||||||
ConnectionParams(
|
ConnectionParams(
|
||||||
destElementId: switch4Element.id,
|
destElementId: switch4Element.id,
|
||||||
arrowParams: ArrowParams(
|
arrowParams: ArrowParams(
|
||||||
@@ -361,11 +356,10 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
thickness: 2,
|
thickness: 2,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
);
|
||||||
|
|
||||||
// MDF -> Servidor (Dedicado)
|
// MDF -> Servidor (Dedicado)
|
||||||
mdfElement.next = [
|
mdfElement.next!.add(
|
||||||
...mdfElement.next ?? [],
|
|
||||||
ConnectionParams(
|
ConnectionParams(
|
||||||
destElementId: serverElement.id,
|
destElementId: serverElement.id,
|
||||||
arrowParams: ArrowParams(
|
arrowParams: ArrowParams(
|
||||||
@@ -373,7 +367,7 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
thickness: 5,
|
thickness: 5,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -934,6 +928,8 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
return Icons.network_check;
|
return Icons.network_check;
|
||||||
case 'Server':
|
case 'Server':
|
||||||
return Icons.dns;
|
return Icons.dns;
|
||||||
|
case 'Router':
|
||||||
|
return Icons.router;
|
||||||
default:
|
default:
|
||||||
return Icons.device_unknown;
|
return Icons.device_unknown;
|
||||||
}
|
}
|
||||||
@@ -949,6 +945,8 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
return const Color(0xFF9C27B0);
|
return const Color(0xFF9C27B0);
|
||||||
case 'Server':
|
case 'Server':
|
||||||
return const Color(0xFFE91E63);
|
return const Color(0xFFE91E63);
|
||||||
|
case 'Router':
|
||||||
|
return const Color(0xFFFF5722);
|
||||||
default:
|
default:
|
||||||
return Colors.grey;
|
return Colors.grey;
|
||||||
}
|
}
|
||||||
@@ -988,8 +986,15 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Cargar toda la topología del negocio seleccionado usando el método optimizado
|
||||||
|
await componentesProvider.cargarTopologiaCompletaOptimizada(
|
||||||
|
componentesProvider.negocioSeleccionadoId!);
|
||||||
|
|
||||||
|
// Mostrar estadísticas detalladas para debug
|
||||||
|
_mostrarEstadisticasComponentes();
|
||||||
|
|
||||||
// Construir la topología con datos reales del negocio seleccionado
|
// Construir la topología con datos reales del negocio seleccionado
|
||||||
await _buildRealNetworkTopology();
|
await _buildRealNetworkTopologyOptimized();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
print('Error al cargar datos de topología: ${e.toString()}');
|
print('Error al cargar datos de topología: ${e.toString()}');
|
||||||
_showErrorDialog('Error al cargar la topología: ${e.toString()}');
|
_showErrorDialog('Error al cargar la topología: ${e.toString()}');
|
||||||
@@ -1000,23 +1005,25 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _buildRealNetworkTopology() async {
|
Future<void> _buildRealNetworkTopologyOptimized() async {
|
||||||
dashboard.removeAllElements();
|
dashboard.removeAllElements();
|
||||||
|
|
||||||
final componentesProvider =
|
final componentesProvider =
|
||||||
Provider.of<ComponentesProvider>(context, listen: false);
|
Provider.of<ComponentesProvider>(context, listen: false);
|
||||||
|
|
||||||
// Obtener componentes agrupados por tipo
|
// Usar los datos optimizados
|
||||||
final mdfComponents = componentesProvider.getComponentesPorTipo('mdf');
|
final mdfComponents = componentesProvider.getComponentesMDFOptimizados();
|
||||||
final idfComponents = componentesProvider.getComponentesPorTipo('idf');
|
final idfComponents = componentesProvider.getComponentesIDFOptimizados();
|
||||||
final switchesAcceso = componentesProvider
|
final switchesAcceso = componentesProvider
|
||||||
.getComponentesPorTipo('switch')
|
.getComponentesPorTipoOptimizado('switch')
|
||||||
.where((s) => !mdfComponents.contains(s) && !idfComponents.contains(s))
|
.where((s) => !s.esMDF && !s.esIDF)
|
||||||
.toList();
|
.toList();
|
||||||
final routers = componentesProvider.getComponentesPorTipo('router');
|
final routers =
|
||||||
final servidores = componentesProvider.getComponentesPorTipo('servidor');
|
componentesProvider.getComponentesPorTipoOptimizado('router');
|
||||||
|
final servidores =
|
||||||
|
componentesProvider.getComponentesPorTipoOptimizado('servidor');
|
||||||
|
|
||||||
print('Componentes encontrados:');
|
print('Componentes optimizados encontrados:');
|
||||||
print('- MDF: ${mdfComponents.length}');
|
print('- MDF: ${mdfComponents.length}');
|
||||||
print('- IDF: ${idfComponents.length}');
|
print('- IDF: ${idfComponents.length}');
|
||||||
print('- Switches de acceso: ${switchesAcceso.length}');
|
print('- Switches de acceso: ${switchesAcceso.length}');
|
||||||
@@ -1030,63 +1037,63 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
|
|
||||||
Map<String, FlowElement> elementosMap = {};
|
Map<String, FlowElement> elementosMap = {};
|
||||||
|
|
||||||
// Crear elementos MDF
|
// Crear elementos MDF usando datos optimizados
|
||||||
if (mdfComponents.isNotEmpty) {
|
if (mdfComponents.isNotEmpty) {
|
||||||
final mdfElement = _createMDFElement(
|
final mdfElement = _createMDFElementOptimized(
|
||||||
mdfComponents, Offset(currentX + espacioX * 2, currentY));
|
mdfComponents, Offset(currentX + espacioX * 2, currentY));
|
||||||
dashboard.addElement(mdfElement);
|
dashboard.addElement(mdfElement);
|
||||||
elementosMap[mdfComponents.first.id] = mdfElement;
|
elementosMap[mdfComponents.first.componenteId] = mdfElement;
|
||||||
currentY += espacioY;
|
currentY += espacioY;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear elementos IDF
|
// Crear elementos IDF usando datos optimizados
|
||||||
double idfX = currentX;
|
double idfX = currentX;
|
||||||
for (var idfComp in idfComponents) {
|
for (var idfComp in idfComponents) {
|
||||||
final idfElement =
|
final idfElement = _createIDFElementOptimized(
|
||||||
_createIDFElement(idfComp, Offset(idfX, currentY + espacioY));
|
idfComp, Offset(idfX, currentY + espacioY));
|
||||||
dashboard.addElement(idfElement);
|
dashboard.addElement(idfElement);
|
||||||
elementosMap[idfComp.id] = idfElement;
|
elementosMap[idfComp.componenteId] = idfElement;
|
||||||
idfX += espacioX;
|
idfX += espacioX;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear switches de acceso
|
// Crear switches de acceso usando datos optimizados
|
||||||
double switchX = currentX;
|
double switchX = currentX;
|
||||||
currentY += espacioY * 2;
|
currentY += espacioY * 2;
|
||||||
for (var switchComp in switchesAcceso) {
|
for (var switchComp in switchesAcceso) {
|
||||||
final switchElement =
|
final switchElement =
|
||||||
_createSwitchElement(switchComp, Offset(switchX, currentY));
|
_createSwitchElementOptimized(switchComp, Offset(switchX, currentY));
|
||||||
dashboard.addElement(switchElement);
|
dashboard.addElement(switchElement);
|
||||||
elementosMap[switchComp.id] = switchElement;
|
elementosMap[switchComp.componenteId] = switchElement;
|
||||||
switchX += espacioX * 0.8;
|
switchX += espacioX * 0.8;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear servidores
|
// Crear servidores usando datos optimizados
|
||||||
if (servidores.isNotEmpty) {
|
if (servidores.isNotEmpty) {
|
||||||
currentY += espacioY;
|
currentY += espacioY;
|
||||||
double serverX = currentX + espacioX;
|
double serverX = currentX + espacioX;
|
||||||
for (var servidor in servidores) {
|
for (var servidor in servidores) {
|
||||||
final serverElement =
|
final serverElement =
|
||||||
_createServerElement(servidor, Offset(serverX, currentY));
|
_createServerElementOptimized(servidor, Offset(serverX, currentY));
|
||||||
dashboard.addElement(serverElement);
|
dashboard.addElement(serverElement);
|
||||||
elementosMap[servidor.id] = serverElement;
|
elementosMap[servidor.componenteId] = serverElement;
|
||||||
serverX += espacioX * 0.8;
|
serverX += espacioX * 0.8;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear routers/firewalls
|
// Crear routers/firewalls usando datos optimizados
|
||||||
if (routers.isNotEmpty) {
|
if (routers.isNotEmpty) {
|
||||||
double routerX = currentX;
|
double routerX = currentX;
|
||||||
for (var router in routers) {
|
for (var router in routers) {
|
||||||
final routerElement = _createRouterElement(
|
final routerElement = _createRouterElementOptimized(
|
||||||
router, Offset(routerX, currentY - espacioY * 3));
|
router, Offset(routerX, currentY - espacioY * 3));
|
||||||
dashboard.addElement(routerElement);
|
dashboard.addElement(routerElement);
|
||||||
elementosMap[router.id] = routerElement;
|
elementosMap[router.componenteId] = routerElement;
|
||||||
routerX += espacioX;
|
routerX += espacioX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Crear conexiones basadas en la base de datos
|
// Crear conexiones basadas en la vista optimizada de cables
|
||||||
await _createRealConnections(elementosMap, componentesProvider);
|
await _createOptimizedConnections(elementosMap, componentesProvider);
|
||||||
|
|
||||||
// Si no hay elementos reales, mostrar mensaje
|
// Si no hay elementos reales, mostrar mensaje
|
||||||
if (elementosMap.isEmpty) {
|
if (elementosMap.isEmpty) {
|
||||||
@@ -1096,18 +1103,14 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
setState(() {});
|
setState(() {});
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowElement _createMDFElement(
|
FlowElement _createMDFElementOptimized(
|
||||||
List<Componente> mdfComponents, Offset position) {
|
List<VistaTopologiaPorNegocio> mdfComponents, Offset position) {
|
||||||
final mainComponent = mdfComponents.first;
|
final mainComponent = mdfComponents.first;
|
||||||
final componentesProvider =
|
|
||||||
Provider.of<ComponentesProvider>(context, listen: false);
|
|
||||||
final categoria =
|
|
||||||
componentesProvider.getCategoriaById(mainComponent.categoriaId);
|
|
||||||
|
|
||||||
return FlowElement(
|
return FlowElement(
|
||||||
position: position,
|
position: position,
|
||||||
size: const Size(180, 140),
|
size: const Size(180, 140),
|
||||||
text: 'MDF\n${mainComponent.nombre}',
|
text: 'MDF\n${mainComponent.componenteNombre}',
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
textSize: 14,
|
textSize: 14,
|
||||||
textIsBold: true,
|
textIsBold: true,
|
||||||
@@ -1118,13 +1121,14 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
elevation: 8,
|
elevation: 8,
|
||||||
data: {
|
data: {
|
||||||
'type': 'MDF',
|
'type': 'MDF',
|
||||||
'componenteId': mainComponent.id,
|
'componenteId': mainComponent.componenteId,
|
||||||
'name': mainComponent.nombre,
|
'name': mainComponent.componenteNombre,
|
||||||
'status': mainComponent.activo ? 'active' : 'disconnected',
|
'status': mainComponent.activo ? 'active' : 'disconnected',
|
||||||
'description': mainComponent.descripcion ?? 'Main Distribution Frame',
|
'description': mainComponent.descripcion ?? 'Main Distribution Frame',
|
||||||
'ubicacion': mainComponent.ubicacion ?? 'Sin ubicación',
|
'ubicacion': mainComponent.ubicacion ?? 'Sin ubicación',
|
||||||
'categoria': categoria?.nombre ?? 'Sin categoría',
|
'categoria': mainComponent.categoriaComponente,
|
||||||
'componentes': mdfComponents.length,
|
'componentes': mdfComponents.length,
|
||||||
|
'distribucion': mainComponent.distribucionNombre ?? 'MDF Principal',
|
||||||
},
|
},
|
||||||
handlers: [
|
handlers: [
|
||||||
Handler.bottomCenter,
|
Handler.bottomCenter,
|
||||||
@@ -1134,16 +1138,12 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowElement _createIDFElement(Componente idfComponent, Offset position) {
|
FlowElement _createIDFElementOptimized(
|
||||||
final componentesProvider =
|
VistaTopologiaPorNegocio idfComponent, Offset position) {
|
||||||
Provider.of<ComponentesProvider>(context, listen: false);
|
|
||||||
final categoria =
|
|
||||||
componentesProvider.getCategoriaById(idfComponent.categoriaId);
|
|
||||||
|
|
||||||
return FlowElement(
|
return FlowElement(
|
||||||
position: position,
|
position: position,
|
||||||
size: const Size(160, 120),
|
size: const Size(160, 120),
|
||||||
text: 'IDF\n${idfComponent.nombre}',
|
text: 'IDF\n${idfComponent.componenteNombre}',
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
textSize: 12,
|
textSize: 12,
|
||||||
textIsBold: true,
|
textIsBold: true,
|
||||||
@@ -1158,16 +1158,17 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
elevation: 6,
|
elevation: 6,
|
||||||
data: {
|
data: {
|
||||||
'type': 'IDF',
|
'type': 'IDF',
|
||||||
'componenteId': idfComponent.id,
|
'componenteId': idfComponent.componenteId,
|
||||||
'name': idfComponent.nombre,
|
'name': idfComponent.componenteNombre,
|
||||||
'status': idfComponent.activo
|
'status': idfComponent.activo
|
||||||
? (idfComponent.enUso ? 'active' : 'warning')
|
? (idfComponent.enUso ? 'active' : 'warning')
|
||||||
: 'disconnected',
|
: 'disconnected',
|
||||||
'description':
|
'description':
|
||||||
idfComponent.descripcion ?? 'Intermediate Distribution Frame',
|
idfComponent.descripcion ?? 'Intermediate Distribution Frame',
|
||||||
'ubicacion': idfComponent.ubicacion ?? 'Sin ubicación',
|
'ubicacion': idfComponent.ubicacion ?? 'Sin ubicación',
|
||||||
'categoria': categoria?.nombre ?? 'Sin categoría',
|
'categoria': idfComponent.categoriaComponente,
|
||||||
'enUso': idfComponent.enUso,
|
'enUso': idfComponent.enUso,
|
||||||
|
'distribucion': idfComponent.distribucionNombre ?? 'IDF',
|
||||||
},
|
},
|
||||||
handlers: [
|
handlers: [
|
||||||
Handler.topCenter,
|
Handler.topCenter,
|
||||||
@@ -1178,17 +1179,12 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowElement _createSwitchElement(
|
FlowElement _createSwitchElementOptimized(
|
||||||
Componente switchComponent, Offset position) {
|
VistaTopologiaPorNegocio switchComponent, Offset position) {
|
||||||
final componentesProvider =
|
|
||||||
Provider.of<ComponentesProvider>(context, listen: false);
|
|
||||||
final categoria =
|
|
||||||
componentesProvider.getCategoriaById(switchComponent.categoriaId);
|
|
||||||
|
|
||||||
return FlowElement(
|
return FlowElement(
|
||||||
position: position,
|
position: position,
|
||||||
size: const Size(140, 100),
|
size: const Size(140, 100),
|
||||||
text: 'Switch\n${switchComponent.nombre}',
|
text: 'Switch\n${switchComponent.componenteNombre}',
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
textSize: 10,
|
textSize: 10,
|
||||||
textIsBold: true,
|
textIsBold: true,
|
||||||
@@ -1203,12 +1199,13 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
elevation: switchComponent.activo ? 4 : 2,
|
elevation: switchComponent.activo ? 4 : 2,
|
||||||
data: {
|
data: {
|
||||||
'type': 'AccessSwitch',
|
'type': 'AccessSwitch',
|
||||||
'componenteId': switchComponent.id,
|
'componenteId': switchComponent.componenteId,
|
||||||
'name': switchComponent.nombre,
|
'name': switchComponent.componenteNombre,
|
||||||
'status': switchComponent.activo ? 'active' : 'disconnected',
|
'status': switchComponent.activo ? 'active' : 'disconnected',
|
||||||
'description': switchComponent.descripcion ?? 'Switch de Acceso',
|
'description': switchComponent.descripcion ?? 'Switch de Acceso',
|
||||||
'ubicacion': switchComponent.ubicacion ?? 'Sin ubicación',
|
'ubicacion': switchComponent.ubicacion ?? 'Sin ubicación',
|
||||||
'categoria': categoria?.nombre ?? 'Sin categoría',
|
'categoria': switchComponent.categoriaComponente,
|
||||||
|
'enUso': switchComponent.enUso,
|
||||||
},
|
},
|
||||||
handlers: [
|
handlers: [
|
||||||
Handler.topCenter,
|
Handler.topCenter,
|
||||||
@@ -1216,239 +1213,158 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
FlowElement _createServerElement(
|
FlowElement _createServerElementOptimized(
|
||||||
Componente serverComponent, Offset position) {
|
VistaTopologiaPorNegocio serverComponent, Offset position) {
|
||||||
final componentesProvider =
|
|
||||||
Provider.of<ComponentesProvider>(context, listen: false);
|
|
||||||
final categoria =
|
|
||||||
componentesProvider.getCategoriaById(serverComponent.categoriaId);
|
|
||||||
|
|
||||||
return FlowElement(
|
return FlowElement(
|
||||||
position: position,
|
position: position,
|
||||||
size: const Size(160, 100),
|
size: const Size(150, 100),
|
||||||
text: 'Servidor\n${serverComponent.nombre}',
|
text: 'Servidor\n${serverComponent.componenteNombre}',
|
||||||
textColor: Colors.white,
|
textColor: Colors.white,
|
||||||
textSize: 12,
|
textSize: 11,
|
||||||
textIsBold: true,
|
textIsBold: true,
|
||||||
kind: ElementKind.rectangle,
|
kind: ElementKind.rectangle,
|
||||||
backgroundColor: const Color(0xFFE91E63),
|
backgroundColor: serverComponent.activo
|
||||||
borderColor: const Color(0xFFC2185B),
|
? const Color(0xFFE91E63)
|
||||||
|
: const Color(0xFF757575),
|
||||||
|
borderColor: serverComponent.activo
|
||||||
|
? const Color(0xFFC2185B)
|
||||||
|
: const Color(0xFF424242),
|
||||||
borderThickness: 3,
|
borderThickness: 3,
|
||||||
elevation: 6,
|
elevation: serverComponent.activo ? 6 : 2,
|
||||||
data: {
|
data: {
|
||||||
'type': 'Server',
|
'type': 'Server',
|
||||||
'componenteId': serverComponent.id,
|
'componenteId': serverComponent.componenteId,
|
||||||
'name': serverComponent.nombre,
|
'name': serverComponent.componenteNombre,
|
||||||
'status': serverComponent.activo ? 'active' : 'disconnected',
|
'status': serverComponent.activo ? 'active' : 'disconnected',
|
||||||
'description': serverComponent.descripcion ?? 'Servidor',
|
'description': serverComponent.descripcion ?? 'Servidor de red',
|
||||||
'ubicacion': serverComponent.ubicacion ?? 'Sin ubicación',
|
'ubicacion': serverComponent.ubicacion ?? 'Sin ubicación',
|
||||||
'categoria': categoria?.nombre ?? 'Sin categoría',
|
'categoria': serverComponent.categoriaComponente,
|
||||||
|
'enUso': serverComponent.enUso,
|
||||||
},
|
},
|
||||||
handlers: [
|
handlers: [
|
||||||
Handler.topCenter,
|
Handler.topCenter,
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
FlowElement _createRouterElement(
|
|
||||||
Componente routerComponent, Offset position) {
|
|
||||||
final componentesProvider =
|
|
||||||
Provider.of<ComponentesProvider>(context, listen: false);
|
|
||||||
final categoria =
|
|
||||||
componentesProvider.getCategoriaById(routerComponent.categoriaId);
|
|
||||||
|
|
||||||
return FlowElement(
|
|
||||||
position: position,
|
|
||||||
size: const Size(160, 100),
|
|
||||||
text: 'Router\n${routerComponent.nombre}',
|
|
||||||
textColor: Colors.white,
|
|
||||||
textSize: 12,
|
|
||||||
textIsBold: true,
|
|
||||||
kind: ElementKind.rectangle,
|
|
||||||
backgroundColor: const Color(0xFFFF5722),
|
|
||||||
borderColor: const Color(0xFFD84315),
|
|
||||||
borderThickness: 3,
|
|
||||||
elevation: 6,
|
|
||||||
data: {
|
|
||||||
'type': 'Router',
|
|
||||||
'componenteId': routerComponent.id,
|
|
||||||
'name': routerComponent.nombre,
|
|
||||||
'status': routerComponent.activo ? 'active' : 'disconnected',
|
|
||||||
'description': routerComponent.descripcion ?? 'Router/Firewall',
|
|
||||||
'ubicacion': routerComponent.ubicacion ?? 'Sin ubicación',
|
|
||||||
'categoria': categoria?.nombre ?? 'Sin categoría',
|
|
||||||
},
|
|
||||||
handlers: [
|
|
||||||
Handler.bottomCenter,
|
|
||||||
Handler.topCenter,
|
|
||||||
Handler.leftCenter,
|
Handler.leftCenter,
|
||||||
Handler.rightCenter,
|
Handler.rightCenter,
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _createRealConnections(Map<String, FlowElement> elementosMap,
|
FlowElement _createRouterElementOptimized(
|
||||||
|
VistaTopologiaPorNegocio routerComponent, Offset position) {
|
||||||
|
return FlowElement(
|
||||||
|
position: position,
|
||||||
|
size: const Size(160, 100),
|
||||||
|
text: 'Router\n${routerComponent.componenteNombre}',
|
||||||
|
textColor: Colors.white,
|
||||||
|
textSize: 11,
|
||||||
|
textIsBold: true,
|
||||||
|
kind: ElementKind.rectangle,
|
||||||
|
backgroundColor: routerComponent.activo
|
||||||
|
? const Color(0xFFFF5722)
|
||||||
|
: const Color(0xFF757575),
|
||||||
|
borderColor: routerComponent.activo
|
||||||
|
? const Color(0xFFE64A19)
|
||||||
|
: const Color(0xFF424242),
|
||||||
|
borderThickness: 3,
|
||||||
|
elevation: routerComponent.activo ? 6 : 2,
|
||||||
|
data: {
|
||||||
|
'type': 'Router',
|
||||||
|
'componenteId': routerComponent.componenteId,
|
||||||
|
'name': routerComponent.componenteNombre,
|
||||||
|
'status': routerComponent.activo ? 'active' : 'disconnected',
|
||||||
|
'description': routerComponent.descripcion ?? 'Router/Firewall',
|
||||||
|
'ubicacion': routerComponent.ubicacion ?? 'Sin ubicación',
|
||||||
|
'categoria': routerComponent.categoriaComponente,
|
||||||
|
'enUso': routerComponent.enUso,
|
||||||
|
},
|
||||||
|
handlers: [
|
||||||
|
Handler.topCenter,
|
||||||
|
Handler.bottomCenter,
|
||||||
|
Handler.leftCenter,
|
||||||
|
Handler.rightCenter,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _createOptimizedConnections(
|
||||||
|
Map<String, FlowElement> elementosMap,
|
||||||
ComponentesProvider componentesProvider) async {
|
ComponentesProvider componentesProvider) async {
|
||||||
// Obtener conexiones reales de la base de datos
|
try {
|
||||||
final conexiones = componentesProvider.conexiones;
|
print('Creando conexiones optimizadas...');
|
||||||
|
print(
|
||||||
|
'Conexiones con cables encontradas: ${componentesProvider.conexionesConCables.length}');
|
||||||
|
|
||||||
print('Creando ${conexiones.length} conexiones...');
|
for (var conexionCable in componentesProvider.conexionesConCables) {
|
||||||
|
if (!conexionCable.activo) continue;
|
||||||
|
|
||||||
for (var conexion in conexiones) {
|
final elementoOrigen = elementosMap[conexionCable.origenId];
|
||||||
final origenElement = elementosMap[conexion.componenteOrigenId];
|
final elementoDestino = elementosMap[conexionCable.destinoId];
|
||||||
final destinoElement = elementosMap[conexion.componenteDestinoId];
|
|
||||||
|
|
||||||
if (origenElement != null && destinoElement != null) {
|
if (elementoOrigen != null && elementoDestino != null) {
|
||||||
// Determinar el color y grosor de la conexión basado en los tipos de componentes
|
// Usar la información real del cable para determinar color y grosor
|
||||||
final colorConexion =
|
final colorConexion = _getColorFromCableData(conexionCable);
|
||||||
_getConnectionColor(conexion, componentesProvider);
|
final grosorConexion = _getThicknessFromCableData(conexionCable);
|
||||||
final grosorConexion =
|
|
||||||
_getConnectionThickness(conexion, componentesProvider);
|
|
||||||
|
|
||||||
print('Conectando: ${origenElement.text} -> ${destinoElement.text}');
|
print(
|
||||||
|
'Creando conexión: ${conexionCable.componenteOrigen} -> ${conexionCable.componenteDestino}');
|
||||||
|
if (conexionCable.tipoCable != null) {
|
||||||
|
print(
|
||||||
|
' Cable: ${conexionCable.tipoCable} (${conexionCable.color ?? 'sin color'})');
|
||||||
|
}
|
||||||
|
|
||||||
// Agregar la conexión al elemento origen
|
// Crear la conexión en el FlowChart
|
||||||
origenElement.next = [
|
elementoOrigen.next ??= [];
|
||||||
...origenElement.next ?? [],
|
|
||||||
|
elementoOrigen.next!.add(
|
||||||
ConnectionParams(
|
ConnectionParams(
|
||||||
destElementId: destinoElement.id,
|
destElementId: elementoDestino.id,
|
||||||
arrowParams: ArrowParams(
|
arrowParams: ArrowParams(
|
||||||
color: colorConexion,
|
color: colorConexion,
|
||||||
thickness: grosorConexion,
|
thickness: grosorConexion,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
];
|
);
|
||||||
}
|
} else {
|
||||||
}
|
|
||||||
|
|
||||||
// Si no hay conexiones en la BD, crear conexiones automáticas basadas en la ubicación
|
|
||||||
if (conexiones.isEmpty) {
|
|
||||||
print('No hay conexiones en BD, creando automáticas...');
|
|
||||||
_createAutomaticConnections(elementosMap, componentesProvider);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Color _getConnectionColor(
|
|
||||||
ConexionComponente conexion, ComponentesProvider componentesProvider) {
|
|
||||||
// Obtener los componentes origen y destino
|
|
||||||
final origenComp =
|
|
||||||
componentesProvider.getComponenteById(conexion.componenteOrigenId);
|
|
||||||
final destinoComp =
|
|
||||||
componentesProvider.getComponenteById(conexion.componenteDestinoId);
|
|
||||||
|
|
||||||
if (origenComp == null || destinoComp == null) return Colors.grey;
|
|
||||||
|
|
||||||
// Determinar el tipo de conexión basado en las ubicaciones
|
|
||||||
final origenUbicacion = origenComp.ubicacion?.toUpperCase() ?? '';
|
|
||||||
final destinoUbicacion = destinoComp.ubicacion?.toUpperCase() ?? '';
|
|
||||||
|
|
||||||
// MDF a IDF = Fibra (cyan)
|
|
||||||
if (origenUbicacion.contains('MDF') && destinoUbicacion.contains('IDF')) {
|
|
||||||
return Colors.cyan;
|
|
||||||
}
|
|
||||||
|
|
||||||
// IDF a Switch = UTP (yellow)
|
|
||||||
if (origenUbicacion.contains('IDF')) {
|
|
||||||
return Colors.yellow;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Servidor = Dedicado (purple)
|
|
||||||
final origenCategoria =
|
|
||||||
componentesProvider.getCategoriaById(origenComp.categoriaId);
|
|
||||||
final destinoCategoria =
|
|
||||||
componentesProvider.getCategoriaById(destinoComp.categoriaId);
|
|
||||||
|
|
||||||
if ((origenCategoria?.nombre?.toLowerCase().contains('servidor') ??
|
|
||||||
false) ||
|
|
||||||
(destinoCategoria?.nombre?.toLowerCase().contains('servidor') ??
|
|
||||||
false)) {
|
|
||||||
return Colors.purple;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Colors.green; // Por defecto
|
|
||||||
}
|
|
||||||
|
|
||||||
double _getConnectionThickness(
|
|
||||||
ConexionComponente conexion, ComponentesProvider componentesProvider) {
|
|
||||||
final origenComp =
|
|
||||||
componentesProvider.getComponenteById(conexion.componenteOrigenId);
|
|
||||||
final destinoComp =
|
|
||||||
componentesProvider.getComponenteById(conexion.componenteDestinoId);
|
|
||||||
|
|
||||||
if (origenComp == null || destinoComp == null) return 2.0;
|
|
||||||
|
|
||||||
final origenUbicacion = origenComp.ubicacion?.toUpperCase() ?? '';
|
|
||||||
final destinoUbicacion = destinoComp.ubicacion?.toUpperCase() ?? '';
|
|
||||||
|
|
||||||
// Conexiones principales más gruesas
|
|
||||||
if (origenUbicacion.contains('MDF') && destinoUbicacion.contains('IDF')) {
|
|
||||||
return 4.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return conexion.activo ? 3.0 : 2.0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void _createAutomaticConnections(Map<String, FlowElement> elementosMap,
|
|
||||||
ComponentesProvider componentesProvider) {
|
|
||||||
// Crear conexiones automáticas cuando no hay datos en la BD
|
|
||||||
final mdfElements = elementosMap.values
|
|
||||||
.where((e) => (e.data as Map)['type'] == 'MDF')
|
|
||||||
.toList();
|
|
||||||
final idfElements = elementosMap.values
|
|
||||||
.where((e) => (e.data as Map)['type'] == 'IDF')
|
|
||||||
.toList();
|
|
||||||
final switchElements = elementosMap.values
|
|
||||||
.where((e) => (e.data as Map)['type'] == 'AccessSwitch')
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
print('Creando conexiones automáticas...');
|
|
||||||
print(
|
print(
|
||||||
'MDF: ${mdfElements.length}, IDF: ${idfElements.length}, Switches: ${switchElements.length}');
|
'Elementos no encontrados para conexión: ${conexionCable.origenId} -> ${conexionCable.destinoId}');
|
||||||
|
|
||||||
// Conectar MDF a IDFs
|
|
||||||
for (var mdf in mdfElements) {
|
|
||||||
for (var idf in idfElements) {
|
|
||||||
mdf.next = [
|
|
||||||
...mdf.next ?? [],
|
|
||||||
ConnectionParams(
|
|
||||||
destElementId: idf.id,
|
|
||||||
arrowParams: ArrowParams(
|
|
||||||
color: Colors.cyan,
|
|
||||||
thickness: 4,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conectar IDFs a Switches
|
setState(() {});
|
||||||
for (int i = 0; i < idfElements.length && i < switchElements.length; i++) {
|
} catch (e) {
|
||||||
final idf = idfElements[i];
|
print('Error en _createOptimizedConnections: ${e.toString()}');
|
||||||
final switchesParaEsteIdf = switchElements.skip(i * 2).take(2);
|
|
||||||
|
|
||||||
for (var switch_ in switchesParaEsteIdf) {
|
|
||||||
idf.next = [
|
|
||||||
...idf.next ?? [],
|
|
||||||
ConnectionParams(
|
|
||||||
destElementId: switch_.id,
|
|
||||||
arrowParams: ArrowParams(
|
|
||||||
color: Colors.yellow,
|
|
||||||
thickness: 3,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showNoComponentsMessage() {
|
Color _getColorFromCableData(VistaConexionesPorCables conexionCable) {
|
||||||
|
// Usar el método del modelo para obtener el color
|
||||||
|
final colorHex = conexionCable.getColorForVisualization();
|
||||||
|
return _hexToColor(colorHex);
|
||||||
|
}
|
||||||
|
|
||||||
|
double _getThicknessFromCableData(VistaConexionesPorCables conexionCable) {
|
||||||
|
// Usar el método del modelo para obtener el grosor
|
||||||
|
return conexionCable.getThicknessForVisualization();
|
||||||
|
}
|
||||||
|
|
||||||
|
Color _hexToColor(String hex) {
|
||||||
|
hex = hex.replaceAll('#', '');
|
||||||
|
return Color(int.parse('FF$hex', radix: 16));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _showNoBusinessSelectedDialog() {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Sin componentes'),
|
title: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.business, color: Colors.orange),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Negocio no seleccionado'),
|
||||||
|
],
|
||||||
|
),
|
||||||
content: const Text(
|
content: const Text(
|
||||||
'No se encontraron componentes de red para este negocio.\n\n'
|
'Para visualizar la topología de red, primero debe seleccionar un negocio desde la página de empresas.',
|
||||||
'Para ver una topología completa, agregue componentes en el módulo de Inventario con ubicaciones como "MDF", "IDF", etc.',
|
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
@@ -1458,44 +1374,28 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
// Ir al módulo de inventario (esto depende de tu estructura de navegación)
|
// Navegar a la página de empresas
|
||||||
// context.go('/infrastructure/inventory');
|
// router.pushNamed('/infrastructure/empresas');
|
||||||
},
|
},
|
||||||
child: const Text('Ir a Inventario'),
|
child: const Text('Ir a Empresas'),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _showNoBusinessSelectedDialog() {
|
void _showErrorDialog(String mensaje) {
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AlertDialog(
|
builder: (context) => AlertDialog(
|
||||||
title: const Text('Negocio no seleccionado'),
|
title: const Row(
|
||||||
content: const Text(
|
children: [
|
||||||
'No se ha seleccionado ningún negocio. Por favor, regrese a la página de negocios y seleccione "Acceder a Infraestructura" en la tabla.',
|
Icon(Icons.error, color: Colors.red),
|
||||||
),
|
SizedBox(width: 8),
|
||||||
actions: [
|
Text('Error'),
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
// Regresar a la página de empresas/negocios
|
|
||||||
context.go('/empresa-negocios');
|
|
||||||
},
|
|
||||||
child: const Text('Ir a Negocios'),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
content: Text(mensaje),
|
||||||
}
|
|
||||||
|
|
||||||
void _showErrorDialog(String message) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder: (context) => AlertDialog(
|
|
||||||
title: const Text('Error'),
|
|
||||||
content: Text(message),
|
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
@@ -1505,4 +1405,95 @@ class _TopologiaPageState extends State<TopologiaPage>
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _showNoComponentsMessage() {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => AlertDialog(
|
||||||
|
title: const Row(
|
||||||
|
children: [
|
||||||
|
Icon(Icons.info, color: Colors.blue),
|
||||||
|
SizedBox(width: 8),
|
||||||
|
Text('Sin componentes'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'No se encontraron componentes de infraestructura para este negocio.',
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const Text(
|
||||||
|
'Para visualizar la topología, necesita:',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
const Text('• Registrar componentes (switches, routers, etc.)'),
|
||||||
|
const Text('• Configurar distribuciones (MDF/IDF)'),
|
||||||
|
const Text('• Crear conexiones entre componentes'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: const Text('Entendido'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
// Navegar a la página de componentes
|
||||||
|
// router.pushNamed('/infrastructure/componentes');
|
||||||
|
},
|
||||||
|
child: const Text('Gestionar Componentes'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Método para mostrar estadísticas detalladas de componentes
|
||||||
|
void _mostrarEstadisticasComponentes() {
|
||||||
|
final provider = Provider.of<ComponentesProvider>(context, listen: false);
|
||||||
|
print('\n=== ESTADÍSTICAS DETALLADAS DE COMPONENTES ===');
|
||||||
|
print('Total de componentes cargados: ${provider.topologiaOptimizada.length}');
|
||||||
|
|
||||||
|
if (provider.topologiaOptimizada.isEmpty) {
|
||||||
|
print('❌ No hay componentes cargados');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Agrupar por categoría
|
||||||
|
final componentesPorCategoria = <String, List<VistaTopologiaPorNegocio>>{};
|
||||||
|
for (final componente in provider.topologiaOptimizada) {
|
||||||
|
final categoria = componente.categoriaComponente;
|
||||||
|
componentesPorCategoria.putIfAbsent(categoria, () => []).add(componente);
|
||||||
|
}
|
||||||
|
|
||||||
|
print('\n📊 Componentes por categoría:');
|
||||||
|
componentesPorCategoria.forEach((categoria, lista) {
|
||||||
|
print(' - $categoria: ${lista.length} componentes');
|
||||||
|
for (final comp in lista) {
|
||||||
|
print(' • ${comp.componenteNombre} (${comp.tipoComponentePrincipal}) - Activo: ${comp.activo}');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clasificación por tipo principal
|
||||||
|
final mdfComponents = provider.getComponentesMDFOptimizados();
|
||||||
|
final idfComponents = provider.getComponentesIDFOptimizados();
|
||||||
|
final switchComponents = provider.getComponentesPorTipoOptimizado('switch');
|
||||||
|
final routerComponents = provider.getComponentesPorTipoOptimizado('router');
|
||||||
|
final servidorComponents = provider.getComponentesPorTipoOptimizado('servidor');
|
||||||
|
|
||||||
|
print('\n🔧 Clasificación por tipo:');
|
||||||
|
print(' - MDF: ${mdfComponents.length}');
|
||||||
|
print(' - IDF: ${idfComponents.length}');
|
||||||
|
print(' - Switches: ${switchComponents.length}');
|
||||||
|
print(' - Routers: ${routerComponents.length}');
|
||||||
|
print(' - Servidores: ${servidorComponents.length}');
|
||||||
|
|
||||||
|
print('\n🔗 Conexiones disponibles: ${provider.conexionesConCables.length}');
|
||||||
|
print('===============================================\n');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,8 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:nethive_neo/helpers/globals.dart';
|
import 'package:nethive_neo/helpers/globals.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:nethive_neo/providers/nethive/componentes_provider.dart';
|
import 'package:nethive_neo/providers/nethive/componentes_provider.dart';
|
||||||
import 'package:nethive_neo/theme/theme.dart';
|
import 'package:nethive_neo/theme/theme.dart';
|
||||||
import 'package:nethive_neo/models/nethive/componente_model.dart';
|
import 'package:nethive_neo/models/nethive/componente_model.dart';
|
||||||
import 'package:nethive_neo/models/nethive/categoria_componente_model.dart';
|
|
||||||
|
|
||||||
class EditComponenteDialog extends StatefulWidget {
|
class EditComponenteDialog extends StatefulWidget {
|
||||||
final ComponentesProvider provider;
|
final ComponentesProvider provider;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user