- Add ControlPlaneStatusClient for querying control plane state - Add control plane status widgets for displaying status in client - Update main.dart to integrate control plane status features - Update widget_test.dart - Archive completed task documents
220 lines
6.8 KiB
Dart
220 lines
6.8 KiB
Dart
import 'dart:convert';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
class EdgeRegistryView {
|
|
final String edgeId;
|
|
final String edgeName;
|
|
final String version;
|
|
final List<String> capabilities;
|
|
final String protocol;
|
|
final bool connected;
|
|
final DateTime lastSeen;
|
|
|
|
EdgeRegistryView({
|
|
required this.edgeId,
|
|
required this.edgeName,
|
|
required this.version,
|
|
required this.capabilities,
|
|
required this.protocol,
|
|
required this.connected,
|
|
required this.lastSeen,
|
|
});
|
|
|
|
factory EdgeRegistryView.fromJson(Map<String, dynamic> json) {
|
|
return EdgeRegistryView(
|
|
edgeId: json['edge_id'] as String? ?? '',
|
|
edgeName: json['edge_name'] as String? ?? '',
|
|
version: json['version'] as String? ?? '',
|
|
capabilities: List<String>.from(json['capabilities'] ?? []),
|
|
protocol: json['protocol'] as String? ?? '',
|
|
connected: json['connected'] as bool? ?? false,
|
|
lastSeen: json['last_seen'] != null
|
|
? DateTime.parse(json['last_seen'] as String)
|
|
: DateTime.now(),
|
|
);
|
|
}
|
|
}
|
|
|
|
class AdapterSummaryView {
|
|
final String type;
|
|
final bool enabled;
|
|
|
|
AdapterSummaryView({required this.type, required this.enabled});
|
|
|
|
factory AdapterSummaryView.fromJson(Map<String, dynamic> json) {
|
|
return AdapterSummaryView(
|
|
type: json['type'] as String? ?? '',
|
|
enabled: json['enabled'] as bool? ?? false,
|
|
);
|
|
}
|
|
}
|
|
|
|
class NodeConfigSummaryView {
|
|
final List<AdapterSummaryView> adapters;
|
|
final int concurrency;
|
|
|
|
NodeConfigSummaryView({required this.adapters, required this.concurrency});
|
|
|
|
factory NodeConfigSummaryView.fromJson(Map<String, dynamic> json) {
|
|
return NodeConfigSummaryView(
|
|
adapters: (json['adapters'] as List? ?? [])
|
|
.map((e) => AdapterSummaryView.fromJson(e as Map<String, dynamic>))
|
|
.toList(),
|
|
concurrency: json['concurrency'] as int? ?? 0,
|
|
);
|
|
}
|
|
}
|
|
|
|
class EdgeNodeSnapshotView {
|
|
final String nodeId;
|
|
final String alias;
|
|
final String label;
|
|
final bool connected;
|
|
final NodeConfigSummaryView? config;
|
|
|
|
EdgeNodeSnapshotView({
|
|
required this.nodeId,
|
|
required this.alias,
|
|
required this.label,
|
|
required this.connected,
|
|
this.config,
|
|
});
|
|
|
|
factory EdgeNodeSnapshotView.fromJson(Map<String, dynamic> json) {
|
|
return EdgeNodeSnapshotView(
|
|
nodeId: json['node_id'] as String? ?? '',
|
|
alias: json['alias'] as String? ?? '',
|
|
label: json['label'] as String? ?? '',
|
|
connected: json['connected'] as bool? ?? false,
|
|
config: json['config'] != null
|
|
? NodeConfigSummaryView.fromJson(json['config'] as Map<String, dynamic>)
|
|
: null,
|
|
);
|
|
}
|
|
}
|
|
|
|
class EdgeStatusResponseView {
|
|
final String requestId;
|
|
final String edgeId;
|
|
final String edgeName;
|
|
final int observedTimeUnixNano;
|
|
final List<EdgeNodeSnapshotView> nodes;
|
|
final Map<String, String> metadata;
|
|
final String error;
|
|
|
|
EdgeStatusResponseView({
|
|
required this.requestId,
|
|
required this.edgeId,
|
|
required this.edgeName,
|
|
required this.observedTimeUnixNano,
|
|
required this.nodes,
|
|
required this.metadata,
|
|
required this.error,
|
|
});
|
|
|
|
factory EdgeStatusResponseView.fromJson(Map<String, dynamic> json) {
|
|
return EdgeStatusResponseView(
|
|
requestId: json['request_id'] as String? ?? '',
|
|
edgeId: json['edge_id'] as String? ?? '',
|
|
edgeName: json['edge_name'] as String? ?? '',
|
|
observedTimeUnixNano: json['observed_time_unix_nano'] as int? ?? 0,
|
|
nodes: (json['nodes'] as List? ?? [])
|
|
.map((e) => EdgeNodeSnapshotView.fromJson(e as Map<String, dynamic>))
|
|
.toList(),
|
|
metadata: Map<String, String>.from(json['metadata'] ?? {}),
|
|
error: json['error'] as String? ?? '',
|
|
);
|
|
}
|
|
}
|
|
|
|
class EdgeNodeEventView {
|
|
final String edgeId;
|
|
final String eventId;
|
|
final String type;
|
|
final String source;
|
|
final String nodeId;
|
|
final String alias;
|
|
final String reason;
|
|
final DateTime timestamp;
|
|
final DateTime receivedAt;
|
|
final Map<String, String> metadata;
|
|
|
|
EdgeNodeEventView({
|
|
required this.edgeId,
|
|
required this.eventId,
|
|
required this.type,
|
|
required this.source,
|
|
required this.nodeId,
|
|
required this.alias,
|
|
required this.reason,
|
|
required this.timestamp,
|
|
required this.receivedAt,
|
|
required this.metadata,
|
|
});
|
|
|
|
factory EdgeNodeEventView.fromJson(Map<String, dynamic> json) {
|
|
return EdgeNodeEventView(
|
|
edgeId: json['edge_id'] as String? ?? '',
|
|
eventId: json['event_id'] as String? ?? '',
|
|
type: json['type'] as String? ?? '',
|
|
source: json['source'] as String? ?? '',
|
|
nodeId: json['node_id'] as String? ?? '',
|
|
alias: json['alias'] as String? ?? '',
|
|
reason: json['reason'] as String? ?? '',
|
|
timestamp: json['timestamp'] != null
|
|
? DateTime.parse(json['timestamp'] as String)
|
|
: DateTime.now(),
|
|
receivedAt: json['received_at'] != null
|
|
? DateTime.parse(json['received_at'] as String)
|
|
: DateTime.now(),
|
|
metadata: Map<String, String>.from(json['metadata'] ?? {}),
|
|
);
|
|
}
|
|
}
|
|
|
|
abstract class ControlPlaneStatusRepository {
|
|
Future<List<EdgeRegistryView>> fetchEdges();
|
|
Future<EdgeStatusResponseView> fetchEdgeStatus(String edgeId);
|
|
Future<List<EdgeNodeEventView>> fetchEdgeEvents(String edgeId);
|
|
}
|
|
|
|
class HttpControlPlaneStatusRepository implements ControlPlaneStatusRepository {
|
|
final String baseUrl;
|
|
final http.Client? client;
|
|
|
|
HttpControlPlaneStatusRepository({required this.baseUrl, this.client});
|
|
|
|
http.Client get _httpClient => client ?? http.Client();
|
|
|
|
@override
|
|
Future<List<EdgeRegistryView>> fetchEdges() async {
|
|
final response = await _httpClient.get(Uri.parse('$baseUrl/edges'));
|
|
if (response.statusCode != 200) {
|
|
throw Exception('Failed to fetch edges: ${response.statusCode}');
|
|
}
|
|
final body = json.decode(response.body) as Map<String, dynamic>;
|
|
final list = body['edges'] as List? ?? [];
|
|
return list.map((e) => EdgeRegistryView.fromJson(e as Map<String, dynamic>)).toList();
|
|
}
|
|
|
|
@override
|
|
Future<EdgeStatusResponseView> fetchEdgeStatus(String edgeId) async {
|
|
final response = await _httpClient.get(Uri.parse('$baseUrl/edges/$edgeId/status'));
|
|
if (response.statusCode != 200) {
|
|
throw Exception('Failed to fetch status for $edgeId: ${response.statusCode}');
|
|
}
|
|
final body = json.decode(response.body) as Map<String, dynamic>;
|
|
return EdgeStatusResponseView.fromJson(body);
|
|
}
|
|
|
|
@override
|
|
Future<List<EdgeNodeEventView>> fetchEdgeEvents(String edgeId) async {
|
|
final response = await _httpClient.get(Uri.parse('$baseUrl/edges/$edgeId/events'));
|
|
if (response.statusCode != 200) {
|
|
throw Exception('Failed to fetch events for $edgeId: ${response.statusCode}');
|
|
}
|
|
final body = json.decode(response.body) as Map<String, dynamic>;
|
|
final list = body['events'] as List? ?? [];
|
|
return list.map((e) => EdgeNodeEventView.fromJson(e as Map<String, dynamic>)).toList();
|
|
}
|
|
}
|