Allow generated URL's to be pointed at another webapp server.

master
Pacman Ghost 4 years ago
parent 7afae4fd8d
commit 8c6e3a6902
  1. 6
      conftest.py
  2. 8
      vasl_templates/webapp/main.py
  3. 4
      vasl_templates/webapp/static/css/main.css
  4. 7
      vasl_templates/webapp/static/main.js
  5. 12
      vasl_templates/webapp/static/snippets.js
  6. 11
      vasl_templates/webapp/static/utils.js
  7. 13
      vasl_templates/webapp/static/vo.js
  8. 3
      vasl_templates/webapp/templates/counter-image-urls.html
  9. 2
      vasl_templates/webapp/templates/index.html
  10. 1
      vasl_templates/webapp/templates/national-capabilities.html
  11. 1
      vasl_templates/webapp/templates/vo-notes-report.html
  12. 2
      vasl_templates/webapp/testing.py
  13. 8
      vasl_templates/webapp/tests/remote.py
  14. 73
      vasl_templates/webapp/tests/test_user_settings.py

@ -90,6 +90,7 @@ def webapp():
# initialize
server_url = pytest.config.option.server_url #pylint: disable=no-member
app.base_url = server_url if server_url else "http://localhost:{}".format(FLASK_WEBAPP_PORT)
logging.disable( logging.CRITICAL )
# initialize
@ -113,10 +114,7 @@ def webapp():
# to avoid problems if something else uses the clipboard while the tests are running.
kwargs["store_clipboard"] = 1
url = url_for( endpoint, _external=True, **kwargs )
if server_url:
url = url.replace( "http://localhost", server_url )
else:
url = url.replace( "localhost/", "localhost:{}/".format(FLASK_WEBAPP_PORT) )
url = url.replace( "http://localhost", app.base_url )
return url
app.url_for = make_webapp_url

@ -80,6 +80,14 @@ def get_app_config():
for key in ["APP_NAME","APP_VERSION","APP_DESCRIPTION","APP_HOME_URL"]:
vals[ key ] = getattr( vasl_templates.webapp.config.constants, key )
# NOTE: We allow the front-end to generate snippets that point to an alternative webapp server (so that
# VASSAL can get images, etc. from a Docker container rather than the desktop app). However, since it's
# unlikely anyone else will want this option, we implement it as a debug setting, rather than exposing it
# as an option in the UI.
alt_webapp_base_url = app.config.get( "ALTERNATE_WEBAPP_BASE_URL" )
if alt_webapp_base_url:
vals[ "ALTERNATE_WEBAPP_BASE_URL" ] = alt_webapp_base_url
# include information about VASSAL and VASL
from vasl_templates.webapp.vassal import VassalShim
try:

@ -18,6 +18,10 @@ label { height: 1.25em ; margin-top: -3px ; }
.PopMenu-Item a { padding: 5px 10px 5px 10px ; }
.PopMenu-Icon { display: none ; }
#alt-webapp-base-url { position: absolute ; top: 30px ; right: 110px ;
font-size: 80% ; font-style: italic ; color: #cc0000 ;
}
#watermark { position: absolute ; left: 8px ; right: 8px ; bottom: 6px ; height: 30% ; }
#watermark { background: url("../images/watermark2.png") left bottom repeat-x ; background-size: auto 100% ; z-index: -999 ; }
#watermark img { height: 100% ; }

@ -1,5 +1,3 @@
APP_URL_BASE = window.location.origin ;
gAppConfig = {} ;
gDefaultTemplatePack = null ;
gTemplatePack = {} ;
@ -258,6 +256,11 @@ $(document).ready( function () {
$.getJSON( gAppConfigUrl, function(data) {
gAppConfig = data ;
update_page_load_status( "app-config" ) ;
var alt_base_url = gAppConfig.ALTERNATE_WEBAPP_BASE_URL ;
if ( alt_base_url ) {
var $elem = $( "#alt-webapp-base-url" ) ;
$elem.text( $elem.text() + " " + alt_base_url ).show() ;
}
} ).fail( function( xhr, status, errorMsg ) {
showErrorMsg( "Can't get the application config:<div class='pre'>" + escapeHTML(errorMsg) + "</div>" ) ;
} ) ;

@ -136,7 +136,7 @@ function make_snippet( $btn, params, extra_params, show_date_warnings )
params.TIMESTAMP = (new Date()).toISOString() ;
params.IMAGES_BASE_URL = gUserSettings["scenario-images-source"] == SCENARIO_IMAGES_SOURCE_INTERNET ?
gAppConfig.ONLINE_IMAGES_URL_BASE :
APP_URL_BASE + gImagesBaseUrl ;
make_app_url( gImagesBaseUrl, true ) ;
if ( gUserSettings["snippet-font-family"] ) {
// NOTE: Layout of snippets ends up being slightly different on Windows and Linux, presumably because
// VASSAL is using different fonts. Unfortunately, explicitly specifying which font to use doesn't
@ -459,8 +459,12 @@ function make_snippet( $btn, params, extra_params, show_date_warnings )
}
// fixup any user file URL's
snippet = strReplaceAll( snippet, "{{USER_FILES}}", APP_URL_BASE+"/user" ) ;
snippet = strReplaceAll( snippet, "{{CHAPTER_H}}", APP_URL_BASE+"/chapter-h" ) ;
snippet = strReplaceAll( snippet, "{{USER_FILES}}",
make_app_url( "/user", true )
) ;
snippet = strReplaceAll( snippet, "{{CHAPTER_H}}",
make_app_url( "/chapter-h", true )
) ;
// tidy up the final snippet
snippet = snippet.replace( /[^\S\r\n]+$/gm, "" ) ; // nb: trim trailing whitespace
@ -562,7 +566,7 @@ function get_vo_note( vo_type, nat, key )
// FUDGE! We need to detect between a full HTML note and an image-based one.
// This is not great, but it'll do... :-/
if ( vo_note.substr( 0, nat.length+1 ) === nat+"/" )
return APP_URL_BASE + "/" + vo_type + "/" + nat + "/note/" + key ;
return make_app_url( "/" + vo_type + "/" + nat + "/note/" + key, true ) ;
else
return vo_note ;
}

@ -1,6 +1,15 @@
// --------------------------------------------------------------------
function make_app_url( url, for_snippet )
{
// generate a URL that accesses this webapp
var base_url = window.location.origin ;
if ( for_snippet && gAppConfig.ALTERNATE_WEBAPP_BASE_URL )
base_url = gAppConfig.ALTERNATE_WEBAPP_BASE_URL ;
return base_url + url ;
}
function get_nationality_display_name( nat_id )
{
// get the nationality's display name
@ -59,7 +68,7 @@ function make_player_flag_url( nat, for_snippet ) {
if ( for_snippet && gUserSettings["scenario-images-source"] == SCENARIO_IMAGES_SOURCE_INTERNET )
return gAppConfig.ONLINE_IMAGES_URL_BASE + "/flags/" + nat + ".png" ;
else
return APP_URL_BASE + "/flags/" + nat ;
return make_app_url( "/flags/" + nat, for_snippet ) ;
}
function get_player_no_for_element( $elem )

@ -197,7 +197,7 @@ function do_add_vo( vo_type, player_no, vo_entry, vo_image_id, elite, custom_cap
var vo_note = get_vo_note( vo_type, nat, vo_note_key ) ;
var vo_note_image_url = null ;
if ( vo_note )
vo_note_image_url = APP_URL_BASE + "/" + vo_type + "/" + nat + "/note/" + vo_note_key ;
vo_note_image_url = make_app_url( "/" + vo_type + "/" + nat + "/note/" + vo_note_key, true ) ;
else {
// NOTE: Note numbers seem to be distinct across all Allied Minor or all Axis Minor vehicles/ordnance,
// so if we don't find a note in a given nationality's normal vehicles/ordnance, we can get away with
@ -206,7 +206,7 @@ function do_add_vo( vo_type, player_no, vo_entry, vo_image_id, elite, custom_cap
if ( ["allied-minor","axis-minor"].indexOf( nat_type ) !== -1 ) {
vo_note = get_vo_note( vo_type, nat_type, vo_note_key ) ;
if ( vo_note )
vo_note_image_url = APP_URL_BASE + "/" + vo_type + "/" + nat_type + "/note/" + vo_note_key ;
vo_note_image_url = make_app_url( "/" + vo_type + "/" + nat_type + "/note/" + vo_note_key, true ) ;
}
}
if ( vo_note ) {
@ -426,7 +426,7 @@ function get_vo_image_url( vo_entry, vo_image_id, allow_missing_image, for_snipp
if ( for_snippet && gUserSettings["scenario-images-source"] == SCENARIO_IMAGES_SOURCE_INTERNET )
return make_online_counter_image_url( gpid, index ) ;
else
return make_local_counter_image_url( gpid, index ) ;
return make_local_counter_image_url( gpid, index, for_snippet ) ;
}
// couldn't find an image
@ -439,9 +439,12 @@ function get_vo_image_url( vo_entry, vo_image_id, allow_missing_image, for_snipp
return null ;
}
function make_local_counter_image_url( gpid, index )
function make_local_counter_image_url( gpid, index, for_snippet )
{
url = APP_URL_BASE + "/counter/" + gpid + "/front" ;
// generate the image URL for the specified vehicle/ordnance
// NOTE: This originally generated a URL that pointed back to the local webapp server,
// but this could possibly be changed to another webapp server (hence we need for_snippet).
url = make_app_url( "/counter/" + gpid + "/front", for_snippet ) ;
if ( index !== null )
url += "/" + index ;
return url ;

@ -20,7 +20,6 @@ td { border-bottom: 1px solid #eee ; font-size: 90% ; }
<script src="{{url_for('static',filename='utils.js')}}"></script>
<script>
APP_URL_BASE = window.location.origin ;
gAppConfig = null ;
gVaslPieceInfo = null ;
@ -99,7 +98,7 @@ function show_counter_image_urls( counters )
var index = 0 ;
// generate the counter image URL's
var url = make_local_counter_image_url( gpids[j], index ) ;
var url = make_local_counter_image_url( gpids[j], index, false ) ;
local_urls.push( "<a href='" + url + "' target='_blank'>" + url + "</a>" ) ;
url = make_online_counter_image_url( gpids[j], index ) ;
online_urls.push( "<a href='" + url + "' target='_blank'>" + url + "</a>" ) ;

@ -50,6 +50,8 @@
{%include "tabs.html"%}
<div id="alt-webapp-base-url" style="display:none;"> Webapp base URL: </div>
<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<div id="watermark" style="display:none;">

@ -28,7 +28,6 @@
<script>
APP_URL_BASE = window.location.origin ;
gAppConfig = {} ;
gUserSettings = {} ;
gTemplatePack = null ;

@ -2,7 +2,6 @@
<html lang="en">
<script>
APP_URL_BASE = window.location.origin ;
var nat = "{{NATIONALITY}}" ;
var vo_type = "{{VO_TYPE}}" ;
var gTemplatePack = {} ;

@ -29,7 +29,7 @@ def control_tests( action ):
sig = inspect.signature( func )
kwargs = {}
for param in sig.parameters.values():
if param.name in ("vengine","vmod","gpids","dtype","fname","dname","extns_dtype","bin_data"):
if param.name in ("vengine","vmod","gpids","key","val","dtype","fname","dname","extns_dtype","bin_data"):
kwargs[ param.name ] = request.args.get( param.name, param.default )
if param.name == "bin_data":
kwargs["bin_data"] = base64.b64decode( kwargs["bin_data"] )

@ -82,6 +82,14 @@ class ControlTests:
if isinstance( v, (str,int,bool,list,dict) )
}
def _set_app_config( self, key=None, val=None ):
"""Set the webapp config."""
if val is None:
del app.config[ key ]
else:
app.config[ key ] = val
return self
def _set_data_dir( self, dtype=None ):
"""Set the webapp's data directory."""
if dtype == "real":

@ -3,11 +3,12 @@
import json
import re
import pytest
from selenium.webdriver.support.ui import Select
from selenium.webdriver.common.keys import Keys
from vasl_templates.webapp.tests.utils import \
init_webapp, find_child, find_children, wait_for_clipboard, \
init_webapp, find_child, find_children, find_snippet_buttons, wait_for_clipboard, \
select_tab, select_menu_option, select_droplist_val, set_player, click_dialog_button, add_simple_note
from vasl_templates.webapp.tests.test_vehicles_ordnance import add_vo
from vasl_templates.webapp.tests.test_scenario_persistence import save_scenario, load_scenario
@ -284,6 +285,76 @@ def test_vo_notes_as_images( webapp, webdriver ):
# ---------------------------------------------------------------------
@pytest.mark.skipif( not pytest.config.option.vasl_mods, #pylint: disable=no-member
reason="--vasl-mods not specified"
)
def test_alternate_webapp_base_url( webapp, webdriver ):
"""Test changing the webapp base URL."""
# initialize
def _init_webapp(): #pylint: disable=missing-docstring
return init_webapp( webapp, webdriver, scenario_persistence=1,
reset = lambda ct:
ct.set_data_dir( dtype="real" ) \
.set_vasl_mod( vmod="random", extns_dtype="test" )
)
control_tests = _init_webapp()
# enable images
set_user_settings( {
"scenario-images-source": SCENARIO_IMAGES_SOURCE_THIS_PROGRAM,
"include-vasl-images-in-snippets": True,
"include-flags-in-snippets": True,
"custom-list-bullets": True,
"vo-notes-as-images": True,
} )
# load the scenario
load_scenario( {
"SCENARIO_NAME": "test scenario",
"SCENARIO_DATE": "01/01/1940",
"VICTORY_CONDITIONS": "Just do it!",
"SCENARIO_NOTES": [ { "caption": "Scenario note #1" } ],
"SSR": [ "SSR #1", "SSR #2", "SSR #3" ],
"PLAYER_1": "german",
"OB_SETUPS_1": [ { "caption": "OB setup note 1" } ],
"OB_NOTES_1": [ { "caption": "OB note 1" } ],
"OB_VEHICLES_1": [ { "name": "PzKpfw VG" } ],
"OB_ORDNANCE_1": [ { "name": "8.8cm PaK 43" } ],
"PLAYER_2": "russian",
"OB_SETUPS_2": [ { "caption": "OB setup note 2" } ],
"OB_NOTES_2": [ { "caption": "OB note 2" } ],
"OB_VEHICLES_2": [ { "name": "T-34/85" } ],
"OB_ORDNANCE_2": [ { "name": "82mm BM obr. 37" } ],
} )
def do_test( expected ): #pylint: disable=missing-docstring
# generate each snippet
snippet_btns = find_snippet_buttons()
for tab_id,btns in snippet_btns.items():
select_tab( tab_id )
for btn in btns:
snippet_id = btn.get_attribute( "data-id" )
btn.click()
buf = wait_for_clipboard( 2, re.compile( "<!-- vasl-templates:id (german/|russian/)?"+snippet_id ) )
# check each URL
for mo in re.finditer( r"<img .*?src=[\"'](.*?)[\"']", buf ):
url = mo.group(1)
assert url.startswith( expected )
# test with the default base URL
do_test( webapp.base_url + "/" )
# test with a custom base URL
try:
control_tests.set_app_config( key="ALTERNATE_WEBAPP_BASE_URL", val="http://ALT-BASE-URL" )
_init_webapp()
do_test( "http://ALT-BASE-URL/" )
finally:
control_tests.set_app_config( key="ALTERNATE_WEBAPP_BASE_URL", val=None )
# ---------------------------------------------------------------------
def set_user_settings( opts ):
"""Configure the user settings."""
select_menu_option( "user_settings" )

Loading…
Cancel
Save