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>
249 lines
4.1 KiB
CSS
249 lines
4.1 KiB
CSS
/*<meta />*/
|
|
|
|
/* Topic Popup */
|
|
|
|
.MCTopicPopup
|
|
{
|
|
text-decoration: none;
|
|
}
|
|
|
|
.MCTopicPopupHotSpot
|
|
{
|
|
cursor: pointer;
|
|
background-position: left center;
|
|
background-repeat: no-repeat;
|
|
}
|
|
|
|
.MCTopicPopup_Open.MCTopicPopupHotSpot
|
|
{
|
|
|
|
}
|
|
|
|
.MCTopicPopup_Closed.MCTopicPopupHotSpot
|
|
{
|
|
|
|
}
|
|
|
|
.MCTopicPopupContainer
|
|
{
|
|
background-color: #FFFFFF;
|
|
padding: 10px;
|
|
position: fixed;
|
|
top: 100px;
|
|
left: 100px;
|
|
right: 100px;
|
|
bottom: 100px;
|
|
-moz-border-radius: 5px;
|
|
border-radius: 5px;
|
|
-webkit-box-shadow: 0 4px 10px #333333;
|
|
-moz-box-shadow: 0 4px 10px #333333;
|
|
box-shadow: 0 4px 10px #333333;
|
|
filter: alpha( opacity = 0 );
|
|
opacity: 0.0;
|
|
z-index: 10001;
|
|
}
|
|
|
|
.MCTopicPopupBody
|
|
{
|
|
width: 100%;
|
|
border: none;
|
|
}
|
|
|
|
/**/
|
|
/* Thumbnail Popup */
|
|
|
|
.MCPopupThumbnailLink
|
|
{
|
|
|
|
}
|
|
|
|
.MCPopupThumbnail
|
|
{
|
|
-moz-border-radius: 5px;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
.MCPopupContainer
|
|
{
|
|
background-color: #FFFFFF;
|
|
border: solid 1px #000000;
|
|
padding: 10px;
|
|
position: absolute;
|
|
cursor: pointer;
|
|
-moz-border-radius: 5px;
|
|
border-radius: 5px;
|
|
z-index: 10001;
|
|
}
|
|
|
|
.MCPopupContainer2
|
|
{
|
|
background-color: #FFFFFF;
|
|
border: solid 1px #000000;
|
|
padding: 10px;
|
|
position: absolute;
|
|
cursor: pointer;
|
|
-moz-box-shadow: 2px 2px 8px #FFFFFF;
|
|
-webkit-box-shadow: 2px 2px 8px #FFFFFF;
|
|
box-shadow: 2px 2px 8px #FFFFFF;
|
|
}
|
|
|
|
.MCPopupFullImage
|
|
{
|
|
width: 0px;
|
|
height: 0px;
|
|
-moz-border-radius: 5px;
|
|
border-radius: 5px;
|
|
}
|
|
|
|
/**/
|
|
/* HelpControl */
|
|
|
|
.MCHelpControl span
|
|
{
|
|
background: url("Images/help-control.png") no-repeat left center;
|
|
padding-left: 18px;
|
|
}
|
|
|
|
a.MCHelpControl
|
|
{
|
|
cursor: pointer;
|
|
}
|
|
|
|
/**/
|
|
/* Dialog */
|
|
|
|
.MCDialog
|
|
{
|
|
display: none;
|
|
width: 400px;
|
|
position: fixed;
|
|
top: 20px;
|
|
left: 20px;
|
|
padding: 6px;
|
|
background-color: #000000;
|
|
border: 1px solid #000000;
|
|
-moz-border-radius: 4px;
|
|
-webkit-border-radius: 4px;
|
|
border-radius: 4px;
|
|
-moz-box-shadow: 0 3px 0 rgba(0, 0, 0, 0.1);
|
|
-webkit-box-shadow: 0 3px 0 rgba(0, 0, 0, 0.1);
|
|
box-shadow: 0 3px 0 rgba(0, 0, 0, 0.1);
|
|
filter: alpha( opacity = 0 );
|
|
opacity: 0.0;
|
|
z-index: 10001;
|
|
}
|
|
|
|
.MCDialogHeader
|
|
{
|
|
margin: 0 0 4px;
|
|
padding: 5px 0 5px 5px;
|
|
color: #FFFFFF;
|
|
font-size: 15px;
|
|
font-family: Helvetica;
|
|
}
|
|
|
|
.MCDialogClose
|
|
{
|
|
color: #FFFFFF;
|
|
font-family: tahoma, sans-serif;
|
|
font-weight: bold;
|
|
font-size: 16px;
|
|
line-height: 12px;
|
|
text-align: center;
|
|
text-decoration: none;
|
|
float: right;
|
|
width: 20px;
|
|
height: 18px;
|
|
padding-top: 2px;
|
|
margin-top: -2px;
|
|
background-color: #999999;
|
|
-moz-border-radius: 3px;
|
|
-webkit-border-radius: 3px;
|
|
border-radius: 3px;
|
|
}
|
|
|
|
.MCDialogBody
|
|
{
|
|
color: #555555;
|
|
padding: 10px;
|
|
background-color: #FFFFFF;
|
|
-moz-border-radius: 4px;
|
|
-webkit-border-radius: 4px;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
/**/
|
|
|
|
#ios-wrapper
|
|
{
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: auto;
|
|
-webkit-overflow-scrolling: touch;
|
|
}
|
|
|
|
div.MCBreadcrumbsBox_0
|
|
{
|
|
color: #696969;
|
|
font-size: 8pt;
|
|
font-family: Verdana;
|
|
border-bottom-color: #a9a9a9;
|
|
border-bottom-width: 1px;
|
|
border-bottom-style: solid;
|
|
padding-bottom: 10px;
|
|
margin-bottom: 10px;
|
|
}
|
|
|
|
.mcReset
|
|
{
|
|
margin-left: 0;
|
|
margin-right: 0;
|
|
margin-top: 0;
|
|
margin-bottom: 0;
|
|
padding-left: 0;
|
|
padding-right: 0;
|
|
padding-top: 0;
|
|
padding-bottom: 0;
|
|
border-left-color: transparent;
|
|
border-left-style: none;
|
|
border-left-width: 0;
|
|
border-right-color: transparent;
|
|
border-right-style: none;
|
|
border-right-width: 0;
|
|
border-top-color: transparent;
|
|
border-top-style: none;
|
|
border-top-width: 0;
|
|
border-bottom-color: transparent;
|
|
border-bottom-style: none;
|
|
border-bottom-width: 0;
|
|
background-color: transparent;
|
|
background-image: none;
|
|
float: inherit;
|
|
font-size: inherit;
|
|
font-family: inherit;
|
|
font-style: inherit;
|
|
font-variant: inherit;
|
|
text-transform: inherit;
|
|
color: inherit;
|
|
letter-spacing: inherit;
|
|
word-spacing: inherit;
|
|
text-decoration: inherit;
|
|
text-align: inherit;
|
|
}
|
|
|
|
.MCWebHelpFramesetLink a
|
|
{
|
|
|
|
}
|
|
|
|
.MCWebHelpFramesetLink.MCWebHelpFramesetLinkTop a
|
|
{
|
|
|
|
}
|
|
|
|
.MCWebHelpFramesetLink.MCWebHelpFramesetLinkBottom a
|
|
{
|
|
|
|
}
|
|
|