This MVP release provides a complete full-stack solution for managing action mappings in Geutebruck's GeViScope and GeViSoft video surveillance systems. ## Features ### Flutter Web Application (Port 8081) - Modern, responsive UI for managing action mappings - Action picker dialog with full parameter configuration - Support for both GSC (GeViScope) and G-Core server actions - Consistent UI for input and output actions with edit/delete capabilities - Real-time action mapping creation, editing, and deletion - Server categorization (GSC: prefix for GeViScope, G-Core: prefix for G-Core servers) ### FastAPI REST Backend (Port 8000) - RESTful API for action mapping CRUD operations - Action template service with comprehensive action catalog (247 actions) - Server management (G-Core and GeViScope servers) - Configuration tree reading and writing - JWT authentication with role-based access control - PostgreSQL database integration ### C# SDK Bridge (gRPC, Port 50051) - Native integration with GeViSoft SDK (GeViProcAPINET_4_0.dll) - Action mapping creation with correct binary format - Support for GSC and G-Core action types - Proper Camera parameter inclusion in action strings (fixes CrossSwitch bug) - Action ID lookup table with server-specific action IDs - Configuration reading/writing via SetupClient ## Bug Fixes - **CrossSwitch Bug**: GSC and G-Core actions now correctly display camera/PTZ head parameters in GeViSet - Action strings now include Camera parameter: `@ PanLeft (Comment: "", Camera: 101028)` - Proper filter flags and VideoInput=0 for action mappings - Correct action ID assignment (4198 for GSC, 9294 for G-Core PanLeft) ## Technical Stack - **Frontend**: Flutter Web, Dart, Dio HTTP client - **Backend**: Python FastAPI, PostgreSQL, Redis - **SDK Bridge**: C# .NET 8.0, gRPC, GeViSoft SDK - **Authentication**: JWT tokens - **Configuration**: GeViSoft .set files (binary format) ## Credentials - GeViSoft/GeViScope: username=sysadmin, password=masterkey - Default admin: username=admin, password=admin123 ## Deployment All services run on localhost: - Flutter Web: http://localhost:8081 - FastAPI: http://localhost:8000 - SDK Bridge gRPC: localhost:50051 - GeViServer: localhost (default port) Generated with Claude Code (https://claude.com/claude-code) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
310 lines
9.6 KiB
Markdown
310 lines
9.6 KiB
Markdown
# ✅ Integration Complete - ActionPickerDialog in Action Mapping Form
|
|
|
|
## Summary
|
|
|
|
Successfully integrated the ActionPickerDialog into the action mapping form screen. The form now uses the native GeViSet-style action picker instead of dropdowns.
|
|
|
|
## Changes Made
|
|
|
|
### 1. Updated Imports
|
|
Added new imports for action templates and the ActionPickerDialog:
|
|
```dart
|
|
import '../../../data/models/action_template.dart';
|
|
import '../../../data/services/action_template_service.dart';
|
|
import '../../../core/constants/api_constants.dart';
|
|
import '../../blocs/auth/auth_bloc.dart';
|
|
import '../../blocs/auth/auth_state.dart';
|
|
import '../../widgets/action_picker_dialog.dart';
|
|
```
|
|
|
|
### 2. Refactored State Management
|
|
**Before:**
|
|
- Used `List<TextEditingController>` for output actions
|
|
- Used `Map<int, Map<String, dynamic>>` for parameters
|
|
- Manual parameter editing dialogs
|
|
|
|
**After:**
|
|
- Uses `List<ActionOutput>` directly
|
|
- Loads categories and templates on init
|
|
- ActionPickerDialog handles all action selection and parameter editing
|
|
|
|
**New State Variables:**
|
|
```dart
|
|
bool _isLoadingTemplates = true;
|
|
Map<String, List<String>>? _categories;
|
|
Map<String, ActionTemplate>? _templates;
|
|
List<ActionOutput> _outputActions = [];
|
|
```
|
|
|
|
### 3. Added Template Loading
|
|
```dart
|
|
Future<void> _loadActionTemplates() async {
|
|
try {
|
|
// Get auth token from AuthBloc
|
|
final authState = context.read<AuthBloc>().state;
|
|
String? token;
|
|
if (authState is Authenticated) {
|
|
token = authState.token;
|
|
}
|
|
|
|
final service = ActionTemplateService(
|
|
baseUrl: ApiConstants.baseUrl,
|
|
authToken: token,
|
|
);
|
|
|
|
final categoriesResponse = await service.getActionCategories();
|
|
final templates = await service.getActionTemplates();
|
|
|
|
setState(() {
|
|
_categories = categoriesResponse.categories;
|
|
_templates = templates;
|
|
_isLoadingTemplates = false;
|
|
});
|
|
} catch (e) {
|
|
// Handle error...
|
|
}
|
|
}
|
|
```
|
|
|
|
### 4. New Action Management Methods
|
|
|
|
**Add Output Action** - Opens ActionPickerDialog:
|
|
```dart
|
|
Future<void> _addOutputAction() async {
|
|
if (_categories == null || _templates == null) return;
|
|
|
|
final result = await showDialog<ActionOutput>(
|
|
context: context,
|
|
builder: (context) => ActionPickerDialog(
|
|
categories: _categories!,
|
|
templates: _templates!,
|
|
),
|
|
);
|
|
|
|
if (result != null) {
|
|
setState(() {
|
|
_outputActions.add(result);
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
**Edit Output Action** - Opens ActionPickerDialog with existing action:
|
|
```dart
|
|
Future<void> _editOutputAction(int index) async {
|
|
final result = await showDialog<ActionOutput>(
|
|
context: context,
|
|
builder: (context) => ActionPickerDialog(
|
|
categories: _categories!,
|
|
templates: _templates!,
|
|
existingAction: _outputActions[index],
|
|
),
|
|
);
|
|
|
|
if (result != null) {
|
|
setState(() {
|
|
_outputActions[index] = result;
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
**Remove Output Action:**
|
|
```dart
|
|
void _removeOutputAction(int index) {
|
|
setState(() {
|
|
_outputActions.removeAt(index);
|
|
});
|
|
}
|
|
```
|
|
|
|
**Reorder Output Actions** (matching native app):
|
|
```dart
|
|
void _moveOutputActionUp(int index) {
|
|
if (index > 0) {
|
|
setState(() {
|
|
final action = _outputActions.removeAt(index);
|
|
_outputActions.insert(index - 1, action);
|
|
});
|
|
}
|
|
}
|
|
|
|
void _moveOutputActionDown(int index) {
|
|
if (index < _outputActions.length - 1) {
|
|
setState(() {
|
|
final action = _outputActions.removeAt(index);
|
|
_outputActions.insert(index + 1, action);
|
|
});
|
|
}
|
|
}
|
|
```
|
|
|
|
### 5. Simplified Submit Form
|
|
```dart
|
|
void _submitForm() {
|
|
if (_formKey.currentState!.validate()) {
|
|
setState(() {
|
|
_isSaving = true;
|
|
});
|
|
|
|
// Validate that at least one output action is provided
|
|
if (_outputActions.isEmpty) {
|
|
// Show error...
|
|
return;
|
|
}
|
|
|
|
final mapping = ActionMapping(
|
|
// ...
|
|
outputActions: _outputActions, // ← Direct use, no transformation needed!
|
|
// ...
|
|
);
|
|
|
|
// Submit...
|
|
}
|
|
}
|
|
```
|
|
|
|
### 6. Updated UI - Output Actions Section
|
|
|
|
**New Features:**
|
|
- ✅ Loading indicator while templates are loading
|
|
- ✅ Empty state message when no actions
|
|
- ✅ Cards showing action name and parameters
|
|
- ✅ Edit button opens ActionPickerDialog
|
|
- ✅ Up/Down buttons for reordering (like native app!)
|
|
- ✅ Remove button to delete actions
|
|
- ✅ Clean parameter display (read-only, edited via dialog)
|
|
|
|
**UI Layout:**
|
|
```
|
|
┌─────────────────────────────────────────────────────┐
|
|
│ Output Actions * [Add Output Action] │
|
|
├─────────────────────────────────────────────────────┤
|
|
│ ┌─────────────────────────────────────────────────┐ │
|
|
│ │ Output 1 ↑ ↓ ✎ ✗ │ │
|
|
│ │ PanStop │ │
|
|
│ │ ─────────────────────────────────────────────── │ │
|
|
│ │ Parameters (2) │ │
|
|
│ │ GCoreServer: gscope-cdu-3 │ │
|
|
│ │ PTZ head: 101027 │ │
|
|
│ └─────────────────────────────────────────────────┘ │
|
|
│ │
|
|
│ ┌─────────────────────────────────────────────────┐ │
|
|
│ │ Output 2 ↑ ↓ ✎ ✗ │ │
|
|
│ │ SystemWarning │ │
|
|
│ │ ─────────────────────────────────────────────── │ │
|
|
│ │ Parameters (2) │ │
|
|
│ │ Caption: Warning message │ │
|
|
│ │ Source: 5 │ │
|
|
│ └─────────────────────────────────────────────────┘ │
|
|
└─────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
## Files Modified
|
|
|
|
```
|
|
geutebruck_app/
|
|
└── lib/
|
|
└── presentation/
|
|
└── screens/
|
|
└── action_mappings/
|
|
└── action_mapping_form_screen.dart ✅ UPDATED
|
|
```
|
|
|
|
## Files Created (Previously)
|
|
|
|
```
|
|
geutebruck_app/
|
|
└── lib/
|
|
├── data/
|
|
│ ├── models/
|
|
│ │ └── action_template.dart ✅ NEW
|
|
│ └── services/
|
|
│ └── action_template_service.dart ✅ NEW
|
|
└── presentation/
|
|
└── widgets/
|
|
└── action_picker_dialog.dart ✅ NEW
|
|
```
|
|
|
|
## User Experience Improvements
|
|
|
|
### Before
|
|
1. Select action from dropdown (29 hardcoded options)
|
|
2. Click "Parameters" to expand
|
|
3. Click "+" to add each parameter manually
|
|
4. Type parameter name and value
|
|
5. Repeat for each parameter
|
|
6. No way to reorder actions
|
|
|
|
### After
|
|
1. Click "Add Output Action" button
|
|
2. ActionPickerDialog opens with:
|
|
- Category dropdown (10 categories)
|
|
- Filtered action list (45 actions total)
|
|
- Dynamic parameter fields based on selected action
|
|
- Checkboxes to enable/disable optional parameters
|
|
- Action description shown at bottom
|
|
- Caption and delay execution fields
|
|
3. Parameters are pre-filled and validated
|
|
4. Actions can be reordered with up/down buttons
|
|
5. Actions can be edited by clicking edit button
|
|
|
|
## Testing Checklist
|
|
|
|
- [ ] Open action mapping form
|
|
- [ ] Wait for templates to load
|
|
- [ ] Click "Add Output Action"
|
|
- [ ] Select a category (e.g., "Camera Control")
|
|
- [ ] Select an action (e.g., "PanStop")
|
|
- [ ] Enable parameters using checkboxes
|
|
- [ ] Enter parameter values
|
|
- [ ] Enter caption
|
|
- [ ] Click "Ok"
|
|
- [ ] Verify action appears in list
|
|
- [ ] Click edit button
|
|
- [ ] Verify ActionPickerDialog opens with existing values
|
|
- [ ] Modify action
|
|
- [ ] Click "Ok"
|
|
- [ ] Verify changes are reflected
|
|
- [ ] Add multiple actions
|
|
- [ ] Test reordering with up/down buttons
|
|
- [ ] Remove an action
|
|
- [ ] Submit form
|
|
- [ ] Verify action mapping is created/updated correctly
|
|
|
|
## Next Steps (Optional)
|
|
|
|
### Phase 3: DataTable Main List View
|
|
Replace the card-based list with a DataTable showing:
|
|
- Input action column
|
|
- Output action 1, 2, 3 columns
|
|
- Better information density
|
|
- Matches native app exactly
|
|
|
|
### Future Enhancements
|
|
1. **Browse buttons for parameters**
|
|
- GCoreServer → Browse from server list
|
|
- PTZ head → Browse from available cameras
|
|
- VideoInput/Output → Browse from channels
|
|
|
|
2. **Parameter validation**
|
|
- Number fields → Enforce numeric input
|
|
- Range validation where applicable
|
|
|
|
3. **Search in action list**
|
|
- Quick filter for finding actions in ActionPickerDialog
|
|
|
|
4. **Input action picker**
|
|
- Use ActionPickerDialog for input actions too
|
|
|
|
## Status
|
|
|
|
**✅ INTEGRATION COMPLETE**
|
|
|
|
The ActionPickerDialog is fully integrated into the action mapping form. Users can now add, edit, remove, and reorder output actions using the native GeViSet-style UI with category-based navigation and dynamic parameter fields.
|
|
|
|
**Backend:** ✅ Complete (45 actions, 10 categories)
|
|
**Flutter UI:** ✅ Complete (ActionPickerDialog created)
|
|
**Integration:** ✅ Complete (Form updated)
|
|
**Ready for:** Testing and deployment
|