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>
This commit is contained in:
co-authored by
Claude Opus 4.5
parent
dd6bcbdbda
commit
3b89ed8c18
@@ -0,0 +1,142 @@
|
||||
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();
|
||||
}
|
||||
Reference in New Issue
Block a user