Changed how template packs are loaded.

master
Pacman Ghost 6 years ago
parent 6efa5be3a1
commit 57ba72724d
  1. 6
      vasl_templates/main.py
  2. 0
      vasl_templates/webapp/data/default-template-pack/atmm.j2
  3. 0
      vasl_templates/webapp/data/default-template-pack/baz.j2
  4. 0
      vasl_templates/webapp/data/default-template-pack/mol-p.j2
  5. 0
      vasl_templates/webapp/data/default-template-pack/mol.j2
  6. 0
      vasl_templates/webapp/data/default-template-pack/nationalities.json
  7. 0
      vasl_templates/webapp/data/default-template-pack/ob_setup.j2
  8. 0
      vasl_templates/webapp/data/default-template-pack/pf.j2
  9. 0
      vasl_templates/webapp/data/default-template-pack/piat.j2
  10. 0
      vasl_templates/webapp/data/default-template-pack/players.j2
  11. 0
      vasl_templates/webapp/data/default-template-pack/psk.j2
  12. 0
      vasl_templates/webapp/data/default-template-pack/scenario.j2
  13. 0
      vasl_templates/webapp/data/default-template-pack/ssr.j2
  14. 0
      vasl_templates/webapp/data/default-template-pack/victory_conditions.j2
  15. 122
      vasl_templates/webapp/snippets.py
  16. 49
      vasl_templates/webapp/static/main.js
  17. 72
      vasl_templates/webapp/static/snippets.js
  18. 4
      vasl_templates/webapp/templates/index.html
  19. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/american/baz.j2
  20. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/british/piat.j2
  21. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/german/atmm.j2
  22. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/german/pf.j2
  23. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/german/psk.j2
  24. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/ob_setup.j2
  25. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/players.j2
  26. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/russian/mol-p.j2
  27. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/russian/mol.j2
  28. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/scenario.j2
  29. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/ssr.j2
  30. 1
      vasl_templates/webapp/tests/fixtures/template-packs/autoload/victory_conditions.j2
  31. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/american/baz.j2
  32. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/british/piat.j2
  33. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/german/atmm.j2
  34. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/german/pf.j2
  35. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/german/psk.j2
  36. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/ob_setup.j2
  37. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/players.j2
  38. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/russian/mol-p.j2
  39. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/russian/mol.j2
  40. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/scenario.j2
  41. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/ssr.j2
  42. 1
      vasl_templates/webapp/tests/fixtures/template-packs/new-default/victory_conditions.j2
  43. 14
      vasl_templates/webapp/tests/test_template_packs.py
  44. 7
      vasl_templates/webapp/tests/utils.py

@ -44,16 +44,16 @@ class LoggerProxy:
def main( template_pack, debug ):
"""Main entry point for the application."""
# configure the autoload template pack
# configure the default template pack
if template_pack:
if template_pack.lower().endswith( ".zip" ):
rc = os.path.isfile( template_pack )
else:
rc = os.path.isdir( template_pack )
if not rc:
click.echo( "ERROR: The template pack must be a ZIP file or a directory containing the template files." )
click.echo( "ERROR: The template pack must be a ZIP file, or a directory containing the template files." )
return 1
snippets.autoload_template_pack = template_pack
snippets.default_template_pack = template_pack
# install the debug config file
if debug:

@ -9,83 +9,73 @@ from flask import jsonify, abort
from vasl_templates.webapp import app
from vasl_templates.webapp.config.constants import DATA_DIR
autoload_template_pack = None
default_template_pack = None
# ---------------------------------------------------------------------
@app.route( "/templates/default" )
def get_default_templates():
"""Get the default templates."""
@app.route( "/template-pack" )
def get_template_pack():
"""Return a template pack.
# return the default templates
dname = os.path.join( DATA_DIR, "default-templates" )
return jsonify( _do_get_templates( dname ) )
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@app.route( "/templates/autoload" )
def get_autoload_templates():
"""Get the templates to auto-load at startup.
We would like the user to be able to specify a template pack to auto-load
when starting the desktop app, but it's a little tricky to programatically
get the frontend Javascript to accept an upload. We could possibly do it
by using QWebChannel, but this would only work if the webapp was running
inside PyQt. Instead, we get the frontend to call this endpoint when it
starts up, to get the (optional) autoload templates.
Loading template packs is currently handled in the front-end, but we need
this entry point for the webapp to get the *default* template pack.
If, in the future, we support loading other template packs from the backend,
we can add a parameter here to specify which one to return.
"""
# check if an autoload template pack has been configured
if not autoload_template_pack:
# nope - return an empty response
return jsonify( {} )
# check if the template pack is a directory
if os.path.isdir( autoload_template_pack ):
# yup - return the template files in it
templates = _do_get_templates( autoload_template_pack )
templates["_path_"] = autoload_template_pack
return jsonify( templates )
# initialize
# NOTE: We always start with the default nationalities data. Unlike template files,
# user-defined template packs can add to it, or modify existing entries, but not replace it.
base_dir = os.path.join( DATA_DIR, "default-template-pack/" )
data = { "templates": {} }
fname = os.path.join( base_dir, "nationalities.json" )
with open(fname,"r") as fp:
data["nationalities"] = json.load( fp )
# check if a default template pack has been configured
if default_template_pack:
dname = default_template_pack
data["_path_"] = dname
else:
# nope - use our default template pack
dname = base_dir
# check if we're loading the template pack from a directory
if os.path.isdir( dname ):
# yup - return the files in it
nat, templates =_do_get_template_pack( dname )
data["nationalities"].update( nat )
data["templates"] = templates
else:
# extract the template pack files from the specified ZIP file
if not os.path.isfile( dname ):
return jsonify( { "error": "Can't find template pack: {}".format(dname) } )
with zipfile.ZipFile( dname, "r" ) as zip_file:
for fname in zip_file.namelist():
if fname.endswith( "/" ):
continue
fdata = zip_file.read( fname ).decode( "utf-8" )
fname = os.path.split(fname)[1]
if fname.lower() == "nationalities.json":
data["nationalities"].update( json.loads( fdata ) )
else:
data[os.path.splitext(fname)[0]] = fdata
# return the template files in the specified ZIP file
if not os.path.isfile( autoload_template_pack ):
return jsonify( { "error": "Can't find template pack: {}".format(autoload_template_pack) } )
templates = {}
with zipfile.ZipFile( autoload_template_pack, "r" ) as zip_file:
for fname in zip_file.namelist():
if fname.endswith( "/" ):
continue
fname2 = os.path.split(fname)[1]
templates[os.path.splitext(fname2)[0]] = zip_file.read( fname ).decode( "utf-8" )
templates["_path_"] = autoload_template_pack
return jsonify( templates )
return jsonify( data )
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def _do_get_templates( dname ):
"""Get the specified templates."""
def _do_get_template_pack( dname ):
"""Get the specified template pack."""
if not os.path.isdir( dname ):
abort( 404 )
templates = {}
nationalities, templates = {}, {}
for root,_,fnames in os.walk(dname):
for fname in fnames:
fname = os.path.join( root, fname )
if os.path.splitext(fname)[1] != ".j2":
continue
with open(fname,"r") as fp:
fname = os.path.split(fname)[1]
templates[os.path.splitext(fname)[0]] = fp.read()
return templates
# ---------------------------------------------------------------------
@app.route( "/nationalities" )
def get_nationalities():
"""Get the nationalities table."""
# load the nationalities table
fname = os.path.join( DATA_DIR, "nationalities.json" )
with open(fname,"r") as fp:
nationalities = json.load( fp )
return jsonify( nationalities )
# add the next file to the results
with open( os.path.join(root,fname), "r" ) as fp:
if fname.lower() == "nationalities.json":
nationalities = json.load( fp )
elif os.path.splitext(fname)[1] == ".j2":
templates[os.path.splitext(fname)[0]] = fp.read()
return nationalities, templates

@ -1,7 +1,6 @@
var gNationalities = {} ;
var gTemplatePack = {} ;
var gDefaultNationalities = {} ;
var gDefaultTemplates = {} ;
var gUserDefinedTemplates = {} ;
var gValidTemplateIds = [] ;
var _NATIONALITY_SPECIFIC_BUTTONS = {
"russian": [ "mol", "mol-p" ],
@ -104,38 +103,28 @@ $(document).ready( function () {
$("select[name='PLAYER_1_SAN']").html( buf ) ;
$("select[name='PLAYER_2_SAN']").html( buf ) ;
// load the nationalities
$.getJSON( gGetNationalitiesUrl, function(data) {
gNationalities = data ;
gDefaultNationalities = $.extend( true, {}, data ) ;
load_nationalities() ;
on_new_scenario( false ) ;
} ).fail( function( xhr, status, errorMsg ) {
showErrorMsg( "Can't get the nationalities:<div class='pre'>" + escapeHTML(errorMsg) + "</div>" ) ;
} ) ;
// add handlers for player changes
$("select[name='PLAYER_1']").change( function() { on_player_change($(this)) ; } ) ;
$("select[name='PLAYER_2']").change( function() { on_player_change($(this)) ; } ) ;
// get the templates
$.getJSON( gGetDefaultTemplatesUrl, function(data) {
gDefaultTemplates = data ;
} ).fail( function( xhr, status, errorMsg ) {
showErrorMsg( "Can't get the default templates:<div class='pre'>" + escapeHTML(errorMsg) + "</div>" ) ;
} ) ;
$.getJSON( gGetAutoloadTemplatesUrl, function(data) {
// get the template pack
$.getJSON( gGetTemplatePackUrl, function(data) {
if ( "error" in data )
showErrorMsg( "Can't get the autoload templates:<div class='pre'>" + escapeHTML(data.error) + "</div>" ) ;
showErrorMsg( "Can't get the template pack:<div class='pre'>" + escapeHTML(data.error) + "</div>" ) ;
else {
if ( "_path_" in data ) {
showInfoMsg( "Auto-loaded template pack:<div class='pre'>" + escapeHTML(data._path_) + "</div>" ) ;
delete data._path_ ;
}
gUserDefinedTemplates = data ;
}
install_template_pack( data ) ;
on_new_scenario( false ) ;
gDefaultNationalities = $.extend( true, {}, data.nationalities ) ;
// NOTE: If we are loading a user-defined template pack, then what we think
// is the set of valid template ID's will depend on what's in it :-/
gValidTemplateIds = Object.keys( data.templates ) ;
} ).fail( function( xhr, status, errorMsg ) {
showErrorMsg( "Can't get the autoload templates:<div class='pre'>" + escapeHTML(errorMsg) + "</div>" ) ;
showErrorMsg( "Can't get the template pack:<div class='pre'>" + escapeHTML(errorMsg) + "</div>" ) ;
} ) ;
var prevHeight = [] ;
@ -211,14 +200,19 @@ $(document).ready( function () {
// --------------------------------------------------------------------
function load_nationalities()
function install_template_pack( data )
{
// install the template pack
gTemplatePack = data ;
// update the player droplists
var curSel1 = $("select[name='PLAYER_1']").val() ;
var curSel2 = $("select[name='PLAYER_2']").val() ;
var buf = [] ;
for ( var id in gNationalities )
buf.push( "<option value='" + id + "'>" + gNationalities[id].display_name + "</option>" ) ;
var nationalities = gTemplatePack.nationalities ;
for ( var id in nationalities )
buf.push( "<option value='" + id + "'>" + nationalities[id].display_name + "</option>" ) ;
buf = buf.join( "" ) ;
$("select[name='PLAYER_1']").html( buf ).val( curSel1 ) ;
$("select[name='PLAYER_2']").html( buf ).val( curSel2 ) ;
@ -241,9 +235,10 @@ function on_player_change( $select )
var player_nat = $select.find( "option:selected" ).val() ;
var $elem = $("#tabs .ui-tabs-nav a[href='#tabs-ob" + player_id + "']") ;
var image_url = gImagesBaseUrl + "/flags/" + player_nat + ".png" ;
var nationalities = gTemplatePack.nationalities ;
$elem.html(
"<img src='" + image_url + "'>&nbsp;" +
"<span>" + escapeHTML(gNationalities[player_nat].display_name) + " OB</span>"
"<span>" + escapeHTML(nationalities[player_nat].display_name) + " OB</span>"
) ;
// show/hide the nationality-specific buttons

@ -19,8 +19,10 @@ function generate_snippet( $btn )
storeMsgForTestSuite( "_last-error_", "" ) ;
// unload the template parameters
var params = unload_params() ;
var template_id = $btn.data( "id" ) ;
var params = unload_params() ;
// set player-specific parameters
if ( template_id === "ob_setup_1" ) {
template_id = "ob_setup" ;
params.OB_SETUP = params.OB_SETUP_1 ;
@ -35,18 +37,19 @@ function generate_snippet( $btn )
params.OB_SETUP_WIDTH = params.OB_SETUP_WIDTH_2 ;
delete params.OB_SETUP_WIDTH_2 ;
}
var nationalities = gTemplatePack.nationalities ;
var curr_tab = $("#tabs .ui-tabs-active a").attr( "href" ) ;
if ( curr_tab === "#tabs-ob1" ) {
params.OB_COLOR = gNationalities[params.PLAYER_1].ob_colors[0] ;
params.OB_COLOR_2 = gNationalities[params.PLAYER_1].ob_colors[1] ;
params.OB_COLOR = nationalities[params.PLAYER_1].ob_colors[0] ;
params.OB_COLOR_2 = nationalities[params.PLAYER_1].ob_colors[1] ;
} if ( curr_tab === "#tabs-ob2" ) {
params.OB_COLOR = gNationalities[params.PLAYER_2].ob_colors[0] ;
params.OB_COLOR_2 = gNationalities[params.PLAYER_2].ob_colors[1] ;
params.OB_COLOR = nationalities[params.PLAYER_2].ob_colors[0] ;
params.OB_COLOR_2 = nationalities[params.PLAYER_2].ob_colors[1] ;
}
// include the player display names
params.PLAYER_1_NAME = gNationalities[params.PLAYER_1].display_name ;
params.PLAYER_2_NAME = gNationalities[params.PLAYER_2].display_name ;
params.PLAYER_1_NAME = nationalities[params.PLAYER_1].display_name ;
params.PLAYER_2_NAME = nationalities[params.PLAYER_2].display_name ;
// extract the scenario date components
var scenario_date = $("input[name='SCENARIO_DATE']").datepicker( "getDate" ) ;
@ -117,7 +120,11 @@ function generate_snippet( $btn )
}
if ( template_id === "baz" ) {
if ( params.SCENARIO_DATE === "" || params.SCENARIO_YEAR <= 1941 || (params.SCENARIO_YEAR == 1942 && params.SCENARIO_MONTH < 11) )
showWarningMsg( "BAZ are only available from November 1942." ) ;
showWarningMsg( "BAZ are only available from November 1942." ) ;
}
if ( template_id === "atmm" ) {
if ( params.SCENARIO_DATE === "" || params.SCENARIO_YEAR < 1944 )
showWarningMsg( "ATMM are only available from 1944." ) ;
}
// check that the players have different nationalities
@ -187,10 +194,8 @@ function unload_params()
function get_template( template_id )
{
// get the specified template
if ( template_id in gUserDefinedTemplates )
return gUserDefinedTemplates[template_id] ;
else if ( template_id in gDefaultTemplates )
return gDefaultTemplates[template_id] ;
if ( template_id in gTemplatePack.templates )
return gTemplatePack.templates[template_id] ;
showErrorMsg( "Unknown template: <span class='pre'>" + escapeHTML(template_id) + "</span>" ) ;
return null ;
}
@ -206,7 +211,7 @@ function edit_template( template_id )
function on_template_change() {
// install the new template
gUserDefinedTemplates[template_id] = $("#edit-template textarea").val() ;
gTemplatePack.templates[template_id] = $("#edit-template textarea").val() ;
}
// let the user edit the template
@ -406,19 +411,23 @@ function do_load_template_pack( fname, data )
// initialize
var invalid_filename_extns = [] ;
var unknown_template_ids = [] ;
var new_templates = {} ;
var nationalities = null ;
var template_pack = {
nationalities: $.extend( true, {}, gDefaultNationalities ),
templates: {},
} ;
// initialize
function on_new_template( fname, data ) {
function on_template_pack_file( fname, data ) {
// make sure the filename is valid
if ( fname.toLowerCase() === "nationalities.json" ) {
var nationalities = null ;
try {
nationalities = JSON.parse( data ) ;
} catch( ex ) {
showWarningMsg( "Can't parse the nationalities JSON data:<div class='pre'>" + escapeHTML(ex) + "</div>" ) ;
return ;
}
$.extend( true, template_pack.nationalities, nationalities ) ;
return ;
}
if ( fname.substring(fname.length-3) != ".j2" ) {
@ -426,16 +435,16 @@ function do_load_template_pack( fname, data )
return ;
}
var template_id = fname.substring( 0, fname.length-3 ).toLowerCase() ;
if ( ! (template_id in gDefaultTemplates) ) {
if ( gValidTemplateIds.indexOf( template_id ) === -1 ) {
unknown_template_ids.push( fname ) ;
return ;
}
// save the new template file
new_templates[template_id] = data ;
// save the template pack file
template_pack.templates[template_id] = data ;
}
// initialize
function install_new_templates( success_msg ) {
function install_new_template_pack( success_msg ) {
// check if there were any errors
var ok = true ;
var buf, tid, i ;
@ -464,23 +473,16 @@ function do_load_template_pack( fname, data )
buf.push( escapeHTML(unknown_template_ids[i]) + "<br>" ) ;
buf.push( "</div>" ) ;
buf.push( "Must be one of:<div class='pre'><ul>" ) ;
for ( tid in gDefaultTemplates )
buf.push( "<li>" + escapeHTML(tid) + ".j2" ) ;
for ( i=0 ; i < gValidTemplateIds.length ; ++i )
buf.push( "<li>" + escapeHTML(gValidTemplateIds[i]) + ".j2" ) ;
buf.push( "</ul></div>" ) ;
showErrorMsg( buf.join("") ) ;
ok = false ;
}
if ( ! ok )
return ;
// all good - install the new templates
for ( tid in new_templates ){
gUserDefinedTemplates[tid] = new_templates[tid] ;
}
// install any user-defined nationality data
if ( nationalities !== null ) {
gNationalities = $.extend( true, {}, gDefaultNationalities, nationalities ) ;
load_nationalities() ;
}
// all good - install the new template pack
install_template_pack( template_pack ) ;
showInfoMsg( success_msg ) ;
}
@ -500,10 +502,10 @@ function do_load_template_pack( fname, data )
return ; // nb: ignore directory entries
if ( pos !== -1 )
fname = fname.substring( pos+1 ) ;
on_new_template( fname, data ) ;
on_template_pack_file( fname, data ) ;
} ).then( function() {
if ( --nFiles === 0 ) {
install_new_templates( "The template pack was loaded." ) ;
install_new_template_pack( "The template pack was loaded." ) ;
}
} ) ;
} ) ;
@ -515,8 +517,8 @@ function do_load_template_pack( fname, data )
// nope - assume an individual template file
if ( data instanceof ArrayBuffer )
data = String.fromCharCode.apply( null, new Uint8Array(data) ) ;
on_new_template( fname, data ) ;
install_new_templates( "The template file was loaded." ) ;
on_template_pack_file( fname, data ) ;
install_new_template_pack( "The template file was loaded." ) ;
}
}

@ -142,9 +142,7 @@
<script src="{{url_for('static',filename='jszip/jszip.min.js')}}"></script>
<script>
gImagesBaseUrl = "{{url_for('static',filename='images')}}" ;
gGetDefaultTemplatesUrl = "{{url_for('get_default_templates')}}" ;
gGetAutoloadTemplatesUrl = "{{url_for('get_autoload_templates')}}" ;
gGetNationalitiesUrl = "{{url_for('get_nationalities')}}" ;
gGetTemplatePackUrl = "{{url_for('get_template_pack')}}" ;
</script>
<script src="{{url_for('static',filename='main.js')}}"></script>
<script src="{{url_for('static',filename='snippets.js')}}"></script>

@ -88,20 +88,20 @@ def test_zip_files( webapp, webdriver ):
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def test_autoload_template_pack( webapp, webdriver ):
"""Test auto-loading template packs."""
def test_new_default_template_pack( webapp, webdriver ):
"""Test changing the default template pack."""
# configure the autoload template pack
dname = os.path.join( os.path.split(__file__)[0], "fixtures/template-packs/autoload/" )
# configure a new default template pack
dname = os.path.join( os.path.split(__file__)[0], "fixtures/template-packs/new-default/" )
from vasl_templates.webapp import snippets
snippets.autoload_template_pack = dname
snippets.default_template_pack = dname
# initialize
webdriver.get( webapp.url_for( "main" ) )
# check that the autoload'ed templates are being used
# check that the new templates are being used
_check_snippets(
lambda tid: "Autoload'ed {}.".format( tid.upper() )
lambda tid: "New default {}.".format( tid.upper() )
)
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

@ -34,7 +34,7 @@ def for_each_template( func ):
# generate a list of all the templates we need to test
templates_to_test = set()
dname = os.path.join( os.path.split(__file__)[0], "../data/default-templates" )
dname = os.path.join( os.path.split(__file__)[0], "../data/default-template-pack" )
for fname in os.listdir(dname):
fname,extn = os.path.splitext( fname )
if extn != ".j2":
@ -116,8 +116,9 @@ def set_template_params( params ):
def get_nationalities( webapp ):
"""Get the nationalities table."""
url = webapp.url_for( "get_nationalities" )
return json.load( urllib.request.urlopen( url ) )
url = webapp.url_for( "get_template_pack" )
template_pack = json.load( urllib.request.urlopen( url ) )
return template_pack["nationalities"]
# ---------------------------------------------------------------------

Loading…
Cancel
Save