import '@/global/widgets/filebrowser/TImage'; import TTVueUtils from '@/services/TTVueUtils'; import TimeSheetControlBar from '@/components/timesheet/TimeSheetControlBar'; import { TTUUID } from '@/global/TTUUID'; import { Global } from '@/global/Global'; export class TimeSheetViewController extends BaseViewController { constructor( options = {} ) { _.defaults( options, { el: '#timesheet_view_container', //Must set el here and can only set string, so events can work // _required_files: { // 10: ['TImage'], // 15: ['leaflet-timetrex'] // }, status_array: null, type_array: null, employee_nav: null, start_date_picker: null, full_timesheet_data: null, //full timesheet data full_format: 'ddd-MMM-DD-YYYY', weekly_format: 'ddd, MMM DD', day_format: 'ddd', date_format: 'MMM DD', start_date: null, end_date: null, select_cells_Array: [], //Timesheet grid select_punches_array: [], //Timesheet grid. absence_select_cells_Array: [], //Absence grid accumulated_time_cells_array: [], premium_cells_array: [], timesheet_data_source: null, accumulated_time_source: null, accumulated_time_grid: null, accumulated_time_source_map: null, branch_grid: null, branch_source_map: null, branch_source: null, department_grid: null, department_source_map: null, department_source: null, job_grid: null, job_source_map: null, job_source: null, job_item_grid: null, job_item_source_map: null, job_item_source: null, punch_tag_source_map: null, punch_tag_source: null, premium_grid: null, premium_source_map: null, premium_source: null, absence_grid: null, absence_source: null, absence_original_source: null, accumulated_total_grid: null, accumulated_total_grid_source_map: null, accumulated_total_grid_source: null, punch_note_grid: null, punch_note_grid_source: null, verification_grid: null, verification_grid_source: null, grid_dic: null, pay_period_map: null, pay_period_data: null, timesheet_verify_data: null, api_timesheet: null, api_user_date_total: null, api_date: null, api_station: null, api_punch: null, absence_model: false, select_drag_menu_id: '', //Do drag move or copy is_mass_adding: false, department_cell_count: 0, branch_cell_count: 0, premium_cell_count: 0, job_cell_count: 0, task_cell_count: 0, punch_tag_cell_count: 0, absence_cell_count: 0, punch_note_account: 0, show_navigation_box: true, station: null, scroll_position: 0, job_api: null, job_item_api: null, user_group_id: null, punch_tag_api: null, user_api: null, department_api: null, default_punch_tag: [], previous_punch_tag_selection: [], api_absence_policy: null, pre_total_time: null, absence_available_balance_dataList: {}, available_balance_info: null, show_job_ui: false, show_job_item_ui: false, show_punch_tag_ui: false, show_branch_ui: false, show_department_ui: false, show_good_quantity_ui: false, show_bad_quantity_ui: false, show_note_ui: false, show_station_ui: false, show_absence_job_ui: false, show_absence_job_item_ui: false, show_absence_punch_tag_ui: false, show_absence_branch_ui: false, show_absence_department_ui: false, holiday_data_dic: {}, grid_div: null, actual_time_label: null, column_maps: null, accmulated_order_map: {}, url_args_before_set_date_url: {}, allow_auto_switch: true, vue_control_bar_id: '', previous_absence_policy_id: false, events: {}, //Issue #3286 - Users without permission to display "Current View" dropdown still need to load select layout from user generic data //This is to ensure the API attempts to update the current layout and not create a new one causing a validation error. force_get_select_layout: true } ); super( options ); } init( options ) { ////this._super('initialize', options ); this.permission_id = 'punch'; this.viewId = 'TimeSheet'; this.script_name = 'TimeSheetView'; this.context_menu_name = $.i18n._( 'TimeSheet' ); this.navigation_label = $.i18n._( 'TimeSheet' ); this.api = TTAPI.APIPunch; this.api_timesheet = TTAPI.APITimeSheet; this.api_user_date_total = TTAPI.APIUserDateTotal; this.api_date = TTAPI.APITTDate; this.api_station = TTAPI.APIStation; this.api_punch = TTAPI.APIPunch; if ( ( Global.getProductEdition() >= 20 ) ) { this.job_api = TTAPI.APIJob; this.job_item_api = TTAPI.APIJobItem; this.punch_tag_api = TTAPI.APIPunchTag; this.department_api = TTAPI.APIDepartment; } this.api_absence_policy = TTAPI.APIAbsencePolicy; this.scroll_position = 0; this.grid_dic = {}; // this.event_bus = new TTEventBus({ view_id: this.viewId }); // TimeSheet does not use TTEventBus yet, its currently using direct access to the Vue component by reference, as a proof of concept. Best to use TTEventBus for future work though. this.initPermission(); this.render(); this.buildContextMenu(); this.initData(); } initEditView() { TTPromise.resolve( 'TimeSheetViewController', 'addclick' ); super.initEditView(); } onSubViewRemoved( is_cancel ) { if ( !is_cancel ) { this.search(); } if ( !this.edit_view ) { this.setDefaultMenu(); } else { this.setEditMenu(); } } setScrollPosition() { if ( this.scroll_position > 0 ) { this.grid_div.scrollTop( this.scroll_position ); } } punchModeValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if ( PermissionManager.validate( p_id, 'punch_timesheet' ) && PermissionManager.validate( p_id, 'manual_timesheet' ) ) { return true; } return false; } getPunchPermissionType() { return this.absence_model ? 'absence' : 'punch'; } jobUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if (Global.getProductEdition() >= 20 && PermissionManager.validate( 'job', 'enabled' ) && PermissionManager.validate( p_id, 'edit_job' ) ) { return true; } return false; } jobItemUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if (Global.getProductEdition() >= 20 && PermissionManager.validate( p_id, 'edit_job_item' ) ) { return true; } return false; } punchTagUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if (Global.getProductEdition() >= 20 && PermissionManager.validate( p_id, 'edit_punch_tag' ) ) { return true; } return false; } //Refresh to clear warnning messages after saving from employee edit view updateSelectUserAndRefresh( new_item ) { this.employee_nav.updateSelectItem( new_item ); this.search(); } branchUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if ( PermissionManager.validate( p_id, 'edit_branch' ) ) { return true; } return false; } departmentUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if ( PermissionManager.validate( p_id, 'edit_department' ) ) { return true; } return false; } goodQuantityUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if ( PermissionManager.validate( p_id, 'edit_quantity' ) ) { return true; } return false; } badQuantityUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if ( PermissionManager.validate( p_id, 'edit_quantity' ) && PermissionManager.validate( p_id, 'edit_bad_quantity' ) ) { return true; } return false; } locationUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if ( PermissionManager.validate( p_id, 'edit_location' ) ) { return true; } return false; } noteUIValidate( p_id ) { if ( !p_id ) { p_id = 'punch'; } if ( PermissionManager.validate( p_id, 'edit_note' ) ) { return true; } return false; } stationValidate() { if ( PermissionManager.validate( 'station', 'enabled' ) ) { return true; } return false; } /* jshint ignore:start */ //Special permission check for views, need override initPermission() { super.initPermission(); if ( !PermissionManager.validate( 'punch', 'view' ) && !PermissionManager.validate( 'punch', 'view_child' ) ) { this.show_navigation_box = false; this.show_search_tab = false; } else { this.show_navigation_box = true; this.show_search_tab = true; } if ( this.punchModeValidate() ) { this.show_punch_mode_ui = true; } else { this.show_punch_mode_ui = false; } this.allow_auto_switch && this.show_punch_mode_ui && ( this.is_auto_switch = true ); if ( this.jobUIValidate() ) { this.show_job_ui = true; } else { this.show_job_ui = false; } if ( this.jobItemUIValidate() ) { this.show_job_item_ui = true; } else { this.show_job_item_ui = false; } if ( this.punchTagUIValidate() ) { this.show_punch_tag_ui = true; } else { this.show_punch_tag_ui = false; } if ( this.branchUIValidate() ) { this.show_branch_ui = true; } else { this.show_branch_ui = false; } if ( this.departmentUIValidate() ) { this.show_department_ui = true; } else { this.show_department_ui = false; } if ( this.goodQuantityUIValidate() ) { this.show_good_quantity_ui = true; } else { this.show_good_quantity_ui = false; } if ( this.badQuantityUIValidate() ) { this.show_bad_quantity_ui = true; } else { this.show_bad_quantity_ui = false; } if ( this.noteUIValidate() ) { this.show_note_ui = true; } else { this.show_note_ui = false; } if ( this.locationUIValidate() ) { this.show_location_ui = true; } else { this.show_location_ui = false; } if ( this.stationValidate() ) { this.show_station_ui = true; } else { this.show_station_ui = false; } if ( this.jobUIValidate( 'absence' ) ) { this.show_absence_job_ui = true; } else { this.show_absence_job_ui = false; } if ( this.jobItemUIValidate( 'absence' ) ) { this.show_absence_job_item_ui = true; } else { this.show_absence_job_item_ui = false; } if ( this.punchTagUIValidate( 'absence' ) ) { this.show_absence_punch_tag_ui = true; } else { this.show_absence_punch_tag_ui = false; } if ( this.branchUIValidate( 'absence' ) ) { this.show_absence_branch_ui = true; } else { this.show_absence_branch_ui = false; } if ( this.departmentUIValidate( 'absence' ) ) { this.show_absence_department_ui = true; } else { this.show_absence_department_ui = false; } } /* jshint ignore:end */ ownerOrChildPermissionValidate( p_id, permission_name, selected_item ) { var field; if ( permission_name && permission_name.indexOf( 'child' ) > -1 ) { field = 'is_child'; } else { field = 'is_owner'; } var user = this.getSelectEmployee( true ); if ( PermissionManager.validate( p_id, permission_name ) && ( !user || !Global.isSet( user[field] ) || ( user && user[field] ) ) ) { return true; } return false; } initOptions() { var options = [ { option_name: 'type', api: this.api }, { option_name: 'status', api: this.api }, ]; this.initDropDownOptions( options); } getCustomContextMenuModel() { var context_menu_model = { groups: { drag_and_drop: { label: $.i18n._( 'Drag & Drop' ), id: this.viewId + 'drag_and_drop' } }, exclude: [ 'export_excel', 'add', 'copy', 'copy_as_new' ], include: [ { label: $.i18n._( 'New Punch' ), id: 'add_punch', action_group: 'new', group: 'editor', vue_icon: 'tticon tticon-add_black_24dp', show_on_right_click: true, sort_order: 910 }, { label: $.i18n._( 'New Absence' ), id: 'add_absence', action_group: 'new', group: 'editor', vue_icon: 'tticon tticon-add_black_24dp', show_on_right_click: true, sort_order: 920 }, { label: $.i18n._( 'In/Out' ), id: 'in_out', action_group: 'in_out', group: 'editor', vue_icon: 'tticon tticon-timer_black_24dp', show_on_right_click: true, sort_order: 1050 }, { label: $.i18n._( 'Drag & Drop: Move' ), id: 'move', menu_align: 'right', action_group: 'move_copy', multi_select_group: 1 }, { label: $.i18n._( 'Drag & Drop: Copy' ), id: 'drag_copy', menu_align: 'right', action_group: 'move_copy', multi_select_group: 1 }, ] }; if ( PermissionManager.validate( 'request', 'add' ) ) { context_menu_model.include.push( { label: $.i18n._( 'Add Request' ), id: 'AddRequest', vue_icon: 'tticon tticon-post_add_black_24dp', menu_align: 'right', permission_result: true, permission: true, show_on_right_click: true, sort_order: 1000 } ); } if ( ( Global.getProductEdition() >= 15 ) ) { context_menu_model.include.push( { label: $.i18n._( 'Map' ), id: 'map', menu_align: 'right', vue_icon: 'tticon tticon-map_black_24dp', show_on_right_click: true, sort_order: 2000, } ); } context_menu_model.include.push( { label: $.i18n._( 'Print' ), id: 'print', action_group_header: true, action_group: 'print_menu', sort_order: 7000, menu_align: 'right', type: 2, permission_result: true, permission: true }, { label: $.i18n._( 'Summary' ), id: 'print_summary', action_group: 'print_menu', sort_order: 7000, menu_align: 'right' }, { label: $.i18n._( 'Detailed' ), id: 'print_detailed', action_group: 'print_menu', sort_order: 7000, menu_align: 'right' }, { label: $.i18n._( 'Jump To' ), id: 'jump_to_header', menu_align: 'right', action_group: 'jump_to', sort_order: 8000, action_group_header: true, permission_result: false // to hide it in legacy context menu and avoid errors in legacy parsers. }, { label: $.i18n._( 'Schedules' ), id: 'schedule', menu_align: 'right', action_group: 'jump_to', sort_order: 8000 }, { label: $.i18n._( 'Pay Stubs' ), id: 'pay_stub', menu_align: 'right', action_group: 'jump_to', sort_order: 8000 }, { label: $.i18n._( 'Edit Employee' ), id: 'edit_employee', menu_align: 'right', action_group: 'jump_to', sort_order: 8000 }, { label: $.i18n._( 'Edit Pay Period' ), id: 'edit_pay_period', menu_align: 'right', action_group: 'jump_to', sort_order: 8000 }, { label: $.i18n._( 'Accumulated Time' ), id: 'accumulated_time', menu_align: 'right', action_group: 'jump_to', sort_order: 8000 }, { label: '', //Empty label. vue_icon is displayed instead of text. id: 'other_header', menu_align: 'right', action_group: 'other', action_group_header: true, vue_icon: 'tticon tticon-more_vert_black_24dp', }, { label: $.i18n._( 'ReCalculate TimeSheet' ), id: 're_calculate_timesheet', menu_align: 'right', action_group: 'other', }, { label: $.i18n._( 'Generate Pay Stub' ), id: 'generate_pay_stub', menu_align: 'right', action_group: 'other', }, ); return context_menu_model; } parseCustomContextModelForEditViews( context_menu_model ) { context_menu_model = super.parseCustomContextModelForEditViews( context_menu_model ); if( this.determineContextMenuMountAttributes().menu_type === 'editview_contextmenu' ) { context_menu_model.exclude.push( 'move', 'drag_copy', 're_calculate_timesheet', 'generate_pay_stub', 'print', 'print_detailed', 'print_summary', ) } return context_menu_model; } openEditView() { //#2295 - Re-initialize previous_absence_policy_id to ensure that previously saved values are passed correctly into the estimation of projected available balance. this.previous_absence_policy_id = false; Global.setUINotready(); TTPromise.add( 'init', 'init' ); TTPromise.wait(); if ( !this.edit_view ) { this.is_edit = true; this.initEditViewUI( 'TimeSheet', 'TimeSheetEditView.html' ); } } /* jshint ignore:start */ //set widget disablebility if view mode or edit mode setEditViewWidgetsMode() { var did_clean = false; for ( var key in this.edit_view_ui_dic ) { if ( !this.edit_view_ui_dic.hasOwnProperty( key ) ) { continue; } var widget = this.edit_view_ui_dic[key]; var widgetContainer = this.edit_view_form_item_dic[key]; var column = widget.parent().parent().parent(); if ( !column.hasClass( 'v-box' ) ) { if ( !did_clean ) { did_clean = true; } } if ( this.absence_model ) { switch ( key ) { case 'punch_date': case 'punch_time': case 'status_id': case 'type_id': case 'quantity': case 'station_id': case 'has_image': case 'latitude': case 'split_punch_control': this.detachElement( key ); widget.css( 'opacity', 0 ); break; case 'punch_dates': if ( this.is_mass_adding ) { this.attachElement( key ); widget.css( 'opacity', 1 ); } else { this.detachElement( key ); widget.css( 'opacity', 0 ); } break; case 'date_stamp': if ( this.is_mass_adding ) { this.detachElement( key ); widget.css( 'opacity', 0 ); } else { this.attachElement( key ); widget.css( 'opacity', 1 ); } break; case 'total_time': case 'src_object_id': case 'override': this.attachElement( key ); widget.css( 'opacity', 1 ); break; case 'available_balance': this.detachElement( key ); widget.css( 'opacity', 1 ); break; default: widget.css( 'opacity', 1 ); break; } } else { switch ( key ) { case 'punch_dates': if ( this.is_mass_adding ) { this.attachElement( key ); widget.css( 'opacity', 1 ); } else { this.detachElement( key ); widget.css( 'opacity', 0 ); } break; case 'punch_date': if ( this.is_mass_adding ) { this.detachElement( key ); widget.css( 'opacity', 0 ); } else { this.attachElement( key ); widget.css( 'opacity', 1 ); } break; case 'quantity': if ( this.show_good_quantity_ui && this.show_bad_quantity_ui ) { this.attachElement( key ); widget.css( 'opacity', 1 ); } break; case 'station': this.attachElement( key ); widget.css( 'opacity', 1 ); break; case 'punch_time': case 'status_id': case 'type_id': case 'has_image': case 'latitude': this.attachElement( key ); widget.css( 'opacity', 1 ); break; case 'date_stamp': case 'total_time': case 'src_object_id': case 'override': this.detachElement( key ); widget.css( 'opacity', 0 ); break; default: widget.css( 'opacity', 1 ); break; } } if ( this.is_viewing ) { if ( Global.isSet( widget.setEnabled ) ) { widget.setEnabled( false ); } } else { if ( Global.isSet( widget.setEnabled ) ) { widget.setEnabled( true ); } } } } getCustomFieldReferenceField() { return 'note'; } setCustomFields() { //Custom fields are only shown on punch types and not on absence types. if ( this.getPunchPermissionType() === 'punch' ) { super.setCustomFields(); } } buildEditViewUI() { super.buildEditViewUI(); var $this = this; var tab_model = { 'tab_punch': { 'label': this.absence_model ? $.i18n._( 'Absence' ) : $.i18n._( 'Punch' ) }, 'tab_audit': true, }; this.setTabModel( tab_model ); var form_item_input; var widgetContainer; //Tab 0 start var tab_punch = this.edit_view_tab.find( '#tab_punch' ); var tab_punch_column1 = tab_punch.find( '.first-column' ); //Employee form_item_input = Global.loadWidgetByName( FormItemType.TEXT ); form_item_input.TText( { field: 'first_last_name' } ); this.addEditFieldToColumn( $.i18n._( 'Employee' ), form_item_input, tab_punch_column1, '' ); //Time form_item_input = Global.loadWidgetByName( FormItemType.TIME_PICKER ); form_item_input.TTimePicker( { field: 'punch_time', validation_field: 'time_stamp' } ); widgetContainer = $( '
' ); this.actual_time_label = $( '' ); widgetContainer.append( form_item_input ); widgetContainer.append( this.actual_time_label ); this.addEditFieldToColumn( $.i18n._( 'Time' ), form_item_input, tab_punch_column1, '', widgetContainer, true ); //Absence Model //Absence Policy Type form_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX ); form_item_input.AComboBox( { api_class: TTAPI.APIAbsencePolicy, allow_multiple_selection: false, layout_name: 'global_absences', show_search_inputs: true, set_empty: true, field: 'src_object_id', validation_field: 'absence_policy_id' } ); form_item_input.customSearchFilter = function( filter ) { return $this.setAbsencePolicyFilter( filter ); }; this.addEditFieldToColumn( $.i18n._( 'Absence Policy' ), form_item_input, tab_punch_column1, '', null, true ); //Available Balance form_item_input = Global.loadWidgetByName( FormItemType.TEXT ); form_item_input.TText( { field: 'available_balance' } ); widgetContainer = $( '
' ); this.available_balance_info = $( '' ); widgetContainer.append( form_item_input ); widgetContainer.append( this.available_balance_info ); this.addEditFieldToColumn( $.i18n._( 'Available Balance' ), [form_item_input], tab_punch_column1, '', widgetContainer, true ); //Date form_item_input = Global.loadWidgetByName( FormItemType.DATE_PICKER ); form_item_input.TDatePicker( { field: 'punch_date', validation_field: 'date_stamp' } ); this.addEditFieldToColumn( $.i18n._( 'Date' ), form_item_input, tab_punch_column1, '', null, true ); //Mass Add Date form_item_input = Global.loadWidgetByName( FormItemType.DATE_PICKER ); form_item_input.TRangePicker( { field: 'punch_dates', validation_field: 'date_stamp' } ); this.addEditFieldToColumn( $.i18n._( 'Date' ), form_item_input, tab_punch_column1, '', null, true ); //Absence Model //Date form_item_input = Global.loadWidgetByName( FormItemType.DATE_PICKER ); form_item_input.TDatePicker( { field: 'date_stamp' } ); this.addEditFieldToColumn( $.i18n._( 'Date' ), form_item_input, tab_punch_column1, '', null, true ); //Absence Model //Time form_item_input = Global.loadWidgetByName( FormItemType.TEXT_INPUT ); form_item_input.TTextInput( { field: 'total_time', mode: 'time_unit' } ); var widgetContainer = $( '
' ); var release_balance_button = $( '' ); release_balance_button.css( 'display', 'none' ); release_balance_button.click( function() { $this.getAvailableBalance( true ); } ); widgetContainer.append( form_item_input ); widgetContainer.append( release_balance_button ); this.addEditFieldToColumn( $.i18n._( 'Time' ), form_item_input, tab_punch_column1, '', widgetContainer, true ); //Punch Type form_item_input = Global.loadWidgetByName( FormItemType.COMBO_BOX ); form_item_input.TComboBox( { field: 'type_id' } ); form_item_input.setSourceData( $this.type_array ); widgetContainer = $( '
' ); var check_box = Global.loadWidgetByName( FormItemType.CHECKBOX ); check_box.TCheckbox( { field: 'disable_rounding' } ); var label = $( '' + $.i18n._( 'Disable Rounding' ) + '' ); widgetContainer.append( form_item_input ); // Check if view only mode. To prevent option appearing but disabled, as disabled checkboxes are not very clear - same in PunchViewController if ( this.is_viewing ) { // dev-note: not sure if we need to pass widgetContainer here, or if we can omit if its only one element now (due to the if is_viewing). // to be safe, will continue to use widgetContainer for this case. We only want to affect viewing mode (hide rounding checkbox), less risk of regression to keep widget container in. this.addEditFieldToColumn( $.i18n._( 'Punch Type' ), form_item_input, tab_punch_column1, '', widgetContainer, true ); } else { widgetContainer.append( label ); widgetContainer.append( check_box ); this.addEditFieldToColumn( $.i18n._( 'Punch Type' ), [form_item_input, check_box], tab_punch_column1, '', widgetContainer, true ); } //In Out (Status) form_item_input = Global.loadWidgetByName( FormItemType.COMBO_BOX ); form_item_input.TComboBox( { field: 'status_id' } ); form_item_input.setSourceData( $this.status_array ); this.addEditFieldToColumn( $.i18n._( 'In/Out' ), form_item_input, tab_punch_column1, '', null, true ); //Default Branch form_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX ); form_item_input.AComboBox( { api_class: TTAPI.APIBranch, allow_multiple_selection: false, layout_name: 'global_branch', show_search_inputs: true, set_empty: true, field: 'branch_id' } ); this.addEditFieldToColumn( $.i18n._( 'Branch' ), form_item_input, tab_punch_column1, '', null, true ); if ( !this.absence_model ) { if ( !this.show_branch_ui ) { this.detachElement( 'branch_id' ); } } else { if ( !this.show_absence_branch_ui ) { this.detachElement( 'branch_id' ); } } //Department form_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX ); form_item_input.AComboBox( { api_class: TTAPI.APIDepartment, allow_multiple_selection: false, layout_name: 'global_department', show_search_inputs: true, set_empty: true, field: 'department_id' } ); this.addEditFieldToColumn( $.i18n._( 'Department' ), form_item_input, tab_punch_column1, '', null, true ); if ( !this.absence_model ) { if ( !this.show_department_ui ) { this.detachElement( 'department_id' ); } } else { if ( !this.show_absence_department_ui ) { this.detachElement( 'department_id' ); } } if ( ( Global.getProductEdition() >= 20 ) ) { //Job form_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX ); form_item_input.AComboBox( { api_class: TTAPI.APIJob, allow_multiple_selection: false, layout_name: 'global_job', show_search_inputs: true, set_empty: true, setRealValueCallBack: ( function( val ) { if ( val ) { job_coder.setValue( val.manual_id ); } } ), field: 'job_id' } ); widgetContainer = $( '
' ); var job_coder = Global.loadWidgetByName( FormItemType.TEXT_INPUT ); job_coder.TTextInput( { field: 'job_quick_search', disable_keyup_event: true } ); job_coder.addClass( 'job-coder' ); widgetContainer.append( job_coder ); widgetContainer.append( form_item_input ); this.addEditFieldToColumn( $.i18n._( 'Job' ), [form_item_input, job_coder], tab_punch_column1, '', widgetContainer, true ); if ( !this.absence_model ) { if ( !this.show_job_ui ) { this.detachElement( 'job_id' ); } } else { if ( !this.show_absence_job_ui ) { this.detachElement( 'job_id' ); } } //Job Item form_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX ); form_item_input.AComboBox( { api_class: TTAPI.APIJobItem, allow_multiple_selection: false, layout_name: 'global_job_item', show_search_inputs: true, set_empty: true, setRealValueCallBack: ( function( val ) { if ( val ) { job_item_coder.setValue( val.manual_id ); } } ), field: 'job_item_id' } ); widgetContainer = $( '
' ); var job_item_coder = Global.loadWidgetByName( FormItemType.TEXT_INPUT ); job_item_coder.TTextInput( { field: 'job_item_quick_search', disable_keyup_event: true } ); job_item_coder.addClass( 'job-coder' ); widgetContainer.append( job_item_coder ); widgetContainer.append( form_item_input ); this.addEditFieldToColumn( $.i18n._( 'Task' ), [form_item_input, job_item_coder], tab_punch_column1, '', widgetContainer, true ); if ( !this.absence_model ) { if ( !this.show_job_item_ui ) { this.detachElement( 'job_item_id' ); } } else { if ( !this.show_absence_job_item_ui ) { this.detachElement( 'job_item_id' ); } } //Punch Tag form_item_input = Global.loadWidgetByName( FormItemType.AWESOME_BOX ); form_item_input.AComboBox( { api_class: TTAPI.APIPunchTag, allow_multiple_selection: true, layout_name: 'global_punch_tag', show_search_inputs: true, set_empty: true, get_real_data_on_multi: true, setRealValueCallBack: ( ( punch_tags, get_real_data ) => { if ( punch_tags ) { this.setPunchTagQuickSearchManualIds( punch_tags, get_real_data ); } } ), field: 'punch_tag_id' } ); widgetContainer = $( '
' ); var punch_tag_coder = Global.loadWidgetByName( FormItemType.TEXT_INPUT ); punch_tag_coder.TTextInput( { field: 'punch_tag_quick_search', disable_keyup_event: true } ); punch_tag_coder.addClass( 'job-coder' ); widgetContainer.append( punch_tag_coder ); widgetContainer.append( form_item_input ); this.addEditFieldToColumn( $.i18n._( 'Tags' ), [form_item_input, punch_tag_coder], tab_punch_column1, '', widgetContainer, true ); if ( !this.absence_model ) { if ( !this.show_punch_tag_ui ) { this.detachElement( 'punch_tag_id' ); } } else { if ( !this.show_absence_punch_tag_ui ) { this.detachElement( 'punch_tag_id' ); } } } if ( ( Global.getProductEdition() >= 20 ) ) { //Quanitity var good = Global.loadWidgetByName( FormItemType.TEXT_INPUT ); good.TTextInput( { field: 'quantity' } ); good.addClass( 'quantity-input' ); var good_label = $( '' + $.i18n._( 'Good' ) + ': ' ); var bad = Global.loadWidgetByName( FormItemType.TEXT_INPUT ); bad.TTextInput( { field: 'bad_quantity' } ); bad.addClass( 'quantity-input' ); var bad_label = $( '/ ' + $.i18n._( 'Bad' ) + ': ' ); widgetContainer = $( '
' ); widgetContainer.append( good_label ); widgetContainer.append( good ); widgetContainer.append( bad_label ); widgetContainer.append( bad ); this.addEditFieldToColumn( $.i18n._( 'Quantity' ), [good, bad], tab_punch_column1, '', widgetContainer, true ); if ( !this.show_bad_quantity_ui && !this.show_good_quantity_ui ) { this.detachElement( 'quantity' ); } else { if ( !this.show_bad_quantity_ui ) { bad_label.hide(); bad.hide(); } if ( !this.show_good_quantity_ui ) { good_label.hide(); good.hide(); } } } //Note form_item_input = Global.loadWidgetByName( FormItemType.TEXT_AREA ); form_item_input.TTextArea( { field: 'note', width: '100%' } ); this.addEditFieldToColumn( $.i18n._( 'Note' ), form_item_input, tab_punch_column1, '', null, true, true ); form_item_input.parent().width( '45%' ); if ( !this.show_note_ui ) { this.detachElement( 'note' ); } //Absence Mode //Override form_item_input = Global.loadWidgetByName( FormItemType.CHECKBOX ); form_item_input.TCheckbox( { field: 'override' } ); this.addEditFieldToColumn( $.i18n._( 'Override' ), form_item_input, tab_punch_column1, '', null, true, true ); //Location if ( Global.getProductEdition() >= 15 ) { var latitude = Global.loadWidgetByName( FormItemType.TEXT ); latitude.TText( { field: 'latitude' } ); var longitude = Global.loadWidgetByName( FormItemType.TEXT ); longitude.TText( { field: 'longitude' } ); widgetContainer = $( '
' ); var accuracy = Global.loadWidgetByName( FormItemType.TEXT ); accuracy.TText( { field: 'position_accuracy' } ); label = $( '' + $.i18n._( 'Accuracy' ) + ':' ); var map_icon = $( '' ); this.location_wrapper = $( '
' ); widgetContainer.append( map_icon ); widgetContainer.append( this.location_wrapper ); this.location_wrapper.append( latitude ); this.location_wrapper.append( $( ', ' ) ); this.location_wrapper.append( longitude ); this.location_wrapper.append( label ); this.location_wrapper.append( accuracy ); this.location_wrapper.append( $( 'm' ) ); this.addEditFieldToColumn( $.i18n._( 'Location' ), [latitude, longitude, accuracy], tab_punch_column1, '', widgetContainer, true ); widgetContainer.click( function() { $this.onMapClick(); } ); // #2117 - Manual location only supported in edit because we need a punch record to append the data to. if ( ( !this.is_edit && !this.is_viewing ) || !this.show_location_ui ) { widgetContainer.parents( '.edit-view-form-item-div' ).hide(); } } //Station form_item_input = Global.loadWidgetByName( FormItemType.TEXT ); form_item_input.TText( { field: 'station_id' } ); this.addEditFieldToColumn( $.i18n._( 'Station' ), form_item_input, tab_punch_column1, '', null, true, true ); form_item_input.click( function() { if ( $this.current_edit_record.station_id && $this.show_station_ui ) { IndexViewController.openEditView( $this, 'Station', $this.current_edit_record.station_id ); } } ); //Split Punch Control form_item_input = Global.loadWidgetByName( FormItemType.CHECKBOX ); form_item_input.TCheckbox( { field: 'split_punch_control' } ); this.addEditFieldToColumn( $.i18n._( 'Split Existing Punches' ), form_item_input, tab_punch_column1, '', null, true, true ); if ( this.is_mass_adding == false ) { this.detachElement( 'split_punch_control' ); } //Punch Image form_item_input = Global.loadWidgetByName( FormItemType.IMAGE ); form_item_input.TImage( { field: 'punch_image' } ); this.addEditFieldToColumn( $.i18n._( 'Image' ), form_item_input, tab_punch_column1, '', null, true, true ); } /* jshint ignore:end */ onEditStationDone() { this.setStation(); } setAbsencePolicyFilter( filter ) { if ( !filter.filter_data ) { filter.filter_data = {}; } filter.filter_data.user_id = this.current_edit_record.user_id; if ( filter.filter_columns ) { filter.filter_columns.absence_policy = true; } return filter; } onSetSearchFilterFinished() { } onBuildBasicUIFinished() { } onBuildAdvUIFinished() { } parserDatesRange( date ) { var dates = date.split( ' - ' ); var resultArray = []; var beginDate = Global.strToDate( dates[0] ); var endDate = Global.strToDate( dates[1] ); var nextDate = beginDate; while ( nextDate.getTime() < endDate.getTime() ) { resultArray.push( nextDate.format() ); nextDate = new Date( new Date( nextDate.getTime() ).setDate( nextDate.getDate() + 1 ) ); } resultArray.push( dates[1] ); return resultArray; } validate() { var $this = this; var record = this.current_edit_record; var i; if ( this.is_mass_editing ) { record = []; var len = this.mass_edit_record_ids.length; for ( var i = 0; i < len; i++ ) { var temp_item = Global.clone( this.current_edit_record ); temp_item.id = this.mass_edit_record_ids[i]; record.push( temp_item ); } } if ( this.is_mass_adding ) { record = []; var dates_array = this.current_edit_record.punch_dates; if ( dates_array && dates_array.indexOf( ' - ' ) > 0 ) { dates_array = this.parserDatesRange( dates_array ); } for ( var i = 0; i < dates_array.length; i++ ) { var common_record = Global.clone( this.current_edit_record ); delete common_record.punch_dates; if ( this.absence_model ) { common_record.date_stamp = dates_array[i]; } else { common_record.punch_date = dates_array[i]; } record.push( common_record ); } } if ( !this.absence_model ) { this.api['validate' + this.api.key_name]( record, { onResult: function( result ) { $this.validateResult( result ); } } ); } else { this.api_user_date_total['validate' + this.api_user_date_total.key_name]( record, { onResult: function( result ) { $this.clearErrorTips(); //Always clear error if ( result.isValid() ) { $this.setEditMenu(); } else { $this.setErrorMenu(); $this.setErrorTips( result ); } } } ); } } /* jshint ignore:start */ onFormItemChange( target, doNotValidate ) { var $this = this; this.setIsChanged( target ); this.setMassEditingFieldsWhenFormChange( target ); var key = target.getField(); var c_value = target.getValue(); // Error: TypeError: this.current_edit_record is null in interface/html5/framework/jquery.min.js?v=9.0.5-20151222-094938 line 2 > eval line 1409 if ( !this.current_edit_record ) { return; } this.current_edit_record[key] = c_value; switch ( key ) { case 'job_id': if ( ( Global.getProductEdition() >= 20 ) ) { this.edit_view_ui_dic['job_quick_search'].setValue( target.getValue( true ) ? ( target.getValue( true ).manual_id ? target.getValue( true ).manual_id : '' ) : '' ); this.setJobItemValueWhenJobChanged( target.getValue( true ), 'job_item_id', { status_id: 10, job_id: this.current_edit_record.job_id } ); this.edit_view_ui_dic['job_quick_search'].setCheckBox( true ); this.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' ); } break; case 'job_item_id': if ( ( Global.getProductEdition() >= 20 ) ) { this.edit_view_ui_dic['job_item_quick_search'].setValue( target.getValue( true ) ? ( target.getValue( true ).manual_id ? target.getValue( true ).manual_id : '' ) : '' ); this.edit_view_ui_dic['job_item_quick_search'].setCheckBox( true ); this.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' ); } break; case 'punch_tag_id': if ( ( Global.getProductEdition() >= 20 ) ) { if ( c_value !== TTUUID.zero_id && c_value !== false && c_value.length > 0 ) { this.setPunchTagQuickSearchManualIds( target.getSelectItems() ); } else { this.edit_view_ui_dic['punch_tag_quick_search'].setValue( '' ); } $this.previous_punch_tag_selection = c_value; //Reset source data to make sure correct punch tags are always shown. this.edit_view_ui_dic['punch_tag_id'].setSourceData( null ); } break; case 'branch_id': if ( ( Global.getProductEdition() >= 20 ) ) { this.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' ); this.setJobValueWhenCriteriaChanged( 'job_id', { status_id: 10, user_id: this.current_edit_record.user_id, punch_branch_id: this.current_edit_record.branch_id, punch_department_id: this.current_edit_record.department_id } ); this.setDepartmentValueWhenBranchChanged( target.getValue( true ), 'department_id', { branch_id: this.current_edit_record.branch_id, user_id: this.current_edit_record.user_id } ); } break; case 'user_id': case 'department_id': if ( ( Global.getProductEdition() >= 20 ) ) { this.setPunchTagValuesWhenCriteriaChanged( this.getPunchTagFilterData(), 'punch_tag_id' ); this.setJobValueWhenCriteriaChanged( 'job_id', { status_id: 10, user_id: this.current_edit_record.user_id, punch_branch_id: this.current_edit_record.branch_id, punch_department_id: this.current_edit_record.department_id } ); } break; case 'job_quick_search': case 'job_item_quick_search': if ( ( Global.getProductEdition() >= 20 ) ) { this.onJobQuickSearch( key, c_value ); TTPromise.wait( 'BaseViewController', 'onJobQuickSearch', function() { $this.setPunchTagValuesWhenCriteriaChanged( $this.getPunchTagFilterData(), 'punch_tag_id' ); } ); //Don't validate immediately as onJobQuickSearch is doing async API calls, and it would cause a guaranteed validation failure. doNotValidate = true; } break; case 'punch_tag_quick_search': if ( ( Global.getProductEdition() >= 20 ) ) { this.onPunchTagQuickSearch( c_value, this.getPunchTagFilterData(), 'punch_tag_id' ); //Don't validate immediately as onJobQuickSearch is doing async API calls, and it would cause a guaranteed validation failure. doNotValidate = true; } break; case 'punch_dates': this.setEditMenu(); break; } if ( this.absence_model ) { if ( key === 'total_time' ) { if ( this.current_edit_record ) { this.current_edit_record[key] = Global.parseTimeUnit( c_value ); // parsed_total_time_obj = this.api_date.parseTimeUnit( c_value, { async: false } ); // if ( parsed_total_time_obj ) { // this.current_edit_record[key] = parsed_total_time_obj.getResult(); // } //When handling absences, always remove the start/end time stamps otherwise they may be incorrect and trigger a validation error, as the user doesn't see them anyways. // The API will automatically calculated these on save anyways. this.current_edit_record['start_time_stamp'] = false; this.current_edit_record['end_time_stamp'] = false; } } if ( key !== 'override' && this.edit_view_ui_dic['override'] ) { this.edit_view_ui_dic['override'].setValue( true ); this.current_edit_record['override'] = true; } } else { this.current_edit_record[key] = c_value; } if ( !doNotValidate ) { if ( this.absence_model ) { if ( key === 'total_time' || key === 'date_stamp' || key === 'punch_dates' || key === 'src_object_id' ) { this.onAvailableBalanceChange(); } } this.validate(); } } /* jshint ignore:end */ buildSearchAndLayoutUI() { var layout_div = this.search_panel.find( 'div #saved_layout_content_div' ); var form_item = $( $.fn.SearchPanel.html.form_item ); var form_item_label = form_item.find( '.form-item-label' ); var form_item_input_div = form_item.find( '.form-item-input-div' ); form_item_label.text( $.i18n._( 'Save Search As' ) ); this.save_search_as_input = Global.loadWidgetByName( FormItemType.TEXT_INPUT ); this.save_search_as_input.TTextInput(); var save_btn = $( '' ); form_item_input_div.append( this.save_search_as_input ); form_item_input_div.append( save_btn ); var $this = this; save_btn.click( function() { $this.onSaveNewLayout(); } ); //Previous Saved Layout this.previous_saved_layout_div = $( '
' ); form_item_input_div.append( this.previous_saved_layout_div ); form_item_label = $( '' + $.i18n._( 'Previous Saved Searches' ) + ':' ); this.previous_saved_layout_div.append( form_item_label ); this.previous_saved_layout_selector = $( '