diff --git a/vasl_templates/webapp/static/main.js b/vasl_templates/webapp/static/main.js index 3c1ff49..1ef372f 100644 --- a/vasl_templates/webapp/static/main.js +++ b/vasl_templates/webapp/static/main.js @@ -317,7 +317,7 @@ $(document).ready( function () { edit_template( $(this).data( "id" ) ) ; } ).html( "
Edit
" ) .attr( "title", "Edit the template." ) - .addClass( "ui-button" ) ; + .button( {} ) ; // watch for changes to the scenario name $("input[name='SCENARIO_NAME']").on( "input propertychange paste", function() { @@ -581,6 +581,22 @@ function install_template_pack( data ) update_ob_tab_header( 1 ) ; update_ob_tab_header( 2 ) ; } + + // update the snippet buttons + function update_button( $btn ) { + var template_id = $btn.attr( "data-id" ) ; + if ( template_id.substr( 0, 7 ) === "extras/" ) + return ; + if ( template_id.match( /^ob_(vehicles|ordnance).*_[12]$/ ) ) + template_id = template_id.substring( 0, template_id.length-2 ) ; + var enable = is_template_available( template_id ) ; + if ( $btn.parent().hasClass( "snippet-control" ) ) + $btn.parent().controlgroup( enable ? "enable" : "disable" ) ; + else + $btn.button( enable ? "enable": "disable" ) ; + } + $( "button.generate" ).each( function() { update_button( $(this) ) ; } ) ; + $( "button.edit-template" ).each( function() { update_button( $(this) ) ; } ) ; } // -------------------------------------------------------------------- diff --git a/vasl_templates/webapp/static/simple_notes.js b/vasl_templates/webapp/static/simple_notes.js index 75979de..21c62b4 100644 --- a/vasl_templates/webapp/static/simple_notes.js +++ b/vasl_templates/webapp/static/simple_notes.js @@ -125,10 +125,12 @@ function _make_simple_note( note_type, caption ) var buf = [ "
" ] ; if ( ["scenario_notes","ob_setups","ob_notes"].indexOf( note_type ) !== -1 ) { var note_type0 = note_type.substring( 0, note_type.length-1 ) ; - buf.push( - "" - ) ; + if ( is_template_available( note_type0 ) ) { + buf.push( + "" + ) ; + } } buf.push( caption, "
" ) ; var $content = $( buf.join("") ) ; diff --git a/vasl_templates/webapp/static/snippets.js b/vasl_templates/webapp/static/snippets.js index f69c9e3..29700d4 100644 --- a/vasl_templates/webapp/static/snippets.js +++ b/vasl_templates/webapp/static/snippets.js @@ -103,6 +103,10 @@ function generate_snippet( $btn, evt, extra_params ) showErrorMsg( "Can't copy to the clipboard:
" + escapeHTML(ex) + "
" ) ; return ; } + // NOTE: This notification will be shown even if there was an error generating the snippet, + // but the error message was copied to the clipboard, so it's still techincally correct... :-/ + // We disabled the ability to generate a snippet if a template file is not present, so it should + // only be an issue if there was a problem processing the template. showInfoMsg( "The HTML snippet has been copied to the clipboard." ) ; } diff --git a/vasl_templates/webapp/static/sortable.js b/vasl_templates/webapp/static/sortable.js index a0d83e9..f9a2822 100644 --- a/vasl_templates/webapp/static/sortable.js +++ b/vasl_templates/webapp/static/sortable.js @@ -78,7 +78,7 @@ $.fn.sortable2 = function( action, args ) $sortable2.data( "on_edit", args.edit ) ; var $add_btn = find_helper( $sortable2, "add" ) ; $add_btn.prepend( $( "
Add
" ) ) - .addClass( "ui-button" ) ; + .button( {} ) ; var $add = find_helper( $sortable2, "add" ) ; $add.prop( "title", "Add a new " + display_name[0] ) .click( args.add ) ; @@ -86,7 +86,7 @@ $.fn.sortable2 = function( action, args ) $sortable2.data( "on_reset", args.reset ) ; var $reset_btn = find_helper( $sortable2, "reset" ) ; $reset_btn.prepend( $( "
Reset
" ) ) - .addClass( "ui-button" ) ; + .button( {} ) ; var $reset = find_helper( $sortable2, "reset" ) ; $reset.prop( "title", "Reset the " + display_name[1] ) .click( args.reset ) ; diff --git a/vasl_templates/webapp/static/utils.js b/vasl_templates/webapp/static/utils.js index 53d4b3a..b556c1c 100644 --- a/vasl_templates/webapp/static/utils.js +++ b/vasl_templates/webapp/static/utils.js @@ -57,6 +57,14 @@ function get_scenario_date() return scenario_date ; } +function is_template_available( template_id ) +{ + // check if the specified template is available + if ( template_id.match( /^ob_(vehicles|ordnance).*_[12]$/ ) ) + template_id = template_id.substring( 0, template_id.length-2 ) ; + return gTemplatePack.templates[ template_id ] !== undefined ; +} + // -------------------------------------------------------------------- function copyToClipboard( val ) diff --git a/vasl_templates/webapp/static/vassal.js b/vasl_templates/webapp/static/vassal.js index e31d414..cacdf75 100644 --- a/vasl_templates/webapp/static/vassal.js +++ b/vasl_templates/webapp/static/vassal.js @@ -174,6 +174,8 @@ function _generate_snippets() function on_snippet_button( $btn, inactive ) { var template_id = $btn.attr( "data-id" ) ; + if ( ! is_template_available( template_id ) ) + return ; if ( template_id.substr(0,7) === "extras/" ) { // NOTE: We don't handle extras templates, since they can be parameterized. We would need to store // the parameter values in the generated snippet, and extract them here so that we can re-generate diff --git a/vasl_templates/webapp/static/vo.js b/vasl_templates/webapp/static/vo.js index f2db0b2..6f09c2f 100644 --- a/vasl_templates/webapp/static/vo.js +++ b/vasl_templates/webapp/static/vo.js @@ -179,10 +179,12 @@ function do_add_vo( vo_type, player_no, vo_entry, vo_image_id, custom_capabiliti } if ( vo_nat ) { var template_id = (vo_type === "vehicles") ? "ob_vehicle_note" : "ob_ordnance_note" ; - buf.push( - "" - ) ; + if ( is_template_available( template_id ) ) { + buf.push( + "" + ) ; + } var url = APP_URL_BASE + "/" + vo_type + "/" + vo_nat + "/note/" ; data.vo_note_url = url + vo_note_key ; } diff --git a/vasl_templates/webapp/tests/test_template_packs.py b/vasl_templates/webapp/tests/test_template_packs.py index 07b25d0..533e5a0 100644 --- a/vasl_templates/webapp/tests/test_template_packs.py +++ b/vasl_templates/webapp/tests/test_template_packs.py @@ -6,12 +6,14 @@ import tempfile import base64 import re +import pytest + from vasl_templates.webapp.tests.test_vehicles_ordnance import add_vo from vasl_templates.webapp.tests.utils import \ select_tab, select_menu_option, set_player, \ wait_for_clipboard, get_stored_msg, set_stored_msg, set_stored_msg_marker,\ add_simple_note, for_each_template, find_child, find_children, wait_for, \ - get_droplist_vals_index, init_webapp + get_droplist_vals_index, init_webapp, get_css_classes # --------------------------------------------------------------------- @@ -134,6 +136,69 @@ def test_nationality_data( webapp, webdriver ): # --------------------------------------------------------------------- +@pytest.mark.skipif( pytest.config.option.short_tests, reason="--short-tests specified" ) #pylint: disable=no-member +def test_missing_templates( webapp, webdriver ): + """Test UI updates for missing templates.""" + + # initialize + init_webapp( webapp, webdriver, template_pack_persistence=1 ) + + # get the files in the default template pack + files = {} + dname = os.path.normpath( os.path.join( os.path.split(__file__)[0], "../data/default-template-pack" ) ) + for root,_,fnames in os.walk( dname ): + for fname in fnames: + fname = os.path.join( root, fname ) + fname2 = os.path.relpath( fname, start=dname ) + if fname2.startswith( "extras/" ): + continue + files[ fname2 ] = "dummy template" # nb: we don't care about the content + + def adjust_template_id( template_id ): #pylint: disable=missing-docstring + if template_id.startswith( ( "ob_vehicles_", "ob_ordnance_" ) ) and template_id.endswith( ( "_1", "_2" ) ): + return template_id[:-2] + return template_id + + # upload the template pack, with one file missing each time + for fname in files: + + # generate and upload the modified template pack + zip_data = _make_zip( + { k: v for k,v in files.items() if k != fname } + ) + upload_template_pack_zip( zip_data, False ) + + # check the state of each button (everything should be enabled, except for the one + # corresponding to the template file we excluded from the upload) + def check_buttons( sel, is_snippet_control ): #pylint: disable=missing-docstring + for btn in find_children( sel ): + # check the UI state of the next button + template_id = adjust_template_id( btn.get_attribute( "data-id" ) ) + expected = os.path.splitext( fname )[0] == template_id + disabled = webdriver.execute_script( "return $(arguments[0]).button('option','disabled')", btn ) + assert expected == disabled + # check that snippet control groups have been enabled/disabled correctly + parent = btn.find_element_by_xpath( ".." ) + parent_classes = get_css_classes( parent ) + if is_snippet_control: + assert "snippet-control" in parent_classes + elem = find_child( ".ui-selectmenu-button", parent ) + elem_classes = get_css_classes( elem ) + if expected: + assert "ui-selectmenu-disabled" in elem_classes + else: + assert "ui-selectmenu-disabled" not in elem_classes + else: + assert "snippet-control" not in parent_classes + check_buttons( "button.generate", True ) + check_buttons( "button.edit-template", False ) + + # NOTE: We should really check that the "generate snippet" buttons don't appear in sortable entries, + # but that's more trouble than it's worth - templates such as ob_setup and ob_vehicles are never + # going to be missing, since the program becomes kinda pointless if they're not there :-/ + +# --------------------------------------------------------------------- + def _make_zip( files ): """Generate a ZIP file.""" with tempfile.NamedTemporaryFile() as temp_file: diff --git a/vasl_templates/webapp/tests/utils.py b/vasl_templates/webapp/tests/utils.py index ffcc153..353dc18 100644 --- a/vasl_templates/webapp/tests/utils.py +++ b/vasl_templates/webapp/tests/utils.py @@ -539,3 +539,10 @@ def adjust_html( val ): close_tag = "