feat: Enhance dataset variable configuration with manual and symbol-based options
- Updated the dataset variables UI schema to support two configuration types: manual and symbol-based. - Implemented a new DatasetVariableSymbolWidget for symbol selection with auto-fill capabilities. - Modified the DatasetManager to handle the new schema structure and UI layout. - Integrated the new widget into the DatasetVariablesRJSF component for improved user experience. - Updated the SymbolSelectorWidget to support callbacks for symbol selection. - Refactored the FormTable component to utilize the new allWidgets import for better widget management. - Added error handling and loading states for improved user feedback during data fetching.
This commit is contained in:
parent
e3b1b48556
commit
31cb5cc515
|
@ -1,257 +1,5 @@
|
|||
{
|
||||
"events": [
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.768669",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: DB 2121",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.776678",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: UDT 82",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.785672",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: UDT 82",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.794673",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: UDT 1",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.803233",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: UDT 1",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.811243",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: VAT 22",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.819268",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: VAT 22",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.826782",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: DB 959",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.834787",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: DB 959",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.841796",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 1804",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.848796",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 1804",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.857991",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: DB 972",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.864990",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: DB 972",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.872997",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: DB 930",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.881999",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: DB 930",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.890523",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FB 1800",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.898534",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FB 1800",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.907703",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: DB 971",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.914685",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: DB 971",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.922698",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: DB 970",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.929693",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: DB 970",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.937844",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2000",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.944860",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 2000",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.954008",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2036",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.962012",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 2036",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.971003",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2013",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.978013",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 2013",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.987006",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2001",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:25.994321",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 2001",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.002877",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2003",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.009876",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 2003",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.017866",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2037",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.025863",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 2037",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.033864",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2033",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.041875",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Could not parse PLC address: FC 2033",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.049093",
|
||||
"level": "warning",
|
||||
"event_type": "symbol_parse_warning",
|
||||
"message": "Unrecognized address format: FC 2012",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T16:52:26.063705",
|
||||
"level": "warning",
|
||||
|
@ -6999,8 +6747,354 @@
|
|||
"event_type": "symbols_loaded",
|
||||
"message": "Loaded 2077 symbols from C:/Users/migue/Downloads/symSAE452.asc",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:00:00.267126",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:06:22.110502",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:06:22.161221",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:06:22.174891",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:06:22.183906",
|
||||
"level": "info",
|
||||
"event_type": "udp_streaming_started",
|
||||
"message": "UDP streaming to PlotJuggler started",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:06:22.192523",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:14.827169",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:14.876601",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:14.884605",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:14.892976",
|
||||
"level": "info",
|
||||
"event_type": "udp_streaming_started",
|
||||
"message": "UDP streaming to PlotJuggler started",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:14.908569",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:32.756676",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:32.805384",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:32.814382",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:32.823381",
|
||||
"level": "info",
|
||||
"event_type": "udp_streaming_started",
|
||||
"message": "UDP streaming to PlotJuggler started",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:10:32.837621",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:14:00.334194",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:14:00.401621",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:14:00.410620",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:14:00.421480",
|
||||
"level": "info",
|
||||
"event_type": "udp_streaming_started",
|
||||
"message": "UDP streaming to PlotJuggler started",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:14:00.435620",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:25:34.393400",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:25:34.443828",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:25:34.451828",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:25:34.464832",
|
||||
"level": "info",
|
||||
"event_type": "udp_streaming_started",
|
||||
"message": "UDP streaming to PlotJuggler started",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:25:34.477358",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:31:05.141755",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:31:05.207794",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:31:05.219935",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:31:05.234342",
|
||||
"level": "info",
|
||||
"event_type": "udp_streaming_started",
|
||||
"message": "UDP streaming to PlotJuggler started",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:31:05.240939",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:32:09.019907",
|
||||
"level": "info",
|
||||
"event_type": "application_started",
|
||||
"message": "Application initialization completed successfully",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:32:09.087100",
|
||||
"level": "info",
|
||||
"event_type": "dataset_activated",
|
||||
"message": "Dataset activated: DAR",
|
||||
"details": {
|
||||
"dataset_id": "DAR",
|
||||
"variables_count": 2,
|
||||
"streaming_count": 2,
|
||||
"prefix": "gateway_phoenix"
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:32:09.107982",
|
||||
"level": "info",
|
||||
"event_type": "csv_recording_started",
|
||||
"message": "CSV recording started: 1 datasets activated",
|
||||
"details": {
|
||||
"activated_datasets": 1,
|
||||
"total_datasets": 3
|
||||
}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:32:09.122999",
|
||||
"level": "error",
|
||||
"event_type": "csv_cleanup_failed",
|
||||
"message": "CSV cleanup failed: 'max_hours'",
|
||||
"details": {}
|
||||
},
|
||||
{
|
||||
"timestamp": "2025-08-14T17:32:09.144483",
|
||||
"level": "info",
|
||||
"event_type": "udp_streaming_started",
|
||||
"message": "UDP streaming to PlotJuggler started",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"last_updated": "2025-08-14T16:52:36.475776",
|
||||
"last_updated": "2025-08-14T17:32:09.144483",
|
||||
"total_entries": 1000
|
||||
}ted",
|
||||
"details": {
|
||||
"udp_host": "127.0.0.1",
|
||||
"udp_port": 9870,
|
||||
"datasets_available": 3
|
||||
}
|
||||
}
|
||||
],
|
||||
"last_updated": "2025-08-14T17:32:09.123999",
|
||||
"total_entries": 1000
|
||||
}
|
|
@ -4,6 +4,7 @@
|
|||
"dataset_id": "DAR",
|
||||
"variables": [
|
||||
{
|
||||
"configType": "manual",
|
||||
"area": "db",
|
||||
"db": 1011,
|
||||
"name": "UR29_Brix",
|
||||
|
@ -12,6 +13,7 @@
|
|||
"type": "real"
|
||||
},
|
||||
{
|
||||
"configType": "manual",
|
||||
"area": "db",
|
||||
"db": 1011,
|
||||
"name": "UR29_ma",
|
||||
|
@ -23,7 +25,15 @@
|
|||
},
|
||||
{
|
||||
"dataset_id": "Fast",
|
||||
"variables": []
|
||||
"variables": [
|
||||
{
|
||||
"configType": "symbol",
|
||||
"area": "db",
|
||||
"type": "real",
|
||||
"streaming": false,
|
||||
"symbol": "FTP302_Brix"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
|
@ -25,167 +25,215 @@
|
|||
"removable": true
|
||||
},
|
||||
"items": {
|
||||
"ui:order": [
|
||||
"name",
|
||||
"area",
|
||||
"db",
|
||||
"offset",
|
||||
"bit",
|
||||
"type",
|
||||
"streaming"
|
||||
],
|
||||
"ui:layout": [
|
||||
[
|
||||
{
|
||||
"name": "name",
|
||||
"width": 4
|
||||
"oneOf": [
|
||||
{
|
||||
"ui:title": "Manual Configuration",
|
||||
"ui:description": "Configure PLC variable parameters manually",
|
||||
"ui:order": [
|
||||
"name",
|
||||
"area",
|
||||
"db",
|
||||
"offset",
|
||||
"bit",
|
||||
"type",
|
||||
"streaming"
|
||||
],
|
||||
"ui:layout": [
|
||||
[
|
||||
{
|
||||
"name": "name",
|
||||
"width": 4
|
||||
},
|
||||
{
|
||||
"name": "area",
|
||||
"width": 2
|
||||
},
|
||||
{
|
||||
"name": "db",
|
||||
"width": 2
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"width": 2
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"width": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "bit",
|
||||
"width": 3
|
||||
},
|
||||
{
|
||||
"name": "streaming",
|
||||
"width": 9
|
||||
}
|
||||
]
|
||||
],
|
||||
"name": {
|
||||
"ui:widget": "text",
|
||||
"ui:placeholder": "Variable name",
|
||||
"ui:help": "📝 Human-readable name for this variable"
|
||||
},
|
||||
{
|
||||
"name": "area",
|
||||
"width": 2
|
||||
},
|
||||
{
|
||||
"name": "db",
|
||||
"width": 2
|
||||
},
|
||||
{
|
||||
"name": "offset",
|
||||
"width": 2
|
||||
},
|
||||
{
|
||||
"name": "type",
|
||||
"width": 2
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "bit",
|
||||
"width": 3
|
||||
},
|
||||
{
|
||||
"name": "streaming",
|
||||
"width": 9
|
||||
}
|
||||
]
|
||||
],
|
||||
"name": {
|
||||
"ui:widget": "text",
|
||||
"ui:placeholder": "Variable name",
|
||||
"ui:help": "📝 Human-readable name for this variable"
|
||||
},
|
||||
"area": {
|
||||
"ui:widget": "select",
|
||||
"ui:help": "PLC memory area (DB=DataBlock, MW=MemoryWord, etc.)",
|
||||
"ui:options": {
|
||||
"enumOptions": [
|
||||
{
|
||||
"value": "db",
|
||||
"label": "🗃️ DB (Data Block)"
|
||||
},
|
||||
{
|
||||
"value": "mw",
|
||||
"label": "📊 MW (Memory Word)"
|
||||
},
|
||||
{
|
||||
"value": "m",
|
||||
"label": "💾 M (Memory)"
|
||||
},
|
||||
{
|
||||
"value": "pew",
|
||||
"label": "📥 PEW (Process Input Word)"
|
||||
},
|
||||
{
|
||||
"value": "pe",
|
||||
"label": "📥 PE (Process Input)"
|
||||
},
|
||||
{
|
||||
"value": "paw",
|
||||
"label": "📤 PAW (Process Output Word)"
|
||||
},
|
||||
{
|
||||
"value": "pa",
|
||||
"label": "📤 PA (Process Output)"
|
||||
},
|
||||
{
|
||||
"value": "e",
|
||||
"label": "🔌 E (Input)"
|
||||
},
|
||||
{
|
||||
"value": "a",
|
||||
"label": "🔌 A (Output)"
|
||||
},
|
||||
{
|
||||
"value": "mb",
|
||||
"label": "💾 MB (Memory Byte)"
|
||||
"area": {
|
||||
"ui:widget": "select",
|
||||
"ui:help": "PLC memory area (DB=DataBlock, MW=MemoryWord, etc.)",
|
||||
"ui:options": {
|
||||
"enumOptions": [
|
||||
{
|
||||
"value": "db",
|
||||
"label": "🗃️ DB (Data Block)"
|
||||
},
|
||||
{
|
||||
"value": "mw",
|
||||
"label": "📊 MW (Memory Word)"
|
||||
},
|
||||
{
|
||||
"value": "m",
|
||||
"label": "💾 M (Memory)"
|
||||
},
|
||||
{
|
||||
"value": "pew",
|
||||
"label": "📥 PEW (Process Input Word)"
|
||||
},
|
||||
{
|
||||
"value": "pe",
|
||||
"label": "📥 PE (Process Input)"
|
||||
},
|
||||
{
|
||||
"value": "paw",
|
||||
"label": "📤 PAW (Process Output Word)"
|
||||
},
|
||||
{
|
||||
"value": "pa",
|
||||
"label": "📤 PA (Process Output)"
|
||||
},
|
||||
{
|
||||
"value": "e",
|
||||
"label": "🔌 E (Input)"
|
||||
},
|
||||
{
|
||||
"value": "a",
|
||||
"label": "🔌 A (Output)"
|
||||
},
|
||||
{
|
||||
"value": "mb",
|
||||
"label": "💾 MB (Memory Byte)"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"db": {
|
||||
"ui:widget": "updown",
|
||||
"ui:help": "Data Block number (required for DB area)",
|
||||
"ui:placeholder": "1011"
|
||||
},
|
||||
"offset": {
|
||||
"ui:widget": "updown",
|
||||
"ui:help": "Byte offset within the memory area"
|
||||
},
|
||||
"bit": {
|
||||
"ui:widget": "updown",
|
||||
"ui:help": "Bit position (0-7) for bit-addressable areas"
|
||||
},
|
||||
"type": {
|
||||
"ui:widget": "select",
|
||||
"ui:help": "PLC data type",
|
||||
"ui:options": {
|
||||
"enumOptions": [
|
||||
{
|
||||
"value": "real",
|
||||
"label": "🔢 REAL (32-bit float)"
|
||||
},
|
||||
{
|
||||
"value": "int",
|
||||
"label": "🔢 INT (16-bit signed)"
|
||||
},
|
||||
{
|
||||
"value": "bool",
|
||||
"label": "✅ BOOL (1-bit boolean)"
|
||||
},
|
||||
{
|
||||
"value": "dint",
|
||||
"label": "🔢 DINT (32-bit signed)"
|
||||
},
|
||||
{
|
||||
"value": "word",
|
||||
"label": "🔢 WORD (16-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "byte",
|
||||
"label": "🔢 BYTE (8-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "uint",
|
||||
"label": "🔢 UINT (16-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "udint",
|
||||
"label": "🔢 UDINT (32-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "sint",
|
||||
"label": "🔢 SINT (8-bit signed)"
|
||||
},
|
||||
{
|
||||
"value": "usint",
|
||||
"label": "🔢 USINT (8-bit unsigned)"
|
||||
},
|
||||
"db": {
|
||||
"ui:widget": "updown",
|
||||
"ui:help": "Data Block number (required for DB area)",
|
||||
"ui:placeholder": "1011"
|
||||
},
|
||||
"offset": {
|
||||
"ui:widget": "updown",
|
||||
"ui:help": "Byte offset within the memory area"
|
||||
},
|
||||
"bit": {
|
||||
"ui:widget": "updown",
|
||||
"ui:help": "Bit position (0-7) for bit-addressable areas"
|
||||
},
|
||||
"type": {
|
||||
"ui:widget": "select",
|
||||
"ui:help": "PLC data type",
|
||||
"ui:options": {
|
||||
"enumOptions": [
|
||||
{
|
||||
"value": "real",
|
||||
"label": "🔢 REAL (32-bit float)"
|
||||
},
|
||||
{
|
||||
"value": "int",
|
||||
"label": "🔢 INT (16-bit signed)"
|
||||
},
|
||||
{
|
||||
"value": "bool",
|
||||
"label": "✅ BOOL (1-bit boolean)"
|
||||
},
|
||||
{
|
||||
"value": "dint",
|
||||
"label": "🔢 DINT (32-bit signed)"
|
||||
},
|
||||
{
|
||||
"value": "word",
|
||||
"label": "🔢 WORD (16-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "byte",
|
||||
"label": "🔢 BYTE (8-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "uint",
|
||||
"label": "🔢 UINT (16-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "udint",
|
||||
"label": "🔢 UDINT (32-bit unsigned)"
|
||||
},
|
||||
{
|
||||
"value": "sint",
|
||||
"label": "🔢 SINT (8-bit signed)"
|
||||
},
|
||||
{
|
||||
"value": "usint",
|
||||
"label": "🔢 USINT (8-bit unsigned)"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"streaming": {
|
||||
"ui:widget": "checkbox",
|
||||
"ui:help": "📡 Enable real-time streaming to PlotJuggler for visualization"
|
||||
}
|
||||
},
|
||||
{
|
||||
"ui:title": "Symbol-based Configuration",
|
||||
"ui:description": "Use a symbol from the loaded ASC file",
|
||||
"ui:order": [
|
||||
"name",
|
||||
"symbol",
|
||||
"streaming"
|
||||
],
|
||||
"ui:layout": [
|
||||
[
|
||||
{
|
||||
"name": "name",
|
||||
"width": 6
|
||||
},
|
||||
{
|
||||
"name": "symbol",
|
||||
"width": 6
|
||||
}
|
||||
],
|
||||
[
|
||||
{
|
||||
"name": "streaming",
|
||||
"width": 12
|
||||
}
|
||||
]
|
||||
],
|
||||
"name": {
|
||||
"ui:widget": "text",
|
||||
"ui:placeholder": "Variable name (auto-filled from symbol)",
|
||||
"ui:help": "📝 Human-readable name for this variable",
|
||||
"ui:readonly": true
|
||||
},
|
||||
"symbol": {
|
||||
"ui:widget": "dataset-variable-symbol",
|
||||
"ui:placeholder": "Select a PLC symbol...",
|
||||
"ui:help": "🔍 Search and select a symbol from the loaded ASC file"
|
||||
},
|
||||
"streaming": {
|
||||
"ui:widget": "checkbox",
|
||||
"ui:help": "📡 Enable real-time streaming to PlotJuggler for visualization"
|
||||
}
|
||||
}
|
||||
},
|
||||
"streaming": {
|
||||
"ui:widget": "checkbox",
|
||||
"ui:help": "📡 Enable real-time streaming to PlotJuggler for visualization"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import {
|
||||
Box,
|
||||
VStack,
|
||||
HStack,
|
||||
Card,
|
||||
CardBody,
|
||||
CardHeader,
|
||||
Heading,
|
||||
Text,
|
||||
Select,
|
||||
Alert,
|
||||
AlertIcon,
|
||||
useColorModeValue,
|
||||
Spinner
|
||||
} from '@chakra-ui/react'
|
||||
import Form from '@rjsf/chakra-ui'
|
||||
import validator from '@rjsf/validator-ajv8'
|
||||
import LayoutObjectFieldTemplate from './rjsf/LayoutObjectFieldTemplate.jsx'
|
||||
import { allWidgets } from './widgets/AllWidgets.jsx'
|
||||
|
||||
/**
|
||||
* DatasetVariablesRJSF - Maneja variables de dataset usando RJSF Type 3 pattern
|
||||
*/
|
||||
export default function DatasetVariablesRJSF({
|
||||
datasets = {},
|
||||
selectedDatasetId,
|
||||
onSelectDataset,
|
||||
onVariablesUpdate
|
||||
}) {
|
||||
const [schema, setSchema] = useState(null)
|
||||
const [uiSchema, setUiSchema] = useState(null)
|
||||
const [variables, setVariables] = useState({ variables: [] })
|
||||
const [loading, setLoading] = useState(true)
|
||||
const [saving, setSaving] = useState(false)
|
||||
const [message, setMessage] = useState('')
|
||||
|
||||
const muted = useColorModeValue('gray.600', 'gray.300')
|
||||
|
||||
// Load schema and data
|
||||
useEffect(() => {
|
||||
loadSchemaAndData()
|
||||
}, [])
|
||||
|
||||
const loadSchemaAndData = async () => {
|
||||
setLoading(true)
|
||||
try {
|
||||
// Load schema
|
||||
const schemaResp = await fetch('/api/config/schema/dataset-variables')
|
||||
const schemaData = await schemaResp.json()
|
||||
|
||||
if (schemaData.success) {
|
||||
setSchema(schemaData.schema)
|
||||
setUiSchema(schemaData.ui_schema || {})
|
||||
}
|
||||
|
||||
// Load data
|
||||
const dataResp = await fetch('/api/config/dataset-variables')
|
||||
const data = await dataResp.json()
|
||||
|
||||
if (data.success) {
|
||||
setVariables(data.data || { variables: [] })
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error loading schema/data:', error)
|
||||
setMessage(`Error loading: ${error.message}`)
|
||||
} finally {
|
||||
setLoading(false)
|
||||
}
|
||||
}
|
||||
|
||||
const saveVariables = async (formData) => {
|
||||
setSaving(true)
|
||||
try {
|
||||
const response = await fetch('/api/config/dataset-variables', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify(formData)
|
||||
})
|
||||
|
||||
const result = await response.json()
|
||||
|
||||
if (result.success) {
|
||||
setVariables(formData)
|
||||
setMessage('Variables saved successfully')
|
||||
setTimeout(() => setMessage(''), 3000)
|
||||
|
||||
if (onVariablesUpdate) {
|
||||
onVariablesUpdate(formData)
|
||||
}
|
||||
} else {
|
||||
throw new Error(result.error || 'Failed to save variables')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error saving variables:', error)
|
||||
setMessage(`Error saving: ${error.message}`)
|
||||
} finally {
|
||||
setSaving(false)
|
||||
}
|
||||
}
|
||||
|
||||
// Get available datasets for selector
|
||||
const datasetOptions = Object.entries(datasets).map(([id, dataset]) => ({
|
||||
value: id,
|
||||
label: `${dataset.name || id} (${id})`
|
||||
}))
|
||||
|
||||
if (loading) {
|
||||
return (
|
||||
<Card>
|
||||
<CardBody>
|
||||
<VStack spacing={4}>
|
||||
<Spinner />
|
||||
<Text>Loading dataset variables configuration...</Text>
|
||||
</VStack>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
if (!schema) {
|
||||
return (
|
||||
<Card>
|
||||
<CardBody>
|
||||
<Alert status="error">
|
||||
<AlertIcon />
|
||||
Failed to load schema for dataset variables
|
||||
</Alert>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<VStack align="start" spacing={2}>
|
||||
<Heading size="sm">🔧 Dataset Variables</Heading>
|
||||
<Text fontSize="sm" color={muted}>
|
||||
Configure PLC variables for each dataset - use symbols or manual configuration
|
||||
</Text>
|
||||
|
||||
{datasetOptions.length > 0 && (
|
||||
<HStack>
|
||||
<Text fontSize="sm" color={muted}>Reference Dataset:</Text>
|
||||
<Select
|
||||
size="sm"
|
||||
value={selectedDatasetId || ''}
|
||||
onChange={(e) => onSelectDataset && onSelectDataset(e.target.value)}
|
||||
placeholder="Select dataset for reference"
|
||||
width="250px"
|
||||
>
|
||||
{datasetOptions.map(option => (
|
||||
<option key={option.value} value={option.value}>
|
||||
{option.label}
|
||||
</option>
|
||||
))}
|
||||
</Select>
|
||||
</HStack>
|
||||
)}
|
||||
</VStack>
|
||||
</CardHeader>
|
||||
<CardBody>
|
||||
{message && (
|
||||
<Alert status={message.includes('Error') ? 'error' : 'success'} mb={4}>
|
||||
<AlertIcon />
|
||||
{message}
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<Form
|
||||
schema={schema}
|
||||
uiSchema={uiSchema}
|
||||
formData={variables}
|
||||
validator={validator}
|
||||
onChange={({ formData }) => setVariables(formData)}
|
||||
onSubmit={({ formData }) => saveVariables(formData)}
|
||||
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
|
||||
widgets={allWidgets}
|
||||
showErrorList={false}
|
||||
disabled={saving}
|
||||
>
|
||||
<HStack mt={4}>
|
||||
<button type="submit" disabled={saving}>
|
||||
{saving ? 'Saving...' : 'Save Variables'}
|
||||
</button>
|
||||
</HStack>
|
||||
</Form>
|
||||
</CardBody>
|
||||
</Card>
|
||||
)
|
||||
}
|
|
@ -21,7 +21,7 @@ import { AddIcon, DeleteIcon, EditIcon } from '@chakra-ui/icons'
|
|||
import Form from '@rjsf/chakra-ui'
|
||||
import validator from '@rjsf/validator-ajv8'
|
||||
import LayoutObjectFieldTemplate from './rjsf/LayoutObjectFieldTemplate.jsx'
|
||||
import { widgets } from './rjsf/widgets.jsx'
|
||||
import { allWidgets } from './widgets/AllWidgets.jsx'
|
||||
|
||||
/**
|
||||
* FormTable - Muestra objetos como filas de formularios usando schemas RJSF
|
||||
|
@ -152,7 +152,7 @@ export default function FormTable({
|
|||
validator={validator}
|
||||
onSubmit={({ formData }) => handleAdd(formData)}
|
||||
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
|
||||
widgets={widgets}
|
||||
widgets={allWidgets}
|
||||
showErrorList={false}
|
||||
>
|
||||
<HStack mt={3}>
|
||||
|
@ -231,7 +231,7 @@ export default function FormTable({
|
|||
onChange={editingKey === key ? ({ formData }) => setEditingFormData(formData) : () => { }}
|
||||
onSubmit={editingKey === key ? ({ formData }) => handleEdit(key, formData) : undefined}
|
||||
templates={{ ObjectFieldTemplate: LayoutObjectFieldTemplate }}
|
||||
widgets={widgets}
|
||||
widgets={allWidgets}
|
||||
readonly={editingKey !== key}
|
||||
showErrorList={false}
|
||||
>
|
||||
|
|
|
@ -3,6 +3,7 @@ import { widgets } from '../rjsf/widgets'
|
|||
import VariableSelectorWidget from '../rjsf/VariableSelectorWidget'
|
||||
import FilePathWidget from './FilePathWidget'
|
||||
import SymbolSelectorWidget from './SymbolSelectorWidget'
|
||||
import DatasetVariableSymbolWidget from './DatasetVariableSymbolWidget'
|
||||
|
||||
// Comprehensive widget collection that merges all available widgets
|
||||
// for full UI schema support with layouts
|
||||
|
@ -35,6 +36,11 @@ export const allWidgets = {
|
|||
'symbol-selector': SymbolSelectorWidget,
|
||||
SymbolSelectorWidget: SymbolSelectorWidget,
|
||||
|
||||
// Dataset variable symbol widget with auto-fill
|
||||
datasetVariableSymbol: DatasetVariableSymbolWidget,
|
||||
'dataset-variable-symbol': DatasetVariableSymbolWidget,
|
||||
DatasetVariableSymbolWidget: DatasetVariableSymbolWidget,
|
||||
|
||||
// PLC-specific widget aliases (if available)
|
||||
plcArea: widgets.PlcAreaWidget,
|
||||
plcDataType: widgets.PlcDataTypeWidget,
|
||||
|
|
|
@ -0,0 +1,100 @@
|
|||
import React, { useState, useEffect } from 'react'
|
||||
import {
|
||||
Box,
|
||||
VStack,
|
||||
Text,
|
||||
Badge,
|
||||
useToast
|
||||
} from '@chakra-ui/react'
|
||||
import SymbolSelectorWidget from './SymbolSelectorWidget'
|
||||
|
||||
const DatasetVariableSymbolWidget = ({ value, onChange, label, disabled, readonly, required, placeholder, formContext }) => {
|
||||
const [selectedSymbol, setSelectedSymbol] = useState(null)
|
||||
const toast = useToast()
|
||||
|
||||
// Load symbol details when value changes
|
||||
useEffect(() => {
|
||||
if (value && !selectedSymbol) {
|
||||
loadSymbolDetails(value)
|
||||
}
|
||||
}, [value])
|
||||
|
||||
const loadSymbolDetails = async (symbolName) => {
|
||||
try {
|
||||
const response = await fetch('/api/symbols')
|
||||
const data = await response.json()
|
||||
|
||||
if (data.success && data.symbols) {
|
||||
const symbol = data.symbols.find(s => s.name === symbolName)
|
||||
if (symbol) {
|
||||
setSelectedSymbol(symbol)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error loading symbol details:', error)
|
||||
}
|
||||
}
|
||||
|
||||
const handleSymbolSelect = (symbolName) => {
|
||||
// Update the symbol field
|
||||
onChange(symbolName)
|
||||
|
||||
// Show success message
|
||||
toast({
|
||||
title: 'Symbol Selected',
|
||||
description: `Selected: ${symbolName}`,
|
||||
status: 'success',
|
||||
duration: 2000,
|
||||
isClosable: true,
|
||||
})
|
||||
}
|
||||
|
||||
const symbolOptions = {
|
||||
onSymbolSelect: (symbol) => {
|
||||
setSelectedSymbol(symbol)
|
||||
handleSymbolSelect(symbol.name)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<SymbolSelectorWidget
|
||||
value={value}
|
||||
onChange={handleSymbolSelect}
|
||||
label={label}
|
||||
disabled={disabled}
|
||||
readonly={readonly}
|
||||
required={required}
|
||||
placeholder={placeholder}
|
||||
formContext={formContext}
|
||||
options={symbolOptions}
|
||||
/>
|
||||
|
||||
{selectedSymbol && (
|
||||
<Box mt={2} p={2} border="1px" borderColor="green.200" borderRadius="md" bg="green.50">
|
||||
<Text fontSize="xs" color="green.700" fontWeight="medium">
|
||||
Symbol Information:
|
||||
</Text>
|
||||
<VStack align="start" spacing={1} mt={1}>
|
||||
<Text fontSize="xs" color="green.600">
|
||||
📝 Name: {selectedSymbol.description || selectedSymbol.name}
|
||||
</Text>
|
||||
<Text fontSize="xs" color="green.600" fontFamily="mono">
|
||||
📍 Address: {selectedSymbol.plc_address}
|
||||
</Text>
|
||||
<Text fontSize="xs" color="green.600">
|
||||
🔧 Area: {selectedSymbol.area?.toUpperCase()}, Offset: {selectedSymbol.offset}
|
||||
{selectedSymbol.db && `, DB: ${selectedSymbol.db}`}
|
||||
{selectedSymbol.bit !== null && selectedSymbol.bit !== undefined && `, Bit: ${selectedSymbol.bit}`}
|
||||
</Text>
|
||||
<Badge colorScheme="green" fontSize="xs">
|
||||
{selectedSymbol.data_type}
|
||||
</Badge>
|
||||
</VStack>
|
||||
</Box>
|
||||
)}
|
||||
</Box>
|
||||
)
|
||||
}
|
||||
|
||||
export default DatasetVariableSymbolWidget
|
|
@ -26,7 +26,7 @@ import {
|
|||
} from '@chakra-ui/react'
|
||||
import { FiSearch, FiX, FiList, FiInfo } from 'react-icons/fi'
|
||||
|
||||
const SymbolSelectorWidget = ({ value, onChange, label, disabled, readonly, required, placeholder }) => {
|
||||
const SymbolSelectorWidget = ({ value, onChange, label, disabled, readonly, required, placeholder, formContext, options }) => {
|
||||
const [symbols, setSymbols] = useState([])
|
||||
const [searchQuery, setSearchQuery] = useState('')
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
@ -92,6 +92,12 @@ const SymbolSelectorWidget = ({ value, onChange, label, disabled, readonly, requ
|
|||
const handleSymbolSelect = (symbol) => {
|
||||
setSelectedSymbol(symbol)
|
||||
onChange(symbol.name)
|
||||
|
||||
// If we have formContext and the widget options include callbacks for auto-fill
|
||||
if (formContext && options && options.onSymbolSelect) {
|
||||
options.onSymbolSelect(symbol)
|
||||
}
|
||||
|
||||
onClose()
|
||||
|
||||
toast({
|
||||
|
|
|
@ -783,25 +783,60 @@ function DatasetManager() {
|
|||
items: {
|
||||
type: "object",
|
||||
properties: {
|
||||
name: { type: "string", title: "Variable Name" },
|
||||
area: {
|
||||
type: "string",
|
||||
title: "Memory Area",
|
||||
enum: ["db", "mw", "m", "pew", "pe", "paw", "pa", "e", "a", "mb"],
|
||||
default: "db"
|
||||
},
|
||||
db: { type: "integer", title: "DB Number", minimum: 1, maximum: 9999 },
|
||||
offset: { type: "integer", title: "Offset", minimum: 0, maximum: 8191 },
|
||||
bit: { type: "integer", title: "Bit Position", minimum: 0, maximum: 7 },
|
||||
type: {
|
||||
type: "string",
|
||||
title: "Data Type",
|
||||
enum: ["real", "int", "dint", "bool", "word", "byte"],
|
||||
default: "real"
|
||||
},
|
||||
streaming: { type: "boolean", title: "Stream to UDP", default: false }
|
||||
configType: {
|
||||
type: "string",
|
||||
title: "Configuration Type",
|
||||
enum: ["manual", "symbol"],
|
||||
default: "manual"
|
||||
}
|
||||
},
|
||||
required: ["name", "area", "offset", "type"]
|
||||
allOf: [
|
||||
{
|
||||
if: { properties: { configType: { const: "manual" } } },
|
||||
then: {
|
||||
properties: {
|
||||
name: { type: "string", title: "Variable Name" },
|
||||
area: {
|
||||
type: "string",
|
||||
title: "Memory Area",
|
||||
enum: ["db", "mw", "m", "pew", "pe", "paw", "pa", "e", "a", "mb"],
|
||||
default: "db"
|
||||
},
|
||||
db: { type: "integer", title: "DB Number", minimum: 1, maximum: 9999 },
|
||||
offset: { type: "integer", title: "Offset", minimum: 0, maximum: 8191 },
|
||||
bit: { type: "integer", title: "Bit Position", minimum: 0, maximum: 7 },
|
||||
type: {
|
||||
type: "string",
|
||||
title: "Data Type",
|
||||
enum: ["real", "int", "dint", "bool", "word", "byte"],
|
||||
default: "real"
|
||||
},
|
||||
streaming: { type: "boolean", title: "Stream to UDP", default: false }
|
||||
},
|
||||
required: ["name", "area", "offset", "type"]
|
||||
}
|
||||
},
|
||||
{
|
||||
if: { properties: { configType: { const: "symbol" } } },
|
||||
then: {
|
||||
properties: {
|
||||
name: {
|
||||
type: "string",
|
||||
title: "Variable Name",
|
||||
description: "Auto-filled from symbol",
|
||||
readOnly: true
|
||||
},
|
||||
symbol: {
|
||||
type: "string",
|
||||
title: "PLC Symbol",
|
||||
description: "Select a symbol from loaded ASC file"
|
||||
},
|
||||
streaming: { type: "boolean", title: "Stream to UDP", default: false }
|
||||
},
|
||||
required: ["symbol"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -810,14 +845,49 @@ function DatasetManager() {
|
|||
const singleDatasetUiSchema = {
|
||||
variables: {
|
||||
items: {
|
||||
"ui:layout": [[
|
||||
{ "name": "name", "width": 3 },
|
||||
{ "name": "area", "width": 2 },
|
||||
{ "name": "db", "width": 1 },
|
||||
{ "name": "offset", "width": 2 },
|
||||
{ "name": "type", "width": 2 },
|
||||
{ "name": "streaming", "width": 2 }
|
||||
]]
|
||||
"ui:order": ["configType", "name", "symbol", "area", "db", "offset", "bit", "type", "streaming"],
|
||||
"ui:layout": [
|
||||
[
|
||||
{ "name": "configType", "width": 3 }
|
||||
],
|
||||
[
|
||||
{ "name": "name", "width": 4 },
|
||||
{ "name": "symbol", "width": 8 }
|
||||
],
|
||||
[
|
||||
{ "name": "area", "width": 2 },
|
||||
{ "name": "db", "width": 2 },
|
||||
{ "name": "offset", "width": 2 },
|
||||
{ "name": "bit", "width": 2 },
|
||||
{ "name": "type", "width": 2 },
|
||||
{ "name": "streaming", "width": 2 }
|
||||
]
|
||||
],
|
||||
"configType": {
|
||||
"ui:widget": "select",
|
||||
"ui:help": "Choose between manual configuration or symbol-based setup",
|
||||
"ui:enumNames": ["Manual Configuration", "Symbol-based Configuration"]
|
||||
},
|
||||
"symbol": {
|
||||
"ui:widget": "symbol-selector",
|
||||
"ui:placeholder": "Select a PLC symbol...",
|
||||
"ui:help": "🔍 Search and select a symbol from the loaded ASC file"
|
||||
},
|
||||
"name": {
|
||||
"ui:help": "Human-readable name for this variable"
|
||||
},
|
||||
"area": {
|
||||
"ui:widget": "select",
|
||||
"ui:help": "PLC memory area"
|
||||
},
|
||||
"type": {
|
||||
"ui:widget": "select",
|
||||
"ui:help": "PLC data type"
|
||||
},
|
||||
"streaming": {
|
||||
"ui:widget": "checkbox",
|
||||
"ui:help": "Enable UDP streaming to PlotJuggler"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,11 +3,11 @@
|
|||
"should_connect": true,
|
||||
"should_stream": true,
|
||||
"active_datasets": [
|
||||
"Fast",
|
||||
"Test",
|
||||
"DAR",
|
||||
"Fast"
|
||||
"DAR"
|
||||
]
|
||||
},
|
||||
"auto_recovery_enabled": true,
|
||||
"last_update": "2025-08-14T16:52:19.757206"
|
||||
"last_update": "2025-08-14T17:32:09.169720"
|
||||
}
|
Loading…
Reference in New Issue