diff --git a/vasl_templates/webapp/static/simple_notes.js b/vasl_templates/webapp/static/simple_notes.js
index 2bb75f4..c64d911 100644
--- a/vasl_templates/webapp/static/simple_notes.js
+++ b/vasl_templates/webapp/static/simple_notes.js
@@ -4,30 +4,73 @@
// --------------------------------------------------------------------
-function add_scenario_note() { _do_edit_simple_note( $("#scenario_notes-sortable"), null, gDefaultScenario._SCENARIO_NOTE_WIDTH ) ; }
+function add_scenario_note() { _do_edit_simple_note( "scenario_note", null, $("#scenario_notes-sortable"), null, gDefaultScenario._SCENARIO_NOTE_WIDTH ) ; }
function do_add_scenario_note( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
-function edit_scenario_note( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
+function edit_scenario_note( $sortable2, $entry ) { _do_edit_simple_note( "scenario_note", null, $sortable2, $entry, null ) ; }
-function add_ssr() { _do_edit_simple_note( $("#ssr-sortable"), null, null ) ; }
+function add_ssr() { _do_edit_simple_note( "ssr", null, $("#ssr-sortable"), null, null ) ; }
function do_add_ssr( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
-function edit_ssr( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
+function edit_ssr( $sortable2, $entry ) { _do_edit_simple_note( "ssr", null, $sortable2, $entry, null ) ; }
-function add_ob_setup( player_no ) { _do_edit_simple_note( $("#ob_setups-sortable_"+player_no), null, gDefaultScenario._OB_SETUP_WIDTH ) ; }
+function add_ob_setup( player_no ) { _do_edit_simple_note( "ob_setup", player_no, $("#ob_setups-sortable_"+player_no), null, gDefaultScenario._OB_SETUP_WIDTH ) ; }
function do_add_ob_setup( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
-function edit_ob_setup( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
+function edit_ob_setup( $sortable2, $entry ) { _do_edit_simple_note( "ob_setup", get_player_no_for_element($sortable2), $sortable2, $entry, null ) ; }
-function add_ob_note( player_no ) { _do_edit_simple_note( $("#ob_notes-sortable_"+player_no), null, gDefaultScenario._OB_NOTE_WIDTH ) ; }
+function add_ob_note( player_no ) { _do_edit_simple_note( "ob_note", player_no, $("#ob_notes-sortable_"+player_no), null, gDefaultScenario._OB_NOTE_WIDTH ) ; }
function do_add_ob_note( $sortable2, data ) { _do_add_simple_note($sortable2,data) ; }
-function edit_ob_note( $sortable2, $entry ) { _do_edit_simple_note( $sortable2, $entry, null ) ; }
+function edit_ob_note( $sortable2, $entry ) { _do_edit_simple_note( "ob_note", get_player_no_for_element($sortable2), $sortable2, $entry, null ) ; }
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
-function _do_edit_simple_note( $sortable2, $entry, default_width )
+function _do_edit_simple_note( template_id, player_no, $sortable2, $entry, default_width )
{
// figure out what we're editing
var note_type = _get_note_type_for_sortable( $sortable2 ) ;
var note_type0 = note_type.substring( 0, note_type.length-1 ) ; // plural -> singular :-/
+ // determine the next available ID
+ var usedIds = {} ;
+ $sortable2.children( "li" ).each( function() {
+ usedIds[ $(this).data("sortable2-data").id ] = true ;
+ } ) ;
+ var nextAvailableId = auto_assign_id( usedIds, "id" ) ;
+
+ function makeSimpleSnippet( evt ) {
+ // initialize
+ var $btnPane = $( ".ui-dialog.edit-simple_note .ui-dialog-buttonpane" ) ;
+ var $btn = $btnPane.find( "button.snippet" ) ;
+ var caption = $caption.val().trim() ;
+ var width = $width.val().trim() ;
+ // prepare the template parameters
+ // NOTE: We don't bother handling the case of an empty caption.
+ var extraParams = {} ;
+ if ( template_id === "ssr" ) {
+ // NOTE: All the SSR's are combined into a single snippet, so it doesn't actually make sense
+ // to have a snippet button for individual SSR's, but it's convenient. We unload all the SSR's
+ // from the UI, then update the content for the one being edited (if it already exists), or
+ // add it to the end of the list (if it's a new one).
+ var ssrs = unload_ssrs() ;
+ if ( $entry ) {
+ // find and update the SSR being edited
+ $( "#ssr-sortable > li" ).each( function( index ) {
+ if ( $(this)[0] === $entry[0] )
+ ssrs[ index ] = caption ;
+ } ) ;
+ } else {
+ // add the new SSR to the end of the list
+ ssrs.push( caption ) ;
+ }
+ extraParams.SSR = ssrs ;
+ } else {
+ // override the template parameters unloaded from the UI with the current values from the dialog
+ var paramKey = template_id.toUpperCase() ;
+ extraParams[ paramKey ] = caption ;
+ extraParams[ paramKey+"_WIDTH" ] = width ;
+ }
+ // generate the snippet
+ generate_snippet( $btn, evt.shiftKey, extraParams ) ;
+ }
+
// let the user edit the note
var $caption, $width ;
$("#edit-simple_note").dialog( {
@@ -45,16 +88,35 @@ function _do_edit_simple_note( $sortable2, $entry, default_width )
on_dialog_open( $(this), $caption ) ;
add_flag_to_dialog_titlebar( $(this), get_player_no_for_element($sortable2) ) ;
var $btn_pane = $(".ui-dialog.edit-simple_note .ui-dialog-buttonpane") ;
- $width = $btn_pane.children( "input[name='width']" ) ;
+ var $btn = $btn_pane.find( "button.snippet" ) ;
+ $btn.prepend(
+ $( "" )
+ ) ;
+ $width = $btn_pane.find( "input[name='width']" ) ;
if ( $width.length === 0 ) {
// create the width controls
- $btn_pane.prepend( $(" ") ) ;
- $width = $btn_pane.children( "input[name='width']" ) ;
+ $btn_pane.prepend( $( "
" +
+ " " +
+ "
" ) ) ;
+ $width = $btn_pane.find( "input[name='width']" ) ;
}
+ // tweak the SNIPPETS button so that snippets will work
+ $btn.data( { id: template_id, "player-no": player_no } ) ;
+ var snippet_id = template_id ;
+ if ( player_no )
+ snippet_id += "_" + player_no ;
+ var entryData = $entry ? $entry.data("sortable2-data") : null ;
+ if ( template_id !== "ssr" )
+ snippet_id += "." + (entryData ? entryData.id : nextAvailableId) ;
+ $btn.data( "snippet-id", snippet_id ) ;
+ $btn.button( is_template_available( template_id ) ? "enable" : "disable" ) ;
// show/hide the width controls (nb: SSR's have a separate width setting that affects all of them)
var show = (note_type !== "ssr") ;
- $btn_pane.children( "label[for='width']" ).css( "display", show?"inline":"none" ) ;
+ $btn_pane.find( "label[for='width']" ).css( "display", show?"inline":"none" ) ;
$width.css( "display", show?"inline":"none" ) ;
+ $btn.css( { position: "absolute", left:
+ show ? $width.offset().left + $width.width() - $btn_pane.find("label[for='width']").offset().left + 25 : 15
+ } ) ;
// enable auto-dismiss for the dialog
var $dlg = $(this) ;
$width.keydown( function(evt) { auto_dismiss_dialog( $dlg, evt, "OK" ) ; } ) ;
@@ -65,12 +127,12 @@ function _do_edit_simple_note( $sortable2, $entry, default_width )
border: "1px solid "+colors[2]
} ) ;
// load the dialog
- var data = $entry ? $entry.data("sortable2-data") : null ;
- $caption.val( data ? data.caption : "" ).focus() ;
- $width.val( data ? data.width : default_width ) ;
+ $caption.val( entryData ? entryData.caption : "" ).focus() ;
+ $width.val( entryData ? entryData.width : default_width ) ;
$(this).height( $(this).height() ) ; // fudge: force the textarea to resize
},
buttons: {
+ Snippet: { text:" Snippet", class: "snippet", click: makeSimpleSnippet },
OK: function() {
var caption = $caption.val().trim() ;
var width = $width.val().trim() ;
@@ -88,13 +150,8 @@ function _do_edit_simple_note( $sortable2, $entry, default_width )
// create a new note
if ( caption !== "" ) {
data = { caption: caption, width: width } ;
- if ( note_type === "scenario_notes" || note_type === "ob_setups" || note_type === "ob_notes" ) {
- var usedIds = {} ;
- $sortable2.children( "li" ).each( function() {
- usedIds[ $(this).data("sortable2-data").id ] = true ;
- } ) ;
- data.id = auto_assign_id( usedIds, "id" ) ;
- }
+ if ( note_type === "scenario_notes" || note_type === "ob_setups" || note_type === "ob_notes" )
+ data.id = nextAvailableId ;
$entry = _do_add_simple_note( $sortable2, data ) ;
}
}
diff --git a/vasl_templates/webapp/static/snippets.js b/vasl_templates/webapp/static/snippets.js
index 836ee5b..93903d3 100644
--- a/vasl_templates/webapp/static/snippets.js
+++ b/vasl_templates/webapp/static/snippets.js
@@ -162,15 +162,20 @@ function make_snippet( $btn, params, extra_params, show_date_warnings )
}
// set the snippet ID
- var data ;
- if ( ["ob_setup","ob_note","ob_vehicle_note","ob_ordnance_note"].indexOf( template_id ) !== -1 ) {
- data = $btn.parent().parent().data( "sortable2-data" ) ;
- params.SNIPPET_ID = template_id + "_" + player_no + "." + data.id ;
- } else if ( template_id === "scenario_note" ) {
- data = $btn.parent().parent().data( "sortable2-data" ) ;
- params.SNIPPET_ID = template_id + "." + data.id ;
- } else
- params.SNIPPET_ID = template_id ;
+ var snippetId = $btn.data( "snippet-id" ) ;
+ if ( snippetId )
+ params.SNIPPET_ID = snippetId ;
+ else {
+ var data ;
+ if ( ["ob_setup","ob_note","ob_vehicle_note","ob_ordnance_note"].indexOf( template_id ) !== -1 ) {
+ data = $btn.parent().parent().data( "sortable2-data" ) ;
+ params.SNIPPET_ID = template_id + "_" + player_no + "." + data.id ;
+ } else if ( template_id === "scenario_note" ) {
+ data = $btn.parent().parent().data( "sortable2-data" ) ;
+ params.SNIPPET_ID = template_id + "." + data.id ;
+ } else
+ params.SNIPPET_ID = template_id ;
+ }
if ( player_nat )
params.SNIPPET_ID = player_nat + "/" + params.SNIPPET_ID ;
@@ -985,10 +990,7 @@ function unload_snippet_params( unpack_scenario_date, template_id )
} ) ;
// collect the SSR's
- params.SSR = [] ;
- var data = $("#ssr-sortable").sortable2( "get-entry-data" ) ;
- for ( var i=0 ; i < data.length ; ++i )
- params.SSR.push( data[i].caption ) ;
+ params.SSR = unload_ssrs() ;
// collect the vehicles/ordnance
function get_vo( vo_type, player_no, key, show_warnings ) {
@@ -1084,6 +1086,16 @@ function unload_snippet_params( unpack_scenario_date, template_id )
return params ;
}
+function unload_ssrs()
+{
+ // unload the SSR's
+ ssrs = [] ;
+ var data = $( "#ssr-sortable" ).sortable2( "get-entry-data" ) ;
+ for ( var i=0 ; i < data.length ; ++i )
+ ssrs.push( data[i].caption ) ;
+ return ssrs ;
+}
+
function get_vo_comments( vo_entry, month, year )
{
if ( ! vo_entry.comments )
diff --git a/vasl_templates/webapp/static/utils.js b/vasl_templates/webapp/static/utils.js
index c7f4d86..a0c35bc 100644
--- a/vasl_templates/webapp/static/utils.js
+++ b/vasl_templates/webapp/static/utils.js
@@ -77,6 +77,9 @@ function make_player_flag_url( nat, for_snippet, force_local_image ) {
function get_player_no_for_element( $elem )
{
// get the player that owns the specified element
+ var playerNo = $elem.data( "player-no" ) ;
+ if ( playerNo )
+ return playerNo ;
if ( $.contains( $("#tabs-ob1")[0], $elem[0] ) )
return 1 ;
if ( $.contains( $("#tabs-ob2")[0], $elem[0] ) )
diff --git a/vasl_templates/webapp/tests/test_snippets.py b/vasl_templates/webapp/tests/test_snippets.py
index c0da5c5..05bdc1b 100644
--- a/vasl_templates/webapp/tests/test_snippets.py
+++ b/vasl_templates/webapp/tests/test_snippets.py
@@ -1,5 +1,6 @@
""" Test HTML snippet generation. """
+import re
import base64
import pytest
@@ -9,8 +10,8 @@ from selenium.webdriver.common.keys import Keys
from vasl_templates.webapp.tests import pytest_options
from vasl_templates.webapp.tests.utils import \
init_webapp, select_tab, find_snippet_buttons, set_template_params, wait_for, wait_for_clipboard, \
- get_stored_msg, set_stored_msg_marker, find_child, find_children, adjust_html, \
- for_each_template, add_simple_note, edit_simple_note, \
+ get_stored_msg, set_stored_msg_marker, find_child, find_children, find_sortable_helper, adjust_html, \
+ for_each_template, add_simple_note, edit_simple_note, click_dialog_button, \
get_sortable_entry_count, generate_sortable_entry_snippet, drag_sortable_entry_to_trash, \
new_scenario, set_scenario_date
from vasl_templates.webapp.tests.test_scenario_persistence import load_scenario
@@ -229,6 +230,107 @@ def test_players_snippets( webapp, webdriver ):
# ---------------------------------------------------------------------
+def test_simple_snippets_from_dialog( webapp, webdriver ):
+ """Test generating snippets from the "add/edit simple note" dialog."""
+
+ # initialize
+ webapp.control_tests.set_data_dir( "{REAL}" )
+ init_webapp( webapp, webdriver, scenario_persistence=1 )
+ load_scenario( {
+ "SCENARIO_NOTES": [
+ { "id": 1, "caption": "scenario note 1", "width": "111px" },
+ { "id": 2, "caption": "scenario note 2" }
+ ],
+ "SSR": [ "SSR #1", "SSR #2" ],
+ "SSR_WIDTH": "222px",
+ "OB_SETUPS_1": [
+ { "id": 1, "caption": "german ob setup #1", "width": "991px" },
+ { "id": 2, "caption": "german ob setup #2" }
+ ],
+ "OB_NOTES_2": [
+ { "id": 1, "caption": "russian setup note #1", "width": "992px" },
+ { "id": 2, "caption": "russian setup note #2" }
+ ]
+ } )
+
+ def test_existing_simple_note( sortable, entry_no, expected ):
+ # edit the simple note
+ elems = find_children( "li", sortable )
+ ActionChains(webdriver).double_click( elems[entry_no] ).perform()
+ # change the snippet content
+ elem = find_child( ".ui-dialog.edit-simple_note textarea" )
+ elem.clear()
+ elem.send_keys( "modified content" )
+ # change the snippet width
+ elem = find_child( ".ui-dialog.edit-simple_note input[name='width']" )
+ if elem.is_displayed():
+ elem.clear()
+ elem.send_keys( "123px" )
+ # generate the snippet
+ click_dialog_button( "Snippet" )
+ if isinstance( expected, str ):
+ # NOTE: We also check that the snippet ID is correct.
+ expected = re.compile( ".*".join( [
+ "".format( expected ),
+ "width: 123px",
+ "modified content",
+ ] ), re.DOTALL )
+ wait_for_clipboard( 2, expected )
+ click_dialog_button( "Cancel" )
+
+ def test_new_simple_note( sortable, expected ) :
+ # add a new simple note
+ find_sortable_helper( sortable, "add" ).click()
+ elem = find_child( ".ui-dialog.edit-simple_note textarea" )
+ elem.send_keys( "new content" )
+ elem = find_child( ".ui-dialog.edit-simple_note input[name='width']" )
+ if elem.is_displayed():
+ elem.clear()
+ elem.send_keys( "789px" )
+ # generate the snippet
+ click_dialog_button( "Snippet" )
+ if isinstance( expected, str ):
+ # NOTE: We also check that the snippet ID is correct.
+ expected = re.compile( ".*".join( [
+ "".format( expected ),
+ "width: 789px",
+ "new content",
+ ] ), re.DOTALL )
+ wait_for_clipboard( 2, expected )
+ click_dialog_button( "Cancel" )
+
+ # test scenario notes
+ sortable = find_child( "#scenario_notes-sortable" )
+ test_existing_simple_note( sortable, 1, "scenario_note.2" )
+ test_new_simple_note( sortable, "scenario_note.3" )
+
+ # test SSR's
+ sortable = find_child( "#ssr-sortable" )
+ test_existing_simple_note( sortable, 1, re.compile( ".*".join( [
+ "",
+ "width: 222px",
+ r'\s*- \s*SSR #1\s*
- \s*modified content\s*
',
+ ] ), re.DOTALL ) )
+ test_new_simple_note( sortable, re.compile( ".*".join( [
+ "",
+ "width: 222px",
+ r'\s*- \s*SSR #1\s*
- \s*SSR #2\s*
- \s*new content\s*
',
+ ] ), re.DOTALL ) )
+
+ # test OB setups
+ select_tab( "ob1" )
+ sortable = find_child( "#ob_setups-sortable_1" )
+ test_existing_simple_note( sortable, 1, "german/ob_setup_1.2" )
+ test_new_simple_note( sortable, "german/ob_setup_1.3" )
+
+ # test OB setups
+ select_tab( "ob2" )
+ sortable = find_child( "#ob_notes-sortable_2" )
+ test_existing_simple_note( sortable, 1, "russian/ob_note_2.2" )
+ test_new_simple_note( sortable, "russian/ob_note_2.3" )
+
+# ---------------------------------------------------------------------
+
def test_edit_templates( webapp, webdriver ):
"""Test editing templates."""