I'm trying to configure a modal lookup window by following Example 2 in this academy page https://academy.creatio.com/documents/technic-sdk/7-15/creating-detail-selection-lookup and everything works as described, but I cannot figure out how to add a default sort to the modal lookup window - are there some parameters which can be added to the config object passed to the this.openLookup method call?

 

While on that subject, are there any other potential parameters which can be added to this config object which might be useful for other tasks?

Like 0

Like

1 comments

Dear Harvey, 



There is no description for all parameters of the lookup config. The possible way is to check the existing openLookup calls. 

Sorting can be specified in sortedColumns parameter. 

You can find the example in method selectPeriod in the ForecastTab. 

Collection of columns with sorting parameters is passed to it this way: 

var config = {

    entitySchemaName: "Contact",

    multiSelect: false,

    columns: ["Name", "Account.Name"],

    sortedColumns: [{

        name: "Account.Name",

        orderPosition: 0,

        orderDirection: this.Terrasoft.core.enums.OrderDirection.ASC

    }]

};

this.openLookup(config, this.lookupCallback, this);



Kind regards, 

Roman

Show all comments

I have read this article regarding adding multiple value to a detail.

Link - https://academy.creatio.com/documents/technic-sdk/7-15/adding-multiple-records-detail

 

 

But I do not understand these variable values. The opportunity and contact are the sections that are already created in the system. I want to know what values should I put in custom detail schema.

 

Details of Objects (every object is custom) -

  1. Client section with a detail of Partners
  2. Partners detail is made from Partner section

I want to change the Partner detail in Client to add multiple records. But I do not understand what should be the values of rootEntitySchemaName, rootColumnName, relatedEntitySchemaName, relatedColumnName.

 

Can anyone please help in this matter?

 

Thanks 

Ram

Like 0

Like

4 comments
Best reply

Hello Ramnath,

 

rootEntitySchemaName is the name of the parent object. This is likely the object for the page where the detail is located, so if the detail is on the Account page, this would be Account

 

rootColumnName is the name of the column on the detail object that relates it to the parent object. In the example of being on the Account page, this would be the name of the column on the detail object that is the account lookup, such as UsrAccount

 

relatedEntitySchemaName is the name of the object you're looking up to add to the detail. So, if the lookup is looking up contacts, this would be Contact

 

relatedColumnName is the name of the column on the detail object that the result from the lookup is stored in. So in the example of looking up contacts, this would be a contact lookup on the detail object, such as UsrContact.

 

Maybe this article will help? https://customerfx.com/article/adding-to-a-detail-from-a-lookup-in-crea…

 

Ryan

Hello Ramnath,

 

rootEntitySchemaName is the name of the parent object. This is likely the object for the page where the detail is located, so if the detail is on the Account page, this would be Account

 

rootColumnName is the name of the column on the detail object that relates it to the parent object. In the example of being on the Account page, this would be the name of the column on the detail object that is the account lookup, such as UsrAccount

 

relatedEntitySchemaName is the name of the object you're looking up to add to the detail. So, if the lookup is looking up contacts, this would be Contact

 

relatedColumnName is the name of the column on the detail object that the result from the lookup is stored in. So in the example of looking up contacts, this would be a contact lookup on the detail object, such as UsrContact.

 

Maybe this article will help? https://customerfx.com/article/adding-to-a-detail-from-a-lookup-in-crea…

 

Ryan

Ryan,

 

Thanks for helping me out.

 

Please guide me in this situation more.

Overview of whole scenario

I created a custom detail in a custom section.  I have created a Section Contacts (neither base object nor replacing object, It is custom made) and Clients Section. Clients section has a detail Contacts. The detail's object name is the Contacts section.

 

Section Page - UsrClients

Detail object - UsrContacts (has lookup of UsrClient for connecting record to UsrClients with other inherited columns present in UsrContacts)

 

Now the name will be

rootEntitySchemaName - UsrClients (section page object name)

rootColumnName - UsrClient  (the referencing lookup present in UsrContacts)

relatedEntitySchemaName - UsrContacts (Section page from where records will be read)

relatedColumnName - UsrContact (lookup present in detail)

 

Now the problem is how can I create a lookup pointing to the same object on which detail is build.

Lookup points to UsrContacts and detail is also created on UsrContacts.

 

RAMNATH SHARMA,

 

The detail should be a separate object. Like in the example on the academy, OpportunityContact object on which the detail is built on contains Opportunity and Contact columns. In your case, you would need to create a separate object for the detail that would contain UsrClients and UscrContacts columns, and build the detail on this object. 

Dennis Hudson,

 

Yes, you are right. I have created a new object with 2 looks fields to add this functionality. And it works.

Thanks

Show all comments

Hi everybody,

 

I'm trying to introduce a method that when selecting an element from the grid, it saves the id of an attribute in a variable I created and when I delete that same record it has to start a process.

However, when I run all this pops up this error.

This is the code i implemented in order to achieve this.

Thanks in advance.

 

Best regards,

Pedro Pinheiro

Like 1

Like

2 comments
Best reply

The order of the modules at the top doesn't match/line up. You have this:

define("imdSchema10Detail", ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities", "ProcessModuleUtilities"] function(ProcessModuleUtilities) {

You're actually getting ConfigurationGrid loaded into the ProcessModuleUtilities param since it's the first AMD module listed, which will go into the first param. You need to change the order to this:

define("imdSchema10Detail", ["ProcessModuleUtilities", "ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"] function(ProcessModuleUtilities) {

Ryan 

The order of the modules at the top doesn't match/line up. You have this:

define("imdSchema10Detail", ["ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities", "ProcessModuleUtilities"] function(ProcessModuleUtilities) {

You're actually getting ConfigurationGrid loaded into the ProcessModuleUtilities param since it's the first AMD module listed, which will go into the first param. You need to change the order to this:

define("imdSchema10Detail", ["ProcessModuleUtilities", "ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"] function(ProcessModuleUtilities) {

Ryan 

Ryan Farley,

​​​​​​The solution you provided is working. 

 

Thank you.

 

Best regards,

Pedro Pinheiro

Show all comments

I am facing issues with the console flooded with the web-socket errors.

I don't know which element is bugging it.

Because of this sometimes I have to hard reload (empty cache) 3 to 5 times to do my configurations of view any record after some changes in section wizard or in any object.

Like 0

Like

2 comments
Best reply

This is due to the telephony integration being turned on by default in new systems, but not set up to connect to a phone system. To get rid of all that chatter in the console, go into your profile (by clicking the person icon in the top right corner, then select "Your profile". Once there, click the "Call center parameters setup" button and check the box to "Disable phone integration". Once you log out and back in again, all of that chatter and WebSocket errors in the console will be gone.

Ryan

This is due to the telephony integration being turned on by default in new systems, but not set up to connect to a phone system. To get rid of all that chatter in the console, go into your profile (by clicking the person icon in the top right corner, then select "Your profile". Once there, click the "Call center parameters setup" button and check the box to "Disable phone integration". Once you log out and back in again, all of that chatter and WebSocket errors in the console will be gone.

Ryan

Hey Ryan,

It worked.

Thanks for the help.

Show all comments

Hi Community,

I need to fetch data from third party database and display it on edit page, is it posible to connect to third party database on edit page using client code? or what is the best approach?

Like 0

Like

1 comments

Dear Fulgen,

Unfortunately, it is not possible to connect a third-party database to the system to display its data on the edit page. As a solution you can download all the necessary data from your  third-party database and import it via basic Import tool. Here is the article that will help you out:

https://academy.bpmonline.com/documents/base/7-13/excel-data-import

One more solution - you can create your custom web service that would pull the data from a specific service into bpmonline automatically. Here is the article that might help you as well:

https://academy.bpmonline.com/documents/technic-sdk/7-13/how-create-cus…

Best regards,

Dean

Show all comments

Hi Community,

I want to call a process on the 
client side and when it ends, for example, update certain values ​​of the page. 
Is it possible using the callback? 
The callback works but the page with the caption of loading remains. I Have this example:

var someFunction = function (a) { 

                                    

                                    this.loadSchemaCaptionByName("UsrApproveBSRankedCompare", function(caption) {

                                                this._showSuccessfullyRunProcessPopup("The process has been completed");

                                            }, this);

                                    

                                };

                                this.executeProcess(args , someFunction)

 

executeProcess: function(sysProcessName, callback) {

                ProcessModuleUtilities.responseCallback = callback;

                ProcessModuleUtilities.executeProcess(sysProcessName)

            }    

 

 

Thank you!

regards

Like 0

Like

2 comments

Dear Uriel,

In order to complete your task you need to split it into two parts:

1. Launch the business process call from client side. Please see the following article and link for more details:

https://community.bpmonline.com/questions/trigger-business-process-clie…

https://academy.bpmonline.com/documents/technic-sdk/7-13/process-launch…

2. After the process executes, it needs to send the signal to the client side to proceed further with the logic. The example of such logic you can find in the following thread of our Community:

https://community.bpmonline.com/questions/refresh-page-fields-after-pro…

Regards,

Anastasia

 

Show all comments

I would like to get rid of tag button on all my pages. Is it possible to use replacing client modules to remove TagUtilitiesV2 from the list of dependencies of BasePageV2? Or maybe there's a better way to do that?

Like 0

Like

2 comments

You can write something like the code below in the BaseModulePageV2 and in the BaseSectionV2

define("AccountSectionV2", [], function() {
	return {
		entitySchemaName: "Account",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		attributes: {
			"UseTagModule": {
				dataValueType: Terrasoft.DataValueType.BOOLEAN,
				value: false
			}
		},
		methods: {},
		diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
	};
});

 

Thank you very much.

Show all comments

There are onInit and onRender methods available in client modules but neither of them runs after the page has rendered completely. Is there a method that is called after the DOM tree is ready?

Like 0

Like

14 comments

Unfortunately, there is no method that runs after everything on a page  is rendered. Please consider investigating the element that you need to use and find the way to process it after appearing.

Eugene Podkovka,

Ok, thanks for the info. Follow up question - is it fine to do something like in the code snippet below or do you think it's possible that afterRenderMethod will be called when DOM tree is not ready yet? Are parts of pages rendered after AJAX for example?

onRender: function() {
	this.callParent(arguments);
	setTimeout(afterRenderMethod);
}

 

Dear Carlos,

I would rather recommend using following events to listen for page load: DOMContentLoaded or load:

http://javascript.info/onload-ondomcontentloaded

Also,  as for your code snippet, you can achieve your goal in such way. Though, please keep in mind, that you trigger the function not based on the last element rendered, but approximate time of timeout function taken to fully render the page. Give it around 10 seconds for the timeout, so to make sure all elements have rendered.

Regards,

Anastasia

Anastasia Botezat,

Hi Anastasia,

Have the same problem here, can you show me how to use DOMContentLoaded or load in BPM client side code

Thanks

Dear Fulgen,



First of all, if your page is based on some entity, we highly recommend to use onEntityInitialized method

onEntityInitialized: function() {
    this.callParent(arguments);
    // some code
},

This method is guaranteed that not all the HTML is already loaded, but all the data is loaded to the inputs too.

In case your card is not based on the entity, and don't have onEntityInitialized method running, please use the http://javascript.info/onload-ondomcontentloaded approach provided, by writing this subscription in the init method. Something like that:

....methods block...
 
init: function() {
    this.callParent(arguments);
    document.addEventListener("DOMContentLoaded", this.htmlLoadedCallBackMethod);
},
 
htmlLoadedCallBackMethod: function() {
   alert("html loaded");
// some code here
}

Regards,

Anastasia

Dear Anastasia,

Curiously, i have tried to get "ServicePact" lookup value just calling a simple function doing : 



        methods: {

            onEntityInitialized: function() {

                this.callParent(arguments);

                this.getSlaExpertCenterId();

                document.addEventListener("DOMContentLoaded",         this.getSlaExpertCenterId());

            },

......

            getSlaExpertCenterId: function() {

                console.log(this.get("ServicePact"))

            }    

 

In each cases, console returns me "undefined"

But as you can see in picture below the input field is filled in...

 

Dear Maxime,

The reason you are getting undefined is that you haven't saved the record. In this case you have no record in the DB and SLA respectively.

Please add validation to check for empty SLA field and run your custom method in case you have SLA indicated.

If you would open already existing record, you would see the following in the browser console:

Regards,

Anastasia

Anastasia Botezat,

Ok, i still dont understand why the ServicePact is filled and we cant get is value.

Anastasia Botezat,

Hi Anastasia, I am facing the same issue, however, even when adding the listener to the init function, I am not getting my function to be called. Any thoughts?

 

Thanks.

Maxime.o,

In the example above in the screenshot I am retrieving ServicePact from already existing record. When you open a new record onEntityInitialized method runs, triggers getSLlaExpertCenterId, which tries to get ServicePact from non-existing record. The code you shared above works fine for existing records.

Danilo Lage,

It is hard to tell what exactly goes wrong without seeing the schema code itself. Please consider debugging step-bu-step your code using the developers console of your browser. There you can spot the call stack and determine where function goes wrong way.

If you will have difficulties, please share the full page code.

Anastasia Botezat,

 

 This function,

document.addEventListener("DOMContentLoaded", this.htmlLoadedCallBackMethod);

able to call from onEntityInitialized. When I am trying to call the same function in  "onRender function" (Activity Section Page) it's not been called.

How to call this function in the onRender function ?

Any ideas or thoughts over it.



Regards,

Adharsh S

Adharsh,

 

please specify your business task and also please tell us why you cannot use the base onRender or onEntityInitialized so to achieve it and need to use DOMContentLoaded additionally.

 

Thank you in advance!

 

Best regards,

Oscar

Oscar Dylan,

It appears the technique is to initialise a variable to a lookup value using an entity schema query during the 'onEntityInitialized' call and following that when the lookup value is changed 'this.get("LookupName")' returns an object with the 'Id' (the 'value' property) and 'Name' ('displayValue' property) values of the lookup.

 

For example, querying a Case object record for the initial Contact lookup value and the initial UstSubCategory lookup value:

            onEntityInitialized: function(){
                this.callParent(arguments);
                this.getSubCategoryAndContact();
            },
            getSubCategoryAndContact: function() {
				var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
				    rootSchemaName: "Case"
				});
				esq.addColumn("UsrSubCategory");
				esq.addColumn("Contact");
                window.console.log("Case Id: " + this.get("Id"));
				esq.getEntity(this.get("Id"), function (result) {
				    if (result.success) {
				        this.set("PreviousSubCategory", result.entity.values.UsrSubCategory);
				        this.set("PreviousContact", result.entity.values.Contact);
						window.console.log("result.entity.values.UsrSubCategory: " + JSON.stringify(result.entity.values.UsrSubCategory));
						window.console.log("result.entity.values.Contact: " + JSON.stringify(result.entity.values.Contact));
					}
					else {
						throw new Error("System error, unable to read 'Case' data, function 'getSubCategoryAndContact'");
					}
				}, this);
            },

After this initial code has run when the page has loaded, when the value of a lookup changes, you can then retrieve the value with 'this.get("LookupName")', for example:

		attributes: {
			"FieldChange": {
    			dependencies: [{
      				columns: ["UsrSubCategory", "Contact"],
      				methodName: "onFieldChange"
    			}]
			}
			onFieldChange: function() {
				window.console.log("In function 'onFieldChange'.");
				const field = arguments[1];
				window.console.log("'field'. " + field);
				switch (field) {
					case "UsrSubCategory":
						window.console.log("'UsrSubCategory': " +  JSON.stringify(this.get("UsrSubCategory")));
						break;
					case "Contact":
						window.console.log("Contact: " + JSON.stringify(this.get("Contact")));
						break;
					default:
						throw new Error("System error, non valid value for 'field', function 'onFieldChange'.");
				}
			},

Ref. Triggering a Client-Side Event When a Field is Changed on a Page in Creatio (formerly bpm’online)

Show all comments

Is it possible to put a button (or custom link) on the side bar, where sections are? If it's not possible with the current framework - do you think it would break something if such button was placed there using jQuery?

Like 0

Like

2 comments

Dear Carlos,

You may try add a usual custom section, put it at any workplace you want and then override init function in section module:

init: function() { window.location.href = "http://bpmonline.com"; }

After clicking on this section http://bpmonline.com page will be opened.

If everything works fine you can delete all unnecessary code created by Section Wizard leaving only the needed one to your section work properly.

You may add everything on the page using jquery but you should be careful with it. Of course you can break something if do it in a wrong way but it's related to any code that developers write.

Thank you very much, it worked.

Show all comments

Hello, 

I am wondering if anyone could help me solve this issue:

I am trying to have a calculation on the client side figure out how much time is between now (current time) and a due date set on the page.

1: I am grabbing the date from the dueDate field on the page and setting it to a variable 

2: Getting the current date and time and setting that to a variable

3 & 4: Initializing int (Number) variables via meta programming standards (not critical step)

5: set a while loop, checking if boolean/checkbox is checked off.

6: Subtracting values to find the difference with Math.abs();

7: defining the variable even further with Math.ceil();

8: Setting the value to a field on the page, with "this.set" 

This was working before I added the while() condition, am I going wrong somewhere?

I have already been trying to figure this out for 3 hours so hopefully someone can see my mistake and teach me something new, haha. 

 

Thanks, Community!

 

File attachments
Like 0

Like

3 comments

I would do something like this

define("ActivityPageV2", [], function() {
	return {
		entitySchemaName: "Activity",
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		methods: {
			onDueDateChanged: function() {
				var now = new Date();
				var dueDate = this.get("DueDate");
				var diffHrs = this.getDateDiff(now, dueDate, "hours");
				this.set("KwlString1", diffHrs.toString());
			},
			getDateDiff: function(firstDate, secondDate, identifier) {
				var diffMs = (secondDate - firstDate); // milliseconds between firstDate & secondDate
				var diffDays = Math.floor(diffMs / 1000 / 60 / 60 / 24);
				var diffHrs = Math.floor(diffMs / 1000 / 60 / 60);
				var diffMins = Math.floor(diffMs / 1000 / 60);
				switch (identifier) {
					case "milliseconds":
						return diffMs;
					case "minutes":
						return diffMins;
					case "hours":
						return diffHrs;
					case "days":
						return diffDays;
					default:
						return diffMs;
				}
			}
		},
		attributes: {
			"OnDueDateChangeAttribute": {
				dependencies: [
					{
						columns: ["DueDate"],
						methodName: "onDueDateChanged"
					}
				]
			}
		},
		rules: {},
		businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "STRING8bd032e4-6e0f-4e1c-afdb-2ecf1041382b",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 9,
						"layoutName": "Header"
					},
					"bindTo": "KwlString1",
					"enabled": true
				},
				"parentName": "Header",
				"propertyName": "items",
				"index": 17
			}
		]/**SCHEMA_DIFF*/
	};
});

 

Eugene Podkovka,

Thank you for your quick response. It works well, but I was wondering how you would modify the method to: 

  1. Only set the "diffHours" once the page is initialized.
  2. Go into a while loop checking "while a checkbox is unchecked - run loop" that would set the hours/minutes/seconds remaining every second (or n time to create a "live" feel to the process).
  3. Once checkbox is checked, stop entire process and save current time. 

I added the a while loop to check if the boolean/checkbox is false (0) and it seems to be working.

As for getting this while loop to run after initialization, this is where I am having troubles, and after going through bpm'online's and the Mozilla Foundation's Documentation I turn to you, Eugene.

methods: {
	onDueDateChanged: function() {
		var now = new Date();
		var completeTask = this.get("UsrCompleteTask");
		var dueDate = this.get("DueDate");
		var diffHrs = this.getDateDiff(now, dueDate, "minutes");
        while(completeTask == 0) {
			this.set("UsrSTRING1", diffHrs.toString());
		}
	},
	getDateDiff: function(firstDate, secondDate, identifier) {
		var diffMs = (secondDate - firstDate); // milliseconds between firstDate & secondDate
			var diffDays = Math.floor(diffMs / 1000 / 60 / 60 / 24);
			var diffHrs = Math.floor(diffMs / 1000 / 60 / 60);
			var diffMins = Math.floor(diffMs / 1000 / 60);
			switch (identifier) {
				case "milliseconds":
					return diffMs;
				case "minutes":
					return diffMins;
				case "hours":
					return diffHrs;
				case "days":
					return diffDays;
				default:
					return diffMs;
			}
		}
	},

Any knowledge on how to create this would be greatly appreciated, and thanks again on your previous response! 







 

  1. Only set the "diffHours" once the page is initialized.

Please override the "onEntityInitialized" method and set the "diffHours" there.

2. Go into a while loop checking "while a checkbox is unchecked - run loop" that would set the hours/minutes/seconds remaining every second (or n time to create a "live" feel to the process).

3. Once checkbox is checked, stop entire process and save current time. 

If you need to track when people physically work on an activity then It's a very bad idea. Just let people manage how much time they spend on a task by themselves. 

Anyway, technically it would be more correct to save a current date time value when the checkbox is checked and then save it when the checkbox is unchecked. Then calculate the difference. 

 

Show all comments