- Upgrade flutter_riverpod to 3.1.0, riverpod_annotation to 4.0.0 - Upgrade freezed to 3.2.3, freezed_annotation to 3.1.0 - Migrate freezed classes to use sealed keyword (freezed 3.x) - Update provider naming (*NotifierProvider → *Provider) - Add legacy.dart import for StateNotifierProvider compatibility - Fix valueOrNull → value for AsyncValue - Remove unused imports and fields - Add sync from Authentik button to users/groups pages - Suppress invalid_annotation_target warning in analysis_options 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
130 lines
4.0 KiB
Dart
130 lines
4.0 KiB
Dart
import 'package:freezed_annotation/freezed_annotation.dart';
|
|
import 'package:tatlock_ui/features/control_room/containers/domain/entities/container.dart';
|
|
|
|
part 'container_model.freezed.dart';
|
|
part 'container_model.g.dart';
|
|
|
|
/// Container data model for API serialization.
|
|
@freezed
|
|
sealed class ContainerModel with _$ContainerModel {
|
|
const factory ContainerModel({
|
|
@JsonKey(name: 'Id') required String id,
|
|
@JsonKey(name: 'Names') required List<String> names,
|
|
@JsonKey(name: 'Image') required String image,
|
|
@JsonKey(name: 'State') required String state,
|
|
@JsonKey(name: 'Status') required String status,
|
|
@JsonKey(name: 'Labels') @Default({}) Map<String, String> labels,
|
|
@JsonKey(name: 'Ports') @Default([]) List<PortModel> ports,
|
|
@JsonKey(name: 'Mounts') @Default([]) List<MountModel> mounts,
|
|
@JsonKey(name: 'NetworkSettings') NetworkSettingsModel? networkSettings,
|
|
@JsonKey(name: 'Created') int? created,
|
|
@JsonKey(name: 'SizeRw') int? sizeRw,
|
|
@JsonKey(name: 'SizeRootFs') int? sizeRootFs,
|
|
}) = _ContainerModel;
|
|
|
|
const ContainerModel._();
|
|
|
|
factory ContainerModel.fromJson(Map<String, dynamic> json) =>
|
|
_$ContainerModelFromJson(json);
|
|
|
|
/// Converts to domain entity.
|
|
Container toEntity() {
|
|
// Extract stack name from labels (Docker Compose convention)
|
|
final stackName = labels['com.docker.compose.project'];
|
|
final stackId = stackName; // Use project name as ID for now
|
|
|
|
return Container(
|
|
id: id.substring(0, 12),
|
|
fullId: id,
|
|
name: names.isNotEmpty ? names.first.replaceFirst('/', '') : id,
|
|
image: image,
|
|
state: _parseState(state),
|
|
status: status,
|
|
stackName: stackName,
|
|
stackId: stackId,
|
|
ports: ports.map((p) => p.toEntity()).toList(),
|
|
labels: labels,
|
|
mounts: mounts.map((m) => m.toEntity()).toList(),
|
|
networks: networkSettings?.networks.keys.toList() ?? [],
|
|
createdAt: created != null
|
|
? DateTime.fromMillisecondsSinceEpoch(created! * 1000)
|
|
: null,
|
|
);
|
|
}
|
|
|
|
ContainerState _parseState(String state) {
|
|
return switch (state.toLowerCase()) {
|
|
'created' => ContainerState.created,
|
|
'running' => ContainerState.running,
|
|
'paused' => ContainerState.paused,
|
|
'restarting' => ContainerState.restarting,
|
|
'removing' => ContainerState.removing,
|
|
'exited' => ContainerState.exited,
|
|
'dead' => ContainerState.dead,
|
|
_ => ContainerState.exited,
|
|
};
|
|
}
|
|
}
|
|
|
|
/// Port mapping model.
|
|
@freezed
|
|
sealed class PortModel with _$PortModel {
|
|
const factory PortModel({
|
|
@JsonKey(name: 'IP') String? ip,
|
|
@JsonKey(name: 'PrivatePort') required int privatePort,
|
|
@JsonKey(name: 'PublicPort') int? publicPort,
|
|
@JsonKey(name: 'Type') @Default('tcp') String type,
|
|
}) = _PortModel;
|
|
|
|
const PortModel._();
|
|
|
|
factory PortModel.fromJson(Map<String, dynamic> json) =>
|
|
_$PortModelFromJson(json);
|
|
|
|
PortMapping toEntity() {
|
|
return PortMapping(
|
|
hostIp: ip,
|
|
hostPort: publicPort,
|
|
containerPort: privatePort,
|
|
protocol: type,
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Mount model.
|
|
@freezed
|
|
sealed class MountModel with _$MountModel {
|
|
const factory MountModel({
|
|
@JsonKey(name: 'Type') required String type,
|
|
@JsonKey(name: 'Source') required String source,
|
|
@JsonKey(name: 'Destination') required String destination,
|
|
@JsonKey(name: 'Mode') @Default('rw') String mode,
|
|
@JsonKey(name: 'RW') @Default(true) bool rw,
|
|
}) = _MountModel;
|
|
|
|
const MountModel._();
|
|
|
|
factory MountModel.fromJson(Map<String, dynamic> json) =>
|
|
_$MountModelFromJson(json);
|
|
|
|
VolumeMount toEntity() {
|
|
return VolumeMount(
|
|
type: type,
|
|
source: source,
|
|
destination: destination,
|
|
mode: rw ? 'rw' : 'ro',
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Network settings model.
|
|
@freezed
|
|
sealed class NetworkSettingsModel with _$NetworkSettingsModel {
|
|
const factory NetworkSettingsModel({
|
|
@JsonKey(name: 'Networks') @Default({}) Map<String, dynamic> networks,
|
|
}) = _NetworkSettingsModel;
|
|
|
|
factory NetworkSettingsModel.fromJson(Map<String, dynamic> json) =>
|
|
_$NetworkSettingsModelFromJson(json);
|
|
}
|