diff --git a/vasl_templates/webapp/static/snippets.js b/vasl_templates/webapp/static/snippets.js index 961c4e7..5cd38ba 100644 --- a/vasl_templates/webapp/static/snippets.js +++ b/vasl_templates/webapp/static/snippets.js @@ -16,7 +16,8 @@ var _DAY_OF_MONTH_POSTFIXES = { // nb: we assume English :-/ var gDefaultScenario = null ; var gLastSavedScenario = null ; -var gLastSavedScenarioFilename = null; +var gLastSavedScenarioFilename = null ; +var gScenarioCreatedTime = null ; // -------------------------------------------------------------------- @@ -733,6 +734,7 @@ function do_load_scenario_data( params ) { // reset the scenario reset_scenario() ; + gScenarioCreatedTime = params._creation_time ; // auto-assign ID's to the OB setup notes and notes // NOTE: We do this here to handle scenarios that were created before these ID's were implemented. @@ -879,7 +881,7 @@ function do_load_scenario_data( params ) } // remember the state of this scenario - gLastSavedScenario = unload_params_for_save() ; + gLastSavedScenario = unload_params_for_save( false ) ; // update the UI $("#tabs").tabs( "option", "active", 0 ) ; @@ -936,7 +938,7 @@ function auto_assign_id( usedIds ) function on_save_scenario() { // unload the template parameters - var params = unload_params_for_save() ; + var params = unload_params_for_save( true ) ; var data = JSON.stringify( params ) ; // FOR TESTING PORPOISES! We can't control a file download from Selenium (since @@ -972,7 +974,7 @@ function on_save_scenario() gLastSavedScenario = params ; } -function unload_params_for_save() +function unload_params_for_save( user_requested ) { function extract_vo_entries( key ) { if ( !(key in params) ) @@ -1009,6 +1011,19 @@ function unload_params_for_save() if ( scenario_date ) params.SCENARIO_DATE = scenario_date.toISOString().substring( 0, 10 ) ; + // save some admin metadata + if ( user_requested ) { + params._app_version = gAppVersion ; + var now = (new Date()).toISOString() ; + params._last_update_time = now ; + if ( gScenarioCreatedTime ) + params._creation_time = gScenarioCreatedTime ; + else { + params._creation_time = now ; + gScenarioCreatedTime = now ; + } + } + return params ; } @@ -1089,8 +1104,13 @@ function is_scenario_dirty() // check if the scenario has been changed since it was loaded, or last saved if ( gLastSavedScenario === null ) return false ; - var params = unload_params_for_save() ; - return (JSON.stringify(params) != JSON.stringify(gLastSavedScenario) ) ; + var last_saved_scenario = {} ; + for ( var key in gLastSavedScenario ) { + if ( key.substr(0,1) !== "_" ) + last_saved_scenario[key] = gLastSavedScenario[key] ; + } + var params = unload_params_for_save( false ) ; + return (JSON.stringify(params) != JSON.stringify(last_saved_scenario) ) ; } // -------------------------------------------------------------------- diff --git a/vasl_templates/webapp/tests/test_scenario_persistence.py b/vasl_templates/webapp/tests/test_scenario_persistence.py index 476fca3..71eaff4 100644 --- a/vasl_templates/webapp/tests/test_scenario_persistence.py +++ b/vasl_templates/webapp/tests/test_scenario_persistence.py @@ -6,7 +6,7 @@ import re from selenium.webdriver.support.ui import Select -from vasl_templates.webapp.config.constants import APP_NAME +from vasl_templates.webapp.config.constants import APP_NAME, APP_VERSION from vasl_templates.webapp.tests.utils import \ init_webapp, get_nationality_display_name, load_scenario_params, select_tab, select_menu_option, \ get_sortable_entry_text, get_sortable_vo_names, get_stored_msg, set_stored_msg, set_stored_msg_marker, \ @@ -108,14 +108,18 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-st # save the scenario and check the results saved_scenario = save_scenario() + assert saved_scenario["_app_version"] == APP_VERSION + scenario_creation_time = saved_scenario["_creation_time"] + assert saved_scenario["_last_update_time"] == scenario_creation_time expected = { k: v for tab in SCENARIO_PARAMS.values() for k,v in tab.items() } mo = re.search( r"^(\d{2})/(\d{2})/(\d{4})$", expected["SCENARIO_DATE"] ) expected["SCENARIO_DATE"] = "{}-{}-{}".format( mo.group(3), mo.group(1), mo.group(2) ) # nb: convert from ISO-8601 - for key in saved_scenario: + saved_scenario2 = { k: v for k,v in saved_scenario.items() if not k.startswith("_") } + for key in saved_scenario2: if re.search( r"^OB_(VEHICLES|ORDNANCE)_\d$", key ): - for vo_entry in saved_scenario[key]: + for vo_entry in saved_scenario2[key]: del vo_entry["id"] for key in expected: if re.search( r"^OB_(VEHICLES|ORDNANCE)_\d$", key ): @@ -127,10 +131,10 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-st entry["id"] = 1+i for i,entry in enumerate(expected["SCENARIO_NOTES"]): entry["id"] = 1+i - assert saved_scenario == expected + assert saved_scenario2 == expected # make sure that our list of scenario parameters is correct - lhs = set( saved_scenario.keys() ) + lhs = set( saved_scenario2.keys() ) rhs = set( itertools.chain( *ALL_SCENARIO_PARAMS.values() ) ) assert lhs == rhs @@ -141,7 +145,10 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-st check_window_title( "" ) check_ob_tabs( "german", "russian" ) data = save_scenario() - data2 = { k: v for k,v in data.items() if v } + assert data["_app_version"] == APP_VERSION + assert data["_last_update_time"] == data["_creation_time"] + assert data["_creation_time"] > scenario_creation_time + data2 = { k: v for k,v in data.items() if not k.startswith("_") and v } assert data2 == { "SCENARIO_THEATER": "ETO", "PLAYER_1": "german", "PLAYER_1_ELR": "5", "PLAYER_1_SAN": "2", @@ -193,6 +200,11 @@ def test_scenario_persistence( webapp, webdriver ): #pylint: disable=too-many-st assert get_sortable_vo_names(vehicles2) == SCENARIO_PARAMS["ob2"]["OB_VEHICLES_2"] assert get_sortable_vo_names(ordnance2) == SCENARIO_PARAMS["ob2"]["OB_ORDNANCE_2"] + # save the scenario, make sure the timestamps are correct + data = save_scenario() + assert data["_creation_time"] == scenario_creation_time + assert data["_last_update_time"] > scenario_creation_time + def assert_scenario_params_complete( scenario_params ): """Check that a set of scenario parameters is complete.""" lhs = { k: set(v) for k,v in scenario_params.items() }