ObjectiveEditor = function( data, options ) { let instance = this; this.data = $.extend( true, { objType : "PRD" }, data ); instance.validationGroup = `ObjectiveEditorValidationGroup_${data.objectiveId ? data.objectiveId : 0 }`; instance._dataFieldTabIndex = {}; // instance._fieldCombinations = { // "PRD" : { objType : "PRD", // "APL" : { quotaType : "APL", description : "Acct Placements", defaults : { excludeFollowUpStatus : true }, validValues : { excludeFollowUpStatus : true } }, // "APR" : { quotaType : "APR", description : "Acct Presentations", defaults : {} }, // "CAS" : { quotaType : "CAS", description : "Total Cases", defaults : { excludeFollowUpStatus : true }, validValues : { excludeFollowUpStatus : true } }, // "DLR" : { quotaType : "DLR", description : "Total Dollars", defaults : { excludeFollowUpStatus : true }, validValues : { excludeFollowUpStatus : true } }, // "LBS" : { quotaType : "LBS", description : "Total Pounds", defaults : { excludeFollowUpStatus : true }, validValues : { excludeFollowUpStatus : true } }, // "PRS" : { quotaType : "PRS", description : "Item Presentations", defaults : {} }, // "SAL" : { quotaType : "SAL", description : "Item Placements", defaults : { excludeFollowUpStatus : true }, validValues : { excludeFollowUpStatus : true } } // }, // "TSK" : { objType : "TSK", // "OTH" : { quotaType : "OTH", description : "Misc/Other", defaults : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowRepTargeting : true }, validValues : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowAutoTargetLinks : false, fullParticipation : false } }, // "PMV" : { quotaType : "PMV", description : "Product Movement", defaults : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowRepTargeting : true }, validValues : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowAutoTargetLinks : false, fullParticipation : false } }, // "PRS" : { quotaType : "PRS", description : "Presentations", defaults : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowRepTargeting : true }, validValues : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowAutoTargetLinks : false, fullParticipation : false } }, // "RID" : { quotaType : "RID", description : "Ride Withs", defaults : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowRepTargeting : true }, validValues : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowAutoTargetLinks : false, fullParticipation : false } }, // "TRN" : { quotaType : "TRN", description : "Training", defaults : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowRepTargeting : true }, validValues : { excludeFollowUpStatus : true, excludeProtectBaseStatus : true, allowAutoTargetLinks : false, fullParticipation : false } } // } // } instance.dataReady = $.Deferred(); instance.options = $.extend( true, { initialTab : "details", onCancel : function( e ) { let refresh = true; if( e.instance.isDirty() ) { refresh = confirm( "Discard changes?" ); } if( refresh ) e.instance.refresh(); } }, options ? options : {} ); instance.currentTab = instance.options.initialTab; } ObjectiveEditor.prototype.constructor = ObjectiveEditor; ObjectiveEditor.prototype.element = function() { let instance = this; if( instance.rootElement ) return instance.rootElement; instance.rootElement = $("
").addClass( "ObjectiveEditor" ).css( { "height" : "100%" } ); instance.refresh(); return instance.rootElement; } ObjectiveEditor.prototype.load = function( objectiveId ) { let instance = this; let products = null; let staff = null; let objective = null; let territory = null; let dataReady = $.Deferred(); dataReady.progress( function( notify ) { // console.log( "progress", notify ); if( objective && products && staff && territory) { objective.products = products; objective.staff = staff; if( territory.length ) { objective.territory = territory[0]; } dataReady.resolve( objective ); } }) if( objectiveId ) { let objectiveDataStore = Fse.Data.newDataSource( { object : "BOM.objectives", key : "objectiveId" }).store(); objectiveDataStore.byKey( objectiveId ).done( function( data ) { objective = data; if( data.territoryId ) { dataReady.notify( { what : "objective", with : data } ); let objectiveTerritoryDataSource = Fse.Data.newDataSource( { object : "TER.salesTerritories", key : "TerritoryID", objectParams : { "includeTeamMembers" : true }, filter : [ "TerritoryID", "=", data.territoryId ] }); objectiveTerritoryDataSource.load().done( function( t ) { territory = t; dataReady.notify( { what : "territory", with : t } ) }) } else { territory = []; dataReady.notify( { what : "objective", with : data } ); } }) let objectiveProductsDataSource = Fse.Data.newDataSource( { object : "BOM.objectiveProducts", key : [ "linkType", "linkId" ], objectParams : { objectiveId : objectiveId }, paginate : false } ); objectiveProductsDataSource.load().done( function( objectiveProducts ) { if( objectiveProducts ) { products = objectiveProducts; } else { products = []; } dataReady.notify( { what : "products", with : products }); }) let objectiveStaffDataSource = Fse.Data.newDataSource( { object : "BOM.objectiveStaff", key : "linkId", objectParams : { objectiveId : objectiveId }, paginate : false } ); objectiveStaffDataSource.load().done( function( objectiveStaff ) { if( objectiveStaff ) { staff = objectiveStaff; } else { staff = []; } dataReady.notify( { what : "staff", with : staff }); }) } else { objective = { objType : "PRD" }; dataReady.notify( { what : "objective", with : objective }); products = [] dataReady.notify( { what : "products", with : products }); staff = []; dataReady.notify( { what : "staff", with : staff }); territory = []; dataReady.notify( { what : "territory", with : territory }) } return dataReady; } ObjectiveEditor.prototype.refresh = function( data ) { let instance = this; let objectiveId = instance.data.objectiveId; if( data && data.objectiveId ) { objectiveId = data.objectiveId; } instance.load( objectiveId ).done( function( objective ) { instance.data = objective; instance._createUI(); }); } ObjectiveEditor.prototype._getDataFieldTabIndex = function( dataField ) { let instance = this; let tabIndex = -1; if( instance._dataFieldTabIndex[dataField] != undefined ) { tabIndex = instance._dataFieldTabIndex[dataField] } return tabIndex; } ObjectiveEditor.prototype.validate = function( changeTab ) { let instance = this; let vr = DevExpress.validationEngine.validateGroup( instance.validationGroup ); console.log( "Validation Result", vr ); if( changeTab && ! vr.isValid ) { let dataField = vr.brokenRules[0].validator.option( "adapter.editor" ).option( "name" ); console.log( "Broken Rule Editor Options", dataField ); let tabIndex = instance._getDataFieldTabIndex( dataField ); if( tabIndex != -1 ) { instance.tabPanel.option( "selectedIndex", tabIndex ); } } return vr.isValid; } ObjectiveEditor.prototype.next = function() { let instance = this; let selectedIndex = instance.tabPanel.option( "selectedIndex" ); let vr = DevExpress.validationEngine.validateGroup( instance.validationGroup ); if( ! vr.isValid ) { // if the error is on the current tab we don't want to move forward let dataField = vr.brokenRules[0].validator.option( "adapter.editor" ).option( "name" ); let errorTabIndex = instance._getDataFieldTabIndex( dataField ); if( errorTabIndex == selectedIndex ) return; } let tabItems = instance.tabPanel.option( "items" ); for( let nextIndex = selectedIndex + 1; nextIndex < tabItems.length; nextIndex++ ) { if( ! tabItems[nextIndex].disabled ) { selectedIndex = nextIndex; break; } } instance.tabPanel.option( "selectedIndex", selectedIndex ) if( vr.isValid ) { instance.saveButton.option( "disabled", false ); } } ObjectiveEditor.prototype.save = function() { let instance = this; let savePromise = $.Deferred(); let vr = DevExpress.validationEngine.validateGroup( instance.validationGroup ); console.log( "Validation Result", vr ); if( ! vr.isValid ) { let dataField = vr.brokenRules[0].validator.option( "adapter.editor" ).option( "name" ); console.log( "Broken Rule Editor Options", dataField ); let tabIndex = instance._getDataFieldTabIndex( dataField ); if( tabIndex != -1 ) { instance.tabPanel.option( "selectedIndex", tabIndex ); } savePromise.reject(); return savePromise; } // all data from other forms are consilidated into the detailsForm when changes are made so we only have to get // data from this form to save the objective let dataToSave = instance.detailsForm.option( "formData" ); if( dataToSave.targetType != "OPR" ) { // no restrictions unless it targets operators dataToSave.restrictions = {}; } let savingMessage = "Saving Objective..."; let completeMessage = "Objective Saved"; if( dataToSave.updateObjectiveInteractionLinks ) { savingMessage = "Saving & Recalculating Objective..."; } if( ! dataToSave.objectiveId ) { savingMessage = "Creating Objective..."; completeMessage = "Objective Created"; } if( dataToSave.staff.length ) { dataToSave.fullParticipation = false; } let loadPanel = $("
").dxLoadPanel( { messsage : savingMessage, shading : true, hideOnOutsideClick : false, hideOnParentScroll : false, onHidden : function( e ) { e.component.element().remove(); } }).appendTo( $("body") ).dxLoadPanel( "instance" ); loadPanel.show(); Fse.Ajax.performAction( { object : "BOM.saveObjective", data : dataToSave }).done( function( result ) { $("
").dxToast( { onHidden : function( e ) { e.component.element().remove(); }, message : completeMessage, displayTime : 2000, type : "success" }).appendTo( $("body") ).dxToast( "show" ); savePromise.resolve( result ) }).then( function() { loadPanel.hide(); }) return savePromise; } ObjectiveEditor.prototype._registerFields = function( items, tabIndex ) { // we are "registering" these fields so that we can lookup to see what tab they are on let instance = this; items.forEach( function( i ) { if( i.items ) { instance._registerFields( i.items, tabIndex ); } else if( i.dataField ) { instance._dataFieldTabIndex[i.dataField] = tabIndex; } }) } ObjectiveEditor.prototype.createDefinitionForm = function() { let instance = this; let isSubObjective = instance._isSubObjective(); let formData = { targetType : instance.data.targetType, restrictions : { oprSegmentRestrict : instance.data.oprSegmentRestrict, oprParentDistributorRestrict : instance.data.oprParentDistributorRestrict, oprDistributorRestrict : instance.data.oprDistributorRestrict, oprTypeRestrict : instance.data.oprTypeRestrict, mfrOprTypeRestrict : instance.data.mfrOprTypeRestrict, oprPriorityRestrict : instance.data.oprPriorityRestrict, oprAffiliationRestrict : instance.data.oprAffiliationRestrict, oprAssignedOnlyRestrict : instance.data.oprAssignedOnlyRestrict ? true : false }, objType : instance.data.objType, quotaType : instance.data.quotaType, quotaDurationUnit : instance.data.quotaDurationUnit, excludeProtectBaseStatus : instance.data.allowProtectBaseStatus ? false : true, excludeFollowUpStatus : instance.data.allowFollowUpStatus ? false : true } instance.definitionForm = $("
").css( { "padding" : "5px" }).dxForm( { formData : formData, validationGroup : instance.validationGroup, items : [ { dataField : "targetType", label : { text : "Target Type" }, editorType : "dxSelectBox", isRequired : true, editorOptions : { readOnly : isSubObjective, dataSource : { store : { type : "array", key : "value", data : [ { text : "Operator", value : "OPR" }, { text : "Distributor", value : "DST"} ]}}, displayExpr : "text", valueExpr : "value" } }, { dataField : "restrictions", label : { text : "Required Target Criteria" }, editorType : "dxDropDownBox", editorOptions : { openOnFieldClick : false, placeholder : "Target restrictions...", disabled : instance.data.targetType == 'OPR' ? false : true, fieldTemplate : function( data, container ) { let placeholder = "None"; let restrictionText = []; let restrictionFields = [ { dataField : "oprSegmentRestrict", text : "Segment" }, { dataField : "oprParentDistributorRestrict", text : "Parent Distributor" }, { dataField : "oprDistributorRestrict", text : "Distributor"}, { dataField : "oprTypeRestrict", text : "Priority" }, { dataField : "mfrOprTypeRestrict", text : "Mfr Priority" }, { dataField : "oprPriorityRestrict", text : "Classification" }, { dataField : "oprAffiliationRestrict", text : "CMC/GPO" }, { dataField : "oprAssignedOnlyRestrict", text : "Assigned Accounts Only" } ]; restrictionFields.forEach( function( rf ) { if( data && data[rf.dataField] ) restrictionText.push( rf.text ); }) if( restrictionText.length ) placeholder = 'Restricted by: ' + restrictionText.join( ", " ); $('
').dxTextBox({ value : null, placeholder : placeholder, readOnly: true }).appendTo( container ); }, buttons : [ { name : "more", location : "after", stylingMode : "text", options : { icon : "more", onClick : function( e ) { let or = new ObjectiveRestrictions( instance.definitionForm.option( "formData" ), { readOnly : isSubObjective } ); or.updated().done( function( objectiveRestrictions ) { instance.definitionForm.updateData( "restrictions", objectiveRestrictions ); }); let toolbarItems = []; if( ! isSubObjective ) { toolbarItems.push( { toolbar : "bottom", location : "after", widget : "dxButton", options : { text :"Cancel", onClick : function( e ) { popup.hide(); } }}, { toolbar : "bottom", location : "after", widget : "dxButton", options : { text :"Apply", type : "default", disabled : isSubObjective, onClick : function( e ) { or.update(); popup.hide(); } }} ) } else { toolbarItems.push( { toolbar : "bottom", location : "after", widget : "dxButton", options : { text :"Close", onClick : function( e ) { popup.hide(); } }} ) } let popup = $("
").dxPopup( { title : "Target Restrictions", height : "auto", width : "50vw", contentTemplate : function( ) { return or.element(); }, hideOnOutsideClick : true, onHidden : function( e ) { e.component.element().remove(); e.component.dispose(); }, toolbarItems : toolbarItems }).appendTo( $("body") ).dxPopup( "instance" ); popup.show(); } } } ] } }, { dataField : "objType", label : { text : "Quota Type" }, editorType : "dxSelectBox", isRequired : true, editorOptions : { readOnly : isSubObjective, dataSource : { store : { type : "array", key : "value", data : [ { text : "Product Related", value : "PRD"}, { text : "Task Related", value : "TSK" } ]}}, displayExpr : "text", valueExpr : "value" } }, { dataField : "quotaType", label : { text : "Measurement" }, isRequired : true, editorType : "dxSelectBox", editorOptions : { readOnly : isSubObjective, placeholder : "Select Measurement...", dataSource : Fse.Data.newDataSource( { object : 'BOM.quotaTypes', key : "quotaType", filter : [ "objTypes", "contains", formData.objType ? formData.objType : "XXX" ], paginate : false } ), displayExpr : "description", valueExpr : "quotaType" } }, { dataField : "quotaDurationUnit", label : { text : "Volume Timeframe" }, editorType : "dxSelectBox", isRequired : true, editorOptions : { readOnly : isSubObjective, placeholder : "Select timeframe...", disabled : instance.data.isVolumeRelated ? false : true, dataSource : { store : { type : "array", key : "value", data : [ { text : "Weekly Ongoing Volume", value : "WK" }, { text : "Monthly Ongoing volume", value : "MO"}, { text : "Yearly Ongoing volume", value : "YR"}, { text : "Goal for Objective Period", value : "OP"} ]}}, displayExpr : "text", valueExpr : "value" } }, { dataField : "excludeProtectBaseStatus", label : { text : "Exclude \"Existing Business\" from counting towards achievement?", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective}, // validationRules : [ // { type : "custom", message : "invalid field combination", reevaluate : true, validationCallback : function( options ) { return instance._fieldCombinationsRuleValidationCallback( options ) }} // ], colSpan : 3 }, // { itemType : "empty", colSpan : 2 }, { dataField : "excludeFollowUpStatus", label : { text : "Exclude \"Follow Up\" from counting towards achievement?", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective}, // validationRules : [ // { type : "custom", message : "invalid field combination", reevaluate : true, validationCallback : function( options ) { return instance._fieldCombinationsRuleValidationCallback( options ) }} // ], colSpan : 3 }, // { itemType : "empty", colSpan : 2 }, ], onContentReady : function( e ) { let editor; editor = e.component.getEditor( "restrictions" ); if( editor ) { editor.element().attr( "title", "This criteria defines the mandatory attributes for target selection. Salespeople are required to choose targets that meet these rules. This is primarily used when enabling salespeople to define their own targets." ); } editor = e.component.getEditor( "excludeProtectBaseStatus" ); if( editor ) { editor.element().parent().attr( "title", "If this setting is enabled, salespeople will only get credit for opportunities related to new or incremental business. This setting will be forced to ON for task related objectives." ); } editor = e.component.getEditor( "excludeFollowUpStatus" ); if( editor ) { editor.element().parent().attr( "title", "If this setting is enabled, salespeople will only get credit for opportunities that close as either a sale or no sale. This setting will be forced to ON for objectives where measurement is ‘placement’, volume totals, or task related." ); } }, onFieldDataChanged : function( e ) { if( e.dataField == "objType" ) { let quotaTypeField = e.component.getEditor( "quotaType" ); if( quotaTypeField ) { let filter = [ "objTypes", "contains", e.value ? e.value : "XXX" ]; quotaTypeField.getDataSource().filter( filter ); quotaTypeField.getDataSource().load(); e.component.updateData( "quotaType", null ); } } if( e.dataField == "quotaType" ) { let quotaDurationUnitField = e.component.getEditor( "quotaDurationUnit" ); if( ! quotaDurationUnitField ) return; let disabled = true; if( e.value ) { let quotaTypeField = e.component.getEditor( "quotaType" ); let quotaTypeData = quotaTypeField.option( "selectedItem" ); if( quotaTypeData.volumeRelated ) { disabled = false; } } quotaDurationUnitField.option( "disabled", disabled ); if( disabled ) { e.component.updateData( { "quotaDurationUnit" : null } ); } // instance._applyFieldCombinationDefaults( e.value ); } if( e.dataField == "targetType" ) { let restrictionsField = e.component.getEditor( "restrictions" ); if( ! restrictionsField ) return; if( e.value == "OPR" ) { restrictionsField.option( "disabled", false ); } else { restrictionsField.option( "disabled", true ); } } instance.detailsForm.updateData( e.dataField, e.value ); } }).dxForm( "instance" ); instance._registerFields( instance.definitionForm.option( "items"), instance.DEFINITION_TAB_INDEX ); instance.detailsForm.on( "fieldDataChanged", function( e ) { switch( e.dataField ) { case "excludeProtectBaseStatus" : case "excludeFollowUpStatus" : instance.definitionForm.updateData( e.dataField, e.value ); break; } }) return instance.definitionForm; } ObjectiveEditor.prototype.definitionTabTemplate = function( tabPanelItem ) { let instance = this; return instance.createSectionLayout( [ { title : "Achievement Definition", template : function() { return instance.definitionForm.element(); } } ]) } ObjectiveEditor.prototype.createStaffManagementForm = function() { let instance = this; instance.staffManagementForm = $("
").css( { "padding" : "5px" } ).dxForm( { colCount : 2, validationGroup : instance.validationGroup, formData : { objManagerId : instance.data.objManagerId, objManager2Id : instance.data.objManager2Id, objManager3Id : instance.data.objManager3Id }, items : [ { dataField : "objManagerId", label : { text : "Manager" }, editorType : "dxSelectBox", isRequired : true, editorOptions : { placeholder : "Select Manager...", searchEnabled : true, searchMode : "contains", searchExpr : "fullName", dataSource : Fse.Data.newDataSource( { object : "FSPRO.members", key : "fspro_userId" } ), displayExpr : "fullName", valueExpr : "fspro_userId" }, colSpan : 2 }, { dataField : "objManager2Id", label : { text : "Manager #2" }, editorType : "dxSelectBox", isRequired : false, editorOptions : { showClearButton : true, placeholder : "Select Manager #2...", searchEnabled : true, searchMode : "contains", searchExpr : "fullName", dataSource : Fse.Data.newDataSource( { object : "FSPRO.members", key : "fspro_userId" } ), displayExpr : "fullName", valueExpr : "fspro_userId" }}, { dataField : "objManager3Id", label : { text : "Manager #3" }, editorType : "dxSelectBox", isRequired : false, editorOptions : { showClearButton : true, placeholder : "Select Manager #3...", searchEnabled : true, searchMode : "contains", searchExpr : "fullName", dataSource : Fse.Data.newDataSource( { object : "FSPRO.members", key : "fspro_userId" } ), displayExpr : "fullName", valueExpr : "fspro_userId" }}, { itemType : "empty" } ], onFieldDataChanged : function( e ) { instance.detailsForm.updateData( e.dataField, e.value ); } }).dxForm( "instance" ); instance._registerFields( instance.staffManagementForm.option( "items"), instance.STAFF_TAB_INDEX ); return instance.staffManagementForm; } ObjectiveEditor.prototype.createStaffSettingsForm = function() { let instance = this; instance.staffDisclaimerElement = $("
"); instance.staffDisclaimerTooltip = null; let updateStaffDisclaimer = function() { if( instance.staffDisclaimerTooltip ) { instance.staffDisclaimerTooltip.element().remove(); instance.staffDisclaimerTooltip.dispose(); instance.staffDisclaimerTooltip = null; } let formData = instance.staffSettingsForm.option( "formData" ); let disclaimers = []; if( formData.allowRepTargeting || formData.allowAutoTargetLinks ) { disclaimers.push( $("
").text( "You can either add staff now or this can be done later by the managers of each sub-objective." )); } if( formData.allowAutoTargetLinks ) { disclaimers.push( $("
") .append( $("").text( "Auto-Link Eligibility:").css( { "padding-right" : "8px" } ) ) .append( $("" ).text( "All staff are eligible to contribute by default." ) ) .append( $("
") ) .append( $("").text( "Note: Once you manually add staff members, the objective will be limited only to those specific enrolled individuals." )) ) } if( formData.salesOpsTargeting ) { disclaimers.push( $( "
").text( "Staff will be automatically added as targets are imported.") ); } if( disclaimers.length ) { instance.staffDisclaimerElement.text( "*staff disclaimers (mouse over to see)" ).css( { "text-decoration" : "underline" } ); instance.staffDisclaimerTooltip = $("
").dxTooltip( { hideEvent : { name : "mouseout", delay : 70 }, showEvent : { name : "mouseenter", delay : 70 }, contentTemplate : function() { let content = $("
").css( { "text-align" : "left" }); disclaimers.forEach( function( dce ) { content.append( dce.css( { "margin-bottom" : "5px" } ) ); }) return content; }, target : instance.staffDisclaimerElement }).appendTo( "body" ).dxTooltip( "instance" ); } else { instance.staffDisclaimerElement.empty(); } } let isSubObjective = instance._isSubObjective(); instance.staffSettingsForm = $("
").css( { "padding" : "5px" } ).dxForm( { colCount : 3, validationGroup : instance.validationGroup, formData : { allowRepTargeting : instance.data.allowRepTargeting ? true : false, allowAutoTargetLinks : instance.data.allowAutoTargetLinks ? true : false, fullParticipation : instance.data.fullParticipation ? true : false, salesOpsTargeting : instance.data.salesOpsTargeting ? true : false }, items : [ // { // dataField : "settings", isRequired : true, // label : { text : "Select which applies to how targets will be identified for this objective" }, // colSpan : 2, // editorType : "dxSelectBox", // editorOptions : { // valueExpr : "value", // displayExpr : "text", // dataSource : { store : { type : "array", data : [ // { // value : 1, // text : "They will be pre-loaded by sales operations", // disabled : true, // settings : { // allowRepTargeting : false, // allowAutoTargetLinks : false, // fullParticipation : false // } // }, // { // value : 2, // text : "Each staff member will be required to identify targets", // settings : { // allowRepTargeting : true, // allowAutoTargetLinks : true, // fullParticipation : true // } // }, // { // value : 3, // text : "We would like them to automatically link to the objective", // settings : { // allowRepTargeting : true, // allowAutoTargetLinks : true, // fullParticipation : true // } // } // ], key : "option" }} // } // }, { itemType : "empty", colSpan : 1 }, { itemType : "group", colSpan : 3, template : function() { return $("
").css( { "font-size" : "14px" } ).text( "Select which applies to how staff & targets will be identified for this objective:" ) } }, { dataField : "allowAutoTargetLinks", // label : { text : "Should sales calls auto-link?", showColon : false }, label : { text : "We would like them to automatically link to the objective", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective} // , // validationRules : [ // { type : "custom", message : "invalid field combination", reevaluate : true, validationCallback : function( options ) { return instance._fieldCombinationsRuleValidationCallback( options ) }} // ] }, { itemType : "empty", colSpan : 2 }, { dataField : "fullParticipation", disabled : true, label : { text : "Can staff not assigned to the objective contribute?", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective} // , // validationRules : [ // { type : "custom", message : "invalid field combination", reevaluate : true, validationCallback : function( options ) { return instance._fieldCombinationsRuleValidationCallback( options ) }} // ] }, { itemType : "empty", colSpan : 2 }, // { dataField : "limitAutoLinkingToTerritory", label :{ text : "Limit to accounts in objective territory assignment" }, editorType : "dxSwitch", editorOptions : { disabled : instance.data.allowAutoTargetLinks ? false : true } }, // { itemType : "empty", colSpan : 2 }, { dataField : "allowRepTargeting", //label : { text : "Can reps manually assign targets?", showColon : false }, label : { text : "Each staff member will be required to identify targets", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective} // , // validationRules : [ // { type : "custom", message : "invalid field combination", reevaluate : true, validationCallback : function( options ) { return instance._fieldCombinationsRuleValidationCallback( options ) }} // ] }, { itemType : "empty", colSpan : 2 }, { dataField : "salesOpsTargeting", label : { text : "Targets will be pre-loaded by sales operations", showColon : false }, editorType : "dxSwitch", }, { itemType : "empty", colSpan : 2 }, { itemType : "group", colSpan : 3, template : function() { return instance.staffDisclaimerElement; } } ], onFieldDataChanged : function( e ) { // if( e.dataField == "settings" ) { // let editor = e.component.getEditor( "settings" ); // let selectedItem = editor.option( "selectedItem" ); // let settings = { // allowRepTargeting : true, // allowAutoTargetLinks : true, // fullParticipation : true // } // if( selectedItem && selectedItem.settings ) { // for( x in selectedItem.settings ) { // if( selectedItem.settings[x] ) settings[x] = selectedItem.settings[x]; // } // } // e.component.updateData( settings ); // } if( e.dataField == "allowAutoTargetLinks" ) { console.log( "staff.length", instance.data.staff ) if( instance.data.staff.length == 0 ) { e.component.updateData( "fullParticipation", e.value ) } } console.log( `${e.dataField} = ${e.value }` ); instance.detailsForm.updateData( e.dataField, e.value ); updateStaffDisclaimer(); } }).dxForm( "instance" ) instance.detailsForm.on( "fieldDataChanged", function( e ) { switch( e.dataField ) { case "fullParticipation" : case "allowAutoTargetLinks" : case "allowRepTargeting" : instance.staffSettingsForm.updateData( e.dataField, e.value ); break; } }) updateStaffDisclaimer(); instance._registerFields( instance.staffSettingsForm.option( "items"), instance.STAFF_TAB_INDEX ); return instance.staffSettingsForm; } ObjectiveEditor.prototype.staffTabTemplate = function( tabPanelItem ) { let instance = this; let topLeftSection = [ { title : "Management", template : function() { return instance.staffManagementForm.element(); } } ]; let topRightSection = [ { title : "Staff Settings", template : function() { return instance.staffSettingsForm.element(); } } ]; let bottomSection = []; if( ! instance._isNewObjective() && instance.data.objLevel != "P" ) { bottomSection.push( { title : "Staff Definition", template : function() { let os = new ObjectiveStaff( instance.detailsForm.option( "formData" ) ); os.updated().progress( function( objectiveStaff ) { instance.detailsForm.updateData( "staff", objectiveStaff ); }); return $("
").css( { "height" : "100%", "padding" : "5px" } ).append( os.element() ); } } ) } let layoutConfig = { direction : "row", items : [ { ratio : 1, template : function() { return instance.createSectionLayout( topLeftSection ); } }, { ratio : 1, template : function() { return instance.createSectionLayout( topRightSection ); } } ] }; if( bottomSection.length ) { let topConfig = layoutConfig; layoutConfig = { direction : "col", height : "100%", items : [ { baseSize : 235, template : function() { return $("
").dxBox( topConfig ); } }, { ratio : 1, template : function() { return instance.createSectionLayout( bottomSection ); } } ] } } let layout = $("
").dxBox( layoutConfig ); return layout; // return instance.createSectionLayout( sections ); } // ObjectiveEditor.prototype.staffTabTemplate = function( tabPanelItem ) { // let instance = this; // let sections = [ // { // title : "Management", height : 80, // template : function() { // return instance.staffManagementForm.element(); // } // } // ]; // if( ! instance._isNewObjective() && instance.data.objLevel != "P" ) { // sections.push( // { // title : "Staff Settings", height : 180, // template : function() { // return instance.staffSettingsForm.element(); // } // }, // { // title : "Staff Definition", // template : function() { // let os = new ObjectiveStaff( instance.detailsForm.option( "formData" ) ); // os.updated().progress( function( objectiveStaff ) { // instance.detailsForm.updateData( "staff", objectiveStaff ); // }); // return os.element().css( {"padding" : "5px" }); // } // } // ) // } else { // sections.push( // { // title : "Staff Settings", // template : function() { // return instance.staffSettingsForm.element(); // } // } // ) // } // return instance.createSectionLayout( sections ); // } ObjectiveEditor.prototype.createTimelineForm = function() { let instance = this; let dateFieldGroup = { itemType : "group", name : "dateFields", colSpan : 2, colCount : 2, items : [] }; let dateFieldGroupItems = dateFieldGroup.items; let isNewObjective = instance._isNewObjective(); let isSubObjective = instance._isSubObjective(); let isMFR = Fse.Portal.appConfiguration.STP.ownerType === "MFR"; if( isNewObjective ) { dateFieldGroupItems.push( { dataField : "dateRangePicker", isRequired : true, label : { text : "Date Range" }, editorType : "dxSelectBox", editorOptions : { showClearButton : false, placeholder : "Pick A Range", disabled : true, displayExpr : "rangeDisplay", valueExpr : "rangeKey" }, } ) if( isMFR ) { dateFieldGroupItems.push( { dataField : "useFiscalCalendar", editorType : "dxSwitch", label : { text : "Use Fiscal Calendar" } } ) } else { dateFieldGroupItems.push( { itemType : "empty" } ) } } dateFieldGroupItems.push( { dataField: "publishDate", label : { text : "Start Date" }, editorType : "dxDateBox", isRequired : true, editorOptions : { disabled : isNewObjective, readOnly : isSubObjective }}, { dataField : "unpublishDate", label : { text : "End Date" }, editorType : "dxDateBox", isRequired : true, editorOptions : { disabled : isNewObjective, readOnly : isSubObjective }} ); let setObjectiveDates = function() { let form = instance.timelineForm; let dateRangePicker = form.getEditor( "dateRangePicker" ); let dateRangeOption = dateRangePicker.option( "selectedItem" ); if( ! dateRangeOption ) { dateRangeOption = {} }; console.log( "dateRangePicker.selectedItem", dateRangeOption ); let dateFieldsDisabled = dateRangeOption.rangeKey == "CUSTOM" ? false : true; let publishDate = dateRangeOption.startDate ? new Date( dateRangeOption.startDate ) : null; let unpublishDate = dateRangeOption.endDate ? new Date( dateRangeOption.endDate ) : null; form.getEditor( "publishDate" ).option( { "disabled" : dateFieldsDisabled } ); form.getEditor( "unpublishDate" ).option( { "disabled" : dateFieldsDisabled } ); form.updateData( { publishDate : publishDate, unpublishDate : unpublishDate } ); } let setDateRanges = function() { let form = instance.timelineForm; let calendarType = form.option( "formData").useFiscalCalendar ? "F" : "N"; let dateRangePicker = form.getEditor( "dateRangePicker" ); let rangeKey = form.option( "formData" ).dateRangePicker; console.log( `Current Range Key ${rangeKey}`); if( rangeKey ) { if( rangeKey != "CUSTOM" ) { let rangeKeyParts = rangeKey.split( "," ); rangeKeyParts[0] = calendarType; rangeKey = rangeKeyParts.join( "," ); console.log( `New Range Key ${rangeKey}`); } } let dateRangeDataSource = Fse.Data.newDataSource( { object : "CRM.dateRanges", paginate : false, key : "rangeKey", objectParams : { rangeTypes : "M,Y,Q,T", calendarTypes : calendarType, includeThis : true, includeLast : false, includeNext : true }}) dateRangeDataSource.load().done( function( ranges ) { console.log( `RANGES ${calendarType}`, ranges ); ranges.push( { rangeKey : "CUSTOM", rangeDisplay : "Custom Range" }) dateRangePicker.option( { dataSource : { store : { type : "array", data : ranges, key : "rangeKey" } }, disabled : false }) form.updateData( "dateRangePicker", rangeKey ); }) } instance.timelineForm = $("
").css( { "padding" : "5px" } ).dxForm( { colCount : 2, validationGroup : instance.validationGroup, formData : { useFiscalCalendar : false, publishDate : instance.data.publishDate, unpublishDate : instance.data.unpublishDate }, items : dateFieldGroupItems, onFieldDataChanged : function( e ) { if( e.dataField == "useFiscalCalendar" ) { setDateRanges(); } if( e.dataField == "dateRangePicker" ) { console.log( "dateRangePicker", e.value ); setObjectiveDates(); } else { instance.detailsForm.updateData( e.dataField, e.value ); } } }).dxForm( "instance"); if( isNewObjective ) { setDateRanges(); } instance._registerFields( instance.timelineForm.option( "items"), instance.TIMELINE_TAB_INDEX ); return instance.timelineForm; } ObjectiveEditor.prototype.timelineTabTemplate = function( tabPanelItem ) { let instance = this; return instance.createSectionLayout( [ { title : "Objective Period", template : function() { return instance.timelineForm.element(); } } ]) } ObjectiveEditor.prototype.productsTabTemplate = function( tabPanelItem ) { let instance = this; return instance.createSectionLayout( [ { title : "Product Qualification", template : function() { let isSubObjective = instance.data.parentObjectiveId ? true : false; let isEnterpriseObjective = instance.data.objLevel == "P" ? true : false; let formData = instance.detailsForm.option( "formData" ); let op = new ObjectiveProducts( formData, { readOnly : isSubObjective } ); if( ! isSubObjective ) { // keep the form data in sync. op.updated().progress( function( objectiveProducts ) { instance.detailsForm.updateData( "products", objectiveProducts ); }); } return op.element(); } } ]) } ObjectiveEditor.prototype.createQuotaForm = function() { let instance = this; let isSubObjective = instance._isSubObjective(); instance.quotaForm = $("
").css( { "padding" : "5px" }).dxForm( { colCount : 3, validationGroup : instance.validationGroup, formData : { totalQuota : instance.data.totalQuota, batchQuotaSetTargetCount : instance.data.batchQuotaSetTargetCount }, items : [ { dataField : "totalQuota", label : { text : "Total Quota" }, editorType : "dxNumberBox", isRequired : true, editorOptions : { minValue : 0, showSpinButtons : false } , colSpan : 2 }, { itemType : "empty" }, { dataField : "batchQuotaSetTargetCount", label : { text : "Nightly reset of rep quota to target count (recommended)?", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective} }, { itemType : "empty", colSpan : 2 } ], onFieldDataChanged : function( e ) { instance.detailsForm.updateData( e.dataField, e.value ); } }).dxForm( "instance" ); instance.detailsForm.on( "fieldDataChanged", function( e ) { switch( e.dataField ) { case "batchQuotaSetTargetCount" : instance.quotaForm.updateData( e.dataField, e.value ); break; } }) instance._registerFields( instance.quotaForm.option( "items"), instance.QUOTA_TAB_INDEX ); return instance.quotaForm; } ObjectiveEditor.prototype.quotaTabTemplate = function( tabPanelItem ) { // placeholder let instance = this; return instance.createSectionLayout( [ { title : "Quota", template : function() { return instance.quotaForm.element(); } } ]) } ObjectiveEditor.prototype.createTargetsForm = function() { let instance = this; let isSubObjective = instance._isSubObjective(); instance.targetsForm = $("
").css( { "padding" : "5px" }).dxForm( { colCount : 3, validationGroup : instance.validationGroup, formData : { allowRepUnenrollment : instance.data.allowRepUnenrollment ? true : false, }, items : [ { dataField : "allowRepUnenrollment", label : { text : "Can reps unenroll targets?", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective} // , // validationRules : [ // { type : "custom", message : "invalid field combination", reevaluate : true, validationCallback : function( options ) { return instance._fieldCombinationsRuleValidationCallback( options ) }} // ] } ], onFieldDataChanged : function( e ) { instance.detailsForm.updateData( e.dataField, e.value ); } }).dxForm( "instance" ); instance.detailsForm.on( "fieldDataChanged", function( e ) { switch( e.dataField ) { case "allowRepUnenrollment" : instance.targetsForm.updateData( e.dataField, e.value ); break; } }) instance._registerFields( instance.targetsForm.option( "items"), instance.TARGETS_TAB_INDEX ); return instance.targetsForm; } ObjectiveEditor.prototype.targetsTabTemplate = function( tabPanelItem ) { let instance = this; return instance.createSectionLayout( [ { title : "Targets", template : function() { return instance.targetsForm.element(); } } ]) } ObjectiveEditor.prototype.createPublishForm = function() { let instance = this; let isSubObjective = instance._isSubObjective(); instance.publishForm = $("
").css( { "padding" : "5px" }).dxForm( { colCount : 3, validationGroup : instance.validationGroup, formData : { ready : instance.data.ready == "Y" ? true : false, }, items : [ { dataField : "ready", label : { text : "Is this objective ready to be published to sales team?", showColon : false }, editorType : "dxSwitch", editorOptions : { readOnly : isSubObjective} }, { itemType : "empty", colSpan : 2 }, ], onFieldDataChanged : function( e ) { instance.detailsForm.updateData( e.dataField, e.value ); } }).dxForm( "instance" ); instance.detailsForm.on( "fieldDataChanged", function( e ) { switch( e.dataField ) { case "ready" : instance.publishForm.updateData( e.dataField, e.value ); break; } }) instance._registerFields( instance.publishForm.option( "items"), instance.PUBLISH_TAB_INDEX ); return instance.publishForm; } ObjectiveEditor.prototype.publishTabTemplate = function( tabPanelItem ) { // placeholder let instance = this; return instance.createSectionLayout( [ { title : "Notify", template : function() { return instance.publishForm.element(); } } ]) } ObjectiveEditor.prototype._createUI = function() { let instance = this; instance.rootElement.empty(); let tabPanelItems = []; let addTabPanelItem = function( item ) { tabPanelItems.push( item ) return tabPanelItems.length - 1; } instance.cancelButton = $("
").dxButton({ text : "Cancel", type : "normal", visible : instance.data.objectiveId ? false : true, onClick : function( e ) { instance.options.onCancel( { instance : instance } ) } }).dxButton( "instance" ); instance.saveRecalcButton = $("
").dxButton({ text : "Save & Recalc", type : "default", disabled : true, onClick : function( e ) { let vr = instance.detailsForm.validate(); if( ! vr.isValid ) return; instance.detailsForm.updateData( "updateObjectiveInteractionLinks", true ); instance.save().done( function( result ) { instance.refresh(); }) } }).dxButton( "instance" ); instance.saveButton = $("
").dxButton({ text : "Save", type : "default", disabled : true, // instance.data.objectiveId ? false : true, onClick : function( e ) { instance.save().done( function( result ) { instance.refresh( { objectiveId : result.objectiveId } ); }) } }).dxButton( "instance" ); instance.nextButton = $("
").dxButton({ text : "Next", type : "default", disabled : false, onClick : function( e ) { instance.next(); } }).dxButton( "instance" ); instance.DETAILS_TAB_INDEX = addTabPanelItem( { name : "details", title : "Details", showButtons : "main", template : function( tabPanelItem ) { return $("
").css( { "height" : "100%" } ).append( instance.detailsTabTemplate( tabPanelItem )); } }); instance.DEFINITION_TAB_INDEX = addTabPanelItem( { name : "definition", title : "Definition", showButtons : "main", template : function( tabPanelItem ) { return $("
").css( {"height" : "100%"} ).append( instance.definitionTabTemplate( tabPanelItem )); } }) instance.STAFF_TAB_INDEX = addTabPanelItem( { name : "staff", title : "Staff", showButtons : "main", template : function( tabPanelItem ) { let content = $("
").css( {"height" : "100%"} ).append( instance.staffTabTemplate( tabPanelItem )); return content; } }) instance.TIMELINE_TAB_INDEX = addTabPanelItem( { name : "timeline", title : "Objective Period", showButtons : "main", template : function( tabPanelItem ) { return $("
").css( {"height" : "100%"} ).append( instance.timelineTabTemplate( tabPanelItem )); } }) instance.PRODUCTS_TAB_INDEX = addTabPanelItem( { name : "products", title : "Products", showButtons : "main", template : function( tabPanelItem ) { // return instance.createSectionLayout( [{ // title : "Testing", // template : function() { // return $("
").css( { "height" : "100%", "border" : "1px solid lime" } ).text( "Hello world" ); // } // }]) return $("
").css( {"height" : "100%"} ).append( instance.productsTabTemplate( tabPanelItem )); } }) instance.ASSETS_TAB_INDEX = addTabPanelItem( { name : "assets", title : "Assets", disabled : instance.data.objectiveId ? false : true, visible : instance.data.objectiveId ? true : false, template : function( tabPanelItem ) { return $("
").css( { "height" : "100%" } ).append( instance.assetsTabTemplate( tabPanelItem )); } }); instance.subObjectivesCancelButton = $("
").dxButton( { text : "Cancel", disabled : true, onClick : function( e ) { instance.subObjectives.reload(); } }).dxButton( "instance" ); instance.subObjectivesSaveButton = $("
").dxButton( { type : "default", text : "Save Sub-Objectives", disabled : true, onClick : function( e ) { instance.subObjectives.save(); } }).dxButton( "instance" ); if( instance.data.objLevel == 'P' ) { instance.SUB_OBJECTIVES_TAB_INDEX = addTabPanelItem( { name : "subobjectives", title : "Sub Objectives", showButtons : "subobjectives", disabled : instance.data.objectiveId ? false : true, visible : instance.data.objectiveId ? true : false, template : function( tabPanelItem ) { return $("
").css( { "height" : "100%" } ).append( instance.subObjectivesTabTemplate( tabPanelItem )); } }); } instance.QUOTA_TAB_INDEX = addTabPanelItem( { name : "quota", title : "Quota", showButtons : "main", template : function( tabPanelItem ) { return $("
").css( {"height" : "100%"} ).append( instance.quotaTabTemplate( tabPanelItem )); } }) instance.TARGETS_TAB_INDEX = addTabPanelItem( { name : "targets", title : "Targets", showButtons : "main", template : function( tabPanelItem ) { return $("
").css( {"height" : "100%"} ).append( instance.targetsTabTemplate( tabPanelItem )); } }) instance.PUBLISH_TAB_INDEX = addTabPanelItem( { name : "publish", title : "Publish", disabled : instance.data.objectiveId ? false : true, visible : instance.data.objectiveId ? true : false, showButtons : "main", template : function( tabPanelItem ) { return $("
").css( { "height" : "100%", "padding" : "5px" }).append( instance.publishTabTemplate( tabPanelItem )); } }) if( instance.data.objLevel == 'P' ) { instance.PERFORMANCE_TAB_INDEX = addTabPanelItem( { // TODO: change this index to PERFORMANCE_TAB_INDEX name : "performance", // TODO: see if "staff" name was used to reference the tab, it is used by the new staff tab title : "Performance", disabled : instance.data.objectiveId ? false : true, visible : instance.data.objectiveId ? true : false, template : function( tabPanelItem ) { return $("
").css( { "height" : "100%" } ).append( instance.enterprisePerformanceTabTemplate( tabPanelItem )); // TODO: this template has to be renamed } }); } else { instance.PERFORMANCE_TAB_INDEX = addTabPanelItem( { // TODO: change this index to PERFORMANCE_TAB_INDEX name : "performance", // TODO see if "targets" name was used to reference the tab title : "Performance", disabled : instance.data.objectiveId ? false : true, visible : instance.data.objectiveId ? true : false, template : function( tabPanelItem ) { return $("
").css( { "height" : "100%", "padding" : "5px" }).append( instance.performanceTabTemplate( tabPanelItem )); // TODO this template has to be renamed } }); } // the forms are created after the tabs have been defined so that the XXXX_TAB_INDEX values are set properly so the fields can be registered when the forms are created // the details form must be first because the others reference it instance.createDetailsForm(); // the supporting forms, that feed the data in details form instance.createDefinitionForm(); instance.createStaffManagementForm(); instance.createStaffSettingsForm(); instance.createPublishForm(); instance.createTargetsForm(); instance.createTimelineForm(); instance.createQuotaForm(); let selectedIndex = instance.DETAILS_TAB_INDEX; tabPanelItems.forEach( function( tpi, idx ) { if( tpi.name && tpi.name == instance.currentTab ) selectedIndex = idx; }) instance.layout = $("
").dxBox( { direction : "col", height : "100%", items : [ { ratio : 1, template : function() { instance.tabPanel = $("
").dxTabPanel( { swipeEnabled : false, height : "100%", selectedIndex : selectedIndex, items : tabPanelItems, deferRendering : true, onSelectionChanged : function( e ) { let selectedTab = e.component.option( "selectedItem" ); instance.currentTab = selectedTab.name; instance.layout.option( "items[1].visible", selectedTab.showButtons == "main" ? true : false ); instance.layout.option( "items[2].visible", selectedTab.showButtons == "subobjectives" ? true : false ); instance.layout.option( "items[3].visible", selectedTab.showButtons ? false : true ); // no buttons if( instance._isNewObjective() ) { let selectedIndex = e.component.option( "selectedIndex" ); let tabItems = e.component.option( "items" ); // last enabled tab let lastEnabledIndex = 0; tabItems.forEach( function( item, idx ) { if( ! item.disabled ) { lastEnabledIndex = idx; } }) instance.nextButton.option( "disabled", selectedIndex == lastEnabledIndex ? true : false ); } } }).dxTabPanel( "instance" ) return instance.tabPanel.element(); } }, { // main buttons baseSize : 30, visible : true, template : function() { return $("
").css( "margin-top", "5px" ).dxToolbar( { items : [ { location : "after", template : function() { return instance.cancelButton.element(); } }, { location : "after", visible : instance.data.objectiveId ? false : true, template : function() { return instance.nextButton.element(); } }, { location : "after", visible : instance.data.objectiveId ? true : false, template : function() { return instance.saveRecalcButton.element(); } }, { location : "after", template : function() { return instance.saveButton.element(); } } ] }) } }, { // sub-objective buttons baseSize : 30, visible : false, template : function() { return $("
").css( "margin-top", "5px" ).dxToolbar( { items : [ { location : "after", template : function() { return instance.subObjectivesCancelButton.element(); } }, { location : "after", template : function() { return instance.subObjectivesSaveButton.element(); } } ] }) } }, { // no buttons baseSize : 30, visible : false, template : function() { return $("
" ) } } ] }).dxBox( "instance" ); instance.rootElement.append( instance.layout.element() ); // instance.tabPanel = $("
").dxTabPanel( { // swipeEnabled : false, // height : "100%", // selectedIndex : selectedIndex, // items : tabPanelItems, // onSelectionChanged : function( e ) { // } // }).dxTabPanel( "instance" ) // instance.rootElement.append( instance.tabPanel.element() ) } ObjectiveEditor.prototype.showSubObjectives = function( refresh ) { let instance = this; if( refresh ) { if( instance.subObjectiveList ) instance.subObjectiveList.refresh(); } instance.tabPanel.option( "selectedIndex", instance.SUB_OBJECTIVES_TAB_INDEX ) } ObjectiveEditor.prototype.isDirty = function() { let instance = this; if( instance.saveButton ) { return ! instance.saveButton.option( "disabled" ); } else { return false; } } ObjectiveEditor.prototype._isNewObjective = function() { let instance = this; let isNewObjective = instance.data.objectiveId ? false : true; return isNewObjective; } ObjectiveEditor.prototype._isSubObjective = function() { let instance = this; let isSubObjective = instance.data.parentObjectiveId ? true : false; return isSubObjective; } ObjectiveEditor.prototype._isEnterpriseObjective = function() { let instance = this; let isEnterpriseObjective = instance.data.objLevel == "P" ? true : false; return isEnterpriseObjective; } // ObjectiveEditor.prototype._fieldCombinationsRuleValidationCallback = function( options ) { // let instance = this; // let formData = instance.detailsForm.option( "formData" ); // let objType = formData.objType; // let quotaType = formData.quotaType; // let valid = true; // let ruleData = null; // if( instance._fieldCombinations[objType] && instance._fieldCombinations[objType][quotaType] ) { // ruleData = instance._fieldCombinations[objType][quotaType]; // if( ruleData.validValues && options.formItem.dataField in ruleData.validValues ) { // console.log( `Checking ${options.formItem.dataField}`, ruleData.validValues ); // if( options.value !== ruleData.validValues[options.formItem.dataField] ) { // valid = false; // options.rule.message = `Invalid selection for ${ruleData.description}`; // } // } // } // return valid; // } // ObjectiveEditor.prototype._applyFieldCombinationDefaults = function( quotaType ) { // let instance = this; // let form = instance.detailsForm; // let defaultsToSet = false; // if( quotaType ) { // let formData = form.option( "formData" ); // let objType = formData.objType; // if( objType && instance._fieldCombinations[objType] && instance._fieldCombinations[objType][quotaType] ) { // ruleData = instance._fieldCombinations[objType][quotaType]; // if( ruleData.defaults ) { // let defaults = {}; // for( p in ruleData.defaults ) { // defaults[p] = ruleData.defaults[p]; // defaultsToSet = true; // } // if( defaultsToSet ) { // form.updateData( defaults ); // } // } // } // } // form.validate(); // } ObjectiveEditor.prototype.createDetailsForm = function() { let instance = this; // console.log( "data", instance.data ); let isMFR = Fse.Portal.appConfiguration.STP.ownerType === "MFR"; let formData = { objType : "PRD" }; if( isMFR ) formData.objOwnerType = 'MFR'; let isSubObjective = instance.data.parentObjectiveId ? true : false; let isEnterpriseObjective = instance.data.objLevel == "P" ? true : false; let isNewObjective = instance.data.objectiveId ? false : true; if( instance.data.objectiveId ) { formData = { objectiveId : instance.data.objectiveId, parentObjectiveId : instance.data.parentObjectiveId, objName : instance.data.objName, products : instance.data.products, staff : instance.data.staff, territoryId : instance.data.territoryId, targetType : instance.data.targetType, publishDate : instance.data.publishDate, unpublishDate : instance.data.unpublishDate, bundleId : instance.data.bundleId, objDescription : instance.data.objDescription, quotaType : instance.data.quotaType, objType : instance.data.objType, quotaDurationUnit : instance.data.quotaDurationUnit, totalQuota : instance.data.totalQuota, objLevel : instance.data.objLevel, objManagerId : instance.data.objManagerId, objManager2Id : instance.data.objManager2Id, objManager3Id : instance.data.objManager3Id, ownerRefNum : instance.data.ownerRefNum, objOwnerType : instance.data.objOwnerType, objOwnerId : instance.data.objOwnerId, allowFollowUpStatus : instance.data.allowFollowUpStatus ? true : false, excludeFollowUpStatus : instance.data.allowFollowUpStatus ? false : true, batchQuotaSetTargetCount : instance.data.batchQuotaSetTargetCount ? true : false, allowProtectBaseStatus : instance.data.allowProtectBaseStatus ? true : false, excludeProtectBaseStatus : instance.data.allowProtectBaseStatus ? false : true, allowRepUnenrollment : instance.data.allowRepUnenrollment ? true : false, allowRepTargeting : instance.data.allowRepTargeting ? true : false, allowAutoTargetLinks : instance.data.allowAutoTargetLinks ? true : false, fullParticipation : instance.data.fullParticipation ? true : false, ready : instance.data.ready == "Y" ? true : false, // unenrollmentNotifyOwner : instance.data.unenrollmentNotifyOwner ? true : false, // limitAutoLinkingToTerritory : instance.data.limitAutoLinkingToTerritory ? true : false, restrictions : { oprSegmentRestrict : instance.data.oprSegmentRestrict, oprParentDistributorRestrict : instance.data.oprParentDistributorRestrict, oprDistributorRestrict : instance.data.oprDistributorRestrict, oprTypeRestrict : instance.data.oprTypeRestrict, mfrOprTypeRestrict : instance.data.mfrOprTypeRestrict, oprPriorityRestrict : instance.data.oprPriorityRestrict, oprAffiliationRestrict : instance.data.oprAffiliationRestrict, oprAssignedOnlyRestrict : instance.data.oprAssignedOnlyRestrict ? true : false } } } // console.log( "formData", formData ); let objectiveOwnerTypeField = { fieldType : "empty" }; let objectiveOwnerField = { fieldType : "empty" }; let territoryField = { dataField : "territoryId", label : { text : isEnterpriseObjective ? "Top Level Territory" : "Territory" }, isRequired : true, editorType : "dxSelectBox", editorOptions : { readOnly : true, // isSubObjective dataSource : Fse.Data.newDataSource( { object : "TER.salesTerritories", keyField : "TerritoryID" }), displayExpr : "territoryName", valueExpr : "TerritoryID", searchEnabled : true, showClearButton : false, placeholder : "Select Territory" } }; let territoryOptionField = { itemType : "empty" }; if( ! instance.data.objectiveId ) { // this is a new objective so we will alow for multiple territories to be selected territoryField = { dataField : "territoryId", label : { text : "Territory" }, isRequired : true, editorType : "dxDropDownBox", editorOptions : Fse.UI.multiSelectDropDownBoxEditorOptions( { dataSource : Fse.Data.newDataSource( { object : "TER.salesTerritories", keyField : "TerritoryID" }), displayExpr : "territoryName", valueExpr : "TerritoryID", searchExpr : "name", searchMode : "contains", multipleSelectedDisplay : "Multiple Territories", keyExpr : "TerritoryID", title : "Select Territory..." }), validationRules :[ { type : "required", message : "Territory is required" }, { type: "custom", message : "Custom Validation Failed", ignoreEmptyValue : true, reevaluate : true, validationCallback : function( validationOptions ) { instance.detailsForm.updateData( { "createObjectiveTerritoryError" : null, "createObjectiveTerritoryPath" : null, "createObjectiveObjLevel" : null, "createObjectiveChildTerritoryPaths" : null } ); let rule = validationOptions.rule; let territories = validationOptions.formItem.editorOptions.dataSource[0].items; // console.log( "territories to validate", territories ); let localMarkets = 0; let nonLocalMarkets = 0; let valid = true; territories.forEach( function( territory ) { if( territory.localMarket ) { localMarkets++; } else { nonLocalMarkets++; } }) if( valid && ( localMarkets && nonLocalMarkets )) { rule.message = "Local Markets and Non-Local Markets cannot be combined."; valid = false; } if( valid && nonLocalMarkets ) { if( valid && ( nonLocalMarkets > 1 )){ rule.message = "Multiple Non-Local Market not allowed." valid = false; } if( valid && ! territories[0].hasLocalMarkets ) { rule.message = "Non-Local Market does not have any subordinate local markets."; valid = false; } if( valid ) { instance.detailsForm.updateData( { "createObjectiveTerritoryPath" : territories[0].territoryPath, "createObjectiveObjLevel" : "P" } ); } } else if ( valid && localMarkets > 1 ) { // make sure all of the local markets have a common parent, if they do valid, if not invalid let baseNodes = territories[0].territoryPath.split( "/" ); let commonIndex = -1; let compareFault = false; let compareIndex = 0; while( !compareFault ) { for( let x = 0; x < territories.length; x++ ) { let baseNode = "no base"; if( baseNodes.length >= compareIndex + 1 ) { baseNode = baseNodes[compareIndex]; } let compareNode = "nothing to compare"; let compareNodes = territories[x].territoryPath.split( "/" ); if( compareNodes.length >= compareIndex + 1 ) { compareNode = compareNodes[compareIndex]; } if( compareNode !== baseNode ) { compareFault = true; break; } } if( ! compareFault ) commonIndex = compareIndex; compareIndex++; } // console.log( "Check complete", compareFault, commonIndex ); if( commonIndex != -1 ) { let pathParts = []; for( let x = 0; x <= commonIndex; x++ ) { pathParts.push( baseNodes[x] ) } // console.log( "Common Path", pathParts.join( "/" ) ); let childTerritoryPaths = []; territories.forEach( function( t ) { childTerritoryPaths.push( t.territoryPath ); }) instance.detailsForm.updateData( { "createObjectiveTerritoryPath" : pathParts.join( "/" ), "createObjectiveChildTerritoryPaths" : childTerritoryPaths, "createObjectiveObjLevel" : "P" }); } else { valid = false; rule.message( "Selected local markets do not have a common oversight territory" ); } } else if( valid ) { instance.detailsForm.updateData( { "createObjectiveTerritoryPath" : territories[0].territoryPath, "createObjectiveObjLevel" : "S" }); } if( ! valid ) { $("
").dxToast( { onHidden : function( e ) { e.component.element().remove(); }, message : rule.message, displayTime : 2000, type : "error" }).appendTo( $("body") ).dxToast( "show" ); instance.detailsForm.updateData( { "createObjectiveTerritoryError" : rule.message, "createObjectiveTerritoryPath" : null, "createObjectiveObjLevel" : null }); } return valid; } } ] } territoryOptionField = { name : "territoryExplanation", label : { visible : false }, editorType : "dxTextBox", editorOptions : { readOnly : true, } } }; if( ! isMFR ) { objectiveOwnerTypeField ={ dataField : "objOwnerType", visible : ! isMFR, label : { text : "Owner Type" }, editorType : "dxSelectBox", isRequired : true, editorOptions : { readOnly : isSubObjective, dataSource : { store : { type : "array", key : "text", data : [ { text : "Company Internal", value : "INT" }, { text : "Manufacturer", value : "MFR" } ]}}, displayExpr : "text", valueExpr : "value", placeholder : "Select Owner Type...", } } objectiveOwnerField = { dataField : "objOwnerId", label : { location : "left", text : "Manufacturer" }, isRequired : true, editorType : "dxSelectBox", editorOptions : { readOnly : isSubObjective, disabled : formData.objOwnerType != "MFR", dataSource : Fse.Data.newDataSource( { object : "PRD.manufacturers", keyField : "mfr_id" } ), searchExpr : "mfr_name", searchMode : "contains", searchEnabled : true, displayExpr : "mfr_name", valueExpr : "mfr_id", placehoder : "Select Manufacturer" } } } let detailItems = [ { dataField : "objName", label : { text : "Name" }, isRequired : true, editorOptions : { maxLength : 50 } }, { dataField : "bundleId", label : { text : "Group" }, editorType : "dxSelectBox", editorOptions : { readOnly : isSubObjective, dataSource : Fse.Data.newDataSource( { object : "BOM.objectiveBundles", key : "bundleId", paginate : false } ), searchExpr : "bundleName", searchEnabled : true, searchMode : "contains", displayExpr : "bundleName", valueExpr : "bundleId", placeholder : "Select Group...", showClearButton : true, buttons : [ "dropDown", { name : "editBundles", options : { icon : "edit", visible : Fse.Portal.checkPermission( "BCRMObjectiveManagementAdmin" ) && ! isSubObjective, onClick : function( e ) { instance.editBundles().done( function( changesMade ) { if( changesMade ) { let editor = instance.detailsForm.getEditor( "bundleId" ); editor.getDataSource().load(); } }); } } } ], } }, territoryField, territoryOptionField, objectiveOwnerTypeField, objectiveOwnerField, { dataField : "objDescription", label : { text : "Directions" }, colSpan : 2, isRequired : true, editorType : "dxTextArea", editorOptions : { maxLength : 500, height : "4.5em" } }, { dataField : "ownerRefNum", label : { text: "Reference Id" }, editorOptions : { maxLength : 50, showClearButton : false, readOnly : isSubObjective } } ]; if( ! instance.data.objectiveId ) { detailItems.push( { dataField : "autoGenerateOwnerRefNum", label : { text : "Auto Generate Reference Id" }, editorType : "dxSwitch" } ); } instance.detailsForm = $("
").dxForm( { validationGroup : instance.validationGroup, formData : formData, // instance.data.objectiveId ? formData : null, items : [ { itemType : "group", caption : "Details", colCount : 2, items : detailItems } // , // { // itemType : "group", // caption : "Definition & Measurement", // colCount : 2, // items : definitionItems // }, // { // itemType : "group", // caption : "Settings", // colCount : 3, // items : settingsItems // } ], onFieldDataChanged : function( e ) { if( ! isNewObjective ) { instance.saveButton.option( "disabled", false ); instance.saveRecalcButton.option( "disabled", false ); instance.cancelButton.option( "visible", true ); } console.log( "onFieldDataChanged", e ); if( e.dataField == "autoGenerateOwnerRefNum" ) { let ownerRefNumField = instance.detailsForm.getEditor( "ownerRefNum" ); if( e.value ) { ownerRefNumField.option( "disabled", true ); e.component.updateData( { "ownerRefNum" : "WILL AUTO GENERATE ON SAVE" } ); } else { ownerRefNumField.option( "disabled", false ); e.component.updateData( { "ownerRefNum" : null } ); } } if( e.dataField == "objOwnerType" ) { let objOwnerTypeEditor = instance.detailsForm.getEditor( "objOwnerId" ); if( e.value == "MFR" ) { objOwnerTypeEditor.option( "disabled", false ); } else { objOwnerTypeEditor.option( "disabled", true ); } } if( e.dataField == "territoryId" ) { let territoryIdField = e.component.getEditor( "territoryId" ); // console.log( "territoryIdField all options", territoryIdField.option( "dataSource" )[0].items ); } if( e.dataField == "createObjectiveTerritoryError" ) { if( e.value ) { let territoryExplanationEditor = instance.detailsForm.getEditor( "territoryExplanation" ); if( territoryExplanationEditor ) { territoryExplanationEditor.option( "value", e.value ); territoryExplanationEditor.element().css( { color : "red" } ); } } } if( e.dataField == "createObjectiveObjLevel" ) { const { createObjectiveTerritoryPath, createObjectiveObjLevel, createObjectiveChildTerritoryPaths, createObjectiveTerritoryError } = e.component.option( "formData" ); let createObjectiveParams = { createObjectiveTerritoryPath, createObjectiveObjLevel, createObjectiveChildTerritoryPaths, createObjectiveTerritoryError }; if( e.value ) { // console.log( "createObjective", createObjectiveParams ); let createMessage = "Stand-Alone Objective"; if( createObjectiveParams.createObjectiveObjLevel == "P" ) { let pathParts = createObjectiveTerritoryPath.split( "/" ); let topLevelTerritory = pathParts[pathParts.length - 1]; if( createObjectiveParams.createObjectiveChildTerritoryPaths ) { createMessage = `Enterprise Objective for ${topLevelTerritory} with ${createObjectiveParams.createObjectiveChildTerritoryPaths.length} Sub-Objectives`; } else { createMessage = `Enterprise Objective for ${topLevelTerritory}`; } } else { createMessage = "Stand-Alone Objective"; } instance.detailsForm.updateData( { "objLevel" : createObjectiveParams.createObjectiveObjLevel }) let territoryExplanationEditor = instance.detailsForm.getEditor( "territoryExplanation" ); if( territoryExplanationEditor ) { territoryExplanationEditor.option( "value", createMessage ); territoryExplanationEditor.element().css( { color : "blue" } ); } // $("
").dxToast( { // onHidden : function( e ) { // e.component.element().remove(); // }, // message : createMessage, // type : "info" // }).appendTo( $("body") ).dxToast( "show" ); } // else { // let territoryExplanationEditor = instance.detailsForm.getEditor( "territoryExplanation" ); // if( territoryExplanationEditor ) { // territoryExplanationEditor.option( "value", createObjectiveParams.createObjectiveTerritoryError ); // territoryExplanationEditor.element().css( { color : "red" } ); // } // } } // if ( e.dataField == "createObjectiveChildTerritoryPaths" ) { // let editor = e.component.getEditor( "subObjectiveNameOptions" ); // if( editor ) { // if( e.value ) { // editor.option( { "visible" : true, "disabled" : false } ) // } else { // editor.option( { "visible" : false, "disabled" : true } ) // } // } // } if( e.dataField == "objLevel" ) { let staffField = e.component.getEditor( "staff" ); if( staffField ) { if( e.value == "C" || e.value == "S" ) { staffField.option( "disabled", false ); } else { staffField.option( "disabled", true ); e.component.updateData( { "staff" : null } ) } } } } }).dxForm( "instance" ); instance._registerFields( instance.detailsForm.option( "items"), instance.DETAILS_TAB_INDEX ); return instance.detailsForm; // let container = $("
").css( "padding", "5px" ).dxBox( { // height : "100%", // direction : "col", // items : [ // { // ratio : 1, // template : function() { // return $("
").append( instance.detailsForm.element().css( { "margin-right" : "15px" }) ).dxScrollView( { height : "100%" } ) // } // } // ] // }) // return container; } ObjectiveEditor.prototype.detailsTabTemplate = function( tabPanelItem ) { let instance = this; let container = $("
").css( "padding", "5px" ).dxBox( { height : "100%", direction : "col", items : [ { ratio : 1, template : function() { return $("
").append( instance.detailsForm.element().css( { "margin-right" : "15px" }) ).dxScrollView( { height : "100%" } ) } } ] }) return container; } ObjectiveEditor.prototype.subObjectivesTabTemplate = function( tabPanelItem ) { let instance = this; // instance.subObjectiveList = new ObjectiveList( { // parentObjectiveId : instance.data.objectiveId, // openObjective : function( objective, options) { // if( instance.options.openSubObjective ) { // instance.options.openSubObjective( objective, options ); // } // // instance.refresh( objective ); // } // }); // return instance.subObjectiveList.element(); instance.subObjectives = new SubObjectives( { parentObjective : instance.data, onModified : function( e ) { let disabled = true; if( e.changes.length ) { disabled = false; } instance.subObjectivesCancelButton.option( "disabled", disabled ); instance.subObjectivesSaveButton.option( "disabled", disabled ); } }); return instance.subObjectives.element(); } ObjectiveEditor.prototype.enterprisePerformanceTabTemplate = function( tabPanelItem ) { let instance = this; let subObjectiveStaffDataGrid; let subObjectivesDataSource = Fse.Data.newDataSource( { object : "BOM.objectives", key : "objectiveId", filter : [ "parentObjectiveId", "=", instance.data.objectiveId ], paginate : false } ) let subObjectives = []; subObjectiveLoadPromise = subObjectivesDataSource.load(); subObjectiveLoadPromise.done( function( result ) { subObjectives = result; }) let enterpriseStaff = []; let staffLoadPromise; let _refreshDataGrid = function() { let enterpriseStaffDataSource = Fse.Data.newDataSource( { object : 'BOM.subObjectiveStaff', key : "linkId", paginate : false, objectParams : { objectiveId : instance.data.objectiveId }}); staffLoadPromise = enterpriseStaffDataSource.load(); staffLoadPromise.done( function( result ) { enterpriseStaff = result; subObjectiveStaffDataGrid.option( "dataSource", { store : { type : "array", data : enterpriseStaff, key : "linkId" } }); }) } let _addStaff = function() { subObjectiveLoadPromise.done( function() { let pickerOptions = { territories : subObjectives } staffLoadPromise.done( function() { pickerOptions.existingStaff = enterpriseStaff; }) let osp = new ObjectiveStaffPicker( pickerOptions ); osp.show().done( function( staff ) { let addEnterpriseStaffData = { objectiveId : instance.data.objectiveId, staff : staff } console.log( "Adding Enterprise Staff", addEnterpriseStaffData); Fse.Ajax.performAction( { object : "BOM.addEnterpriseObjectiveStaff", data : addEnterpriseStaffData } ).done( function( result ) { _refreshDataGrid(); }) }) }) } subObjectiveStaffDataGrid = $("
").dxDataGrid( { scrolling : { mode : "virtual"}, showBorders : true, filterRow : { visible : true }, height : "100%", onToolbarPreparing : function( e ) { let items = e.toolbarOptions.items; if( ! items ) { items = []; e.toolbarOptions.items = items } items.push( { location : "after", widget : "dxButton", options : { hint : "Refresh", icon : "refresh", onClick : function( e ) { _refreshDataGrid(); } } }) items.push( { location : "after", widget : "dxButton", options : { hint : "Add Staff", icon : "plus", onClick : function( e ) { _addStaff(); } } }) }, columns : [ { dataField : "territoryName", groupIndex : 0, groupCellTemplate: function(element, options) { element.text(options.value); } }, { dataField : "fullName", caption : "Sales Rep" }, { dataField : "title", caption : "Title" }, { dataField : "quota", dataType : "number", format : "fixedPoint", width : 100, }, { dataField : "quotaAchievement", caption : "Achievement", dataType : "number", format : "percent" , width : 100, } ], onRowDblClick : function( e ) { console.log( "onRowDblClick", e ); if( e.data.objectiveId ) { instance.options.openSubObjective( { objectiveId : e.data.objectiveId } ); } } }).dxDataGrid( "instance" ); _refreshDataGrid(); return $("
").addClass( "EnterpriseObjectiveStaff" ).css( { "padding" : "5px", "height" : "100%" } ).append( subObjectiveStaffDataGrid.element() ); } // Red Gold BBQ Sauce Targets OPR - ACEIN ObjectiveEditor.prototype.performanceTabTemplate = function( tabPanelItem ) { let instance = this; let objective = $.extend( true, {}, instance.data ); let ot = new ObjectiveTargets( objective ); return $("
").css( { "padding" : "5px", "height" : "100%" } ).append( ot.element() ); // return $("
").dxDataGrid( { // height : "100%", // scrolling : { mode : "virtual" }, // showBorders : true, // columns : [ // // "staffLinkId", // { dataField : "fullName", caption : "Sales Rep" }, // { dataField : "quota", caption : "Quota", dataType : "number" }, // { dataField : "quotaAchieved", caption : "Achieved", dataType : "number" }, // { // name : "achievement", caption :"Achievement %", dataType : "number", format : { type : "percent", precision : 0 }, // calculateCellValue : function( rowData ) { // if( rowData.quota > 0 ) { // let quotaAchieved = rowData.quotaAchieved ? rowData.quotaAchieved : 0; // return ( (quotaAchieved * 1.0) / ( rowData.quota * 1.0 )); // } else { // return null; // } // } // }, // { // name : "quotaRemaining", caption : "Quota Remaining", dataType : "number", // calculateCellValue : function( rowData ) { // return rowData.quota - ( rowData.quotaAchieved ? rowData.quotaAchieved : 0 ); // } // }, // { // name : "targetsRemaining", caption : "Targets Remaining", dataType : "number", // calculateCellValue : function( rowData ) { // let targets = rowData.targets ? rowData.targets : []; // if( targets.length ) { // let targetsRemaining = 0; // targets.forEach( function( t ) { // if( ! t.targetAchievement > 0 ) { // targetsRemaining++; // } // }) // return targetsRemaining; // } else { // return null; // } // } // }, // { // name : "plannedCount", caption : "Planned", dataType : "number", // calculateCellValue : function( rowData ) { // let targets = rowData.targets ? rowData.targets : []; // if( targets.length ) { // let plannedCount = 0; // targets.forEach( function( t ) { // if( t.targetAchievement ) return; // plannedCount += t.completedCalls ? t.completedCalls : 0; // }) // return plannedCount; // } else { // return null; // } // } // }, // { // name : "unplannedCount", caption : "Unplanned", dataType : "number", // calculateCellValue : function( rowData ) { // let targets = rowData.targets ? rowData.targets : []; // if( targets.length ) { // let unplannedCount = 0; // targets.forEach( function( t ) { // if( t.targetAchievement ) return; // unplannedCount += (( t.callCount ? t.callCount : 0 ) - ( t.completedCalls ? t.completedCalls : 0 )); // }) // return unplannedCount; // } else { // return null; // } // } // } // // "achievement", // // "remainingQuota", // // "remainingTargets", // // "targetAchievement", // // "planned", // // "unplanned", // // "callCount", // // "firstDisposition", // // "lastDisposition", // // "totalWarnings" // ], // masterDetail : { // enabled : true, // template : function( container, options ) { // let targets = options.data.targets ? options.data.targets : []; // let detailGrid = $("
").dxDataGrid( { // dataSource : targets, // columns : [ // // "targetLinkId", // { dataField : "partnerName", caption : "Account" }, // { dataField : "targetStatus", caption : "Status" }, // { dataField : "targetAchievement", caption : "Achievement", dataType : "number" }, // { dataField : "completedCalls", caption : "Completed Calls", dataType : "number" }, // { dataField : "nextCall", caption : "Next Call", dataType : "date" }, // "warnings" // ], // onContextMenuPreparing : function( e ) { // if( e.target != "content" ) return; // if( e.row.rowType == "data" ) { // if( ! e.row.data.interactions || e.row.data.interactions.length == 0 ) return; // if (!e.items) e.items = []; // e.row.data.interactions.forEach( function( i ) { // const interactionId = i.interactionId; // let interactionDateText = DevExpress.localization.formatDate( new Date( i.interactionDate ), 'shortDate' ) // let dispositionText = i.disposition == '?' ? 'Planned' : 'Complete' // e.items.push( { // text : `${interactionDateText}: ${dispositionText}`, // onItemClick : function( ee ) { // Fse.CLOS.openInteractionDialog( interactionId,function() { }) // } // }) // }) // } // }, // scrolling : { mode : "virtual" }, // showBorders : true, // rowAlternationEnabled : true, // height : "100%", // width : "100%" // }) // container.append( detailGrid ); // } // }, // dataSource : Fse.Data.newDataSource( { object : "BOM.objectiveTargets", key : "staffLinkId", objectParams : { // objectiveId : instance.data.objectiveId // }}) // }); // return $("
").text( "Targets Tab" ); } ObjectiveEditor.prototype.assetsTabTemplate = function( tabPanelItem ) { let instance = this; return instance.createSectionLayout( [ { title : "Supporting Assets", template : function() { let assetGrid = new AssetGrid( { contentDomain : "BCRM", containerType : "OBJ", containerId : instance.data.objectiveId, allowLinks : true, visibleColumns : [ "fileExt", "docTitle", "docDescription", "updateDate", "buttons" ], categoryEnabled : false }); return assetGrid.element(); } } ]) } ObjectiveEditor.prototype.createSectionLayout = function( sections ) { let boxItems = []; sections.forEach( function( section ) { // the syling of the title is to match how the for section captions are styled boxItems.push( { baseSize : 42, template : function() { return $("
").css( { "margin" : "5px", "height": "32px", "padding" : "5px", "font-size" : "16px", "background-color" : "#f7f7f7" } ).text( section.title ) }}) let contentItem = { template : function(){ return section.template() }, } if( section.height ) { contentItem.baseSize = section.height } else { contentItem.ratio = 1; } boxItems.push( contentItem ); }) let box = $("
").dxBox( { direction : "col", height : "100%", items : boxItems }) return box; } ObjectiveEditor.prototype.editBundles = function() { let instance = this; let currentBundleId = instance.detailsForm.getEditor( "bundleId" ).option( "value" ); let editPromise = $.Deferred(); let changesMade = 0; let popup = $("
").dxPopup( { title : "Manage Objective Groups", width : 600, height : "auto", contentTemplate : function() { let dataGrid = $("
").dxDataGrid( { dataSource : null, disabled : true, keyExpr : "bundleId", editing : { allowAdding : true, allowUpdating : true, allowDeleting: function( options) { if( options.row.data.bundleId == currentBundleId ) return false; return options.row.data.objectiveCount ? false : true; }, mode : "row", startEditAction : "click", useIcons : true, }, selection : { mode : "single", showCheckBoxesMode : "always" }, onInitNewRow : function( e ) { e.data.active = 'Y'; console.log( "onInitNewRow", e ); }, onRowInserted : function( e ) { console.log( "onRowInserted", e ); }, onSaving : function( e ) { console.log( "onSaving", e ); const change = e.changes[0]; if (change) { e.cancel = true; // loadPanel.show(); let dataToSave = null; if( change.type == "update" || change.type == "remove" ) { e.component.byKey( change.key ).done( function( rowData ) { dataToSave = $.extend( true, {}, rowData, change.data ); if( change.type == "remove" ) dataToSave.delete = true; }) } else { dataToSave = change.data; } // console.log( "dataToSave", dataToSave ); Fse.Ajax.performAction( { object : "BOM.saveObjectiveBundle", data : dataToSave } ) .then( function( result ) { let bundleDataSource = e.component.option( "dataSource" ); if( change.type == "insert" ) { change.key = result.bundleId; change.data.bundleId = result.bundleId; } bundleDataSource = DevExpress.data.applyChanges( bundleDataSource, [ change ], { keyExpr : "bundleId" } ); e.component.option( { dataSource : bundleDataSource, editing : { editingRowKey : null, changes : []} } ); changesMade++; }) } }, columns : [ { dataField : "bundleName", caption : "Name" }, { dataField : "active", caption : "Active", width : 60, lookup : { dataSource : { store : { type : "array", data : [ { "text" : "Y" }, { "text" : "N" } ], key : "text" }}, displayExpr : "text", valueExpr : "text" } }, { dataField : "objectiveCount", caption : "Objectives", dataType : "number", width : 80, format : "fixedPoint", allowEditing : false } ], showBorders : true, scrolling : { mode : "virtual" }, height : 400 }).dxDataGrid( "instance" ); // dataSource option is set to a simple array in order to facilitate in place editing let bundleDataSource = Fse.Data.newDataSource( { object : "BOM.objectiveBundles", key : "bundleId", paginate : false, objectParams : { includeStats : true } } ); bundleDataSource.load().done( function( bundles ) { dataGrid.option( { "dataSource" : bundles, "disabled" : false } ) }) return dataGrid.element(); }, onHidden : function( e ) { e.component.element().remove(); editPromise.resolve( changesMade ) } }).dxPopup("instance"); popup.element().appendTo( $("body") ) popup.show(); return editPromise; }