- Add PageUrlState utility for URL ↔ state serialization - Add column `id` field for unique column identification in URLs - Update idSelector to return String for URL compatibility - All DataGrid pages now support URL params: search, sort, order, id - Browser URL updates via replaceState (no GoRouter rebuilds) - Add FilterPanelSemantics for filter panel semantic IDs - Add TESTING.md documentation 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
82 lines
2.6 KiB
Dart
82 lines
2.6 KiB
Dart
import 'package:flutter/material.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:tatlock_ui/features/control_room/presentation/pages/control_room_page.dart';
|
|
import 'package:tatlock_ui/routing/app_router.dart';
|
|
import 'package:tatlock_ui/shared/layouts/widgets/nav_panel.dart';
|
|
|
|
/// Route paths for Control Room.
|
|
abstract class ControlRoomRoutes {
|
|
static const base = '/control-room';
|
|
// Stack
|
|
static const containers = '/control-room/containers';
|
|
static const proxyHosts = '/control-room/proxy-hosts';
|
|
// Data Management
|
|
static const postgres = '/control-room/postgres';
|
|
static const redis = '/control-room/redis';
|
|
static const qdrant = '/control-room/qdrant';
|
|
static const neo4j = '/control-room/neo4j';
|
|
}
|
|
|
|
/// Control Room navigation items with section grouping.
|
|
enum ControlRoomNav {
|
|
// Stack Management section - Docker containers and reverse proxy
|
|
containers('containers', 'Containers', Icons.dns, 'Stack Management'),
|
|
proxyHosts('proxy-hosts', 'Proxy Hosts', Icons.public, 'Stack Management'),
|
|
// Data Management section - Database browsers
|
|
postgres('postgres', 'PostgreSQL', Icons.table_chart, 'Data Management'),
|
|
redis('redis', 'Redis', Icons.memory, 'Data Management'),
|
|
qdrant('qdrant', 'Qdrant', Icons.scatter_plot, 'Data Management'),
|
|
neo4j('neo4j', 'Neo4j', Icons.hub, 'Data Management');
|
|
|
|
const ControlRoomNav(this.id, this.label, this.icon, this.section);
|
|
|
|
final String id;
|
|
final String label;
|
|
final IconData icon;
|
|
final String section;
|
|
|
|
NavItem toNavItem() => NavItem(
|
|
id: id,
|
|
label: label,
|
|
icon: icon,
|
|
section: section,
|
|
);
|
|
|
|
/// Get route path for this nav item.
|
|
String get path => '/control-room/$id';
|
|
}
|
|
|
|
/// Get route path for a nav item.
|
|
String pathForNav(ControlRoomNav nav) => nav.path;
|
|
|
|
/// Control Room routes for go_router.
|
|
List<RouteBase> controlRoomRoutes() {
|
|
return [
|
|
// Redirect /control-room to /control-room/containers
|
|
GoRoute(
|
|
path: ControlRoomRoutes.base,
|
|
name: 'controlRoom',
|
|
redirect: (context, state) => ControlRoomRoutes.containers,
|
|
),
|
|
// Generate routes for all nav items
|
|
for (final nav in ControlRoomNav.values)
|
|
GoRoute(
|
|
path: nav.path,
|
|
name: 'controlRoom${_capitalize(nav.id.replaceAll('-', '_'))}',
|
|
pageBuilder: (context, state) => noTransitionPage(
|
|
context,
|
|
state,
|
|
ControlRoomPage(nav: nav, routerState: state),
|
|
),
|
|
),
|
|
];
|
|
}
|
|
|
|
String _capitalize(String s) {
|
|
if (s.isEmpty) return s;
|
|
return s
|
|
.split('_')
|
|
.map((part) => part[0].toUpperCase() + part.substring(1))
|
|
.join('');
|
|
}
|