TimeTrex Community Edition v16.2.0

This commit is contained in:
2022-12-13 07:10:06 +01:00
commit 472f000c1b
6810 changed files with 2636142 additions and 0 deletions

View File

@@ -0,0 +1,410 @@
/**
* For an example of implementation see: interface/html5/views/payroll/remittance_wizard/PayrollRemittanceAgencyEventWizard.js
*
* CRITICAL: ALL WIZARDS MUST HAVE A HOME STEP SO THAT THEY HAVE SOMEWHERE TO START.
**/
import { TTBackboneView } from '@/views/TTBackboneView';
export class Wizard extends TTBackboneView {
constructor( options = {} ) {
_.defaults( options, {
current_step: false,
wizard_id: 'generic_wizard',
wizard_name: $.i18n._( 'Wizard' ),
step_history: {},
step_objects: {},
el: $( '.wizard' ),
previous_wizard: null,
_step_map: null,
do_not_initialize_onload: false, //when this flag is set, initialize will not be run automagically.
external_data: null,
events: {
'click .close-btn': 'onCloseClick',
'click .close-icon': 'onCloseClick',
'click .wizard-overlay.onclick-close': 'onCloseClick',
'click .forward-btn': 'onNextClick',
'click .back-btn': 'onPrevClick',
'click .done-btn': 'onDone'
}
} );
super( options );
}
initialize( options ) {
super.initialize( options );
if ( options && options.external_data ) {
this.setExternalData( options.external_data );
}
if ( !this.do_not_initialize_onload ) {
this.step_history = {};
this.step_objects = {};
var $this = this;
this.initStepObject( ( this.getCurrentStepName() ? this.getCurrentStepName() : 'home' ), function( obj ) {
$this.init();
$this.render();
$this.enableButtons();
if ( $this.wizard_id === null ) {
$this.wizard_id = $this.constructor.name;
}
if ( LocalCacheData.current_open_wizard_controllers.some( wizard => wizard.wizard_id === $this.wizard_id ) ) {
$this.previous_wizard = LocalCacheData.current_open_wizard_controllers.find( wizard => wizard.wizard_id === $this.wizard_id );
} else {
$this.previous_wizard = false;
}
LocalCacheData.current_open_wizard_controllers.push( $this );
} );
}
}
//always override
init() {
return;
}
setExternalData( data ) {
this.external_data = data;
}
getExternalData() {
return this.external_data;
}
onNextClick( e ) {
if ( this.button_click_procesing == true ) {
return false;
}
if ( this.getStepObject().isRequiredButtonsClicked() == false ) { //On last step.
var $this = this;
TAlertManager.showConfirmAlert( $.i18n._( '<strong>WARNING</strong>: You are about to proceed to the next step without performing all required actions! <br><br><strong>This may result in payments or reports not being submitted to this agency.</strong> <br><br>Are you sure you wish to continue?<br><br>' ), null, function( flag ) {
if ( flag === true ) {
//Log the fact that the user skipped a step.
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( $this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'step', $this.getStepObject().current_step, 'skip', false, true, {
onResult: function( result ) {
}
} );
$this.onNextClickComplete( e );
}
} );
} else {
if ( this.getStepObject().current_step == 'home' ) {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'wizard', this.getStepObject().current_step, 'start', false, true, {
onResult: function( result ) {
}
} );
} else {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'step', this.getStepObject().current_step, 'complete', false, true, {
onResult: function( result ) {
}
} );
}
this.onNextClickComplete( e );
}
}
onNextClickComplete( e ) {
if ( $( e.target ).hasClass( 'disable-image' ) == false ) {
this.disableButtons();
var name = this.getStepObject().getNextStepName();
var $this = this;
this.initStepObject( name, function( step_obj ) {
step_obj.setPreviousStepName( $this.getCurrentStepName() );
$this.setCurrentStepName( name );
//$this.enableButtons(); //This should be done at the end of each _render() function to avoid race conditions and hammer clicking right arrow causing JS exceptions.
} );
}
}
onPrevClick( e ) {
if ( this.button_click_procesing == true ) {
return false;
}
if ( e === true || $( e.target ).hasClass( 'disable-image' ) == false ) {
this.disableButtons();
var name = this.getStepObject().getPreviousStepName();
var $this = this;
//Needs to be initialized in the event that we came back from the min_tab.
this.initStepObject( name, function( step_obj ) {
//step_obj.setPreviousStepName($this.getCurrentStepName());
$this.setCurrentStepName( name );
//$this.enableButtons(); //This should be done at the end of each _render() function to avoid race conditions and hammer clicking right arrow causing JS exceptions.
} );
}
}
onCloseClick( e ) {
if ( !e || $( e.target ).hasClass( 'disable-image' ) == false ) {
var $this = this;
if ( this.getStepObject().getPreviousStepName() !== false && this.getStepObject().getNextStepName() !== false ) { //Not on first step, and not last step
TAlertManager.showConfirmAlert( $.i18n._( 'Are you sure you wish to cancel without completing all steps for this event?' ), null, function( flag ) {
if ( flag === true ) {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( $this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'wizard', $this.getStepObject().current_step, 'cancel', false, true, {
onResult: function( result ) {
}
} );
$this.cleanUp();
}
} );
} else if ( this.getStepObject().getNextStepName() == false ) { //On last step.
if ( this.getStepObject().isRequiredButtonsClicked() == false ) { //Required actions are not performed.
TAlertManager.showConfirmAlert( $.i18n._( '<strong>WARNING</strong>: You are about to cancel without performing all required actions on this step! <br><br><strong>This may result in payments or reports not being submitted to this agency.</strong> <br><br>Are you sure you wish to continue?<br><br>' ), null, function( flag ) {
if ( flag === true ) {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( $this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'wizard', $this.getStepObject().current_step, 'cancel', false, true, {
onResult: function( result ) {
}
} );
$this.cleanUp();
}
} );
} else { //Required actions ARE performed.
TAlertManager.showConfirmAlert( $.i18n._( 'Are you sure you wish to cancel without marking this event as completed?' ), null, function( flag ) {
if ( flag === true ) {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( $this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'wizard', $this.getStepObject().current_step, 'cancel', false, true, {
onResult: function( result ) {
}
} );
$this.cleanUp();
}
} );
}
} else {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'wizard', this.getStepObject().current_step, 'complete', false, true, {
onResult: function( result ) {
}
} );
$this.cleanUp();
}
}
}
onDone( e ) {
if ( !e || $( e.target ).hasClass( 'disable-image' ) == false ) {
var $this = this;
if ( this.getStepObject().getNextStepName() == false && this.getStepObject().isRequiredButtonsClicked() == false ) { //On last step.
TAlertManager.showConfirmAlert( $.i18n._( '<strong>WARNING</strong>: You are about to mark this event as completed without performing all required actions on this step! <br><br><strong>This may result in payments or reports not being submitted to this agency.</strong> <br><br>Are you sure you wish to continue?<br><br>' ), null, function( flag ) {
if ( flag === true ) {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( $this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'step', $this.getStepObject().current_step, 'skip', false, true, {
onResult: function( result ) {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( $this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'wizard', $this.getStepObject().current_step, 'complete', false, true, {
onResult: function( result ) {
}
} );
}
} );
$this.onDoneComplete();
}
} );
} else {
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( this.getStepObject().getWizardObject().selected_remittance_agency_event_id, 'wizard', this.getStepObject().current_step, 'complete', false, true, {
onResult: function( result ) {
}
} );
$this.onDoneComplete();
}
}
}
//Override this function to perform other actions when the user clicks the green checkmark to complete the wizard.
onDoneComplete( e ) {
$this.cleanUp();
}
addStepObject( name, obj ) {
//always override.
this.step_objects[name] = obj;
return this.step_objects[name]; //returned for chaining.
}
getStepObject( name ) {
if ( typeof name == 'undefined' ) {
name = this.getCurrentStepName();
}
if ( typeof this.step_objects[name] == 'object' ) {
return this.step_objects[name];
}
return this.step_objects['home'];
}
getCurrentStepName() {
return this.current_step;
}
setCurrentStepName( val ) {
this.current_step = val;
}
//Stub to stop backbone from complaining that it's missing, Wizard really doesn't render itself as such, it just displays its template.
render() {
}
/*
* Clean up the markup.
*/
cleanUp() {
$( this.el ).remove();
for ( var n in this.step_objects ) {
if ( this.step_objects[n] ) {
this.step_objects[n].reload = true;
}
}
LocalCacheData.current_open_wizard_controllers = LocalCacheData.current_open_wizard_controllers.filter( wizard => wizard.wizard_id !== this.wizard_id );
$().TFeedback( {
source: this.wizard_id
} );
}
/**
* setup a step object
*
* @param name
* @param callback
*/
initStepObject( name, callback ) {
if ( this._step_map.hasOwnProperty( name ) ) {
if ( this.step_objects[name] == null || typeof this.step_objects[name] != 'object' ) {
var $this = this;
Global.loadScript( this._step_map[name].script_path, function() {
$this.setCurrentStepName( name );
$( $this.el ).find( '.content' ).html( '' );
//var obj = new window[$this._step_map[name].object_name]( $this );
var obj = eval( 'new ' + $this._step_map[name].object_name + '( $this );' );
obj.reload = false;
$this.addStepObject( name, obj );
if ( typeof callback == 'function' ) {
callback( obj );
}
} );
return;
} else {
//reopening a step
this.setCurrentStepName( name );
if ( typeof callback == 'function' ) {
var obj = this.step_objects[name];
$( this.el ).find( '.content' ).html( '' );
//obj = new window[this._step_map[name].object_name]( this );
var obj = eval( 'new ' + this._step_map[name].object_name + '( this );' );
//reopening a step that has been opened in a previously closed wizard.
if ( this.step_objects[name].reload == true ) {
obj.clicked_buttons = {};
obj.reload = false;
}
this.addStepObject( name, obj );
callback( obj );
}
return;
}
}
}
disableButtons() {
this.button_click_procesing = true;
//Changing the button images causes flashing and isn't required for just disabling the buttons while the view loads.
// $( this.el ).find( '.forward-btn' ).addClass( 'disable-image' );
// $( this.el ).find( '.back-btn' ).addClass( 'disable-image' );
}
/**
* Enables the next/prev buttons
* the step object for the first step should return false instead fo a previous step name to disable the previous button
* the step object for the last step should return false instead of a next step name to disable the next button and enable the done button.
*/
enableButtons() {
var step = this.getStepObject();
if ( typeof step.getNextStepName() != 'string' ) {
$( this.el ).find( '.forward-btn' ).addClass( 'disable-image' );
$( this.el ).find( '.done-btn' ).removeClass( 'disable-image' ); //When right arrow is disabled, assume last step and enable done button.
} else {
$( this.el ).find( '.forward-btn' ).removeClass( 'disable-image' );
$( this.el ).find( '.done-btn' ).addClass( 'disable-image' ); //When right arrow is enabled, assume *not* last step, disable done button.
}
if ( typeof step.getPreviousStepName() != 'string' ) {
$( this.el ).find( '.back-btn' ).addClass( 'disable-image' );
} else {
$( this.el ).find( '.back-btn' ).removeClass( 'disable-image' );
}
this._enableButtons();
this.button_click_procesing = false;
}
//override me.
_enableButtons() {
}
/**
* minimize the wiazrd to a min_tab
*/
minimize() {
LocalCacheData.PayrollRemittanceAgencyEventWizardController = this;
//Remove from current_open_wizard_controllers so that when opening a new wizard the user does not get
//a message asking them to close the previous (minimized) wizard that is not viewable.
LocalCacheData.current_open_wizard_controllers = LocalCacheData.current_open_wizard_controllers.filter( wizard => wizard.wizard_id !== this.wizard_id );
Global.addViewTab( this.wizard_id, this.wizard_name, window.location.href );
this.delegateEvents();
$( this.el ).remove();
}
reload() {
for ( var i in this.step_objects ) {
this.step_objects[i].reload = true;
}
}
disableForCommunity( callback ) {
if ( Global.getProductEdition() <= 10 ) {
TAlertManager.showAlert( Global.getUpgradeMessage(), $.i18n._( 'Denied' ) );
} else {
if ( typeof callback == 'function' ) {
callback();
}
}
}
}

View File

@@ -0,0 +1,333 @@
import { TTBackboneView } from '@/views/TTBackboneView';
export class WizardStep extends TTBackboneView {
constructor( options = {} ) {
_.defaults( options, {
previous_step_name: null,
next_step_name: null,
buttons: null,
wizard_obj: null, //rename to wizard_obj
clicked_buttons: {},
reload: false,
api: null,
//override in children
name: 'undefined',
title: $.i18n._( 'Undefined Step' ),
instructions: $.i18n._( 'Undefined step data' )
} );
super( options );
}
initialize( wizard_obj ) {
super.initialize( wizard_obj );
this.buttons = {};
this.clicked_buttons = {}; //Clear clicked buttons on each step so checking that all buttons are clicked doesn't carry state from one step to the next. (ie: They click a required button on Step 2, but not Step 3, the count for required buttons would still match as 1)
this.reload = false;
this.setWizardObject( wizard_obj );
var $this = this;
this.init();
}
//Children must always call render()
init() {
this.render();
}
initCardsBlock() {
$( this.wizard_obj.el ).find( '#cards' ).html( '' );
}
setTitle( title ) {
$( this.wizard_obj.el ).find( '.title-1' ).html( title );
}
setInstructions( instructions, callback ) {
if ( $( this.el ).find( '.instructions' ).length == 0 ) {
$( this.el ).find( '.progress-bar' ).append( '<p class="instructions"></p>' );
}
$( this.el ).find( '.progress-bar .instructions' ).html( instructions );
if ( typeof callback == 'function' ) {
callback();
}
}
setWizardObject( val ) {
this.wizard_obj = val;
this.el = this.wizard_obj.el;
}
getWizardObject() {
return this.wizard_obj;
}
setNextStepName( val ) {
this.next_step_name = val;
}
getNextStepName() {
return false;
}
setPreviousStepName( val ) {
this.previous_step_name = val;
}
getPreviousStepName() {
return false;
}
render() {
this.initCardsBlock();
return this._render();
}
_render() {
return;
//always overrirde
}
append( content ) {
$( this.wizard_obj.el ).find( '.content' ).append( content );
}
appendButton( button ) {
$( this.wizard_obj.el ).find( '#cards' ).append( button );
}
setGrid( gridId, grid_div, allMultipleSelection ) {
if ( !allMultipleSelection ) {
allMultipleSelection = false;
}
$( '#' + gridId ).remove(); //Remove the grid to prevent JS Exception: Uncaught TypeError: Failed to execute 'replaceChild' on 'Node': parameter 2 is not of type 'Node'.
this.append( grid_div );
var grid = $( '#' + gridId );
var grid_columns = this.getGridColumns( gridId );
var $this = this;
grid = new TTGrid( gridId, {
onSelectRow: function( e ) {
$this.onGridSelectRow( e );
},
onSelectAll: function( e ) {
for ( var n in e ) {
$this.onGridSelectRow( e[n] );
}
},
ondblClickRow: function() {
$this.onGridDblClickRow();
},
multiselect: false,
winMultiSelect: false
}, grid_columns );
this.setGridSize( grid );
this.setGridGroupColumns( gridId );
return grid; //allowing chaining off this method.
}
getGridColumns( gridId, callBack ) {
//override if step object needs a grid.
}
setGridAutoHeight( grid, length ) {
if ( length > 0 && length < 10 ) {
grid.grid.setGridHeight( length * 23 );
} else if ( length > 10 ) {
grid.grid.setGridHeight( 400 );
}
}
setGridSize( grid ) {
grid.grid.setGridWidth( $( this.wizard_obj.el ).find( '.content .grid-div' ).width() - 11 );
grid.grid.setGridHeight( $( this.wizard_obj.el ).find( '.content' ).height() - 150 ); //During merge, this wasn't in MASTER branch.
}
getRibbonButtonBox() {
var div = $( '<div class="menu ribbon-button-bar"></div>' );
var ul = $( '<ul></ul>' );
div.append( ul );
return div;
}
/**
* to get old-style icons, don't provide desc
* to get card-style icons, provide desc
* to get card-style icons without a description, send a blank string ('') as desc
*
* @param id
* @param icon
* @param label
* @param desc
* @returns {*|jQuery|HTMLElement}
*/
getRibbonButton( id, icon, label, desc ) {
//prelaod imgages to reduce the appearance of phantom flashing
$( '<img></img>' )[0].src = icon;
if ( typeof desc == 'undefined' ) {
var button = $( '<li><div class="ribbon-sub-menu-icon" id="' + id + '"><img src="' + icon + '" >' + label + '</div></li>' );
return button;
}
var container = $( '<div class="wizard_icon_card" id="' + id + '"></div>' );
var img = $( '<img src="' + icon + '"></img>' );
var right_container = $( '<div class="right_container"></div>' );
var title = $( '<h3 class="button_title"></h3>' );
title.html( label ? label : '' );
var description = $( '<div class="description"></div>' );
description.html( desc ? desc : '' );
container.append( img );
right_container.append( title );
right_container.append( description );
container.append( right_container );
return container;
}
//
//stubs that should be overrideen
//
onGridSelectRow( selected_id ) {
//
}
onGridDblClickRow( selected_id ) {
//
}
onNavigationClick( e, icon ) {
if ( e ) {
this.addButtonClick( e, icon );
}
//Prevent double clicking on tax wizard buttons.
ProgressBar.showOverlay();
//this flag is turned off in ProgressBarManager::closeOverlay, or 2s whichever happens first
if ( window.clickProcessing == true ) {
return;
} else {
window.clickProcessing = true;
window.clickProcessingHandle = window.setTimeout( function() {
if ( window.clickProcessing == true ) {
window.clickProcessing = false;
ProgressBar.closeOverlay();
}
}, 1000 );
}
var api_payroll_remittance_agency_event = TTAPI.APIPayrollRemittanceAgencyEvent;
api_payroll_remittance_agency_event.doLogWizardEvent( this.getWizardObject().selected_remittance_agency_event_id, 'step_action', this.current_step, icon, false, true, {
onResult: function( result ) {
}
} );
this._onNavigationClick( icon );
}
//Overridden in each Wizard step.
_onNavigationClick( icon ) {
}
//Overridden in each Wizard step that needs to determine if required buttons are clicked or not.
isRequiredButtonsClicked() {
return true;
}
addButtonClick( e, icon ) {
// $(e.target).addClass('clicked_wizard_icon');
// $(e.target).find('img').addClass('disable-image');
var element = $( e.target );
if ( !element.hasClass( 'wizard_icon_card' ) ) {
element = $( e.target ).parents( '.wizard_icon_card' );
}
element.addClass( 'clicked_wizard_icon' );
element.addClass( 'disable-image' );
this.clicked_buttons[icon] = true;
}
isButtonClicked( icon ) {
if ( this.clicked_buttons.hasOwnProperty( icon ) && typeof this.clicked_buttons[icon] != 'undefined' ) {
return true;
}
return false;
}
addButton( context_name, icon_name, title, description, button_name ) {
if ( typeof button_name == 'undefined' ) {
button_name = context_name;
}
var button = this.getRibbonButton( context_name, Global.getRibbonIconRealPath( icon_name ), title, description );
var $this = this;
button.unbind( 'click' ).bind( 'click', function( e ) {
$this.onNavigationClick( e, button_name );
} );
//ribbon_button_box.find('ul').append(button);
if ( this.isButtonClicked( button_name ) ) {
button.addClass( 'clicked_wizard_icon' );
button.addClass( 'disable-image' );
}
this.buttons[icon_name] = button;
this.appendButton( button );
return button;
}
setGridGroupColumns( gridId ) {
}
urlClick( action_id ) {
this.api.getMakePaymentData( this.getWizardObject().selected_remittance_agency_event_id, action_id, {
onResult: function( result ) {
var url = result.getResult();
Debug.Text( 'Redirecting to external site: ' + url, 'WizardStep.js', 'WizardStep', 'urlClick', 10 );
window.open( url );
}
} );
}
paymentServicesClick( action_id ) {
this.api.getFileAndPayWithPaymentServicesData( this.getWizardObject().selected_remittance_agency_event_id, action_id, {
onResult: function( result ) {
var retval = result.getResult();
if ( retval['user_message'] && retval['user_message'] != '' ) {
TAlertManager.showAlert( retval['user_message'] );
} else {
if ( retval == false ) {
TAlertManager.showAlert( $.i18n._( 'ERROR! Something went wrong, please contact customer service immediately!' ) );
}
}
}
} );
}
}