").dxButton( {
text : "Go to",
width : 55,
onClick : function( ee ) {
instance.returnOperator( options.data.operatorId, "goto" );
}
})
} else {
button = $("
").dxButton( {
width : 55,
text : "Add",
onClick : function( e ) {
instance.initiateAddFrom1FS( options.data );
}
})
}
container.append( button );
}
}
]
}).dxDataGrid( "instance" );
instance.search1FSResultList.element().css( { "margin-top" : "15px" } ).appendTo( content );
return content;
}
NewOperatorProfileDialog.prototype.addOperatorTemplate = function() {
let instance = this;
let crmItems = [
{ dataField : "territoryId", label : { text : "Sales Territory", location : "left" }, isRequired : true,
editorType : "dxSelectBox", editorOptions : {
valueExpr : "TerritoryID",
displayExpr : "territoryName",
// dataSource : Fse.Data.newDataSource( { object : "TER.salesTerritories", keyField : "TerritoryID" }),
dataSource : Fse.Data.getLocalDataSource( "$.salesTerritories" ),
searchEnabled : true,
searchExpr : "territoryName",
searchMode : "contains"
}
},
{ dataField : "salesRepId", label : { text : "Sales Rep", location : "left" },
editorType : "dxSelectBox", editorOptions : {
valueExpr : "fspro_userId",
displayExpr : "fullName",
// dataSource : Fse.Data.newDataSource( { dataURL : instance.dataURL, object : "CRM.salesRepList", keyField : "fspro_userId" } ),
dataSource : Fse.Data.getLocalDataSource( "$.salesRepList" ),
searchEnabled : true,
searchExpr : "fullName",
searchMode : "contains"
}
},
{ dataField : "priority", label : { text : "Priority", location : "left" },
editorType : "dxSelectBox", editorOptions : {
dataSource : [
{ text : "A+", value : "*" },
{ text : "A", value : "A" },
{ text : "B", value : "B" },
{ text : "C", value : "C" },
{ text : "D", value : "D" }
],
displayExpr : "text",
valueExpr : "value",
value : "C",
width : 75
}
},
{ dataField : "classificationId", label : { location : "left", text : "Classification" }, editorType : "dxSelectBox",
editorOptions : {
// dataSource : Fse.Data.newDataSource( { dataURL : instance.dataURL, object : "OPR.classifications", keyField : "classificationId" } ),
dataSource : Fse.Data.getLocalDataSource( "$.operatorClassifications" ),
searchExpr : "name",
searchMode : "contains",
displayExpr : "name",
valueExpr : "classificationId"
}
}
]
let internetItems = [];
let validURLPattern = Fse.CRM.socialMediaPlatforms.other.urlRegEx;
/*
let validURLPattern = /^https?:\/\/([-\w\.]+)+(:\d+)?(:\w+)?(@\d+)?(@\w+)?([-\w\.]+)(\/([\w\/_\.]*(\?\S+)?)?)?/i;
*/
let internetLocations = [
{
dataField : "url",
label : "Website", placeholder : "Website URL", maxLength : 150,
type : "url"
},
{
dataField : "companyEmail",
label : "Email", placeholder : "email address", maxLength : 150,
validationRules : [ { type : "email", message : "Invalid Email" } ]
},
{
dataField : "facebook",
label : "Facebook", placeholder : "Facebook URL or ID",
type : "url",
socialMediaPlatform : "facebook"
},
{
dataField : "instagram",
label : "Instagram", placeholder : "Instagram URL or ID",
type : "url",
socialMediaPlatform : "instagram"
},
{
dataField : "twitter",
label : "\"X\"", placeholder : "\"X\" URL or ID (1-15 char)",
type : "url",
socialMediaPlatform : "twitter"
},
{
dataField : "tiktok",
label : "TikTok",placeholder : "TikTok URL or ID",
type : "url",
socialMediaPlatform : "tiktok",
},
{
dataField : "youtube",
label : "YouTube", placeholder : "YouTube URL or ID (10 char)",
type : "url",
socialMediaPlatform : "youtube"
},
{
dataField : "linkedIn",
label : "LinkedIn", placeholder : "LinkedIn URL", maxLength : 150,
type : "url",
socialMediaPlatform : "linkedin"
}
];
/*
let internetLocations = [
{ type : "url", dataField : "url", label : "Website", maxLength : 150, placeholder : "url", validationRules : [ { type : "pattern", message : "Invalid URL", pattern : validURLPattern }] },
{ dataField : "companyEmail", label : "Email", maxLength : 150, placeholder : "email address", validationRules : [ { type : "email" } ] },
{ dataField : "facebook", label : "Facebook", prefix : "facebook.com/" },
{ dataField : "instagram", label : "Instagram", prefix : "instagram.com/" },
{ dataField : "twitter", label : "Twitter (X)", prefix : "twitter.com/" },
{ dataField : "tiktok", label : "TikTok", prefix : "tiktok.com/@" },
{ dataField : "youtube", label : "YouTube", prefix : "youtube.com/@" },
{ type : "url", dataField : "linkedIn", label : "LinkedIn", maxLength : 150, placeholder : "url", validationRules : [ { type : "pattern", message : "Invalid URL", pattern : validURLPattern }] }
];
*/
internetLocations.forEach( function( il ) {
let item = {
dataField : il.dataField,
label : { text : il.label },
template : function( options, itemElement ) {
let customEditors = options.component.option( "customEditors" );
if( ! customEditors ) {
customEditors = {};
}
let textBoxConfig = {
maxLength : il.maxLength ? il.maxLength : null,
placeholder : il.placeholder ? il.placeholder : null,
onValueChanged : function( e ) {
options.component.updateData( options.dataField, e.value );
}
}
if( il.type == "url" ) {
textBoxConfig.onOptionChanged = function( e ) {
if( e.name == "validationErrors" ) {
let validationErrors = e.value;
if( validationErrors ) {
let errorHandled = false;
validationErrors.forEach( function( ve ) {
if( errorHandled ) return;
if( ve.type == "pattern" ) {
if( ve.socialMediaPlatform ) {
let value = ve.value;
if( ! value.match( validURLPattern ) ) {
value = ve.urlTransform( value );
if( value.match( validURLPattern ) && value.match( ve.pattern ) ) {
errorHandled = true;
setTimeout( function() {
e.component.option( "value", value )
}, 10 );
}
}
} else {
let value = ve.value;
if( ! value.match( /^https+:\/\//i) ) {
value = value.replace( /^.*:/i, '' ).replace( /^\/\//, '' );
value = `https://${value}`
errorHandled = true;
setTimeout( function() {
e.component.option( "value", value )
}, 10 );
}
}
}
})
}
}
/*
if( e.name == "validationErrors" ) {
let validationErrors = e.value;
if( validationErrors ) {
validationErrors.forEach( function( ve ) {
if( ve.type == "pattern" ) {
let value = ve.value;
if( ! value.match( /^https+:\/\//i) ) {
value = value.replace( /^.*:/i, '' ).replace( /^\/\//, '' );
value = `https://${value}`
console.log( `revised value ${value}` )
setTimeout( function() {
e.component.option( "value", value )
}, 10 );
}
}
})
}
}
*/
}
}
let textBox = $("
").dxTextBox( textBoxConfig ).dxTextBox( "instance" );
let validationRules = il.validationRules ? il.validationRules : null;
if( ! validationRules && il.type == "url" ) {
validationRules = [];
let message = "Invalid URL";
if( il.socialMediaPlatform && Fse.CRM.socialMediaPlatforms[il.socialMediaPlatform] ) {
let pattern = Fse.CRM.socialMediaPlatforms[il.socialMediaPlatform].urlRegEx;
let urlTransform = Fse.CRM.socialMediaPlatforms[il.socialMediaPlatform].urlTransform;
urlTransform ? urlTransform : function( v ) { return v };
message = `Invalid ${il.placeholder}`;
validationRules.push(
{ type : "pattern", socialMediaPlatform : il.socialMediaPlatform, message : message, pattern : pattern, urlTransform : urlTransform }
)
}
validationRules.push(
{ type : "pattern", message : message, pattern : validURLPattern }
);
}
textBox.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : validationRules
})
/*
textBox.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : il.validationRules ? il.validationRules : null
})
let prefix = null;
if( il.prefix ) {
prefix = $("
").css( { "font-style" : "italic", "display" : "inline-block", "margin-right" : "5px", "width" : "95px", "text-align" : "right" } ).text( il.prefix );
textBox.element().css( { "display" : "inline-block" } );
}
*/
let editorContainer = $("
");
/*
if( prefix ) {
editorContainer.append( prefix );
}
*/
editorContainer.append( textBox.element() );
itemElement.append( editorContainer );
customEditors[il.dataField] = textBox;
options.component.option( "customEditors", customEditors );
}
}
internetItems.push( item );
});
let countyDS = Fse.Data.getLocalDataSource( "$.counties" );
countyDS.filter( [
[ "state", "=", '?' ],
"and",
[ "countryId", "=", 0 ]
] );
let companyItems = [];
companyItems.push(
{
dataField : "companyName", isRequired : true, editorType : "dxTextBox", editorOptions : {
maxLength : 150,
xwidth : 200
}
},
{
dataField : "address", label : { text : "Address Line 1" }, isRequired : instance.requiredFields.address, editorType : "dxTextBox", editorOptions : {
maxLength : 75,
xwidth : 200
}
}, {
dataField : "address2", label : { location : "left", text : "Address Line 2" },
editorType : "dxTextBox", editorOptions : {
maxLength : 75,
xwidth : 200
}
}
)
if( instance.showCountryField ) {
companyItems.push( {
dataField : "countryId", label : { text : "Country" },
editorType : "dxSelectBox", editorOptions : {
dataSource : Fse.Data.newDataSource( { object : "UT.countries", keyField : "countryId" } ),
value : instance.defaultCountryId,
displayExpr : "countryAbbrev",
valueExpr : "countryId",
width : 100
}
} );
}
companyItems.push(
{ label : { text : "Location", location : "left"},
template : function( options, itemElement ) {
let cityTextBox = $("
").dxTextBox( {
width : 150,
placeholder : "city",
onValueChanged : function( e ) {
options.component.updateData( "city", e.value );
}
}).css( { "display" : "inline-block" } );
if( instance.requiredFields.city ) {
cityTextBox.dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : [ { type : "required", message : "City is required" } ]
})
}
let stateSelectBox = $("
").dxSelectBox( {
width : 80,
dataSource : Fse.Data.newDataSource( { object : "UT.states", keyField : "state", objectParams : { countryId : instance.defaultCountryId } } ),
placeholder : instance.defaultStatePlaceholder,
displayExpr : "state",
valueExpr : "state",
searchEnabled : true,
searchExpr : "state",
searchMethod : "startswith",
showClearButton : true,
validationGroup : options.component.option( "validationGroup" ),
onValueChanged : function( e ) {
options.component.updateData( "state", e.value );
}
}).css( { "display" : "inline-block", "margin-left" : "8px" } );
if( instance.requiredFields.state ) {
stateSelectBox.dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : [ { type : "required", message : "State is required" } ]
})
}
let zipCodeTextBox = $("
").dxTextBox( {
width : 90,
placeholder : "postal code",
validationGroup : options.component.option( "validationGroup" ),
onValueChanged : function( e ) {
options.component.updateData( "zipCode", e.value );
}
}).css( { "display" : "inline-block", "margin-left" : "8px" } );
if( instance.requiredFields.zipCode ) {
zipCodeTextBox.dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : [ { type : "required", message : "Postal code is required" } ]
})
}
// add the editors to the component's options so we can find them later
let customEditors = options.component.option( "customEditors" );
if( ! customEditors ) {
customEditors = {};
}
customEditors.zipCode = zipCodeTextBox.dxTextBox( "instance" );
customEditors.city = cityTextBox.dxTextBox( "instance" );
customEditors.state = stateSelectBox.dxSelectBox( "instance" );
options.component.option( "customEditors", customEditors );
itemElement.append( cityTextBox )
.append( stateSelectBox )
.append( zipCodeTextBox )
}
},
/*
{
dataField : "county", label : { text : "County" },
editorType : "dxTextBox", editorOptions : {
maxLength : 50,
width : 100
}
},
*/
{ dataField : "county", label : { text : "County" },
editorType : "dxAutocomplete",
editorOptions : {
width : 100,
dataSource : countyDS,
valueExpr : "county"
}
},
{ label : { text : "Main Phone" },
isRequired : instance.requiredFields.phone,
template : function( options, itemElement ) {
let customEditors = options.component.option( "customEditors" );
if( ! customEditors ) {
customEditors = {};
}
let phoneValidationRules = []
if( false ) {
phoneValidationRules.push( {
ignoreEmptyValue : true,
type: 'pattern',
pattern: /^\d{3}-\d{3}-\d{4}$/,
message: 'The phone must have a correct phone format',
})
}
if( instance.requiredFields.phone ) {
phoneValidationRules.push( {
type : "custom",
message : "The phone is required",
reevaluate : true,
ignoreEmptyValue : false,
validationCallback : function( options ) {
let result = false;
if( options.value ) {
result = true;
}
return result;
}
})
}
let phoneTextBox = $("
").dxTextBox( {
width : 100,
maxLength : 30,
/*
mask: '000-000-0000', maskChar : ' ', useMaskedValue : true,
onValueChanged : function( e ) {
if( e.value ) {
if( e.value.replace( /\s|-/g, '' ) == '' ) {
e.component.option( "value", null );
} else {
options.component.updateData( "phone", e.value );
}
} else {
options.component.updateData( "phone", e.value );
}
}
*/
onValueChanged : function( e ) {
let theValue = e.value;
if( e.component.option( "fseReformatted") ) {
e.component.option( "fseReformatted", false );
options.component.updateData( "phone", e.value );
} else {
let formatted = Fse.UI.reformatPhone( e.value );
if( formatted != e.value ) {
e.component.option( {
"fseReformatted" : true,
value : formatted
} )
} else {
options.component.updateData( "phone", e.value );
}
}
}
}).css( { "display" : "inline-block" } ).dxTextBox( "instance" );
if( phoneValidationRules.length ) {
phoneTextBox.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : phoneValidationRules
})
}
customEditors.phone = phoneTextBox;
itemElement.append( phoneTextBox.element() )
let phoneExtTextBox = $("
").dxTextBox( {
width : 50,
maxLength : 10,
onValueChanged : function( e ) {
options.component.updateData( "phoneExt", e.value );
}
}).css( { "display" : "inline-block" } ).dxTextBox( "instance" );
customEditors.phoneExt = phoneExtTextBox;
itemElement
.append( $("
").text( "Ext." ).css( { "padding-left" : "8px", "padding-right" : "8px" }) )
.append( phoneExtTextBox.element() );
options.component.option( "customEditors", customEditors );
}
}
// 1. Sales Territory+
// 1. Sales Rep
// 1. Priority+
// Classification+
// County
// Main Phone
// Extension
// website URL
// Email Address
// instagram, facebook, x(Twitter), TikTok, YouTube // LinkedIn
// 1. Preferred Distributor
// Secondary Distributor
// 1. Acct Nbr (Preferred Distributor)
// Number of Units
// Food Mgmt Co / ID / Since
// Buying Group/GPO / ID / Since
// 1. Primary Segment
// Cuisine
);
let distributionItems = [
{ colSpan : 2, dataField : "distrib1", label : { location : "left", text : `Preferred ${getText( 'DISTRIBUTOR' )}` },
isRequired : instance.requiredFields.distrib1,
editorType : "dxSelectBox",
editorOptions : {
showClearButton : true,
searchEnabled : true,
dataSource : Fse.Data.newDataSource( { dataURL : instance.dataURL, object : "CDR.distributorsLight", keyField : "cdr_recordId" } ),
searchExpr : "cdr_dstName",
searchMode : "contains",
displayExpr : "cdr_dstName",
valueExpr : "cdr_recordId",
}
},
{ dataField : "distrib1_acctNbr", label : { location : "left", text : "Acct. Nbr" },
editorType : "dxTextBox", editorOptions : {
maxLength : 50,
disabled : true
}
},
{ colSpan : 2, dataField : "distrib2", label : { location : "left", text : `Secondary ${getText( 'DISTRIBUTOR' )}` }, editorType : "dxSelectBox",
editorOptions : {
showClearButton : true,
searchEnabled : true,
dataSource : Fse.Data.newDataSource( { dataURL : instance.dataURL, object : "CDR.distributorsLight", keyField : "cdr_recordId" } ),
searchExpr : "cdr_dstName",
searchMode : "contains",
displayExpr : "cdr_dstName",
valueExpr : "cdr_recordId",
}
},
{ dataField : "distrib2_acctNbr", label : { location : "left", text : "Acct. Nbr" },
editorType : "dxTextBox", editorOptions : {
maxLength : 50,
disabled : true
}
}
];
let numUnitsItems = [
{
label : { location : "left", text : "Num. Units" },
template : function( options, itemElement ) {
let customEditors = options.component.option( "customEditors" );
if( ! customEditors ) {
customEditors = {};
}
let currentYear = ( new Date() ).getFullYear();
let fieldDefs = [
{ label : currentYear - 1, dataField : "numUnit_LY" },
{ label : currentYear, dataField : "numUnit_TY" },
{ label : currentYear + 1, dataField : "numUnit_NY" },
];
fieldDefs.forEach( function( fd ) {
let editor = $("").dxTextBox( {
width : 50,
value : 1,
onValueChanged : function( e ) {
options.component.updateData( fd.dataField, e.value );
}
}).dxTextBox( "instance" );
editor.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : [
{ type : "required", message : "A number zero or greater is required" },
{ type : "numeric", message : "A number zero or greater is required" },
{ type : "range", message : "A number zero or greater is required", min : 0 }
]
})
let label = $("
").text( fd.label );
label.css( { "padding-right" : "8px" })
editor.element().css( { "display" : "inline-block", "margin-right" : "10px" } )
itemElement.append( label ).append( editor.element() )
customEditors[fd.dataField] = editor;
})
options.component.option( "customEditors", customEditors );
}
}
];
let memberGroupItems = [
{
colSpan : 2,
label : { text : "Food Mgmt. Co" },
dataField : "cmc_operatorId",
editorType : "dxSelectBox",
editorOptions : {
placeholder : "self managed",
dataSource : Fse.Data.newDataSource( { object : "OPR.cmcs", keyField : "operatorId" }),
searchEnabled : true,
searchExpr : "companyName",
searchMode : "contains",
valueExpr : "operatorId",
displayExpr : "companyName",
showClearButton : true,
}
},
{ label : { text : "ID" },
dataField : "cmc_memberNbr",
editorType : "dxTextBox",
editorOptions : {
maxLength : 50,
disabled : true
}
},
{ label : { text : "Since" },
dataField : "cmc_affiliationDate",
editorType : "dxDateBox",
editorOptions : {
disabled : true
}
},
{
colSpan : 2,
label : { text : "GPO/Buying Group" },
dataField : "gpo_operatorId",
editorType : "dxSelectBox",
editorOptions : {
placeholder : "none",
dataSource : Fse.Data.newDataSource( { object : "OPR.gpos", keyField : "operatorId" }),
searchEnabled : true,
searchExpr : "companyName",
searchMode : "contains",
valueExpr : "operatorId",
displayExpr : "companyName",
showClearButton : true,
}
},
{ label : { text : "ID" },
dataField : "gpo_memberNbr",
editorType : "dxTextBox",
editorOptions : {
maxLength : 50,
disabled : true
}
},
{ label : { text : "Since" },
dataField : "gpo_affiliationDate",
editorType : "dxDateBox",
editorOptions : {
disabled : true
}
}
];
let otherItems = [
{ dataField : "oprSegment", label : { location : "left", text : "Segment" },
isRequired : instance.requiredFields.oprSegment,
editorType : "dxSelectBox",
editorOptions : {
showClearButton : true,
dataSource : Fse.Data.newDataSource( {
object : "OPR.segments",
key : "clientSegId",
map : function( dataItem ) {
return {
clientSegId : dataItem.clientSegId,
segmentPath : dataItem.segmentPath,
disabled : dataItem.hasChildSegments ? true : false,
hierarchyLevel : dataItem.hierarchyLevel
}
}
} ),
itemTemplate : function( item ) {
let itemText = item.segmentPath;
let itemElement = $("").attr( { "title" : itemText } ).text( itemText );
if( item.hierarchyLevel == 1 ) {
itemTextParsed = itemText.split( "/" );
itemTextParsed.shift();
itemElement.css( { "padding-left" : "15px" } ).text( itemTextParsed.join( "/" ) );
}
return itemElement;
},
searchExpr : "segmentPath",
searchMode : "contains",
searchEnabled : true,
displayExpr : "segmentPath",
valueExpr : "clientSegId"
}
},
{ dataField : "cuisineId", label : { location : "left", text : "Cuisine" }, editorType : "dxSelectBox",
editorOptions : {
showClearButton : true,
dataSource : Fse.Data.newDataSource( { object : "OPR.cuisines", keyField : "cuisineId" } ),
searchExpr : "cuisine",
searchEnabled : true,
searchMode : "contains",
displayExpr : "cuisine",
valueExpr : "cuisineId"
}
}
]
let contactItems = instance.addOperatorTemplateContactItems();
instance.addOperatorForm = $("
").dxForm( {
validationGroup : "addOperatorForm",
items : [
{
itemType : "tabbed",
tabPanelOptions : { deferRendering : false }, // this is so all of the fields are rendered at the start
tabs : [
{ title : "Company",
items : [
{ itemType : "group",
items : crmItems,
},
{ itemType: "group",
items : companyItems
},
{ itemType : "group",
items : internetItems
},
{ itemType : "group",
colCount : 3,
items : distributionItems
},
{ itemType : "group",
items : numUnitsItems
},
{ itemType : "group",
colCount : 4,
items : memberGroupItems,
},
{ itemType : "group",
items : otherItems,
}
]
},
{ title : "Contact", items : contactItems }
]
}
],
onFieldDataChanged : function( e ) {
let customEditors = e.component.option( "customEditors" );
if( customEditors && customEditors[e.dataField] ) {
// push the data into the custom editor
customEditors[e.dataField].option( "value", e.value );
}
// handle object value for contact v. qualified field names
if( e.dataField == "contact" && e.value ) {
let customEditors = e.component.option( "customEditors" );
if( customEditors ) {
for( contactField in e.value ) {
let qualifiedContactField = `${e.dataField}.${contactField}`;
if( customEditors && customEditors[qualifiedContactField] ) {
// push the data into the custom editor
customEditors[qualifiedContactField].option( "value", e.value[contactField] );
}
}
}
}
if( e.dataField == "gpo_operatorId" || e.dataField == "cmc_operatorId" ) {
let fieldPrefix = e.dataField.split( "_" )[0];
let memberNbrEditor = e.component.getEditor( `${fieldPrefix}_memberNbr` );
let affiliationDateEditor = e.component.getEditor( `${fieldPrefix}_affiliationDate` );
let editorOptions = {
disabled : e.value ? false : true
}
if( editorOptions.disabled ) {
editorOptions.value = null;
}
memberNbrEditor.option( editorOptions );
affiliationDateEditor.option( editorOptions );
}
if( e.dataField == "zipCode" && e.value ) {
let territoryId = e.component.option( "formData").territoryId;
if( ! territoryId ) {
let salesTerritoryDS = Fse.Data.newDataSource( { object : "TER.salesTerritories", keyField : "territoryId", objectParams : { byZipCode : e.value } });
salesTerritoryDS.load().done( function( data ) {
if( data.length == 1 ) {
e.component.updateData( { territoryId : data[0].TerritoryID } );
}
})
}
}
if( e.dataField == "territoryId" ) {
let distrib1Editor = e.component.getEditor( "distrib1" );
let distrib2Editor = e.component.getEditor( "distrib2" );
let filter = [];
if( e.value ) {
filter.push( "relatedTerritoryIds", "contains", `#${e.value};` );
} else {
filter.push( "territoryId", "=", -1 );
}
let ds1 = distrib1Editor.getDataSource();
ds1.filter( filter );
ds1.load();
let ds2 = distrib2Editor.getDataSource();
ds2.filter( filter );
ds2.load();
let salesRepFilter = [];
if( e.value ) {
salesRepFilter.push( "territoryIdList", "contains", `#${e.value};` );
}
let salesRepEditor = e.component.getEditor( "salesRepId" );
let salesRepDataSource = salesRepEditor.getDataSource();
salesRepDataSource.filter( salesRepFilter );
salesRepDataSource.load();
e.component.updateData( { "distrib1" : null, "distrib2" : null, "salesRepId" : null });
}
if( e.dataField == "distrib1" || e.dataField == "distrib2" ) {
let fieldOptions = {
disabled : e.value ? false : true
};
if( fieldOptions.disabled ) {
fieldOptions.value = null;
}
e.component.getEditor( `${e.dataField}_acctNbr` ).option( fieldOptions );
}
/*
if( e.dataField == "addContact" ) {
instance.enableAddOperatorContactFields( e.value ? true : false );
}
*/
if( e.dataField == "countryId" ) {
let editor = null;
let customEditors = e.component.option( "customEditors" );
if( customEditors ) {
editor = customEditors.state;
}
if( editor ) {
// let formData = e.component.option( "formData" );
let countryId = e.value;
if( ! countryId ) {
countryId = 0;
}
let stateDataSource = Fse.Data.newDataSource( { object : "UT.states", keyField : "state", objectParams : { countryId : countryId } } );
let placeholder = "state";
if( countryId == 5 ) {
placeholder = "prov";
}
editor.option( { dataSource : stateDataSource, "value" : null, placeholder : placeholder } );
editor.repaint();
}
}
if( e.dataField == "state" ) {
let editor = e.component.getEditor( "county" );
if( editor ) {
let formData = e.component.option( "formData" );
let countyDataSource = editor.getDataSource();
let countyFilter = [];
if( formData.countryId ) {
countyFilter.push( [ "countryId", "=", formData.countryId ] )
} else {
countyFilter.push( [ "countryId", "=", 0 ] )
}
countyFilter.push( "and" );
if( formData.state ) {
countyFilter.push( [ "state", "=", formData.state ] );
} else {
countyFilter.push( ["state", "=", "?" ]);
}
countyDataSource.filter( countyFilter );
editor.option( "value", null );
}
}
/*
if( e.dataField.substring( 0, 8 ) == "contact." ) {
console.log( "Contact Field Changed", e.dataField );
let editor = customEditors["contact.jobFunction"];
editor = e.component.getEditor( "contact.jobFunction" );
let validator = editor.element().dxValidator( "instance" );
console.log( validator );
}
*/
if( e.dataField == "contact.countryId" ) {
let stateEditor = e.component.getEditor( "contact.state" );
if( stateEditor ) {
let countryId = e.value;
if( ! countryId ) {
countryId = 0;
}
let placeholder = "state";
if( countryId == 5 ) {
placeholder = "prov";
}
let stateDataSource = Fse.Data.newDataSource( { object : "UT.states", keyField : "state", objectParams : { countryId : countryId } } );
stateEditor.option( { dataSource : stateDataSource, value : null, placeholder : placeholder });
stateEditor.repaint();
}
}
if( e.dataField == "contact.officeAddrSame" ) {
let disabled = e.value ? true : false;
["contact.address1","contact.address2","contact.countryId","contact.city","contact.state","contact.zipCode"].forEach( function( f ) {
let contactAddressEditor = e.component.getEditor( f );
if( contactAddressEditor ) {
contactAddressEditor.option( "disabled", disabled );
}
})
}
}
}).dxForm( "instance" );
return instance.addOperatorForm.element();
}
NewOperatorProfileDialog.prototype.contactFieldValidationCallback = function( v ) {
let instance = this;
let valid = true;
let isRequired = false;
let formData = instance.addOperatorForm.option( "formData" );
for( contactField in formData.contact ) {
if( formData.contact[contactField] ) {
if( instance.contactDefaults[contactField] && instance.contactDefaults[contactField] === formData.contact[contactField] )
continue;
isRequired = true;
break;
}
}
if( isRequired && ! v.value ) {
valid = false;
}
return valid;
}
NewOperatorProfileDialog.prototype.addOperatorTemplateContactItems = function() {
let instance = this;
let contactItems = [];
// the addContact value is determined by the presence of data
// contactItems.push( { label : { text : "Add Contact" }, dataField : "addContact", editorType : "dxCheckBox" });
contactItems.push ( {
label : { text : "Contact Name" },
template : function( options, itemElement ) {
/*
let salutationSelectBox = $("
").dxSelectBox( {
width : 90,
showClearButton : true,
hint : "salutation",
placeholder : null,
dataSource: [
{ text : "Mr." },
{ text : "Ms." },
{ text : "Miss" },
{ text : "Dr." },
{ text : "Chef" }
],
displayExpr: "text",
valueExpr : "text",
onValueChanged : function( e ) {
options.component.updateData( { "contact.salutation" : e.value } );
}
}).dxSelectBox("instance" )
salutationSelectBox.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" )
})
*/
let firstNameTextBox = $("
").dxTextBox( {
width : 150,
//maxLength : 50,
placeholder : "first name",
onValueChanged : function( e ) {
options.component.updateData( { "contact.firstName" : e.value } );
}
}).dxTextBox( "instance");
firstNameTextBox.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : [
{ type : "custom", reevaluate : true, message : "First Name is required",
validationCallback : function( v ) {
return instance.contactFieldValidationCallback( v );
}
}
]
})
let lastNameTextBox = $("
").dxTextBox( {
width : 150,
//maxLength : 50,
placeholder : "last name",
onValueChanged : function( e ) {
options.component.updateData( { "contact.lastName" : e.value } );
}
}).dxTextBox( "instance" )
lastNameTextBox.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" )
})
let primaryContactCheckBox = $("
").dxCheckBox( {
text: "Primary Contact",
onValueChanged: function (e) {
options.component.updateData( "contact.primaryContact", e.value );
}
}).dxCheckBox( "instance" )
let decisionMakerCheckBox = $("
").dxCheckBox( {
text: "Decision maker",
onValueChanged: function (e) {
options.component.updateData( "contact.contactDecisionMaker", e.value );
}
}).dxCheckBox( "instance" )
itemElement
// .append( salutationSelectBox.element().css( { "display" : "inline-block" } ))
.append( firstNameTextBox.element().css( { "display" : "inline-block" } ))
.append( lastNameTextBox.element().css( { "display" : "inline-block", "margin-left" : "8px" } ))
.append( $("
").append( primaryContactCheckBox.element() ))
.append( $("
").append( decisionMakerCheckBox.element() ))
let customEditors = options.component.option( "customEditors" );
if( ! customEditors ) {
customEditors = {};
}
customEditors["contact.firstName"] = firstNameTextBox;
customEditors["contact.lastName"] = lastNameTextBox;
// customEditors["contact.salutation"] = salutationSelectBox;
customEditors["contact.contactDecisionMaker"] = decisionMakerCheckBox;
customEditors["contact.primaryContact"] = primaryContactCheckBox;
options.component.option( "customEditors", customEditors );
}
})
contactItems.push(
{
dataField : "contact.caRelationshipRank",
label : { text : "Relationship Rank" },
editorType : "dxSelectBox",
editorOptions : {
dataSource : Fse.Data.getLocalDataSource( "$.contactRelationshipRanks"),
displayExpr : "caRelationshipRankText",
valueExpr : "caRelationshipRank",
searchEnabled : true,
searchExpr : "caRelationshipRankText",
searchMethod : "startswith",
showClearButton : true,
width : 150
}
}
);
contactItems.push(
{ dataField: "contact.email", label : { text : "Contact Email" }, editorType : "dxTextBox",
editorOptions : {
maxLength : 75,
width : 200
},
validationRules : [
{ type : "email" }
]
},
{ dataField: "contact.title", label : { text : "Contact Title" }, editorType : "dxTextBox",
editorOptions : {
maxLength : 75,
width : 200,
}
},
{
dataField : "contact.jobFunction",
label : { text : "Job Function" },
visible : Fse.Portal.getConfiguration( "CRM.OPR.hasJobFunctions" ),
editorType : "dxSelectBox",
editorOptions : {
dataSource : Fse.Data.getLocalDataSource( "$.operatorContactJobFunctions"),
displayExpr : "caJobFunctionText",
valueExpr : "caJobFunction",
searchEnabled : true,
searchExpr : "caJobFunctionText",
searchMethod : "startswith",
showClearButton : true,
width : 150
},
validationRules : [
{ type : "custom", reevaluate : true, message : "Job Function is required",
validationCallback : function( v ) {
if( ! Fse.Portal.getConfiguration( "CRM.OPR.hasJobFunctions" ) ) {
return true;
}
return instance.contactFieldValidationCallback( v );
}
}
]
},
{ dataField : "contact.preferredCommunication",
label : { text : "Communication Pref." },
editorType: 'dxSelectBox',
editorOptions: {
width : 150,
dataSource: [
{ "dispValue": "Text" , "value": "T"},
{ "dispValue": "Email" ,"value": "E"},
{ "dispValue": "Phone", "value": "P"},
{ "dispValue": "Cell", "value": "C"}
],
showClearButton : true,
displayExpr: "dispValue",
valueExpr : "value",
placeholder : "no preference",
searchEnabled: true
}
},
{ label : { text : "Contact Phone" },
template : function( options, itemElement ) {
let phoneTextBox = $("
").dxTextBox( {
width : 150,
maxLength : 30,
/*
mask: '000-000-0000', maskChar : ' ',
onValueChanged : function( e ) {
options.component.updateData( "contact.phone", e.value );
}
*/
onValueChanged : function( e ) {
console.log( e );
if( e.component.option( "fseReformatted") ) {
console.log( "fseReformatted = false")
e.component.option( "fseReformatted", false );
} else {
let formatted = Fse.UI.reformatPhone( e.value );
if( formatted != e.value ) {
e.component.option( {
"fseReformatted" : true,
value : formatted
} )
console.log( "fseReformatted = true")
} else {
options.component.updateData( "contact.phone", e.value );
}
}
}
}).dxTextBox( "instance");
let phoneExtTextBox = $("
").dxTextBox( {
width : 60,
maxLength : 10,
onValueChanged : function( e ) {
options.component.updateData( "contact.phoneExt", e.value );
}
}).dxTextBox( "instance" );
itemElement
.append( phoneTextBox.element().css( { "display" : "inline-block" } ) )
.append( $("
").text( "Ext." ).css( { "padding-left" : "8px", "padding-right" : "8px" }) )
.append( phoneExtTextBox.element().css( { "display" : "inline-block" } ) );
let customEditors = options.component.option( "customEditors" );
if( ! customEditors ) {
customEditors = {};
}
customEditors["contact.phone"] = phoneTextBox;
customEditors["contact.phoneExt"] = phoneExtTextBox;
options.component.option( "customEditors", customEditors );
}
},
{ dataField: "contact.cell", label : { text : "Contact Mobile" }, editorType : "dxTextBox",
editorOptions : {
maxLength : 30,
width : 150,
// mask: '000-000-0000', maskChar : ' '
//, useMaskedValue : true
onValueChanged : function( e ) {
if( e.component.option( "fseReformatted") ) {
e.component.option( "fseReformatted", false );
} else {
let formatted = Fse.UI.reformatPhone( e.value );
if( formatted != e.value ) {
e.component.option( {
"fseReformatted" : true,
value : formatted
} )
}
}
}
}
},
)
let validURLPattern = Fse.CRM.socialMediaPlatforms.other.urlRegEx;
/*
let validURLPattern = /^https?:\/\/([-\w\.]+)+(:\d+)?(:\w+)?(@\d+)?(@\w+)?([-\w\.]+)(\/([\w\/_\.]*(\?\S+)?)?)?/i;
*/
let internetLocations = [
{
dataField : "contact.linkedIn",
label : "LinkedIn", placeholder : "LinkedIn URL", maxLength : 150, width : 300,
type : "url",
socialMediaPlatform : "linkedin"
},
{
dataField : "contact.facebook",
label : "Facebook", placeholder : "Facebook URL or ID",
type : "url",
socialMediaPlatform : "facebook"
},
{
dataField : "contact.instagram",
label : "Instagram", placeholder : "Instagram URL or ID",
type : "url",
socialMediaPlatform : "instagram"
},
{
dataField : "contact.twitter",
label : "\"X\"", placeholder : "\"X\" URL or ID (1-15 char)",
type : "url",
socialMediaPlatform : "twitter"
},
{
dataField : "contact.tiktok",
label : "TikTok",placeholder : "TikTok URL or ID",
type : "url",
socialMediaPlatform : "tiktok",
},
{
dataField : "contact.youtube",
label : "YouTube", placeholder : "YouTube URL or ID (10 char)",
type : "url",
socialMediaPlatform : "youtube"
},
];
internetLocations.forEach( function( il ) {
let item = {
dataField : il.dataField,
label : { text : il.label },
template : function( options, itemElement ) {
let customEditors = options.component.option( "customEditors" );
if( ! customEditors ) {
customEditors = {};
}
let textBoxConfig = {
maxLength : il.maxLength ? il.maxLength : null,
placeholder : il.placeholder ? il.placeholder : null,
width : il.width ? il.width : null,
onValueChanged : function( e ) {
options.component.updateData( options.dataField, e.value );
}
};
if( il.type == "url" ) {
textBoxConfig.onOptionChanged = function( e ) {
if( e.name == "validationErrors" ) {
let validationErrors = e.value;
if( validationErrors ) {
let errorHandled = false;
validationErrors.forEach( function( ve ) {
if( errorHandled ) return;
if( ve.type == "pattern" ) {
if( ve.socialMediaPlatform ) {
let value = ve.value;
if( ! value.match( validURLPattern ) ) {
value = ve.urlTransform( value );
if( value.match( validURLPattern ) && value.match( ve.pattern ) ) {
errorHandled = true;
setTimeout( function() {
e.component.option( "value", value )
}, 10 );
}
}
} else {
let value = ve.value;
if( ! value.match( /^https+:\/\//i) ) {
value = value.replace( /^.*:/i, '' ).replace( /^\/\//, '' );
value = `https://${value}`
errorHandled = true;
setTimeout( function() {
e.component.option( "value", value )
}, 10 );
}
}
}
})
}
}
}
}
let textBox = $("").dxTextBox( textBoxConfig ).dxTextBox( "instance" );
let validationRules = il.validationRules ? il.validationRules : null;
if( ! validationRules && il.type == "url" ) {
validationRules = [];
let message = "Invalid URL";
if( il.socialMediaPlatform && Fse.CRM.socialMediaPlatforms[il.socialMediaPlatform] ) {
let pattern = Fse.CRM.socialMediaPlatforms[il.socialMediaPlatform].urlRegEx;
let urlTransform = Fse.CRM.socialMediaPlatforms[il.socialMediaPlatform].urlTransform;
urlTransform ? urlTransform : function( v ) { return v };
message = `Invalid ${il.placeholder}`;
validationRules.push(
{ type : "pattern", socialMediaPlatform : il.socialMediaPlatform, message : message, pattern : pattern, urlTransform : urlTransform }
)
}
validationRules.push(
{ type : "pattern", message : message, pattern : validURLPattern }
);
}
textBox.element().dxValidator( {
validationGroup : options.component.option( "validationGroup" ),
validationRules : validationRules
})
let editorContainer = $("
");
editorContainer.append( textBox.element() );
itemElement.append( editorContainer );
customEditors[il.dataField] = textBox;
options.component.option( "customEditors", customEditors );
}
}
contactItems.push( item );
});
contactItems.push(
{ dataField : "contact.preferredLanguage",
label : { text : "Preferred Language" },
editorType: 'dxSelectBox',
editorOptions: {
width : 150,
// dataSource : Fse.Data.newDataSource( { object : "CRM.languages", keyField : "languageCode" } ),
dataSource : Fse.Data.getLocalDataSource( "$.languages"),
displayExpr : "languageName",
valueExpr : "languageCode",
searchEnabled : true,
searchExpr : "languageName",
searchMethod : "startswith",
showClearButton : true,
placeholder : ""
}
}
)
contactItems.push(
{
dataField : "contact.officeAddrSame",
label : { text : "Location" },
editorType : "dxCheckBox",
editorOptions : {
text : "same as Company",
onValueChanged : function( e ) {
if( e.value ) {
} else {
}
}
}
},
{
dataField : "contact.address1", label : { text : "Address" }, isRequired : true, editorOptions : { maxLength : 75, xwidth : 150, disabled : true }
},
{
dataField : "contact.address2", label : { text : "Line 2" }, editorOptions : { maxLength : 75, xwidth : 150, disabled : true }
}
);
if( instance.showCountryField ) {
contactItems.push(
{
dataField : "contact.countryId", label : { text : "Country" },
editorType : "dxSelectBox", editorOptions : {
disabled : true,
dataSource : Fse.Data.newDataSource( { object : "UT.countries", keyField : "countryId" } ),
value : instance.defaultCountryId,
displayExpr : "countryAbbrev",
valueExpr : "countryId",
width : 100
}
})
}
contactItems.push(
{
dataField : "contact.city", label : { text : "City" }, isRequired : true, editorOptions : { maxLength : 75, xwidth : 100, disabled : true }
},
{
dataField : "contact.state", label : { text : instance.defaultStateLabel }, isRequired : true, editorType : "dxSelectBox",
editorOptions : {
disabled : true,
width : 80,
dataSource : Fse.Data.newDataSource( { object : "UT.states", keyField : "state", objectParams : { countryId : instance.defaultCountryId } } ),
placeholder : instance.defaultStatePlaceholder,
displayExpr : "state",
valueExpr : "state",
searchEnabled : true,
searchExpr : "state",
searchMethod : "startswith",
showClearButton : true
}
},
{
dataField : "contact.zipCode", label : { text : "Postal Code" }, isRequired : true, editorOptions : { maxLength : 10, width : 80, disabled : true }
}
)
return contactItems;
}
NewOperatorProfileDialog.prototype.matchedOperatorTemplate = function() {
let instance = this;
let content = $("
");
content.append( $("
" ).css( "font-size", "larger" ).text( `The ${getText( 'OPERATOR' ).toLowerCase()} profile you are attempting to add already exists. Below is a brief view of the existing ${getText( 'OPERATOR' ).toLowerCase()} profile.` ));
instance.matchedOperatorForm = $("
").dxForm( {
readOnly : true,
items : [
"territoryName",
{ itemType : "group", colCount : 3,
items : [
{ dataField : "accountOwnerFullName", label : { text : "Account Owner "} },
{ dataField : "accountOwnerTitle", label : { text : "Title" }},
{ dataField : "accountOwnerEmail", label : { text : "Email"}}
],
},
"companyName", "address", "address2", "city", "state", "zipCode",
{ dataField : "recordSource", label : { text : "Source" } }
]
}).dxForm( "instance" );
content.append( instance.matchedOperatorForm.element() );
content.append( $("
").css( "font-size", "larger" ).text( `You can either use the existing ${getText( 'OPERATOR' ).toLowerCase()} profile, revise your profile and try again, or add your ${getText( 'OPERATOR' ).toLowerCase()} as a duplicate.` ));
instance.dupActionForm = $("
").dxForm( {
items : [
{ dataField : "dupAction", label : { text : "Duplicate Action" }, isRequired : true, editorType : "dxSelectBox", editorOptions : {
placeholder : "select action",
dataSource : [
{ text : `Use Existing & Go to ${getText( 'OPERATOR' )}`, value : "useThisOne" },
{ text : "Revise and try again", value : "revise" },
{ text : "Add as a duplicate", value : "allowDup" }
],
displayExpr : "text",
valueExpr : "value"
}
},
{
dataField : "allowDupReason", label : { text : "Reason for Duplicate" }, isRequired : true, editorType : "dxTextBox", editorOptions : {
maxLength : 200,
disabled : true
}
}
],
onFieldDataChanged : function( e ) {
if( e.dataField == "dupAction" ) {
let reasonOptions = {
disabled : true
}
if( e.value == "allowDup" ) {
reasonOptions.disabled = false;
reasonOptions.value = null;
}
e.component.getEditor( "allowDupReason" ).option( reasonOptions );
if( e.value == "revise" ) {
instance.backToOperatorAdd();
}
}
}
}).dxForm( "instance" );
content.append( instance.dupActionForm.element() )
return content;
}