Build and Push / build (release) Successful in 3m6s
Features: - Health check endpoint for Portainer monitoring - Local search filtering in DataGrid - Container status badges reflect health (green/orange/blue) Improvements: - Standardized 56px header heights across panels - Container grid parses Docker API format correctly - Search bar styling improvements - Status badges have consistent width Fixes: - Quick links persistence (link type, form refresh) - Iframe switching closes existing content first - ContainerState type conflict resolved Branding: - Updated favicon and icons with Tatlock bucket logo 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
105 lines
2.9 KiB
Dart
105 lines
2.9 KiB
Dart
import 'package:dio/dio.dart';
|
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
|
import 'package:tatlock_ui/core/api/api_client.dart';
|
|
import 'package:tatlock_ui/features/front_hall/data/models/quick_link_model.dart';
|
|
import 'package:tatlock_ui/features/front_hall/domain/entities/quick_link.dart';
|
|
|
|
part 'quick_links_datasource.g.dart';
|
|
|
|
/// Data source for quick link operations.
|
|
///
|
|
/// Provides CRUD operations for Front Hall quick links via Core API
|
|
/// dashboard/quick-links endpoint.
|
|
class QuickLinksDatasource {
|
|
QuickLinksDatasource(this._dio);
|
|
|
|
final Dio _dio;
|
|
|
|
static const _basePath = '/dashboard/quick-links';
|
|
|
|
/// Gets all quick links.
|
|
///
|
|
/// API returns: {"links": [...], "total": N}
|
|
Future<List<QuickLink>> getQuickLinks() async {
|
|
final response = await _dio.get<Map<String, dynamic>>(_basePath);
|
|
final data = response.data;
|
|
|
|
if (data == null) {
|
|
return [];
|
|
}
|
|
|
|
final links = data['links'] as List<dynamic>? ?? [];
|
|
return links
|
|
.map((json) => QuickLinkModel.fromJson(json as Map<String, dynamic>))
|
|
.map((model) => model.toEntity())
|
|
.toList();
|
|
}
|
|
|
|
/// Gets a single quick link by ID.
|
|
Future<QuickLink> getQuickLink(int id) async {
|
|
final response = await _dio.get<Map<String, dynamic>>('$_basePath/$id');
|
|
final data = response.data;
|
|
|
|
if (data == null) {
|
|
throw Exception('Quick link not found: $id');
|
|
}
|
|
|
|
return QuickLinkModel.fromJson(data).toEntity();
|
|
}
|
|
|
|
/// Creates a new quick link.
|
|
Future<QuickLink> createQuickLink(QuickLink link) async {
|
|
final model = QuickLinkModel.fromEntity(link);
|
|
final response = await _dio.post<Map<String, dynamic>>(
|
|
_basePath,
|
|
data: model.toJson(),
|
|
);
|
|
final data = response.data;
|
|
|
|
if (data == null) {
|
|
throw Exception('Failed to create quick link');
|
|
}
|
|
|
|
return QuickLinkModel.fromJson(data).toEntity();
|
|
}
|
|
|
|
/// Updates an existing quick link.
|
|
Future<QuickLink> updateQuickLink(QuickLink link) async {
|
|
final model = QuickLinkModel.fromEntity(link);
|
|
final id = int.tryParse(link.id) ?? 0;
|
|
final response = await _dio.put<Map<String, dynamic>>(
|
|
'$_basePath/$id',
|
|
data: model.toJson(),
|
|
);
|
|
final data = response.data;
|
|
|
|
if (data == null) {
|
|
throw Exception('Failed to update quick link');
|
|
}
|
|
|
|
return QuickLinkModel.fromJson(data).toEntity();
|
|
}
|
|
|
|
/// Deletes a quick link.
|
|
Future<void> deleteQuickLink(int id) async {
|
|
await _dio.delete<void>('$_basePath/$id');
|
|
}
|
|
|
|
/// Reorders quick links by updating positions.
|
|
///
|
|
/// API expects: {"link_ids": [1, 2, 3]}
|
|
Future<void> reorderQuickLinks(List<int> orderedIds) async {
|
|
await _dio.post<void>(
|
|
'$_basePath/reorder',
|
|
data: {'link_ids': orderedIds},
|
|
);
|
|
}
|
|
}
|
|
|
|
/// Provides the quick links datasource.
|
|
@riverpod
|
|
QuickLinksDatasource quickLinksDatasource(Ref ref) {
|
|
final dio = ref.watch(coreApiClientProvider);
|
|
return QuickLinksDatasource(dio);
|
|
}
|