feat: add URL deep-linking for DataGrids
Build and Push / release (push) Successful in 3s
Build and Push / build (push) Successful in 3m5s

- 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>
This commit is contained in:
Jeroen Schweitzer
2026-01-05 13:59:08 +01:00
co-authored by Claude Opus 4.5
parent a6c51f757a
commit c494ace5d8
19 changed files with 952 additions and 28 deletions
+26
View File
@@ -20,6 +20,7 @@ lib/
│ ├── auth/ # Authentik OIDC integration
│ ├── config/ # Environment configuration
│ ├── error/ # Error types and handling
│ ├── semantics/ # Semantic IDs for automation
│ └── theme/ # Material 3 theming
├── routing/ # go_router configuration
├── shared/ # Reusable components
@@ -544,3 +545,28 @@ import 'package:tatlock_ui/features/containers/domain/entities/container.dart';
// Bad - importing model in presentation
import '../data/models/container_model.dart'; // Don't do this
```
## Semantic Identifiers for Automation
All interactive widgets should have semantic identifiers for UI automation. This enables reliable testing with Puppeteer, Appium, and other automation tools.
### Quick Reference
```dart
import 'package:tatlock_ui/core/semantics/semantic_ids.dart';
// Wrap interactive widgets with Semantics
Semantics(
identifier: DataGridSemantics.row(item.id),
label: 'Select ${item.name}',
child: MyRowWidget(item: item),
)
```
### Key Points
1. **Central ID Registry** - All IDs defined in `lib/core/semantics/semantic_ids.dart`
2. **Naming Convention** - `{area}_{component}_{identifier}` (e.g., `dataGrid_row_abc123`)
3. **Web Enabled** - Semantics tree exposed via `SemanticsBinding.instance.ensureSemantics()` in `main.dart`
For complete documentation on semantic patterns, automation queries, and best practices, see **[TESTING.md](./TESTING.md)**.