- 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>
143 lines
3.7 KiB
Dart
143 lines
3.7 KiB
Dart
import 'package:flutter/material.dart';
|
|
|
|
import 'data_grid_action.dart';
|
|
import 'data_grid_column.dart';
|
|
|
|
/// Data loading mode for the grid.
|
|
sealed class DataGridDataMode {
|
|
const DataGridDataMode._();
|
|
|
|
/// Load all data at once.
|
|
const factory DataGridDataMode.all() = AllDataMode;
|
|
|
|
/// Paginated loading with page controls.
|
|
const factory DataGridDataMode.paginated({int pageSize}) = PaginatedDataMode;
|
|
|
|
/// Infinite scroll loading.
|
|
const factory DataGridDataMode.infinite({
|
|
int initialLoad,
|
|
int loadMoreThreshold,
|
|
}) = InfiniteDataMode;
|
|
}
|
|
|
|
/// Load all data mode.
|
|
final class AllDataMode extends DataGridDataMode {
|
|
const AllDataMode() : super._();
|
|
}
|
|
|
|
/// Paginated data mode.
|
|
final class PaginatedDataMode extends DataGridDataMode {
|
|
const PaginatedDataMode({this.pageSize = 25}) : super._();
|
|
final int pageSize;
|
|
}
|
|
|
|
/// Infinite scroll data mode.
|
|
final class InfiniteDataMode extends DataGridDataMode {
|
|
const InfiniteDataMode({
|
|
this.initialLoad = 50,
|
|
this.loadMoreThreshold = 10,
|
|
}) : super._();
|
|
|
|
final int initialLoad;
|
|
final int loadMoreThreshold;
|
|
}
|
|
|
|
/// Main configuration for a DataGrid.
|
|
class DataGridConfig<T> {
|
|
const DataGridConfig({
|
|
required this.columns,
|
|
this.actions = const [],
|
|
this.bulkActions = const [],
|
|
this.rowsSelectable = false,
|
|
this.showHeader = true,
|
|
this.showFooter = true,
|
|
this.enableSearch = false,
|
|
this.searchHint = 'Search...',
|
|
this.defaultSortColumn,
|
|
this.defaultSortDescending = false,
|
|
this.emptyStateBuilder,
|
|
this.loadingBuilder,
|
|
this.errorBuilder,
|
|
this.onRowTap,
|
|
this.cellPadding = const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
this.headerHeight = 48.0,
|
|
this.rowHeight,
|
|
this.dataMode = const DataGridDataMode.all(),
|
|
this.rowColor,
|
|
this.alternatingRowColors = false,
|
|
});
|
|
|
|
/// Column definitions.
|
|
final List<DataGridColumn<T>> columns;
|
|
|
|
/// Per-row actions (shown in actions menu).
|
|
final List<DataGridAction<T>> actions;
|
|
|
|
/// Bulk actions for selected rows.
|
|
final List<DataGridBulkAction<T>> bulkActions;
|
|
|
|
/// Whether rows can be selected.
|
|
final bool rowsSelectable;
|
|
|
|
/// Whether to show the header row.
|
|
final bool showHeader;
|
|
|
|
/// Whether to show the footer with count/pagination.
|
|
final bool showFooter;
|
|
|
|
/// Whether to show search bar.
|
|
final bool enableSearch;
|
|
|
|
/// Placeholder text for search input.
|
|
final String searchHint;
|
|
|
|
/// Index of column to sort by default.
|
|
final int? defaultSortColumn;
|
|
|
|
/// Whether default sort is descending.
|
|
final bool defaultSortDescending;
|
|
|
|
/// Custom empty state widget builder.
|
|
final Widget Function(BuildContext context)? emptyStateBuilder;
|
|
|
|
/// Custom loading widget builder.
|
|
final Widget Function(BuildContext context)? loadingBuilder;
|
|
|
|
/// Custom error widget builder.
|
|
final Widget Function(BuildContext context, Object error, VoidCallback retry)?
|
|
errorBuilder;
|
|
|
|
/// Callback when a row is tapped.
|
|
final void Function(T item)? onRowTap;
|
|
|
|
/// Padding for each cell.
|
|
final EdgeInsetsGeometry cellPadding;
|
|
|
|
/// Height of the header row.
|
|
final double headerHeight;
|
|
|
|
/// Height of each data row. If null, rows size to content.
|
|
final double? rowHeight;
|
|
|
|
/// Data loading mode.
|
|
final DataGridDataMode dataMode;
|
|
|
|
/// Custom row background color builder.
|
|
final Color? Function(BuildContext context, T item, int index)? rowColor;
|
|
|
|
/// Whether to use alternating row colors.
|
|
final bool alternatingRowColors;
|
|
|
|
/// Gets visible columns only.
|
|
List<DataGridColumn<T>> get visibleColumns =>
|
|
columns.where((c) => c.visible).toList();
|
|
|
|
/// Gets searchable column indices.
|
|
List<int> get searchableColumnIndices => columns
|
|
.asMap()
|
|
.entries
|
|
.where((e) => e.value.searchable)
|
|
.map((e) => e.key)
|
|
.toList();
|
|
}
|