1
0
Fork 0

Liberate event handlers

These are extracted from rating-fw commit
5d4019f1973f9271f4b1bd24ce1f55b56ccda09e.
master
Mike Gerwitz 2017-02-06 11:48:53 -05:00
parent 25701c747b
commit bd81e2e726
8 changed files with 728 additions and 0 deletions

View File

@ -0,0 +1,77 @@
/**
* Cvv2DialogEventHandler
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* TODO: This can be generalized.
*/
var Class = require( 'easejs' ).Class,
EventHandler = require( './EventHandler' );
/**
* Shows Cvv2 Dialog
*/
module.exports = Class( 'Cvv2DialogEventHandler' )
.implement( EventHandler )
.extend(
{
/**
* jQuery instance
*
* @type {jQuery}
*/
'private _jquery': null,
/**
* Initializes with client that will delegate the event
*
* @param {jQuery} jquery jquery instance
*/
__construct: function( jquery )
{
this._jquery = jquery;
},
/**
* Handles kick-back
*
* @param {string} type event id; ignored
*
* @param {function(*,Object)} continuation to invoke on completion
*
* @return {StatusEventHandler} self
*/
'public handle': function( type, c, data )
{
var $dialog = this._jquery( '#' + data.ref ).dialog( {
title: "CVV/CSV Verification Information",
width: "500px",
resizable: false,
buttons: {
'Close': function()
{
$dialog.dialog( 'close' );
}
}
} );
}
} );

View File

@ -0,0 +1,124 @@
/**
* Event handler proxy
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Class = require( 'easejs' ).Class,
EventHandler = require( './EventHandler' ),
UnknownEventError = require( './UnknownEventError' );
/**
* Delegates events to an apropriate handler
*
* Handlers must be registered to recgonize an event.
*/
module.exports = Class( 'DelegateEventHandler' )
.implement( EventHandler )
.extend(
{
/**
* Hash of event handlers to delegate to for various events
* @type {Object}
*/
'private _handlers': {},
/**
* Initialize delegate with handlers to delegate requests to for each
* supported event type
*
* @param {Object} handlers events as keys, handlers as values
*/
__construct: function( handlers )
{
// register each provided handler
for ( var type in handlers )
{
this._addHandler( type, handlers[ type ] );
}
},
/**
* Determines if a handler has been registered for the given type
*
* @param {string} type event id
*
* @return {boolean} whether a handler exists for the given type
*/
'public hasHandler': function( type )
{
return ( this._handlers[ type ] !== undefined );
},
/**
* Handle an event of the given type
*
* An exception will be thrown if the event cannot be handled.
*
* The handler should always return itself; if a return value is needed to
* the caller, then a callback should be provided as an argument to the
* handler.
*
* Additional arguments will be passed to the appropriate handler.
*
* @param {string} type event id
*
* @return {EventHandler} self
*/
'public handle': function( type )
{
var handler = this._handlers[ type ];
// fail if we do not have a handler for this particular event
if ( !handler )
{
throw UnknownEventError( "Unsupported event type: " + type );
}
// delegate
handler.handle.apply( handler, arguments );
return this;
},
/**
* Add an EventHandler for a given event type
*
* Warning: this will overwrite existing handlers for this type.
*
* @param {string} type event id
* @param {EventHandler} handler handler for event
*
* @return {ClientEventHandler} self
*/
'private _addHandler': function( type, handler )
{
if ( !( Class.isA( EventHandler, handler ) ) )
{
throw TypeError( "Expected EventHandler for event type " + type );
}
this._handlers[ type ] = handler;
return this;
}
} );

View File

@ -0,0 +1,41 @@
/**
* Event handling interface
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Interface = require( 'easejs' ).Interface;
module.exports = Interface( 'EventHandler',
{
/**
* Handle an event of the given type
*
* An exception should be thrown if the event cannot be handled.
*
* The handler should always return itself; if a return value is needed to
* the caller, then a callback should be provided as an argument to the
* handler.
*
* @param {string} type event id
*
* @return {EventHandler} self
*/
'public handle': [ 'type' /*, ... */ ]
} );

View File

@ -0,0 +1,53 @@
/**
* Invidiual rate request event handler
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Class = require( 'easejs' ).Class,
RateEventHandler = require( './RateEventHandler' );
/**
* Performs rate requests
*/
module.exports = Class( 'IndvRateEventHandler' )
.extend( RateEventHandler,
{
'override protected postRate': function( err, data, client, quote )
{
if ( err )
{
var inelig = {};
inelig[ action.id + '_ineligible' ] = 'Error calculating premium.';
// uh oh. notify the user that there was a problem.
quote.setData( inelig ).save();
}
// we must force a screen update (TODO: make this unnecessary)
client.getUi().getCurrentStep().emptyBucket();
},
'override protected queueProgressDialog': function( after_ms )
{
// no dialog.
return function() {};
}
} );

View File

@ -0,0 +1,82 @@
/**
* Kickback event handler
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Class = require( 'easejs' ).Class,
EventHandler = require( './EventHandler' );
/**
* Performs rate requests
*/
module.exports = Class( 'KickbackEventHandler' )
.implement( EventHandler )
.extend(
{
/**
* Client that will perform requests on this handler
* @type {Client}
*/
'private _client': null,
/**
* Initializes with client that will delegate the event
*
* @param {Client} client client object
*/
__construct: function( client )
{
this._client = client;
},
/**
* Handles kick-back
*
* @param {string} type event id; ignored
*
* @param {function(*,Object)} continuation to invoke on completion
*
* @return {KickbackEventHandler} self
*/
'public handle': function( type, c, data )
{
var step_id = +data.stepId,
quote = this._client.getQuote(),
nav = this._client.nav,
ui = this._client.getUi();
if ( quote.getTopVisitedStepId() > step_id )
{
quote.setTopVisitedStepId( step_id );
nav.setTopVisitedStepId( step_id );
if ( quote.getCurrentStepId() > step_id )
{
nav.navigateToStep( step_id );
}
ui.redrawNav();
}
c();
}
} );

View File

@ -0,0 +1,233 @@
/**
* Rate event handler
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Class = require( 'easejs' ).Class,
EventHandler = require( './EventHandler' );
/**
* Performs rate requests
*/
module.exports = Class( 'RateEventHandler' )
.implement( EventHandler )
.extend(
{
/**
* Number of milliseconds to delay rating progress dialog display
* @type {number}
*/
'private const _DIALOG_DELAY_MS': 500,
/**
* Client that will perform requests on this handler
* @type {Client}
*/
'private _client': null,
/**
* Data proxy used for requests
* @type {ClientDataProxy}
*/
'private _dataProxy': null,
/**
* Initializes event handler with a data proxy that may be used to
* communicate with a remote server for rate requests
*
* @param {Client} client client object
* @param {ClientDataProxy} data proxy used for rate requests
*/
__construct: function( client, data_proxy )
{
this._client = client;
this._dataProxy = data_proxy;
},
/**
* Handle rating request and performs rating
*
* If the quote is locked, no rating request will be made and the
* continuation will be immediately invoked with no error and null rate
* data.
*
* If the client is in the process of saving, then rating will be deferred
* until all save operations have completed, after which rating will proceed
* as normal.
*
* After rating is complete, the coninuation will be invoked. If there is an
* error, it will be provided as the first argument and the data argument
* will be null. Otherwise, the error argument will be null and the data
* argument will contain the result of the rate call. Note that the quote
* will be automatically filled with the return data.
*
* @param {string} type event id; ignored
*
* @param {function(*,Object)} continuation to invoke on completion
*
* @return {RateEventHandler} self
*/
'public handle': function( type, c, data )
{
var _self = this,
quote = this._client.getQuote(),
qstep = quote.getCurrentStepId();
// do not perform rating if quote is locked; use existing rates, if
// available (stored in bucket)
if ( quote.isLocked()
|| ( qstep <= quote.getExplicitLockStep() )
)
{
// no error, no data.
c( null, null );
return;
}
// if we're in the process of saving, then wait until all saves are
// complete before continuing
if ( this._client.isSaving() )
{
// defer rating until after saving is complete
this._client.once( 'postSaveAll', function()
{
dorate();
} );
return;
}
function dorate()
{
_self._performRating( quote, c, data.indv, data.stepId );
}
// perform rating immediately
dorate();
return this;
},
'private _performRating': function( quote, c, indv, dest_step_id )
{
var _self = this;
// queue display of "rating in progress" dialog
var dialog_close = this.queueProgressDialog(
this.__self.$( '_DIALOG_DELAY_MS' )
);
// grab the rates from the server for the already posted quote data
this._dataProxy.get( this._genRateUrl( quote, indv ),
function( response, err )
{
var data = ( response.content.data || {} );
if ( err )
{
// error; do not provide rate data
c( err, null );
return;
}
// fill the bucket with the response data and save (client-side
// save only; no transport is specified)
quote.refreshData( data );
// let subtypes handle additional processing
_self.postRate( err, data, _self._client, quote );
// close rating dialog after rates are displayed
dialog_close();
// invalidate the step to force emptying of the bucket, ensuring
// that data is updated on the screen when it's re-rated (will
// be undefined if the step hasn't been loaded yet, in which
// case it doesn't need to be invalidated)
var stepui = _self._client.getUi().getStep( dest_step_id );
if ( stepui !== undefined )
{
stepui.invalidate();
}
c( null, response.content.data );
}
);
},
'virtual protected postRate': function( err, data, client, quote )
{
// reserved for subtypes
},
/**
* Generate the rate request URL
*
* @param {Quote} quote to get premium for
* @param {string} indv optional individual supplier to request
*
* @return {string} request URL
*/
'private _genRateUrl': function( quote, indv )
{
return quote.getId() + '/rate' +
( ( indv )
? '/' + indv
: ''
);
},
/**
* Queue "rating in progress" dialog for display after a short period of
* time
*
* The dialog may be closed/cancelled by invoking the returned function.
*
* @param {number} after_ms display dialog after this number of millisecs
*
* @return {function()} function to close dialog
*/
'virtual protected queueProgressDialog': function( after_ms )
{
var _self = this,
$dialog = null;
// only display the dialog if the rating time exceeds 500ms
var timeout = setTimeout( function()
{
$dialog = _self._client.uiDialog.showRatingInProgressDialog();
}, after_ms );
// return a function that may be used to close the dialog
return function()
{
// prevent the dialog from being displayed and close it if it has
// already been displayed
clearTimeout( timeout );
$dialog && $dialog.close();
}
}
} );

View File

@ -0,0 +1,81 @@
/**
* Field status event handler
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
var Class = require( 'easejs' ).Class,
EventHandler = require( './EventHandler' );
/**
* Performs rate requests
*/
module.exports = Class( 'StatusEventHandler' )
.implement( EventHandler )
.extend(
{
/**
* Styler used to manipulate the DOM
*
* TODO: deprecate
*
* @type {ElementStyler}
*/
'private _styler': null,
/**
* Initializes with client that will delegate the event
*
* @param {ElementStyler} styler element styler
*/
__construct: function( styler )
{
this._styler = styler;
},
/**
* Handles kick-back
*
* @param {string} type event id; ignored
*
* @param {function(*,Object)} continuation to invoke on completion
*
* @return {StatusEventHandler} self
*/
'public handle': function( type, c, data )
{
var indexes = data.indexes || [],
value = data.value || '',
name = data.elementName;
for ( var i in indexes )
{
// string means a static value; otherwise, an array
// represents bucket values, of which we should take the
// associated index
var value = ( typeof value === 'string' )
? value
: value[ i ];
this._styler.setStatus( name, indexes[ i ], value );
}
}
} );

View File

@ -0,0 +1,37 @@
/**
* Contains UnknownEventError
*
* Copyright (C) 2017 LoVullo Associates, Inc.
*
* This file is part of the Liza Data Collection Framework
*
* Liza is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
module.exports = function UnknownEventError( msg )
{
// 'new' keyword optional
if ( !( this instanceof module.exports ) )
{
return new module.exports( msg );
}
Error.prototype.constructor.apply( this, arguments );
};
// extends TypeError
module.exports.constructor = module.exports;
module.exports.prototype = TypeError();
module.exports.prototype.name = 'UnknownEventError';