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>
9.6 KiB
✅ 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:
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:
bool _isLoadingTemplates = true;
Map<String, List<String>>? _categories;
Map<String, ActionTemplate>? _templates;
List<ActionOutput> _outputActions = [];
3. Added Template Loading
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:
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:
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:
void _removeOutputAction(int index) {
setState(() {
_outputActions.removeAt(index);
});
}
Reorder Output Actions (matching native app):
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
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
- Select action from dropdown (29 hardcoded options)
- Click "Parameters" to expand
- Click "+" to add each parameter manually
- Type parameter name and value
- Repeat for each parameter
- No way to reorder actions
After
- Click "Add Output Action" button
- 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
- Parameters are pre-filled and validated
- Actions can be reordered with up/down buttons
- 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
-
Browse buttons for parameters
- GCoreServer → Browse from server list
- PTZ head → Browse from available cameras
- VideoInput/Output → Browse from channels
-
Parameter validation
- Number fields → Enforce numeric input
- Range validation where applicable
-
Search in action list
- Quick filter for finding actions in ActionPickerDialog
-
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