Files
tatlock-ui/lib/shared/components/data_grid/data_grid_source.dart
T
Jeroen SchweitzerandClaude Opus 4.5 3b89ed8c18 feat: add Control Room with containers and stacks management
- Add Control Room page with stacks sidebar and containers list
- Implement container actions (start/stop/restart) with snackbars
- Add container logs viewer dialog
- Add search/filter for both stacks and containers lists
- Add external links for Portainer and Netdata (url_launcher)
- Add VS Code launch configuration for Flutter web debugging

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-31 02:01:01 +01:00

109 lines
3.0 KiB
Dart

/// Result from a data source fetch operation.
class DataGridResult<T> {
const DataGridResult({
required this.items,
required this.totalCount,
this.hasMore = false,
});
/// The fetched items.
final List<T> items;
/// Total count of items (for pagination display).
final int totalCount;
/// Whether there are more items to load (for infinite scroll).
final bool hasMore;
/// Creates an empty result.
const DataGridResult.empty()
: items = const [],
totalCount = 0,
hasMore = false;
}
/// Abstract data source for DataGrid.
///
/// Implement this to provide data to the grid. Can be backed by
/// API calls, local database, or in-memory lists.
abstract class DataGridSource<T> {
/// Fetches items from the data source.
///
/// - [searchQuery]: Optional search text to filter results.
/// - [sortField]: Field name to sort by.
/// - [sortDescending]: Whether to sort in descending order.
/// - [offset]: Number of items to skip (for pagination).
/// - [limit]: Maximum number of items to return.
Future<DataGridResult<T>> fetch({
String? searchQuery,
String? sortField,
bool sortDescending = false,
int? offset,
int? limit,
});
/// Gets the total count of items matching the query.
///
/// Override this if you need a separate count query.
/// By default, returns the totalCount from the last fetch.
Future<int> count({String? searchQuery}) async {
final result = await fetch(searchQuery: searchQuery, limit: 0);
return result.totalCount;
}
}
/// In-memory data source for local data.
class InMemoryDataSource<T> extends DataGridSource<T> {
InMemoryDataSource({
required this.items,
this.searchMatcher,
this.sortComparator,
});
/// All items in the data source.
final List<T> items;
/// Function to check if an item matches the search query.
final bool Function(T item, String query)? searchMatcher;
/// Function to compare two items for sorting.
final int Function(T a, T b, String field, bool descending)? sortComparator;
@override
Future<DataGridResult<T>> fetch({
String? searchQuery,
String? sortField,
bool sortDescending = false,
int? offset,
int? limit,
}) async {
var result = List<T>.from(items);
// Apply search filter
if (searchQuery != null && searchQuery.isNotEmpty && searchMatcher != null) {
result = result.where((item) => searchMatcher!(item, searchQuery)).toList();
}
// Apply sorting
if (sortField != null && sortComparator != null) {
result.sort((a, b) => sortComparator!(a, b, sortField, sortDescending));
}
final totalCount = result.length;
// Apply pagination
if (offset != null && offset > 0) {
result = result.skip(offset).toList();
}
if (limit != null && limit > 0) {
result = result.take(limit).toList();
}
return DataGridResult(
items: result,
totalCount: totalCount,
hasMore: offset != null && limit != null && (offset + limit) < totalCount,
);
}
}