Converted SSR's to use a sortable.

master
Pacman Ghost 6 years ago
parent d3a2e2b5a9
commit 960266b591
  1. 11
      vasl_templates/webapp/static/main.js
  2. 36
      vasl_templates/webapp/static/simple_notes.js
  3. 40
      vasl_templates/webapp/static/snippets.js
  4. 12
      vasl_templates/webapp/static/sortable.js
  5. 87
      vasl_templates/webapp/static/ssr.js
  6. 6
      vasl_templates/webapp/templates/index.html
  7. 58
      vasl_templates/webapp/tests/test_ssr.py
  8. 4
      vasl_templates/webapp/tests/utils.py

@ -81,12 +81,13 @@ $(document).ready( function () {
} ) ;
// initialize
$("#ssr-sortable").sortable( { connectWith: "#ssr-trash", cursor: "move" } ) ;
$("#add-ssr").click( add_ssr ) ;
$("#ssr-trash").sortable( {
receive: function( evt, ui ) { ui.item.remove() ; update_ssr_hint() ; }
init_sortable( $("#ssr-sortable"),
function() { add_ssr() ; },
edit_ssr
) ;
$("#panel-ssr input[type='button'][data-id='ssr']").click( function() {
edit_template( "ssr" ) ;
} ) ;
enable_ctrl_enter( $("#edit-ssr"), "OK" ) ;
// initialize the scenario notes
init_sortable( $("#scenario_notes-sortable"),

@ -8,6 +8,10 @@ function add_scenario_note() { _do_edit_simple_note( $("#scenario_notes-sortable
function do_add_scenario_note( $sortable, data ) { _do_add_simple_note($sortable,data) ; }
function edit_scenario_note( $sortable, $entry ) { _do_edit_simple_note( $sortable, $entry ) ; }
function add_ssr() { _do_edit_simple_note( $("#ssr-sortable"), null ) ; }
function do_add_ssr( $sortable, data ) { _do_add_simple_note($sortable,data) ; }
function edit_ssr( $sortable, $entry ) { _do_edit_simple_note( $sortable, $entry ) ; }
function add_ob_setup( player_id ) { _do_edit_simple_note( $("#ob_setups-sortable_"+player_id), null ) ; }
function do_add_ob_setup( $sortable, data ) { _do_add_simple_note($sortable,data) ; }
function edit_ob_setup( $sortable, $entry ) { _do_edit_simple_note( $sortable, $entry ) ; }
@ -25,7 +29,7 @@ function _do_edit_simple_note( $sortable, $entry )
var note_type0 = note_type.substring( 0, note_type.length-1 ) ; // plural -> singular :-/
// let the user edit the note
var $caption, $width ;
var $caption, $width, $width_label ;
$("#edit-simple_note").dialog( {
dialogClass: "edit-simple_note",
modal: true,
@ -33,7 +37,8 @@ function _do_edit_simple_note( $sortable, $entry )
minHeight: 150,
open: function() {
$caption = $(this).children( "textarea" ) ;
$width = $(this).children( "input[type='text']" ) ;
$width = $(this).children( "input[name='width']" ) ;
$width_label = $(this).children( "label[for='width']" ) ;
if ( $entry ) {
var data = $entry.data( "sortable-data" ) ;
$caption.val( data.caption ) ;
@ -43,8 +48,19 @@ function _do_edit_simple_note( $sortable, $entry )
$caption.val( "" ) ;
$width.val( "" ) ;
}
if ( note_type === "ssr" ) {
// NOTE: Individual SSR's don't have a width, there is one setting for them all.
$width.hide() ;
$width_label.hide() ;
$caption.css( "height", "100%" ) ;
}
$(this).height( $(this).height() ) ; // fudge: force the textarea to resize
},
close: function() {
$width.show() ;
$width_label.show() ;
$caption.css( "height", "calc(100% - 3em)" ) ;
},
buttons: {
OK: function() {
var caption = $caption.val().trim() ;
@ -88,14 +104,12 @@ function _do_add_simple_note( $sortable, data )
function _make_simple_note( note_type, caption )
{
// generate the sortable entry
var note_type0 = note_type.substring( 0, note_type.length-1 ) ;
var buf = [] ;
buf.push(
"<div>",
"<input type='button' data-id='" + note_type0 + "' value='Snippet'>",
caption,
"</div>"
) ;
var buf = [ "<div>" ] ;
if ( note_type !== "ssr" ) {
var note_type0 = note_type.substring( 0, note_type.length-1 ) ;
buf.push( "<input type='button' data-id='" + note_type0 + "' value='Snippet'>" ) ;
}
buf.push( caption, "</div>" ) ;
var $content = $( buf.join("") ) ;
// add a handler for the snippet button
@ -123,6 +137,6 @@ function _get_note_type_for_sortable( $sortable )
{
// figure out what type of note the sortable has
var id = $sortable.prop( "id" ) ;
var match = /^((scenario_notes|ob_setups|ob_notes))-sortable(_\d)?$/.exec( id ) ;
var match = /^((scenario_notes|ssr|ob_setups|ob_notes))-sortable(_\d)?$/.exec( id ) ;
return match[1] ;
}

@ -205,9 +205,9 @@ function unload_params( params, check_date_capabilities )
// collect the SSR's
params.SSR = [] ;
$("#ssr-sortable li").each( function() {
params.SSR.push( $(this).text() ) ;
} ) ;
var data = get_sortable_entry_data( $("#ssr-sortable") ) ;
for ( var i=0 ; i < data.length ; ++i )
params.SSR.push( data[i].caption ) ;
// collect the vehicles/ordnance
function get_vo( vo_type, player_id, paramName )
@ -492,18 +492,14 @@ function do_load_scenario( params )
set_param( $("select[name='PLAYER_2']"), "PLAYER_2" ).trigger( "change" ) ;
var i ;
for ( var key in params ) {
var player_id, $sortable ;
if ( key === "SSR" ) {
for ( i=0 ; i < params[key].length ; ++i ) {
var $ssr = $( "<li></li>" ) ;
$ssr.text( params[key][i] ) ;
$("#ssr-sortable").append( $ssr ) ;
init_ssr( $ssr ) ;
}
update_ssr_hint() ;
$sortable = $( "#ssr-sortable" ) ;
for ( i=0 ; i < params[key].length ; ++i )
do_add_scenario_note( $sortable, { caption: params[key][i] } ) ;
params_loaded[key] = true ;
continue ;
}
var player_id, $sortable ;
if ( key === "SCENARIO_NOTES" ) {
$sortable = $( "#scenario_notes-sortable" ) ;
for ( i=0 ; i < params[key].length ; ++i )
@ -578,13 +574,6 @@ function do_load_scenario( params )
function on_save_scenario()
{
// unload the template parameters
function unload_sortable_entries( $sortable ) {
var entries = [] ;
$sortable.children("li").each( function() {
entries.push( $(this).data( "sortable-data" ) ) ;
} ) ;
return entries ;
}
function extract_vo_names( key ) { // nb: we only need to save the vehicle/ordnance name
if ( !(key in params) )
return ;
@ -595,11 +584,11 @@ function on_save_scenario()
}
var params = {} ;
unload_params( params, false ) ;
params.SCENARIO_NOTES = unload_sortable_entries( $("#scenario_notes-sortable") ) ;
params.OB_SETUPS_1 = unload_sortable_entries( $("#ob_setups-sortable_1") ) ;
params.OB_SETUPS_2 = unload_sortable_entries( $("#ob_setups-sortable_2") ) ;
params.OB_NOTES_1 = unload_sortable_entries( $("#ob_notes-sortable_1") ) ;
params.OB_NOTES_2 = unload_sortable_entries( $("#ob_notes-sortable_2") ) ;
params.SCENARIO_NOTES = get_sortable_entry_data( $("#scenario_notes-sortable") ) ;
params.OB_SETUPS_1 = get_sortable_entry_data( $("#ob_setups-sortable_1") ) ;
params.OB_SETUPS_2 = get_sortable_entry_data( $("#ob_setups-sortable_2") ) ;
params.OB_NOTES_1 = get_sortable_entry_data( $("#ob_notes-sortable_1") ) ;
params.OB_NOTES_2 = get_sortable_entry_data( $("#ob_notes-sortable_2") ) ;
extract_vo_names( "VEHICLES_1" ) ;
extract_vo_names( "ORDNANCE_1" ) ;
extract_vo_names( "VEHICLES_2" ) ;
@ -642,12 +631,9 @@ function on_new_scenario( verbose )
$("select[name='PLAYER_2_ELR']").val( 5 ) ;
$("select[name='PLAYER_2_SAN']").val( 2 ) ;
// reset all the template parameters
$("#ssr-sortable li").each( function() { $(this).remove() ; } ) ;
update_ssr_hint() ;
// reset all the template parameters
delete_all_sortable_entries( $("#scenario_notes-sortable") ) ;
delete_all_sortable_entries( $("#ssr-sortable") ) ;
for ( var i=1 ; i <= 2 ; ++i ) {
delete_all_sortable_entries( $("#ob_setups-sortable_"+i) ) ;
delete_all_sortable_entries( $("#ob_notes-sortable_"+i) ) ;

@ -101,6 +101,18 @@ function delete_all_sortable_entries( $sortable )
// --------------------------------------------------------------------
function get_sortable_entry_data( $sortable )
{
// get the data associated with each sortable entry
var entry_data = [] ;
$sortable.children("li").each( function() {
entry_data.push( $(this).data( "sortable-data" ) ) ;
} ) ;
return entry_data ;
}
// --------------------------------------------------------------------
function _find_sortable_helper( $sortable, type )
{
// find a support element for the specified sortable

@ -1,87 +0,0 @@
// --------------------------------------------------------------------
function add_ssr()
{
// add a new SSR
edit_ssr( null ) ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function edit_ssr( $elem )
{
// let the user edit a SSR's content
$("#edit-ssr textarea").val( $elem ? $elem.text() : "" ) ;
$("#edit-ssr").dialog( {
dialogClass: "edit-ssr",
modal: true,
minWidth: 400,
minHeight: 150,
open: function() {
$(this).height( $(this).height() ) ; // fudge: force the textarea to resize
},
buttons: {
OK: function() {
var val = $("#edit-ssr textarea").val().trim() ;
if ( $elem ) {
// update the existing SSR
if ( val !== "" )
$elem.text( val ) ;
else
delete_ssr( $elem ) ;
}
else {
// create a new SSR
if ( val !== "" ) {
var $new_ssr = $( "<li></li>" ) ;
$new_ssr.text( val ) ;
$("#ssr-sortable").append( $new_ssr ) ;
init_ssr( $new_ssr ) ;
}
}
update_ssr_hint() ;
$(this).dialog( "close" ) ;
},
Cancel: function() { $(this).dialog( "close" ) ; },
},
} ) ;
}
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
function delete_ssr( $elem )
{
// delete the SSR
$elem.addClass( "highlighted" ) ;
ask( "Delete this SSR?", escapeHTML($elem.text()), {
"ok": function() { $elem.remove() ; update_ssr_hint() ; },
"close": function() { $elem.removeClass("highlighted") ; },
} ) ;
}
// --------------------------------------------------------------------
function init_ssr( $elem )
{
// initialize SSR element(s)
$elem.dblclick( function() {
edit_ssr( $(this) ) ;
} ) ;
$elem.click( function( evt ) {
if ( evt.ctrlKey )
delete_ssr( $(this) ) ;
} ) ;
}
function update_ssr_hint()
{
// show/hide the SSR hint
if ( $("#ssr-sortable li").length === 0 ) {
$("#ssr-sortable").hide() ;
$("#ssr-hint").show() ;
} else {
$("#ssr-sortable").show() ;
$("#ssr-hint").hide() ;
}
}

@ -90,7 +90,7 @@
</div>
<div class="footer">
<div class="l">
<input type="button" id="add-ssr" value="+">
<input type="button" id="ssr-add" value="+">
<img id="ssr-trash" src="{{url_for('static',filename='images/trash.png')}}">
</div>
<label for="SSR_WIDTH">Width:</label>
@ -186,10 +186,9 @@
</div>
<div id="edit-template" style="display:none;"> <textarea></textarea> </div>
<div id="edit-ssr" style="display:none;"> <b>Enter the SSR content:</b> <textarea></textarea> </div>
<div id="edit-simple_note" style="display:none;">
<textarea></textarea>
<label>Width:</label> <input type="text" size="5">
<label for="width">Width:</label> <input name="width" type="text" size="5">
</div>
<div id="select-vo" style="display:none;">
<div class="header"> <b>Filter by:</b> <input type="text" size="10"> </div>
@ -216,7 +215,6 @@ gOrdnanceListingsUrl = "{{url_for('get_ordnance_listings')}}" ;
</script>
<script src="{{url_for('static',filename='main.js')}}"></script>
<script src="{{url_for('static',filename='snippets.js')}}"></script>
<script src="{{url_for('static',filename='ssr.js')}}"></script>
<script src="{{url_for('static',filename='simple_notes.js')}}"></script>
<script src="{{url_for('static',filename='vehicles_ordnance.js')}}"></script>
<script src="{{url_for('static',filename='sortable.js')}}"></script>

@ -2,10 +2,9 @@
import html
from selenium.webdriver.common.action_chains import ActionChains
from vasl_templates.webapp.tests.utils import \
select_tab, find_child, find_children, get_clipboard, dismiss_notifications, click_dialog_button
select_tab, find_child, get_clipboard, dismiss_notifications, \
add_simple_note, edit_simple_note, drag_sortable_entry_to_trash, get_sortable_entry_count
# ---------------------------------------------------------------------
@ -15,17 +14,20 @@ def test_ssr( webapp, webdriver ):
# initialize
webdriver.get( webapp.url_for( "main" ) )
select_tab( "scenario" )
sortable = find_child( "#ssr-sortable" )
# initialize
expected = []
generate_snippet_btn = find_child( "input[type='button'][data-id='ssr']" )
def _add_ssr( val ):
def add_ssr( val ):
"""Add a new SSR."""
expected.append( val )
add_ssr( webdriver, val )
add_simple_note( sortable, val, None )
check_snippet()
def _edit_ssr( ssr_no, val ):
def edit_ssr( ssr_no, val ):
"""Edit an existing SSR."""
expected[ssr_no] = val
edit_ssr( webdriver, ssr_no, val )
edit_simple_note( sortable, ssr_no, val, None )
check_snippet()
def check_snippet( width=None ):
"""Check the generated SSR snippet."""
@ -37,23 +39,21 @@ def test_ssr( webapp, webdriver ):
dismiss_notifications()
# add an SSR and generate the SSR snippet
_add_ssr( "This is my first SSR." )
add_ssr( "This is my first SSR." )
# add an SSR that contains HTML
_add_ssr( "This snippet contains <b>bold</b> and <i>italic</i> text." )
add_ssr( "This snippet contains <b>bold</b> and <i>italic</i> text." )
# add a multi-line SSR
_add_ssr( "line 1\nline 2\nline 3" )
add_ssr( "line 1\nline 2\nline 3" )
# edit one of the SSR's
_edit_ssr( 1, "This SSR was <i>modified</i>." )
edit_ssr( 1, "This SSR was <i>modified</i>." )
# delete one of the SSR's
elems = find_children( "#ssr-sortable li" )
assert len(elems) == 3
elem = elems[1]
trash = find_child( "#ssr-trash" )
ActionChains(webdriver).drag_and_drop( elem, trash ).perform()
assert get_sortable_entry_count(sortable) == 3
drag_sortable_entry_to_trash( sortable, 1 )
assert get_sortable_entry_count(sortable) == 2
del expected[1]
check_snippet()
@ -61,29 +61,3 @@ def test_ssr( webapp, webdriver ):
elem = find_child( "input[name='SSR_WIDTH']" )
elem.send_keys( "300px" )
check_snippet( "300px" )
# ---------------------------------------------------------------------
def add_ssr( webdriver, val ):
"""Add a new SSR."""
elem = find_child( "#add-ssr" )
elem.click()
edit_ssr( webdriver, None, val )
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
def edit_ssr( webdriver, ssr_no, val ):
"""Edit an SSR's content."""
# locate the requested SSR and start editing it
if ssr_no is not None:
sortable = find_child( "#ssr-sortable" )
elems = find_children( "li", sortable )
elem = elems[ ssr_no ]
ActionChains(webdriver).double_click( elem ).perform()
# edit the SSR
textarea = find_child( "#edit-ssr textarea" )
textarea.clear()
textarea.send_keys( val )
click_dialog_button( "OK" )

@ -112,9 +112,9 @@ def set_template_params( params ): #pylint: disable=too-many-branches
# check for SSR's (these require special handling)
if key == "SSR":
# add them in (nb: we don't consider any existing SSR's)
from vasl_templates.webapp.tests.test_ssr import add_ssr #pylint: disable=cyclic-import
sortable = find_child( "#ssr-sortable" )
for ssr in val:
add_ssr( _webdriver, ssr )
add_simple_note( sortable, ssr, None )
continue
# check for OB setups/notes (these require special handling)

Loading…
Cancel
Save