wiliot-certificate 4.4.3__py3-none-any.whl → 4.5.0a1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {brg_certificate → certificate}/ag/wlt_cmd_if.html +10 -4
- {brg_certificate → certificate}/ag/wlt_types_ag.py +1878 -519
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/brg2brg_ota.json +69 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/brg2gw_hb.json +109 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/brg2gw_hb_sleep.json +45 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/calibration.json +96 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/custom.json +99 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/datapath.json +241 -13
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/energy2400.json +120 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/energySub1g.json +96 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/externalSensor.json +135 -6
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/interface.json +157 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/powerManagement.json +205 -0
- brg_certificate/ag/wlt_types_ag_jsons/unified_echo_pkt.json → certificate/ag/wlt_types_ag_jsons/unified_echo_ext_pkt.json +27 -11
- certificate/ag/wlt_types_ag_jsons/unified_echo_pkt.json +175 -0
- certificate/ag/wlt_types_ag_jsons/unified_sensor_pkt.json +65 -0
- certificate/cert_common.py +1459 -0
- certificate/cert_config.py +455 -0
- {brg_certificate → certificate}/cert_data_sim.py +131 -46
- {brg_certificate → certificate}/cert_defines.py +120 -128
- {brg_certificate → certificate}/cert_gw_sim.py +151 -49
- {brg_certificate → certificate}/cert_mqtt.py +164 -59
- {brg_certificate → certificate}/cert_prints.py +34 -33
- {brg_certificate → certificate}/cert_protobuf.py +15 -6
- {brg_certificate → certificate}/cert_results.py +205 -48
- certificate/cert_utils.py +622 -0
- certificate/certificate.py +198 -0
- certificate/certificate_cli.py +79 -0
- certificate/certificate_eth_test_list.txt +74 -0
- certificate/certificate_sanity_test_list.txt +65 -0
- certificate/certificate_test_list.txt +75 -0
- {brg_certificate → certificate}/tests/calibration/interval_test/interval_test.json +2 -2
- {brg_certificate → certificate}/tests/calibration/interval_test/interval_test.py +7 -6
- certificate/tests/calibration/output_power_test/output_power_test.json +22 -0
- certificate/tests/calibration/output_power_test/output_power_test.py +39 -0
- {brg_certificate → certificate}/tests/calibration/pattern_test/pattern_test.json +1 -1
- {brg_certificate → certificate}/tests/calibration/pattern_test/pattern_test.py +20 -15
- certificate/tests/cloud_connectivity/acl_ext_adv_test/acl_ext_adv_test.json +14 -0
- certificate/tests/cloud_connectivity/acl_ext_adv_test/acl_ext_adv_test.py +140 -0
- certificate/tests/cloud_connectivity/acl_test/acl_test.json +14 -0
- certificate/tests/cloud_connectivity/acl_test/acl_test.py +98 -0
- certificate/tests/cloud_connectivity/brg_ota_test/brg_ota_test.json +18 -0
- certificate/tests/cloud_connectivity/brg_ota_test/brg_ota_test.py +39 -0
- certificate/tests/cloud_connectivity/channel_scan_behaviour_test/channel_scan_behaviour_test.json +18 -0
- certificate/tests/cloud_connectivity/channel_scan_behaviour_test/channel_scan_behaviour_test.py +215 -0
- certificate/tests/cloud_connectivity/connection_test/connection_test.json +17 -0
- certificate/tests/cloud_connectivity/connection_test/connection_test.py +74 -0
- certificate/tests/cloud_connectivity/downlink_test/downlink_test.json +20 -0
- certificate/tests/cloud_connectivity/downlink_test/downlink_test.py +204 -0
- certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.json +16 -0
- certificate/tests/cloud_connectivity/ext_adv_stress_test/ext_adv_stress_test.py +98 -0
- certificate/tests/cloud_connectivity/reboot_test/reboot_test.json +17 -0
- certificate/tests/cloud_connectivity/reboot_test/reboot_test.py +57 -0
- certificate/tests/cloud_connectivity/registration_test/registration_test.json +19 -0
- certificate/tests/cloud_connectivity/registration_test/registration_test.py +384 -0
- certificate/tests/cloud_connectivity/registration_test/registration_test_cli.py +90 -0
- certificate/tests/cloud_connectivity/stress_test/stress_test.json +16 -0
- certificate/tests/cloud_connectivity/stress_test/stress_test.py +97 -0
- certificate/tests/cloud_connectivity/uplink_ext_adv_test/uplink_ext_adv_test.json +24 -0
- certificate/tests/cloud_connectivity/uplink_ext_adv_test/uplink_ext_adv_test.py +93 -0
- certificate/tests/cloud_connectivity/uplink_test/uplink_test.json +19 -0
- certificate/tests/cloud_connectivity/uplink_test/uplink_test.py +161 -0
- {brg_certificate → certificate}/tests/datapath/aging_test/aging_test.json +1 -1
- certificate/tests/datapath/aging_test/aging_test.py +138 -0
- certificate/tests/datapath/event_ble5_test/event_ble5_test.json +16 -0
- certificate/tests/datapath/event_ble5_test/event_ble5_test.py +95 -0
- certificate/tests/datapath/event_test/event_test.json +16 -0
- certificate/tests/datapath/event_test/event_test.py +85 -0
- {brg_certificate → certificate}/tests/datapath/num_of_tags_test/num_of_tags_test.json +1 -1
- {brg_certificate → certificate}/tests/datapath/num_of_tags_test/num_of_tags_test.py +10 -8
- certificate/tests/datapath/output_power_test/output_power_test.json +22 -0
- {brg_certificate → certificate}/tests/datapath/output_power_test/output_power_test.py +17 -6
- {brg_certificate → certificate}/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.json +1 -1
- {brg_certificate → certificate}/tests/datapath/pacer_interval_ble5_test/pacer_interval_ble5_test.py +10 -8
- {brg_certificate → certificate}/tests/datapath/pacer_interval_test/pacer_interval_test.json +1 -1
- {brg_certificate → certificate}/tests/datapath/pacer_interval_test/pacer_interval_test.py +9 -7
- {brg_certificate → certificate}/tests/datapath/pattern_test/pattern_test.json +2 -2
- {brg_certificate → certificate}/tests/datapath/pattern_test/pattern_test.py +18 -6
- certificate/tests/datapath/pkt_filter_ble5_chl21_test/pkt_filter_ble5_chl21_test.json +19 -0
- certificate/tests/datapath/pkt_filter_ble5_chl21_test/pkt_filter_ble5_chl21_test.py +61 -0
- {brg_certificate → certificate}/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.json +1 -1
- {brg_certificate → certificate}/tests/datapath/pkt_filter_ble5_test/pkt_filter_ble5_test.py +11 -10
- certificate/tests/datapath/pkt_filter_brg2gw_ext_adv_test/pkt_filter_brg2gw_ext_adv_test.json +18 -0
- certificate/tests/datapath/pkt_filter_brg2gw_ext_adv_test/pkt_filter_brg2gw_ext_adv_test.py +83 -0
- {brg_certificate → certificate}/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.json +1 -1
- {brg_certificate → certificate}/tests/datapath/pkt_filter_gen3_test/pkt_filter_gen3_test.py +10 -9
- {brg_certificate → certificate}/tests/datapath/pkt_filter_test/pkt_filter_test.json +1 -1
- {brg_certificate → certificate}/tests/datapath/pkt_filter_test/pkt_filter_test.py +10 -9
- {brg_certificate → certificate}/tests/datapath/rssi_threshold_test/rssi_threshold_test.json +1 -1
- {brg_certificate → certificate}/tests/datapath/rssi_threshold_test/rssi_threshold_test.py +9 -8
- brg_certificate/tests/datapath/output_power_test/output_power_test.json → certificate/tests/datapath/rx_channel_hopping_test/rx_channel_hopping_test.json +5 -4
- certificate/tests/datapath/rx_channel_hopping_test/rx_channel_hopping_test.py +77 -0
- {brg_certificate → certificate}/tests/datapath/rx_channel_test/rx_channel_test.json +2 -2
- {brg_certificate → certificate}/tests/datapath/rx_channel_test/rx_channel_test.py +7 -6
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.json +7 -7
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen2_test/rx_rate_gen2_test.py +112 -72
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.json +7 -7
- {brg_certificate → certificate}/tests/datapath/rx_rate_gen3_test/rx_rate_gen3_test.py +112 -72
- {brg_certificate → certificate}/tests/datapath/stress_gen3_test/stress_gen3_test.json +3 -3
- {brg_certificate → certificate}/tests/datapath/stress_gen3_test/stress_gen3_test.py +12 -11
- {brg_certificate → certificate}/tests/datapath/stress_test/stress_test.json +3 -3
- {brg_certificate → certificate}/tests/datapath/stress_test/stress_test.py +12 -11
- {brg_certificate → certificate}/tests/datapath/tx_repetition_test/tx_repetition_test.json +2 -1
- {brg_certificate → certificate}/tests/datapath/tx_repetition_test/tx_repetition_test.py +14 -13
- certificate/tests/edge_mgmt/action_blink_test/action_blink_test.json +14 -0
- certificate/tests/edge_mgmt/action_blink_test/action_blink_test.py +24 -0
- certificate/tests/edge_mgmt/action_get_battery_sensor_test/action_get_battery_sensor_test.json +14 -0
- certificate/tests/edge_mgmt/action_get_battery_sensor_test/action_get_battery_sensor_test.py +43 -0
- certificate/tests/edge_mgmt/action_get_module_test/action_get_module_test.json +14 -0
- certificate/tests/edge_mgmt/action_get_module_test/action_get_module_test.py +42 -0
- certificate/tests/edge_mgmt/action_get_pof_data_test/action_get_pof_data_test.json +14 -0
- certificate/tests/edge_mgmt/action_get_pof_data_test/action_get_pof_data_test.py +44 -0
- certificate/tests/edge_mgmt/action_gw_hb_test/action_gw_hb_test.json +15 -0
- certificate/tests/edge_mgmt/action_gw_hb_test/action_gw_hb_test.py +42 -0
- certificate/tests/edge_mgmt/action_reboot_test/action_reboot_test.json +14 -0
- certificate/tests/edge_mgmt/action_reboot_test/action_reboot_test.py +49 -0
- certificate/tests/edge_mgmt/action_restore_defaults_test/action_restore_defaults_test.json +14 -0
- certificate/tests/edge_mgmt/action_restore_defaults_test/action_restore_defaults_test.py +102 -0
- certificate/tests/edge_mgmt/action_send_hb_test/action_send_hb_test.json +14 -0
- certificate/tests/edge_mgmt/action_send_hb_test/action_send_hb_test.py +41 -0
- {brg_certificate → certificate}/tests/edge_mgmt/periodic_msgs_test/periodic_msgs_test.json +2 -2
- {brg_certificate → certificate}/tests/edge_mgmt/periodic_msgs_test/periodic_msgs_test.py +22 -11
- {brg_certificate → certificate}/tests/energy2400/duty_cycle_test/duty_cycle_test.json +1 -1
- {brg_certificate → certificate}/tests/energy2400/duty_cycle_test/duty_cycle_test.py +7 -6
- certificate/tests/energy2400/output_power_test/output_power_test.json +22 -0
- {brg_certificate → certificate}/tests/energy2400/output_power_test/output_power_test.py +17 -6
- {brg_certificate → certificate}/tests/energy2400/pattern_test/pattern_test.json +1 -1
- {brg_certificate → certificate}/tests/energy2400/pattern_test/pattern_test.py +7 -6
- certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.json +25 -0
- certificate/tests/energy2400/signal_indicator_ble5_test/signal_indicator_ble5_test.py +378 -0
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.json → certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.json +3 -3
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_500k_test/signal_indicator_ble5_10_500k_test.py → certificate/tests/energy2400/signal_indicator_ext_adv_test/signal_indicator_ext_adv_test.py +97 -87
- certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +23 -0
- certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +350 -0
- {brg_certificate → certificate}/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.json +1 -1
- {brg_certificate → certificate}/tests/energy_sub1g/duty_cycle_test/duty_cycle_test.py +7 -6
- {brg_certificate → certificate}/tests/energy_sub1g/pattern_test/pattern_test.json +1 -1
- {brg_certificate → certificate}/tests/energy_sub1g/pattern_test/pattern_test.py +7 -6
- {brg_certificate → certificate}/tests/pwr_mgmt/pwr_mgmt_test/pwr_mgmt_test.json +1 -1
- {brg_certificate → certificate}/tests/pwr_mgmt/pwr_mgmt_test/pwr_mgmt_test.py +10 -10
- {brg_certificate → certificate}/tests/sensors/ext_sensor_test/ext_sensor_test.json +4 -4
- certificate/tests/sensors/ext_sensor_test/ext_sensor_test.py +455 -0
- certificate/wlt_types.py +122 -0
- {gw_certificate → common}/api_if/202/status.json +6 -0
- {gw_certificate → common}/api_if/203/status.json +6 -0
- {gw_certificate → common}/api_if/204/status.json +6 -0
- common/api_if/206/data.json +85 -0
- common/api_if/206/status.json +69 -0
- common/api_if/api_validation.py +85 -0
- common/web/templates/generator.html +148 -0
- common/web/templates/index.html +20 -0
- common/web/templates/menu.html +54 -0
- common/web/templates/parser.html +53 -0
- {brg_certificate/ag → common/web/templates}/wlt_types.html +1216 -191
- common/web/web_utils.py +377 -0
- {brg_certificate → common}/wltPb_pb2.py +14 -12
- {gw_certificate/common → common}/wltPb_pb2.pyi +16 -2
- gui_certificate/gui_certificate_cli.py +14 -0
- gui_certificate/server.py +1062 -0
- gui_certificate/templates/cert_run.html +1207 -0
- wiliot_certificate-4.5.0a1.dist-info/METADATA +110 -0
- wiliot_certificate-4.5.0a1.dist-info/RECORD +182 -0
- {wiliot_certificate-4.4.3.dist-info → wiliot_certificate-4.5.0a1.dist-info}/WHEEL +1 -1
- wiliot_certificate-4.5.0a1.dist-info/entry_points.txt +5 -0
- wiliot_certificate-4.5.0a1.dist-info/top_level.txt +3 -0
- brg_certificate/ag/energous_v0_defines.py +0 -925
- brg_certificate/ag/energous_v1_defines.py +0 -931
- brg_certificate/ag/energous_v2_defines.py +0 -925
- brg_certificate/ag/energous_v3_defines.py +0 -925
- brg_certificate/ag/energous_v4_defines.py +0 -925
- brg_certificate/ag/fanstel_lan_v0_defines.py +0 -925
- brg_certificate/ag/fanstel_lte_v0_defines.py +0 -925
- brg_certificate/ag/fanstel_wifi_v0_defines.py +0 -925
- brg_certificate/ag/minew_lte_v0_defines.py +0 -925
- brg_certificate/ag/wlt_types_ag_jsons/unified_echo_ext_pkt.json +0 -61
- brg_certificate/brg_certificate.py +0 -225
- brg_certificate/brg_certificate_cli.py +0 -63
- brg_certificate/cert_common.py +0 -923
- brg_certificate/cert_config.py +0 -402
- brg_certificate/cert_utils.py +0 -362
- brg_certificate/certificate_bcc_sanity_test_list.txt +0 -40
- brg_certificate/certificate_bcc_test_list.txt +0 -48
- brg_certificate/certificate_sanity_test_list.txt +0 -43
- brg_certificate/certificate_test_list.txt +0 -53
- brg_certificate/config/eclipse.json +0 -10
- brg_certificate/config/hivemq.json +0 -10
- brg_certificate/config/mosquitto.json +0 -10
- brg_certificate/config/mosquitto.md +0 -95
- brg_certificate/config/wiliot-dev.json +0 -10
- brg_certificate/restore_brg.py +0 -61
- brg_certificate/tests/calibration/output_power_test/output_power_test.json +0 -16
- brg_certificate/tests/calibration/output_power_test/output_power_test.py +0 -28
- brg_certificate/tests/datapath/aging_test/aging_test.py +0 -143
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.json +0 -16
- brg_certificate/tests/datapath/pacer_interval_tags_count_test/pacer_interval_tags_count_test.py +0 -73
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.json +0 -17
- brg_certificate/tests/datapath/tx_repetition_algo_test/tx_repetition_algo_test.py +0 -118
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.json +0 -14
- brg_certificate/tests/edge_mgmt/actions_test/actions_test.py +0 -396
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.json +0 -20
- brg_certificate/tests/edge_mgmt/brg2brg_ota_ble5_test/brg2brg_ota_ble5_test.py +0 -94
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.json +0 -19
- brg_certificate/tests/edge_mgmt/brg2brg_ota_test/brg2brg_ota_test.py +0 -87
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.json +0 -17
- brg_certificate/tests/edge_mgmt/leds_test/leds_test.py +0 -223
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.json +0 -17
- brg_certificate/tests/edge_mgmt/ota_test/ota_test.py +0 -128
- brg_certificate/tests/energy2400/output_power_test/output_power_test.json +0 -16
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.json +0 -20
- brg_certificate/tests/energy2400/signal_indicator_ble5_10_250k_test/signal_indicator_ble5_10_250k_test.py +0 -321
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.json +0 -20
- brg_certificate/tests/energy2400/signal_indicator_sub1g_2_4_test/signal_indicator_sub1g_2_4_test.py +0 -141
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.json +0 -20
- brg_certificate/tests/energy2400/signal_indicator_test/signal_indicator_test.py +0 -276
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.json +0 -20
- brg_certificate/tests/energy_sub1g/signal_indicator_functionality_test/signal_indicator_functionality_test.py +0 -390
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.json +0 -16
- brg_certificate/tests/energy_sub1g/signal_indicator_test/signal_indicator_test.py +0 -28
- brg_certificate/tests/sensors/ext_sensor_test/ext_sensor_test.py +0 -305
- brg_certificate/wltPb_pb2.pyi +0 -234
- brg_certificate/wlt_types.py +0 -113
- gw_certificate/ag/ut_defines.py +0 -364
- gw_certificate/ag/wlt_types.py +0 -85
- gw_certificate/ag/wlt_types_ag.py +0 -5310
- gw_certificate/ag/wlt_types_data.py +0 -64
- gw_certificate/api/extended_api.py +0 -23
- gw_certificate/api_if/200/data.json +0 -106
- gw_certificate/api_if/200/status.json +0 -47
- gw_certificate/api_if/201/data.json +0 -98
- gw_certificate/api_if/201/status.json +0 -53
- gw_certificate/api_if/205/logs.json +0 -12
- gw_certificate/api_if/api_validation.py +0 -38
- gw_certificate/api_if/gw_capabilities.py +0 -54
- gw_certificate/cert_results.py +0 -145
- gw_certificate/common/analysis_data_bricks.py +0 -60
- gw_certificate/common/debug.py +0 -42
- gw_certificate/common/serialization_formatter.py +0 -93
- gw_certificate/common/utils.py +0 -8
- gw_certificate/common/utils_defines.py +0 -15
- gw_certificate/common/wltPb_pb2.py +0 -84
- gw_certificate/gw_certificate.py +0 -154
- gw_certificate/gw_certificate_cli.py +0 -87
- gw_certificate/interface/4.4.93_app.zip +0 -0
- gw_certificate/interface/4.4.93_sd_bl_app.zip +0 -0
- gw_certificate/interface/ble_simulator.py +0 -61
- gw_certificate/interface/ble_sniffer.py +0 -189
- gw_certificate/interface/flash_fw.py +0 -90
- gw_certificate/interface/if_defines.py +0 -36
- gw_certificate/interface/mqtt.py +0 -563
- gw_certificate/interface/nrfutil-linux +0 -0
- gw_certificate/interface/nrfutil-mac +0 -0
- gw_certificate/interface/nrfutil.exe +0 -0
- gw_certificate/interface/pkt_generator.py +0 -594
- gw_certificate/interface/uart_if.py +0 -236
- gw_certificate/interface/uart_ports.py +0 -20
- gw_certificate/templates/results.html +0 -241
- gw_certificate/templates/stage.html +0 -22
- gw_certificate/templates/table.html +0 -6
- gw_certificate/templates/test.html +0 -38
- gw_certificate/tests/__init__.py +0 -10
- gw_certificate/tests/actions.py +0 -289
- gw_certificate/tests/bad_crc_to_PER_quantization.csv +0 -51
- gw_certificate/tests/connection.py +0 -188
- gw_certificate/tests/downlink.py +0 -172
- gw_certificate/tests/generic.py +0 -238
- gw_certificate/tests/registration.py +0 -340
- gw_certificate/tests/static/__init__.py +0 -0
- gw_certificate/tests/static/connection_defines.py +0 -9
- gw_certificate/tests/static/downlink_defines.py +0 -9
- gw_certificate/tests/static/generated_packet_table.py +0 -195
- gw_certificate/tests/static/packet_table.csv +0 -10067
- gw_certificate/tests/static/references.py +0 -5
- gw_certificate/tests/static/uplink_defines.py +0 -14
- gw_certificate/tests/throughput.py +0 -240
- gw_certificate/tests/uplink.py +0 -853
- wiliot_certificate-4.4.3.dist-info/METADATA +0 -211
- wiliot_certificate-4.4.3.dist-info/RECORD +0 -210
- wiliot_certificate-4.4.3.dist-info/entry_points.txt +0 -3
- wiliot_certificate-4.4.3.dist-info/top_level.txt +0 -3
- {brg_certificate → certificate}/__init__.py +0 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/side_info_sensor.json +0 -0
- {brg_certificate → certificate}/ag/wlt_types_ag_jsons/signal_indicator_data.json +0 -0
- {gw_certificate → common}/api_if/202/data.json +0 -0
- {gw_certificate/api_if/200 → common/api_if/202}/logs.json +0 -0
- {gw_certificate → common}/api_if/203/data.json +0 -0
- {gw_certificate/api_if/201 → common/api_if/203}/logs.json +0 -0
- {gw_certificate → common}/api_if/204/data.json +0 -0
- {gw_certificate/api_if/202 → common/api_if/204}/logs.json +0 -0
- {gw_certificate → common}/api_if/205/data.json +0 -0
- {gw_certificate/api_if/203 → common/api_if/205}/logs.json +0 -0
- {gw_certificate → common}/api_if/205/status.json +0 -0
- {gw_certificate/api_if/204 → common/api_if/206}/logs.json +0 -0
- {gw_certificate → common/api_if}/__init__.py +0 -0
- {gw_certificate/api_if → gui_certificate}/__init__.py +0 -0
- {wiliot_certificate-4.4.3.dist-info → wiliot_certificate-4.5.0a1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,1207 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<!-- Required meta tags -->
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
7
|
+
<title>{{ app }}</title>
|
|
8
|
+
<link rel="icon" href="https://www.wiliot.com/favicon.ico" type="image/x-icon" />
|
|
9
|
+
<!-- Bootstrap CSS -->
|
|
10
|
+
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-EVSTQN3/azprG1Anm3QDgpJLIm9Nao0Yz1ztcQTwFspd3yD65VohhpuuCOmLASjC" crossorigin="anonymous">
|
|
11
|
+
<style>
|
|
12
|
+
/* Progress indicator */
|
|
13
|
+
.step-indicator {
|
|
14
|
+
display: flex;
|
|
15
|
+
justify-content: space-between;
|
|
16
|
+
margin-bottom: 2rem;
|
|
17
|
+
position: relative;
|
|
18
|
+
}
|
|
19
|
+
.step-indicator::before {
|
|
20
|
+
content: '';
|
|
21
|
+
position: absolute;
|
|
22
|
+
top: 20px;
|
|
23
|
+
left: 0;
|
|
24
|
+
right: 0;
|
|
25
|
+
height: 2px;
|
|
26
|
+
background: #dee2e6;
|
|
27
|
+
z-index: 0;
|
|
28
|
+
}
|
|
29
|
+
.step-indicator .step {
|
|
30
|
+
position: relative;
|
|
31
|
+
z-index: 1;
|
|
32
|
+
background: white;
|
|
33
|
+
width: 40px;
|
|
34
|
+
height: 40px;
|
|
35
|
+
border-radius: 50%;
|
|
36
|
+
border: 2px solid #dee2e6;
|
|
37
|
+
display: flex;
|
|
38
|
+
align-items: center;
|
|
39
|
+
justify-content: center;
|
|
40
|
+
font-weight: bold;
|
|
41
|
+
color: #6c757d;
|
|
42
|
+
}
|
|
43
|
+
.step-indicator .step.active {
|
|
44
|
+
border-color: #00AB83;
|
|
45
|
+
background: #00AB83;
|
|
46
|
+
color: white;
|
|
47
|
+
}
|
|
48
|
+
.step-indicator .step.completed {
|
|
49
|
+
border-color: #00AB83;
|
|
50
|
+
background: #00AB83;
|
|
51
|
+
color: white;
|
|
52
|
+
}
|
|
53
|
+
.step-indicator > div {
|
|
54
|
+
display: flex;
|
|
55
|
+
flex-direction: column;
|
|
56
|
+
align-items: center;
|
|
57
|
+
flex: 1;
|
|
58
|
+
}
|
|
59
|
+
.step-indicator .step-label {
|
|
60
|
+
margin-top: 0.5rem;
|
|
61
|
+
font-size: 0.875rem;
|
|
62
|
+
text-align: center;
|
|
63
|
+
color: #6c757d;
|
|
64
|
+
}
|
|
65
|
+
.step-indicator .step-label.active {
|
|
66
|
+
color: #00AB83;
|
|
67
|
+
font-weight: 600;
|
|
68
|
+
}
|
|
69
|
+
.step-indicator .step.active span,
|
|
70
|
+
.step-indicator .step.completed span {
|
|
71
|
+
color: white;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/* Step content */
|
|
75
|
+
.step-content {
|
|
76
|
+
min-height: 400px;
|
|
77
|
+
padding: 2rem 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Mandatory badge */
|
|
81
|
+
.mandatory-badge {
|
|
82
|
+
background: #dc3545;
|
|
83
|
+
color: white;
|
|
84
|
+
font-size: 0.75rem;
|
|
85
|
+
padding: 0.25rem 0.5rem;
|
|
86
|
+
border-radius: 0.25rem;
|
|
87
|
+
margin-left: 0.5rem;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/* Knowledge base link */
|
|
91
|
+
.kb-link {
|
|
92
|
+
color: #0066cc;
|
|
93
|
+
text-decoration: none;
|
|
94
|
+
margin-left: 0.5rem;
|
|
95
|
+
font-size: 0.875rem;
|
|
96
|
+
}
|
|
97
|
+
.kb-link:hover {
|
|
98
|
+
text-decoration: underline;
|
|
99
|
+
}
|
|
100
|
+
/* Chevron rotation */
|
|
101
|
+
.test-toggle .chev {
|
|
102
|
+
transition: transform .15s ease;
|
|
103
|
+
transform: rotate(0deg);
|
|
104
|
+
}
|
|
105
|
+
.test-toggle.collapsed .chev {
|
|
106
|
+
transform: rotate(-90deg);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/* Certification warning */
|
|
110
|
+
.cert-warning {
|
|
111
|
+
background: #fff3cd;
|
|
112
|
+
border: 1px solid #ffc107;
|
|
113
|
+
border-radius: 0.5rem;
|
|
114
|
+
padding: 1rem;
|
|
115
|
+
margin: 1rem 0;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* Flavor cards */
|
|
119
|
+
.flavor-card {
|
|
120
|
+
border: 2px solid #dee2e6;
|
|
121
|
+
border-radius: 0.5rem;
|
|
122
|
+
padding: 1.5rem;
|
|
123
|
+
margin-bottom: 1rem;
|
|
124
|
+
cursor: pointer;
|
|
125
|
+
transition: all 0.2s;
|
|
126
|
+
}
|
|
127
|
+
.flavor-card:hover {
|
|
128
|
+
border-color: #00AB83;
|
|
129
|
+
background: #f0fdfa;
|
|
130
|
+
}
|
|
131
|
+
.flavor-card.selected {
|
|
132
|
+
border-color: #00AB83;
|
|
133
|
+
background: #e6f7f4;
|
|
134
|
+
}
|
|
135
|
+
.flavor-card input[type="radio"] {
|
|
136
|
+
margin-right: 0.5rem;
|
|
137
|
+
}
|
|
138
|
+
</style>
|
|
139
|
+
</head>
|
|
140
|
+
<body>
|
|
141
|
+
<div class="container">
|
|
142
|
+
{% include 'menu.html' %}
|
|
143
|
+
<h1 style="color:#00AB83">{{ title }}</h1>
|
|
144
|
+
<hr>
|
|
145
|
+
|
|
146
|
+
{% macro kb_link(doc) -%}
|
|
147
|
+
{% if doc %}
|
|
148
|
+
{% if doc is string %}
|
|
149
|
+
<a href="{{ doc }}" target="_blank" class="kb-link" title="Knowledge Base">📚 KB</a>
|
|
150
|
+
{% elif doc is iterable %}
|
|
151
|
+
{% for url in doc %}
|
|
152
|
+
<a href="{{ url }}" target="_blank" class="kb-link" title="Knowledge Base">📚 KB</a>
|
|
153
|
+
{% endfor %}
|
|
154
|
+
{% endif %}
|
|
155
|
+
{% endif %}
|
|
156
|
+
{%- endmacro %}
|
|
157
|
+
|
|
158
|
+
{% set non_cert_text = "NOT READY FOR CERTIFICATION" %}
|
|
159
|
+
|
|
160
|
+
<!-- Progress Indicator -->
|
|
161
|
+
<div class="step-indicator">
|
|
162
|
+
<div>
|
|
163
|
+
<div class="step {{ 'completed' if step_num > 1 else 'active' if step_num == 1 else '' }}">
|
|
164
|
+
<span>1</span>
|
|
165
|
+
</div>
|
|
166
|
+
<div class="step-label {{ 'active' if step_num >= 1 else '' }}">Flavor</div>
|
|
167
|
+
</div>
|
|
168
|
+
<div>
|
|
169
|
+
<div class="step {{ 'completed' if step_num > 2 else 'active' if step_num == 2 else '' }}">
|
|
170
|
+
<span>2</span>
|
|
171
|
+
</div>
|
|
172
|
+
<div class="step-label {{ 'active' if step_num >= 2 else '' }}">Schema</div>
|
|
173
|
+
</div>
|
|
174
|
+
<div>
|
|
175
|
+
<div class="step {{ 'completed' if (step_num > 3 or (step_num >= 3 and flavor == 'gw_only')) else 'active' if step_num == 3 and flavor != 'gw_only' else '' }}">
|
|
176
|
+
<span>3</span>
|
|
177
|
+
</div>
|
|
178
|
+
<div class="step-label {{ 'active' if (step_num >= 3 or (flavor == 'gw_only' and step_num >= 2)) else '' }}">Modules</div>
|
|
179
|
+
</div>
|
|
180
|
+
<div>
|
|
181
|
+
<div class="step {{ 'completed' if step_num > 4 else 'active' if step_num == 4 else '' }}">
|
|
182
|
+
<span>4</span>
|
|
183
|
+
</div>
|
|
184
|
+
<div class="step-label {{ 'active' if step_num >= 4 else '' }}">Tests</div>
|
|
185
|
+
</div>
|
|
186
|
+
<div>
|
|
187
|
+
<div class="step {{ 'active' if step_num == 5 else '' }}">
|
|
188
|
+
<span>5</span>
|
|
189
|
+
</div>
|
|
190
|
+
<div class="step-label {{ 'active' if step_num >= 5 else '' }}">Review</div>
|
|
191
|
+
</div>
|
|
192
|
+
</div>
|
|
193
|
+
|
|
194
|
+
<!-- Flash Messages -->
|
|
195
|
+
{% with messages = get_flashed_messages(with_categories=true) %}
|
|
196
|
+
{% if messages %}
|
|
197
|
+
{% for category, message in messages %}
|
|
198
|
+
<div class="alert alert-{{ 'danger' if category == 'error' else 'success' if category == 'success' else 'warning' if category == 'warning' else 'info' }}" role="alert">
|
|
199
|
+
{{ message }}
|
|
200
|
+
</div>
|
|
201
|
+
{% endfor %}
|
|
202
|
+
{% endif %}
|
|
203
|
+
{% endwith %}
|
|
204
|
+
|
|
205
|
+
<!-- Error/Warning Messages -->
|
|
206
|
+
{% if error %}
|
|
207
|
+
<div class="alert alert-danger" role="alert">
|
|
208
|
+
{{ error }}
|
|
209
|
+
</div>
|
|
210
|
+
{% endif %}
|
|
211
|
+
|
|
212
|
+
{% if warning %}
|
|
213
|
+
<div class="alert alert-warning" role="alert">
|
|
214
|
+
{{ warning }}
|
|
215
|
+
</div>
|
|
216
|
+
{% endif %}
|
|
217
|
+
|
|
218
|
+
<!-- Step Content -->
|
|
219
|
+
<div class="step-content">
|
|
220
|
+
<form method="POST" enctype="multipart/form-data" id="mainForm">
|
|
221
|
+
<!-- Step 1: Flavor Selection -->
|
|
222
|
+
{% if step_num == 1 %}
|
|
223
|
+
<h3>Step 1: Select Certification Flavor</h3>
|
|
224
|
+
<p class="text-muted">Choose the type of certification you want to run.</p>
|
|
225
|
+
|
|
226
|
+
<div class="flavor-card" onclick="document.getElementById('flavor_gw').click()">
|
|
227
|
+
<input type="radio" name="flavor" id="flavor_gw" value="gw_only" required>
|
|
228
|
+
<label for="flavor_gw" style="cursor: pointer; font-weight: bold; font-size: 1.1rem;">
|
|
229
|
+
Gateway Only
|
|
230
|
+
</label>
|
|
231
|
+
<p class="mt-2 mb-0 text-muted">
|
|
232
|
+
<strong>Mandatory Module:</strong> Cloud Connectivity<br>
|
|
233
|
+
Tests gateway's BLE scans & MQTT data uploads capabilities.
|
|
234
|
+
</p>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<div class="flavor-card" onclick="document.getElementById('flavor_brg').click()">
|
|
238
|
+
<input type="radio" name="flavor" id="flavor_brg" value="bridge_only" required>
|
|
239
|
+
<label for="flavor_brg" style="cursor: pointer; font-weight: bold; font-size: 1.1rem;">
|
|
240
|
+
Bridge Only
|
|
241
|
+
</label>
|
|
242
|
+
<p class="mt-2 mb-0 text-muted">
|
|
243
|
+
<strong>Mandatory Module:</strong> Edge Management<br>
|
|
244
|
+
Requires at least one additional module beyond the mandatory Edge Management module.
|
|
245
|
+
</p>
|
|
246
|
+
</div>
|
|
247
|
+
|
|
248
|
+
<div class="flavor-card" onclick="document.getElementById('flavor_combo').click()">
|
|
249
|
+
<input type="radio" name="flavor" id="flavor_combo" value="combo" required>
|
|
250
|
+
<label for="flavor_combo" style="cursor: pointer; font-weight: bold; font-size: 1.1rem;">
|
|
251
|
+
Combo (Gateway + Bridge)
|
|
252
|
+
</label>
|
|
253
|
+
<p class="mt-2 mb-0 text-muted">
|
|
254
|
+
<strong>Mandatory Modules:</strong> Cloud Connectivity + Edge Management<br>
|
|
255
|
+
Requires at least one additional bridge module beyond the mandatory Edge Management module.<br>
|
|
256
|
+
Tests both gateway and bridge capabilities.
|
|
257
|
+
</p>
|
|
258
|
+
</div>
|
|
259
|
+
|
|
260
|
+
<script>
|
|
261
|
+
document.querySelectorAll('input[name="flavor"]').forEach(radio => {
|
|
262
|
+
radio.addEventListener('change', function() {
|
|
263
|
+
document.querySelectorAll('.flavor-card').forEach(card => {
|
|
264
|
+
card.classList.remove('selected');
|
|
265
|
+
});
|
|
266
|
+
this.closest('.flavor-card').classList.add('selected');
|
|
267
|
+
});
|
|
268
|
+
});
|
|
269
|
+
</script>
|
|
270
|
+
|
|
271
|
+
<!-- Step 2: Validation Schema Upload -->
|
|
272
|
+
{% elif step_num == 2 %}
|
|
273
|
+
<h3>Step 2: Upload Validation Schema</h3>
|
|
274
|
+
<p class="text-muted">Upload the JSON validation schema file for your device. <a href="https://community.wiliot.com/customers/s/article/Validation-Schema" target="_blank" class="kb-link">📚 KB</a></p>
|
|
275
|
+
|
|
276
|
+
<div class="mb-3">
|
|
277
|
+
<label for="schema_file" class="form-label">Validation Schema File (JSON)</label>
|
|
278
|
+
<input type="file" class="form-control" id="schema_file" name="schema_file" accept=".json">
|
|
279
|
+
<div class="form-text">Select a JSON validation schema file that matches your selected flavor.</div>
|
|
280
|
+
</div>
|
|
281
|
+
|
|
282
|
+
{% if schema_path %}
|
|
283
|
+
<div class="alert alert-success">
|
|
284
|
+
Schema uploaded: {{ schema_path.split('/')[-1] }}
|
|
285
|
+
</div>
|
|
286
|
+
{% endif %}
|
|
287
|
+
|
|
288
|
+
<!-- Step 3: Module Selection -->
|
|
289
|
+
{% elif step_num == 3 %}
|
|
290
|
+
<h3>Step 3: Select Modules</h3>
|
|
291
|
+
<p class="text-muted">Select the modules you want to test. Mandatory modules are pre-selected.</p>
|
|
292
|
+
|
|
293
|
+
{% if flavor == 'bridge_only' %}
|
|
294
|
+
<div class="alert alert-info">
|
|
295
|
+
<strong>Note:</strong> Bridge only requires at least one additional module beyond the mandatory Edge Management module.
|
|
296
|
+
</div>
|
|
297
|
+
{% elif flavor == 'combo' %}
|
|
298
|
+
<div class="alert alert-info">
|
|
299
|
+
<strong>Note:</strong> Combo requires at least one additional bridge module beyond the mandatory Edge Management module.
|
|
300
|
+
</div>
|
|
301
|
+
{% endif %}
|
|
302
|
+
|
|
303
|
+
<div id="step3_warning" class="cert-warning" style="display: none;">
|
|
304
|
+
<strong>⚠️ Warning:</strong> {{ non_cert_text }}<br>
|
|
305
|
+
<small id="step3_warning_text"></small>
|
|
306
|
+
</div>
|
|
307
|
+
|
|
308
|
+
{% for mod in filtered_modules %}
|
|
309
|
+
{% set is_mandatory = mod.is_mandatory | default(False) %}
|
|
310
|
+
{% set is_selected = mod.name in selected_modules %}
|
|
311
|
+
{% set has_selections = selected_modules|length > 0 %}
|
|
312
|
+
{% set mod_doc = None %}
|
|
313
|
+
{% if mod.tests and mod.tests|length > 0 %}
|
|
314
|
+
{% for test in mod.tests %}
|
|
315
|
+
{% if test.meta.documentation and not mod_doc %}
|
|
316
|
+
{% set mod_doc = test.meta.documentation %}
|
|
317
|
+
{% endif %}
|
|
318
|
+
{% endfor %}
|
|
319
|
+
{% endif %}
|
|
320
|
+
|
|
321
|
+
<div class="card mb-3">
|
|
322
|
+
<div class="card-body">
|
|
323
|
+
<div class="form-check">
|
|
324
|
+
<input class="form-check-input"
|
|
325
|
+
type="checkbox"
|
|
326
|
+
name="modules[]"
|
|
327
|
+
id="module_{{ mod.name }}"
|
|
328
|
+
value="{{ mod.name }}"
|
|
329
|
+
{% if is_selected %}checked{% elif is_mandatory and not has_selections %}checked{% endif %}>
|
|
330
|
+
<label class="form-check-label" for="module_{{ mod.name }}" style="font-weight: bold; font-size: 1.1rem;">
|
|
331
|
+
{{ mod.name }}
|
|
332
|
+
{% if is_mandatory %}
|
|
333
|
+
<span class="mandatory-badge">Mandatory</span>
|
|
334
|
+
{% endif %}
|
|
335
|
+
{{ kb_link(mod_doc) }}
|
|
336
|
+
</label>
|
|
337
|
+
<p class="text-muted mt-1 mb-0">
|
|
338
|
+
{{ mod.tests|length }} test(s) available
|
|
339
|
+
</p>
|
|
340
|
+
</div>
|
|
341
|
+
</div>
|
|
342
|
+
</div>
|
|
343
|
+
{% endfor %}
|
|
344
|
+
|
|
345
|
+
<!-- Step 4: Test Selection -->
|
|
346
|
+
{% elif step_num == 4 %}
|
|
347
|
+
<h3>Step 4: Select Tests</h3>
|
|
348
|
+
<p class="text-muted">Select the specific tests to run. Mandatory tests are pre-selected and cannot be deselected.</p>
|
|
349
|
+
|
|
350
|
+
<div id="step4_warning" class="cert-warning" style="display: none;">
|
|
351
|
+
<strong>⚠️ Warning:</strong> {{ non_cert_text }}<br>
|
|
352
|
+
<small id="step4_warning_text"></small>
|
|
353
|
+
</div>
|
|
354
|
+
|
|
355
|
+
{% for mod in filtered_modules %}
|
|
356
|
+
{% if mod.name in selected_modules %}
|
|
357
|
+
{% set mod_id = 'mod_' ~ mod.name|replace('/', '_') %}
|
|
358
|
+
<div class="card mb-3">
|
|
359
|
+
<div class="card-header d-flex align-items-center">
|
|
360
|
+
<button class="btn btn-sm btn-link text-decoration-none test-toggle me-2 collapsed"
|
|
361
|
+
type="button"
|
|
362
|
+
data-bs-toggle="collapse"
|
|
363
|
+
data-bs-target="#{{ mod_id }}"
|
|
364
|
+
aria-expanded="false">
|
|
365
|
+
<svg class="chev" width="16" height="16" viewBox="0 0 16 16">
|
|
366
|
+
<path d="M4.646 5.646a.5.5 0 0 1 .708 0L8 8.293l2.646-2.647a.5.5 0 1 1 .708.708L8.354 9.354a.5.5 0 0 1-.708 0L4.646 6.354a.5.5 0 0 1 0-.708z" fill="currentColor"/>
|
|
367
|
+
</svg>
|
|
368
|
+
</button>
|
|
369
|
+
<strong>{{ mod.name }}</strong>
|
|
370
|
+
<span class="text-muted ms-2">({{ mod.tests|length }} tests)</span>
|
|
371
|
+
<div class="ms-auto d-flex gap-2">
|
|
372
|
+
<button type="button"
|
|
373
|
+
class="btn btn-sm btn-primary"
|
|
374
|
+
data-mod-select-all="{{ mod.name }}">
|
|
375
|
+
Select All
|
|
376
|
+
</button>
|
|
377
|
+
<button type="button"
|
|
378
|
+
class="btn btn-sm btn-secondary"
|
|
379
|
+
data-mod-deselect-all="{{ mod.name }}">
|
|
380
|
+
Deselect All
|
|
381
|
+
</button>
|
|
382
|
+
</div>
|
|
383
|
+
</div>
|
|
384
|
+
<div id="{{ mod_id }}" class="collapse">
|
|
385
|
+
<div class="card-body">
|
|
386
|
+
<div class="row row-cols-1 row-cols-md-2 row-cols-lg-3 g-2">
|
|
387
|
+
{% for t in mod.tests %}
|
|
388
|
+
{% set test_id = 'test_' ~ t.id|replace('/','_') %}
|
|
389
|
+
{% set is_mandatory = t.meta.mandatory | default(0) == 1 %}
|
|
390
|
+
{% set is_selected = t.id in selected_tests %}
|
|
391
|
+
{% set has_selections = selected_tests|length > 0 %}
|
|
392
|
+
{% set tip_id = 'tip_' ~ t.id|replace('/','_') %}
|
|
393
|
+
{% set test_doc = t.meta.documentation %}
|
|
394
|
+
|
|
395
|
+
<div class="col">
|
|
396
|
+
<div class="form-check">
|
|
397
|
+
<input class="form-check-input"
|
|
398
|
+
type="checkbox"
|
|
399
|
+
id="{{ test_id }}"
|
|
400
|
+
name="tests[]"
|
|
401
|
+
value="{{ t.id }}"
|
|
402
|
+
data-mod="{{ mod.name }}"
|
|
403
|
+
{% if is_selected %}checked{% elif is_mandatory and not has_selections %}checked{% endif %}>
|
|
404
|
+
<label class="form-check-label {% if is_mandatory %}fw-bold{% endif %}" for="{{ test_id }}">
|
|
405
|
+
{{ t.label }}
|
|
406
|
+
{% if is_mandatory %}
|
|
407
|
+
<span class="mandatory-badge">Mandatory</span>
|
|
408
|
+
{% endif %}
|
|
409
|
+
{{ kb_link(test_doc) }}
|
|
410
|
+
</label>
|
|
411
|
+
{% if t.tooltip %}
|
|
412
|
+
<div class="text-muted" style="font-size: 0.875rem; font-weight: normal; margin-top: 0.25rem;">{{ t.tooltip }}</div>
|
|
413
|
+
{% endif %}
|
|
414
|
+
</div>
|
|
415
|
+
|
|
416
|
+
{# Test parameters #}
|
|
417
|
+
{% set params_list = t.meta.allSupportedValues | default([]) %}
|
|
418
|
+
{% if params_list %}
|
|
419
|
+
<div id="{{ test_id }}_params" class="ms-4 mt-1 ps-2 border-start d-none">
|
|
420
|
+
<div class="small text-muted mb-1">Parameters</div>
|
|
421
|
+
<div class="d-flex flex-wrap gap-2">
|
|
422
|
+
{% for p in params_list %}
|
|
423
|
+
{% set pid = test_id ~ '_p_' ~ loop.index %}
|
|
424
|
+
<div class="form-check">
|
|
425
|
+
<input class="form-check-input"
|
|
426
|
+
type="checkbox"
|
|
427
|
+
id="{{ pid }}"
|
|
428
|
+
name="params_{{ t.id|replace('/','_') }}[]"
|
|
429
|
+
value="{{ p }}"
|
|
430
|
+
checked>
|
|
431
|
+
<label class="form-check-label small" for="{{ pid }}">{{ p }}</label>
|
|
432
|
+
</div>
|
|
433
|
+
{% endfor %}
|
|
434
|
+
</div>
|
|
435
|
+
</div>
|
|
436
|
+
{% endif %}
|
|
437
|
+
</div>
|
|
438
|
+
{% endfor %}
|
|
439
|
+
</div>
|
|
440
|
+
</div>
|
|
441
|
+
</div>
|
|
442
|
+
</div>
|
|
443
|
+
{% endif %}
|
|
444
|
+
{% endfor %}
|
|
445
|
+
|
|
446
|
+
<!-- Additional form fields for CLI parameters -->
|
|
447
|
+
{% set cert_schema = cert_schema %}
|
|
448
|
+
|
|
449
|
+
<hr class="my-4">
|
|
450
|
+
<h4>Run Parameters</h4>
|
|
451
|
+
{% set common_parameters = ['dut', 'custom_broker'] %}
|
|
452
|
+
|
|
453
|
+
{% for f in cert_schema.fields %}
|
|
454
|
+
{% if f.name != 'validation_schema' and f.name != 'tl' and f.name in common_parameters %}
|
|
455
|
+
{% set arg_label = (f.option_strings|join(', ') if f.option_strings else f.name) %}
|
|
456
|
+
{% set tip_id = 'help_' ~ f.name %}
|
|
457
|
+
{% set field_name = cert_schema.title ~ '_' ~ f.name %}
|
|
458
|
+
{% set field_value = form_data.get(field_name, f.default if f.default is not none else '') %}
|
|
459
|
+
|
|
460
|
+
<div class="row mb-3">
|
|
461
|
+
<label for="{{ field_name }}" class="col-sm-3 col-form-label">
|
|
462
|
+
{{ arg_label }}{% if f.required %} <span class="text-danger">*</span>{% endif %}
|
|
463
|
+
</label>
|
|
464
|
+
{% if f.widget == "select" %}
|
|
465
|
+
<div class="col-sm-4">
|
|
466
|
+
<select id="{{ field_name }}" class="form-select" name="{{ field_name }}">
|
|
467
|
+
{% if f.default == None %}
|
|
468
|
+
<option value="">select value</option>
|
|
469
|
+
{% endif %}
|
|
470
|
+
{% for c in f.choices %}
|
|
471
|
+
<option value="{{ c }}" {% if c == field_value %}selected{% endif %}>{{ c }}</option>
|
|
472
|
+
{% endfor %}
|
|
473
|
+
</select>
|
|
474
|
+
</div>
|
|
475
|
+
{% elif f.is_flag %}
|
|
476
|
+
<div class="col-sm-4">
|
|
477
|
+
<div class="form-check">
|
|
478
|
+
<input type="checkbox" class="form-check-input" id="{{ field_name }}" name="{{ field_name }}" {% if field_value %}checked{% endif %}>
|
|
479
|
+
</div>
|
|
480
|
+
</div>
|
|
481
|
+
{% elif f.name == "overwrite_defaults" %}
|
|
482
|
+
<div class="col-sm-4">
|
|
483
|
+
<textarea id="{{ field_name }}" class="form-control" name="{{ field_name }}" rows="3" placeholder="key1=value1 key2=value2">{{ field_value }}</textarea>
|
|
484
|
+
</div>
|
|
485
|
+
{% elif f.name == "custom_broker" %}
|
|
486
|
+
<div class="col-sm-4">
|
|
487
|
+
<input type="file" class="form-control" id="{{ field_name }}" name="{{ field_name }}_file" accept=".json">
|
|
488
|
+
{% if field_value %}
|
|
489
|
+
{% set path_parts = field_value.replace('\\', '/').split('/') %}
|
|
490
|
+
<div class="form-text">Current: {{ path_parts[-1] if path_parts|length > 1 else field_value }}</div>
|
|
491
|
+
{% endif %}
|
|
492
|
+
</div>
|
|
493
|
+
{% else %}
|
|
494
|
+
<div class="col-sm-4">
|
|
495
|
+
<input type="{{ f.type }}" class="form-control" id="{{ field_name }}" name="{{ field_name }}" value="{{ field_value }}">
|
|
496
|
+
</div>
|
|
497
|
+
{% endif %}
|
|
498
|
+
{% if f.help or f.help_link %}
|
|
499
|
+
<div class="col-sm-5 d-flex align-items-center">
|
|
500
|
+
<span class="text-muted" style="font-size: 0.875rem; font-weight: normal;">
|
|
501
|
+
{{ f.help }}
|
|
502
|
+
{% if f.help_link %}
|
|
503
|
+
<a href="{{ f.help_link }}" target="_blank" class="kb-link" title="Knowledge Base">Knowledge Base</a>
|
|
504
|
+
{% endif %}
|
|
505
|
+
</span>
|
|
506
|
+
</div>
|
|
507
|
+
{% endif %}
|
|
508
|
+
</div>
|
|
509
|
+
{% endif %}
|
|
510
|
+
{% endfor %}
|
|
511
|
+
|
|
512
|
+
<div class="card mb-3">
|
|
513
|
+
<div class="card-header d-flex align-items-center">
|
|
514
|
+
<button class="btn btn-sm btn-link text-decoration-none test-toggle me-2 collapsed"
|
|
515
|
+
type="button"
|
|
516
|
+
data-bs-toggle="collapse"
|
|
517
|
+
data-bs-target="#advancedParams"
|
|
518
|
+
aria-expanded="false">
|
|
519
|
+
<svg class="chev" width="16" height="16" viewBox="0 0 16 16">
|
|
520
|
+
<path d="M4.646 5.646a.5.5 0 0 1 .708 0L8 8.293l2.646-2.647a.5.5 0 1 1 .708.708L8.354 9.354a.5.5 0 0 1-.708 0L4.646 6.354a.5.5 0 0 1 0-.708z" fill="currentColor"/>
|
|
521
|
+
</svg>
|
|
522
|
+
</button>
|
|
523
|
+
<strong>Advanced Parameters</strong>
|
|
524
|
+
</div>
|
|
525
|
+
<div id="advancedParams" class="collapse">
|
|
526
|
+
<div class="card-body">
|
|
527
|
+
{% for f in cert_schema.fields %}
|
|
528
|
+
{% if f.name != 'validation_schema' and f.name != 'tl' and f.name not in common_parameters %}
|
|
529
|
+
{% set arg_label = (f.option_strings|join(', ') if f.option_strings else f.name) %}
|
|
530
|
+
{% set tip_id = 'help_' ~ f.name %}
|
|
531
|
+
{% set field_name = cert_schema.title ~ '_' ~ f.name %}
|
|
532
|
+
{% set field_value = form_data.get(field_name, f.default if f.default is not none else '') %}
|
|
533
|
+
|
|
534
|
+
<div class="row mb-3">
|
|
535
|
+
<label for="{{ field_name }}" class="col-sm-3 col-form-label">
|
|
536
|
+
{{ arg_label }}
|
|
537
|
+
</label>
|
|
538
|
+
{% if f.widget == "select" %}
|
|
539
|
+
<div class="col-sm-4">
|
|
540
|
+
<select id="{{ field_name }}" class="form-select" name="{{ field_name }}">
|
|
541
|
+
{% if f.default == None %}
|
|
542
|
+
<option value="">select value</option>
|
|
543
|
+
{% endif %}
|
|
544
|
+
{% for c in f.choices %}
|
|
545
|
+
<option value="{{ c }}" {% if c == field_value %}selected{% endif %}>{{ c }}</option>
|
|
546
|
+
{% endfor %}
|
|
547
|
+
</select>
|
|
548
|
+
</div>
|
|
549
|
+
{% elif f.is_flag %}
|
|
550
|
+
<div class="col-sm-4">
|
|
551
|
+
<div class="form-check">
|
|
552
|
+
<input type="checkbox" class="form-check-input" id="{{ field_name }}" name="{{ field_name }}" {% if field_value %}checked{% endif %}>
|
|
553
|
+
</div>
|
|
554
|
+
</div>
|
|
555
|
+
{% elif f.name == "overwrite_defaults" %}
|
|
556
|
+
<div class="col-sm-4">
|
|
557
|
+
<textarea id="{{ field_name }}" class="form-control" name="{{ field_name }}" rows="3" placeholder="key1=value1 key2=value2">{{ field_value }}</textarea>
|
|
558
|
+
</div>
|
|
559
|
+
{% elif f.name == "port" %}
|
|
560
|
+
<div class="col-sm-4">
|
|
561
|
+
<select id="{{ field_name }}" class="form-select" name="{{ field_name }}">
|
|
562
|
+
<option value="">Select a port</option>
|
|
563
|
+
{% for port_info in available_ports %}
|
|
564
|
+
<option value="{{ port_info.value }}" {% if port_info.value == field_value %}selected{% endif %}>{{ port_info.label }}</option>
|
|
565
|
+
{% endfor %}
|
|
566
|
+
{% if field_value and field_value not in available_ports|map(attribute='value')|list %}
|
|
567
|
+
<option value="{{ field_value }}" selected>{{ field_value }} (not available)</option>
|
|
568
|
+
{% endif %}
|
|
569
|
+
</select>
|
|
570
|
+
</div>
|
|
571
|
+
{% else %}
|
|
572
|
+
<div class="col-sm-4">
|
|
573
|
+
<input type="{{ f.type }}" class="form-control" id="{{ field_name }}" name="{{ field_name }}" value="{{ field_value }}">
|
|
574
|
+
</div>
|
|
575
|
+
{% endif %}
|
|
576
|
+
{% if f.help or f.help_link %}
|
|
577
|
+
<div class="col-sm-5 d-flex align-items-center">
|
|
578
|
+
<span class="text-muted" style="font-size: 0.875rem; font-weight: normal;">
|
|
579
|
+
{{ f.help }}
|
|
580
|
+
{% if f.help_link %}
|
|
581
|
+
<a href="{{ f.help_link }}" target="_blank" class="kb-link" title="Knowledge Base">Knowledge Base</a>
|
|
582
|
+
{% endif %}
|
|
583
|
+
</span>
|
|
584
|
+
</div>
|
|
585
|
+
{% endif %}
|
|
586
|
+
</div>
|
|
587
|
+
{% endif %}
|
|
588
|
+
{% endfor %}
|
|
589
|
+
</div>
|
|
590
|
+
</div>
|
|
591
|
+
</div>
|
|
592
|
+
|
|
593
|
+
<!-- Step 5: Review and Run -->
|
|
594
|
+
{% elif step_num == 5 %}
|
|
595
|
+
<h3>Step 5: Review and Run</h3>
|
|
596
|
+
|
|
597
|
+
<!-- Summary -->
|
|
598
|
+
<div class="card mb-4">
|
|
599
|
+
<div class="card-header">
|
|
600
|
+
<h5 class="mb-0">Configuration Summary</h5>
|
|
601
|
+
</div>
|
|
602
|
+
<div class="card-body">
|
|
603
|
+
<p><strong>Flavor:</strong>
|
|
604
|
+
{% if flavor == 'gw_only' %}Gateway Only
|
|
605
|
+
{% elif flavor == 'bridge_only' %}Bridge Only
|
|
606
|
+
{% elif flavor == 'combo' %}Combo (Gateway + Bridge)
|
|
607
|
+
{% endif %}
|
|
608
|
+
</p>
|
|
609
|
+
<p><strong>Validation Schema:</strong> {{ schema_path.split('/')[-1] if schema_path else 'Not uploaded' }}</p>
|
|
610
|
+
<p><strong>Selected Modules:</strong> {{ selected_modules|join(', ') }}</p>
|
|
611
|
+
<p><strong>Selected Tests:</strong> {{ total_test_count }} test(s)</p>
|
|
612
|
+
<p><strong>Certification Status:</strong>
|
|
613
|
+
{% if is_certified %}
|
|
614
|
+
<span class="badge bg-success">READY FOR CERTIFICATION</span>
|
|
615
|
+
<small class="text-muted d-block mt-1">All mandatory modules and tests are selected</small>
|
|
616
|
+
{% else %}
|
|
617
|
+
<span class="badge bg-warning text-dark">{{ non_cert_text }}</span>
|
|
618
|
+
<small class="text-muted d-block mt-1">Some mandatory modules or tests are missing</small>
|
|
619
|
+
{% endif %}
|
|
620
|
+
</p>
|
|
621
|
+
|
|
622
|
+
{% if not is_certified %}
|
|
623
|
+
{% if missing_modules %}
|
|
624
|
+
<div class="alert alert-warning">
|
|
625
|
+
<strong>Missing Mandatory Modules:</strong>
|
|
626
|
+
<ul class="mb-0">
|
|
627
|
+
{% for mod in missing_modules %}
|
|
628
|
+
<li>{{ mod }}</li>
|
|
629
|
+
{% endfor %}
|
|
630
|
+
</ul>
|
|
631
|
+
</div>
|
|
632
|
+
{% endif %}
|
|
633
|
+
{% if missing_additional_module %}
|
|
634
|
+
<div class="alert alert-warning">
|
|
635
|
+
<strong>Missing Additional Module:</strong>
|
|
636
|
+
<ul class="mb-0">
|
|
637
|
+
{% if flavor == 'bridge_only' %}
|
|
638
|
+
<li>Bridge Only requires at least one additional module beyond the mandatory module (edge_mgmt)</li>
|
|
639
|
+
{% elif flavor == 'combo' %}
|
|
640
|
+
<li>Combo requires at least one additional bridge module beyond the mandatory modules (cloud_connectivity and edge_mgmt)</li>
|
|
641
|
+
{% endif %}
|
|
642
|
+
</ul>
|
|
643
|
+
</div>
|
|
644
|
+
{% endif %}
|
|
645
|
+
{% if missing_tests_details %}
|
|
646
|
+
<div class="alert alert-warning">
|
|
647
|
+
<strong>Missing Mandatory Tests:</strong>
|
|
648
|
+
<ul class="mb-0">
|
|
649
|
+
{% for test in missing_tests_details %}
|
|
650
|
+
<li>{{ test.label }} <small class="text-muted">({{ test.module }})</small></li>
|
|
651
|
+
{% endfor %}
|
|
652
|
+
</ul>
|
|
653
|
+
</div>
|
|
654
|
+
{% endif %}
|
|
655
|
+
{% endif %}
|
|
656
|
+
</div>
|
|
657
|
+
</div>
|
|
658
|
+
|
|
659
|
+
<!-- Schema Verification -->
|
|
660
|
+
<div class="card mb-4">
|
|
661
|
+
<div class="card-header">
|
|
662
|
+
<h5 class="mb-0">Schema Verification</h5>
|
|
663
|
+
</div>
|
|
664
|
+
<div class="card-body">
|
|
665
|
+
{% if schema_errors or schema_warnings %}
|
|
666
|
+
{% if schema_errors %}
|
|
667
|
+
<div class="alert alert-danger">
|
|
668
|
+
<strong>Errors:</strong>
|
|
669
|
+
<ul class="mb-0">
|
|
670
|
+
{% for err in schema_errors %}
|
|
671
|
+
<li>{{ err }}</li>
|
|
672
|
+
{% endfor %}
|
|
673
|
+
</ul>
|
|
674
|
+
</div>
|
|
675
|
+
{% endif %}
|
|
676
|
+
{% if schema_warnings %}
|
|
677
|
+
<div class="alert alert-warning">
|
|
678
|
+
<strong>Warnings:</strong>
|
|
679
|
+
<ul class="mb-0">
|
|
680
|
+
{% for warn in schema_warnings %}
|
|
681
|
+
<li>{{ warn }}</li>
|
|
682
|
+
{% endfor %}
|
|
683
|
+
</ul>
|
|
684
|
+
</div>
|
|
685
|
+
{% endif %}
|
|
686
|
+
{% else %}
|
|
687
|
+
<p><strong>Schema Status:</strong>
|
|
688
|
+
<span class="badge bg-success">SCHEMA MATCHES TEST CONFIGURATION</span>
|
|
689
|
+
<small class="text-muted d-block mt-1">The uploaded schema matches the selected flavor, modules, and tests</small>
|
|
690
|
+
</p>
|
|
691
|
+
{% endif %}
|
|
692
|
+
</div>
|
|
693
|
+
</div>
|
|
694
|
+
|
|
695
|
+
<!-- Run Parameters Summary -->
|
|
696
|
+
{% set cert_schema = cert_schema %}
|
|
697
|
+
{% set cb_index = -1 %}
|
|
698
|
+
{% for f in cert_schema.fields %}
|
|
699
|
+
{% if f.name == 'custom_broker' %}
|
|
700
|
+
{% set cb_index = loop.index0 %}
|
|
701
|
+
{% endif %}
|
|
702
|
+
{% endfor %}
|
|
703
|
+
{% set has_advanced = False %}
|
|
704
|
+
{% for f in cert_schema.fields %}
|
|
705
|
+
{% if f.name != 'validation_schema' and f.name != 'tl' and cb_index >= 0 and loop.index0 > cb_index %}
|
|
706
|
+
{% set has_advanced = True %}
|
|
707
|
+
{% endif %}
|
|
708
|
+
{% endfor %}
|
|
709
|
+
{% if has_advanced %}
|
|
710
|
+
<div class="card mb-4">
|
|
711
|
+
<div class="card-header">
|
|
712
|
+
<h5 class="mb-0">Run Parameters</h5>
|
|
713
|
+
</div>
|
|
714
|
+
<div class="card-body">
|
|
715
|
+
{% for f in cert_schema.fields %}
|
|
716
|
+
{% if f.name != 'validation_schema' and f.name != 'tl' %}
|
|
717
|
+
{% set field_name = cert_schema.title ~ '_' ~ f.name %}
|
|
718
|
+
{% set field_value = form_data.get(field_name, f.default if f.default is not none else '') %}
|
|
719
|
+
{% set is_advanced = cb_index >= 0 and loop.index0 > cb_index %}
|
|
720
|
+
|
|
721
|
+
{% if not is_advanced %}
|
|
722
|
+
{% set arg_label = (f.option_strings|join(', ') if f.option_strings else f.name) %}
|
|
723
|
+
<p><strong>{{ arg_label }}:</strong>
|
|
724
|
+
{% if f.is_flag %}
|
|
725
|
+
{{ 'Yes' if field_value else 'No' }}
|
|
726
|
+
{% else %}
|
|
727
|
+
{{ field_value if field_value else '(not set)' }}
|
|
728
|
+
{% endif %}
|
|
729
|
+
</p>
|
|
730
|
+
{% endif %}
|
|
731
|
+
{% endif %}
|
|
732
|
+
{% endfor %}
|
|
733
|
+
|
|
734
|
+
{% if has_advanced %}
|
|
735
|
+
<div class="mb-3">
|
|
736
|
+
<button class="btn btn-outline-secondary btn-sm" type="button" data-bs-toggle="collapse" data-bs-target="#advancedParamsReview" aria-expanded="false" aria-controls="advancedParamsReview">
|
|
737
|
+
Advanced Parameters ▼
|
|
738
|
+
</button>
|
|
739
|
+
</div>
|
|
740
|
+
<div class="collapse" id="advancedParamsReview">
|
|
741
|
+
{% for f in cert_schema.fields %}
|
|
742
|
+
{% if f.name != 'validation_schema' and f.name != 'tl' %}
|
|
743
|
+
{% set field_name = cert_schema.title ~ '_' ~ f.name %}
|
|
744
|
+
{% set field_value = form_data.get(field_name, f.default if f.default is not none else '') %}
|
|
745
|
+
{% set is_advanced = cb_index >= 0 and loop.index0 > cb_index %}
|
|
746
|
+
|
|
747
|
+
{% if is_advanced %}
|
|
748
|
+
{% set arg_label = (f.option_strings|join(', ') if f.option_strings else f.name) %}
|
|
749
|
+
<p><strong>{{ arg_label }}:</strong>
|
|
750
|
+
{% if f.is_flag %}
|
|
751
|
+
{{ 'Yes' if field_value else 'No' }}
|
|
752
|
+
{% else %}
|
|
753
|
+
{{ field_value if field_value else '(not set)' }}
|
|
754
|
+
{% endif %}
|
|
755
|
+
</p>
|
|
756
|
+
{% endif %}
|
|
757
|
+
{% endif %}
|
|
758
|
+
{% endfor %}
|
|
759
|
+
</div>
|
|
760
|
+
{% endif %}
|
|
761
|
+
</div>
|
|
762
|
+
</div>
|
|
763
|
+
{% endif %}
|
|
764
|
+
|
|
765
|
+
<!-- Edit Links -->
|
|
766
|
+
<div class="mb-4">
|
|
767
|
+
<p>Need to make changes?</p>
|
|
768
|
+
<a href="{{ url_for('step', step_num=1) }}" class="btn btn-outline-secondary btn-sm me-2">Edit Flavor</a>
|
|
769
|
+
<a href="{{ url_for('step', step_num=2) }}" class="btn btn-outline-secondary btn-sm me-2">Edit Schema</a>
|
|
770
|
+
{% if flavor != 'gw_only' %}
|
|
771
|
+
<a href="{{ url_for('step', step_num=3) }}" class="btn btn-outline-secondary btn-sm me-2">Edit Modules</a>
|
|
772
|
+
{% endif %}
|
|
773
|
+
<a href="{{ url_for('step', step_num=4) }}" class="btn btn-outline-secondary btn-sm">Edit Tests</a>
|
|
774
|
+
</div>
|
|
775
|
+
|
|
776
|
+
<!-- Run Button -->
|
|
777
|
+
<div class="d-grid gap-2">
|
|
778
|
+
<button type="submit" name="action" value="run" class="btn btn-primary btn-lg">Run Certificate</button>
|
|
779
|
+
<div class="d-flex gap-2">
|
|
780
|
+
<a href="{{ url_for('export_config') }}" class="btn btn-outline-primary flex-fill">Export Run Settings</a>
|
|
781
|
+
<a href="{{ url_for('clear_session') }}" class="btn btn-outline-secondary flex-fill">Start New Run</a>
|
|
782
|
+
</div>
|
|
783
|
+
</div>
|
|
784
|
+
|
|
785
|
+
{% endif %}
|
|
786
|
+
|
|
787
|
+
<!-- Navigation Buttons -->
|
|
788
|
+
<div class="d-flex justify-content-between mt-4">
|
|
789
|
+
{% if step_num > 1 %}
|
|
790
|
+
<button type="submit" name="action" value="back" class="btn btn-secondary">← Back</button>
|
|
791
|
+
{% else %}
|
|
792
|
+
<div></div>
|
|
793
|
+
{% endif %}
|
|
794
|
+
|
|
795
|
+
{% if step_num < 5 %}
|
|
796
|
+
<button type="submit" name="action" value="next" class="btn btn-primary" id="nextBtn">Next →</button>
|
|
797
|
+
{% else %}
|
|
798
|
+
<div></div>
|
|
799
|
+
{% endif %}
|
|
800
|
+
</div>
|
|
801
|
+
</form>
|
|
802
|
+
|
|
803
|
+
<!-- Load Previous Run Settings -->
|
|
804
|
+
{% if step_num == 1 %}
|
|
805
|
+
<!-- Divider -->
|
|
806
|
+
<br>
|
|
807
|
+
<div class="position-relative my-4">
|
|
808
|
+
<hr>
|
|
809
|
+
<div class="position-absolute top-50 start-50 translate-middle bg-white px-3">
|
|
810
|
+
<span class="text-muted fw-bold">OR Use Previous Run Settings...</span>
|
|
811
|
+
</div>
|
|
812
|
+
</div>
|
|
813
|
+
<br>
|
|
814
|
+
<!-- Load Previous Run Settings -->
|
|
815
|
+
<div class="card mb-4">
|
|
816
|
+
<div class="card-header">
|
|
817
|
+
<h5 class="mb-0">Load Previous Run Settings</h5>
|
|
818
|
+
</div>
|
|
819
|
+
<div class="card-body">
|
|
820
|
+
<form method="POST" action="{{ url_for('import_config') }}" enctype="multipart/form-data">
|
|
821
|
+
<div class="mb-3">
|
|
822
|
+
<label for="config_file" class="form-label">Load Saved Run Settings (JSON)</label>
|
|
823
|
+
<input type="file" class="form-control" id="config_file" name="config_file" accept=".json">
|
|
824
|
+
<div class="form-text">Select a previously exported certificate run settings file.</div>
|
|
825
|
+
</div>
|
|
826
|
+
<button type="submit" class="btn btn-primary">Load Run Settings</button>
|
|
827
|
+
</form>
|
|
828
|
+
</div>
|
|
829
|
+
</div>
|
|
830
|
+
{% endif %}
|
|
831
|
+
</div>
|
|
832
|
+
|
|
833
|
+
<br><br>
|
|
834
|
+
|
|
835
|
+
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.0.2/dist/js/bootstrap.bundle.min.js" integrity="sha384-MrcW6ZMFYlzcLA8Nl+NtUVF0sA7MsXsP1UyJoMp4YLEuNSfAP+JcXn/tWtIaxVXM" crossorigin="anonymous"></script>
|
|
836
|
+
<script>
|
|
837
|
+
// Configuration data from backend
|
|
838
|
+
const stepNum = {{ step_num }};
|
|
839
|
+
const selectedFlavor = {{ flavor|tojson }};
|
|
840
|
+
const mandatoryModules = {{ mandatory_modules_for_js|tojson|safe }};
|
|
841
|
+
const mandatoryTests = {{ mandatory_tests_for_js|tojson|safe }};
|
|
842
|
+
const currentSelectedModules = {{ selected_modules|tojson|safe }};
|
|
843
|
+
const brgCertSchema = {{ cert_schema|tojson|safe }};
|
|
844
|
+
|
|
845
|
+
// Step 3: Module selection validation
|
|
846
|
+
function checkStep3Validation() {
|
|
847
|
+
if (stepNum !== 3) return;
|
|
848
|
+
|
|
849
|
+
const warningDiv = document.getElementById('step3_warning');
|
|
850
|
+
const warningText = document.getElementById('step3_warning_text');
|
|
851
|
+
if (!warningDiv || !warningText) return;
|
|
852
|
+
|
|
853
|
+
const selectedModules = Array.from(document.querySelectorAll('input[name="modules[]"]:checked'))
|
|
854
|
+
.map(cb => cb.value);
|
|
855
|
+
|
|
856
|
+
let warnings = [];
|
|
857
|
+
|
|
858
|
+
// Check if mandatory modules are deselected
|
|
859
|
+
const missingMandatory = mandatoryModules.filter(m => !selectedModules.includes(m));
|
|
860
|
+
if (missingMandatory.length > 0) {
|
|
861
|
+
warnings.push('Missing mandatory modules: ' + missingMandatory.join(', '));
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
// Check Bridge/Combo requirement for at least one additional module
|
|
865
|
+
if (selectedFlavor === 'bridge_only' || selectedFlavor === 'combo') {
|
|
866
|
+
const nonMandatorySelected = selectedModules.filter(m => !mandatoryModules.includes(m));
|
|
867
|
+
if (nonMandatorySelected.length === 0) {
|
|
868
|
+
if (selectedFlavor === 'bridge_only') {
|
|
869
|
+
warnings.push('Bridge only requires at least one additional module beyond the mandatory Edge Management module');
|
|
870
|
+
} else {
|
|
871
|
+
warnings.push('Combo requires at least one additional bridge module beyond the mandatory Edge Management module');
|
|
872
|
+
}
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
if (warnings.length > 0) {
|
|
877
|
+
warningText.innerHTML = warnings.join('<br>');
|
|
878
|
+
warningDiv.style.display = 'block';
|
|
879
|
+
} else {
|
|
880
|
+
warningDiv.style.display = 'none';
|
|
881
|
+
}
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Step 4: Test selection validation
|
|
885
|
+
function checkStep4Validation() {
|
|
886
|
+
if (stepNum !== 4) return;
|
|
887
|
+
|
|
888
|
+
const warningDiv = document.getElementById('step4_warning');
|
|
889
|
+
const warningText = document.getElementById('step4_warning_text');
|
|
890
|
+
if (!warningDiv || !warningText) return;
|
|
891
|
+
|
|
892
|
+
const selectedTests = Array.from(document.querySelectorAll('input[name="tests[]"]:checked'))
|
|
893
|
+
.map(cb => cb.value);
|
|
894
|
+
|
|
895
|
+
// Use modules from backend (selected in step 3)
|
|
896
|
+
const selectedModules = currentSelectedModules || [];
|
|
897
|
+
|
|
898
|
+
let warnings = [];
|
|
899
|
+
|
|
900
|
+
// Check if mandatory modules are deselected (from step 3)
|
|
901
|
+
const missingMandatoryModules = mandatoryModules.filter(m => !selectedModules.includes(m));
|
|
902
|
+
if (missingMandatoryModules.length > 0) {
|
|
903
|
+
warnings.push('Missing mandatory modules: ' + missingMandatoryModules.join(', '));
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
// Check if mandatory tests are deselected
|
|
907
|
+
const missingMandatoryTests = mandatoryTests
|
|
908
|
+
.filter(t => selectedModules.includes(t.module) && !selectedTests.includes(t.id))
|
|
909
|
+
.map(t => t.label + ' (' + t.module + ')');
|
|
910
|
+
if (missingMandatoryTests.length > 0) {
|
|
911
|
+
warnings.push('Missing mandatory tests: ' + missingMandatoryTests.length + ' test(s)');
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
if (warnings.length > 0) {
|
|
915
|
+
warningText.innerHTML = warnings.join('<br>');
|
|
916
|
+
warningDiv.style.display = 'block';
|
|
917
|
+
} else {
|
|
918
|
+
warningDiv.style.display = 'none';
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
// Module select all / deselect all functionality
|
|
923
|
+
document.addEventListener('click', (e) => {
|
|
924
|
+
// Handle Select All button
|
|
925
|
+
if (e.target.matches('button[data-mod-select-all]')) {
|
|
926
|
+
e.preventDefault();
|
|
927
|
+
const modName = e.target.getAttribute('data-mod-select-all');
|
|
928
|
+
|
|
929
|
+
document.querySelectorAll(`input[type=checkbox][data-mod="${modName}"]:not([disabled])`).forEach(cb => {
|
|
930
|
+
cb.checked = true;
|
|
931
|
+
const params = document.getElementById(cb.id + '_params');
|
|
932
|
+
if (params) {
|
|
933
|
+
params.classList.remove('d-none');
|
|
934
|
+
// Also select all parameters for this test
|
|
935
|
+
const paramCheckboxes = params.querySelectorAll('input[type=checkbox][name^="params_"]');
|
|
936
|
+
paramCheckboxes.forEach(paramCb => {
|
|
937
|
+
paramCb.checked = true;
|
|
938
|
+
});
|
|
939
|
+
}
|
|
940
|
+
});
|
|
941
|
+
|
|
942
|
+
// Trigger validation and save
|
|
943
|
+
if (stepNum === 4) {
|
|
944
|
+
checkStep4Validation();
|
|
945
|
+
debouncedSave();
|
|
946
|
+
}
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
// Handle Deselect All button
|
|
950
|
+
if (e.target.matches('button[data-mod-deselect-all]')) {
|
|
951
|
+
e.preventDefault();
|
|
952
|
+
const modName = e.target.getAttribute('data-mod-deselect-all');
|
|
953
|
+
|
|
954
|
+
document.querySelectorAll(`input[type=checkbox][data-mod="${modName}"]:not([disabled])`).forEach(cb => {
|
|
955
|
+
cb.checked = false;
|
|
956
|
+
const params = document.getElementById(cb.id + '_params');
|
|
957
|
+
if (params) {
|
|
958
|
+
params.classList.add('d-none');
|
|
959
|
+
// Also deselect all parameters for this test
|
|
960
|
+
const paramCheckboxes = params.querySelectorAll('input[type=checkbox][name^="params_"]');
|
|
961
|
+
paramCheckboxes.forEach(paramCb => {
|
|
962
|
+
paramCb.checked = false;
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
|
|
967
|
+
// Trigger validation and save
|
|
968
|
+
if (stepNum === 4) {
|
|
969
|
+
checkStep4Validation();
|
|
970
|
+
debouncedSave();
|
|
971
|
+
}
|
|
972
|
+
}
|
|
973
|
+
});
|
|
974
|
+
|
|
975
|
+
document.addEventListener('change', (e) => {
|
|
976
|
+
// Show/hide params panel when test checkbox toggles
|
|
977
|
+
if (e.target.matches('input[type=checkbox][name="tests[]"]')) {
|
|
978
|
+
const params = document.getElementById(e.target.id + '_params');
|
|
979
|
+
if (params) {
|
|
980
|
+
params.classList.toggle('d-none', !e.target.checked);
|
|
981
|
+
|
|
982
|
+
// If test is being checked, select all its parameters
|
|
983
|
+
if (e.target.checked) {
|
|
984
|
+
const paramCheckboxes = params.querySelectorAll('input[type=checkbox][name^="params_"]');
|
|
985
|
+
paramCheckboxes.forEach(paramCb => {
|
|
986
|
+
paramCb.checked = true;
|
|
987
|
+
});
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
// Trigger validation
|
|
992
|
+
if (stepNum === 4) checkStep4Validation();
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
// Handle parameter checkbox changes - deselect test if all parameters are deselected
|
|
996
|
+
if (e.target.matches('input[type=checkbox][name^="params_"]')) {
|
|
997
|
+
// Find the test checkbox associated with this parameter
|
|
998
|
+
// Parameter name format: params_{{ test_id|replace('/','_') }}[]
|
|
999
|
+
const paramName = e.target.name;
|
|
1000
|
+
const testIdMatch = paramName.match(/^params_(.+)\[\]$/);
|
|
1001
|
+
if (testIdMatch) {
|
|
1002
|
+
const testIdBase = testIdMatch[1];
|
|
1003
|
+
// Find all parameter checkboxes for this test
|
|
1004
|
+
const allParams = document.querySelectorAll(`input[type=checkbox][name="${paramName}"]`);
|
|
1005
|
+
const checkedParams = document.querySelectorAll(`input[type=checkbox][name="${paramName}"]:checked`);
|
|
1006
|
+
|
|
1007
|
+
// If all parameters are unchecked, uncheck the test (including mandatory tests)
|
|
1008
|
+
if (checkedParams.length === 0 && allParams.length > 0) {
|
|
1009
|
+
// Find the test checkbox - need to match by test ID
|
|
1010
|
+
// Test IDs are in format like "module_test_id" or similar
|
|
1011
|
+
// We need to find the test checkbox that has parameters with this name pattern
|
|
1012
|
+
const testCheckboxes = document.querySelectorAll('input[type=checkbox][name="tests[]"]');
|
|
1013
|
+
testCheckboxes.forEach(testCb => {
|
|
1014
|
+
const testParamsDiv = document.getElementById(testCb.id + '_params');
|
|
1015
|
+
if (testParamsDiv) {
|
|
1016
|
+
// Check if this test has parameters with the matching name
|
|
1017
|
+
const testParams = testParamsDiv.querySelectorAll(`input[type=checkbox][name="${paramName}"]`);
|
|
1018
|
+
if (testParams.length > 0) {
|
|
1019
|
+
// This is the test that owns these parameters
|
|
1020
|
+
// Uncheck the test (applies to both mandatory and non-mandatory)
|
|
1021
|
+
testCb.checked = false;
|
|
1022
|
+
testParamsDiv.classList.add('d-none');
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
});
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
|
|
1029
|
+
// Trigger validation
|
|
1030
|
+
if (stepNum === 4) checkStep4Validation();
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
// Module checkbox change
|
|
1034
|
+
if (e.target.matches('input[name="modules[]"]')) {
|
|
1035
|
+
if (stepNum === 3) checkStep3Validation();
|
|
1036
|
+
if (stepNum === 4) checkStep4Validation();
|
|
1037
|
+
}
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
// Initialize params visibility for pre-checked tests
|
|
1041
|
+
(function initParamsVisibility() {
|
|
1042
|
+
document.querySelectorAll('input[type=checkbox][name="tests[]"]:checked').forEach(cb => {
|
|
1043
|
+
const params = document.getElementById(cb.id + '_params');
|
|
1044
|
+
if (params) params.classList.remove('d-none');
|
|
1045
|
+
});
|
|
1046
|
+
})();
|
|
1047
|
+
|
|
1048
|
+
// Step 4: Required fields validation for Next button
|
|
1049
|
+
function validateRequiredFieldsBeforeNext() {
|
|
1050
|
+
if (stepNum !== 4) return { valid: true, missing: [] };
|
|
1051
|
+
|
|
1052
|
+
const nextBtn = document.getElementById('nextBtn');
|
|
1053
|
+
if (!nextBtn) return { valid: true, missing: [] };
|
|
1054
|
+
|
|
1055
|
+
// Get required fields from schema (excluding validation_schema and tl)
|
|
1056
|
+
if (!brgCertSchema || !brgCertSchema.fields) {
|
|
1057
|
+
return { valid: true, missing: [] };
|
|
1058
|
+
}
|
|
1059
|
+
|
|
1060
|
+
const requiredFields = brgCertSchema.fields.filter(f =>
|
|
1061
|
+
f.required && f.name !== 'validation_schema' && f.name !== 'tl'
|
|
1062
|
+
);
|
|
1063
|
+
|
|
1064
|
+
const missingFields = [];
|
|
1065
|
+
|
|
1066
|
+
for (const field of requiredFields) {
|
|
1067
|
+
const fieldName = `${brgCertSchema.title}_${field.name}`;
|
|
1068
|
+
let fieldValue = null;
|
|
1069
|
+
|
|
1070
|
+
// Special handling for custom_broker file upload
|
|
1071
|
+
if (field.name === 'custom_broker') {
|
|
1072
|
+
const fileInput = document.querySelector(`input[name="${fieldName}_file"]`);
|
|
1073
|
+
if (fileInput && fileInput.files && fileInput.files.length > 0) {
|
|
1074
|
+
fieldValue = fileInput.files[0].name;
|
|
1075
|
+
} else {
|
|
1076
|
+
// Check if there's a current value displayed
|
|
1077
|
+
const currentValueDiv = fileInput?.closest('.col-sm-4')?.querySelector('.form-text');
|
|
1078
|
+
if (currentValueDiv) {
|
|
1079
|
+
fieldValue = 'exists';
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
} else {
|
|
1083
|
+
// For other fields, check input/select value
|
|
1084
|
+
const inputs = document.querySelectorAll(`input[name="${fieldName}"], select[name="${fieldName}"]`);
|
|
1085
|
+
for (const input of inputs) {
|
|
1086
|
+
if (input.value && input.value.trim()) {
|
|
1087
|
+
fieldValue = input.value.trim();
|
|
1088
|
+
break;
|
|
1089
|
+
}
|
|
1090
|
+
}
|
|
1091
|
+
}
|
|
1092
|
+
|
|
1093
|
+
if (!fieldValue) {
|
|
1094
|
+
missingFields.push(field.name || field.label);
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
|
|
1098
|
+
return {
|
|
1099
|
+
valid: missingFields.length === 0,
|
|
1100
|
+
missing: missingFields
|
|
1101
|
+
};
|
|
1102
|
+
}
|
|
1103
|
+
|
|
1104
|
+
// Intercept form submission for Next button in step 4
|
|
1105
|
+
const mainForm = document.getElementById('mainForm');
|
|
1106
|
+
if (mainForm) {
|
|
1107
|
+
mainForm.addEventListener('submit', function(e) {
|
|
1108
|
+
const action = e.submitter?.value || (new FormData(e.target)).get('action');
|
|
1109
|
+
if (action === 'next' && stepNum === 4) {
|
|
1110
|
+
const validation = validateRequiredFieldsBeforeNext();
|
|
1111
|
+
if (!validation.valid) {
|
|
1112
|
+
e.preventDefault();
|
|
1113
|
+
if (validation.missing.length === 1) {
|
|
1114
|
+
alert(`Please provide ${validation.missing[0]} to continue`);
|
|
1115
|
+
} else {
|
|
1116
|
+
alert(`Please provide the following required fields to continue: ${validation.missing.join(', ')}`);
|
|
1117
|
+
}
|
|
1118
|
+
return false;
|
|
1119
|
+
}
|
|
1120
|
+
}
|
|
1121
|
+
});
|
|
1122
|
+
}
|
|
1123
|
+
|
|
1124
|
+
// Run initial validation on page load
|
|
1125
|
+
if (stepNum === 3) {
|
|
1126
|
+
checkStep3Validation();
|
|
1127
|
+
} else if (stepNum === 4) {
|
|
1128
|
+
checkStep4Validation();
|
|
1129
|
+
}
|
|
1130
|
+
|
|
1131
|
+
// Show run completion modal if run was just completed
|
|
1132
|
+
{% if run_completed %}
|
|
1133
|
+
(function() {
|
|
1134
|
+
const terminal = {{ run_terminal|tojson }} || 'Unknown';
|
|
1135
|
+
const pid = {{ run_pid|tojson }};
|
|
1136
|
+
const isCertified = {{ run_is_certified|tojson }};
|
|
1137
|
+
|
|
1138
|
+
function showModal() {
|
|
1139
|
+
if (stepNum !== 5) return;
|
|
1140
|
+
|
|
1141
|
+
const modalEl = document.getElementById('runCompletionModal');
|
|
1142
|
+
if (!modalEl) {
|
|
1143
|
+
console.error('Modal element not found');
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1146
|
+
|
|
1147
|
+
// Update modal content
|
|
1148
|
+
const terminalEl = document.getElementById('runTerminal');
|
|
1149
|
+
const pidEl = document.getElementById('runPid');
|
|
1150
|
+
const pidSection = document.getElementById('pidSection');
|
|
1151
|
+
const warningEl = document.getElementById('testRunWarning');
|
|
1152
|
+
|
|
1153
|
+
if (terminalEl) terminalEl.textContent = terminal;
|
|
1154
|
+
if (pid && pidEl && pidSection) {
|
|
1155
|
+
pidEl.textContent = pid;
|
|
1156
|
+
pidSection.style.display = 'block';
|
|
1157
|
+
} else if (pidSection) {
|
|
1158
|
+
pidSection.style.display = 'none';
|
|
1159
|
+
}
|
|
1160
|
+
if (warningEl) {
|
|
1161
|
+
warningEl.style.display = !isCertified ? 'block' : 'none';
|
|
1162
|
+
}
|
|
1163
|
+
|
|
1164
|
+
// Show modal
|
|
1165
|
+
if (typeof bootstrap !== 'undefined') {
|
|
1166
|
+
const modal = new bootstrap.Modal(modalEl);
|
|
1167
|
+
modal.show();
|
|
1168
|
+
} else {
|
|
1169
|
+
console.error('Bootstrap not loaded');
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
// Wait for DOM and Bootstrap to be ready
|
|
1174
|
+
if (document.readyState === 'loading') {
|
|
1175
|
+
document.addEventListener('DOMContentLoaded', function() {
|
|
1176
|
+
setTimeout(showModal, 100);
|
|
1177
|
+
});
|
|
1178
|
+
} else {
|
|
1179
|
+
setTimeout(showModal, 100);
|
|
1180
|
+
}
|
|
1181
|
+
})();
|
|
1182
|
+
{% endif %}
|
|
1183
|
+
</script>
|
|
1184
|
+
|
|
1185
|
+
<!-- Run Completion Modal -->
|
|
1186
|
+
<div class="modal fade" id="runCompletionModal" tabindex="-1" aria-labelledby="runCompletionModalLabel" aria-hidden="true">
|
|
1187
|
+
<div class="modal-dialog modal-dialog-centered">
|
|
1188
|
+
<div class="modal-content">
|
|
1189
|
+
<div class="modal-header">
|
|
1190
|
+
<h5 class="modal-title" id="runCompletionModalLabel">Certificate Run Started</h5>
|
|
1191
|
+
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
1192
|
+
</div>
|
|
1193
|
+
<div class="modal-body">
|
|
1194
|
+
<p><strong>Terminal:</strong> <span id="runTerminal">Unknown</span></p>
|
|
1195
|
+
<p id="pidSection" style="display: none;"><strong>PID:</strong> <span id="runPid"></span></p>
|
|
1196
|
+
<div id="testRunWarning" class="alert alert-warning mt-3 mb-0" style="display: none;">
|
|
1197
|
+
<strong>⚠️ WARNING:</strong> This is a non-certifying run (mandatory tests/modules missing)
|
|
1198
|
+
</div>
|
|
1199
|
+
</div>
|
|
1200
|
+
<div class="modal-footer">
|
|
1201
|
+
<button type="button" class="btn btn-primary" data-bs-dismiss="modal">OK</button>
|
|
1202
|
+
</div>
|
|
1203
|
+
</div>
|
|
1204
|
+
</div>
|
|
1205
|
+
</div>
|
|
1206
|
+
</body>
|
|
1207
|
+
</html>
|