Hi Creatio Community,



Can the elements on top of the portal page on Freedom UI be deleted for portal users  only? I only want to retain the logo and the logged in user icon.



Like 0

Like

2 comments

Hello Vishal,

To do this you'll need to override MainShell then you can either remove these elements (conditionally for portal users only) or you can add CSS that is global to the application (which I think is an easier route). You can make the global CSS apply only to portal users by using the details from this article https://customerfx.com/article/applying-global-css-styles-in-the-creati…

As for overriding the MainShell, you'll need to enable the AllowCreateAngularSchema feature (you can search these forums for "AllowCreateAngularSchema" to view details on how to do this)

Ryan

Thanks Ryan

Show all comments

Is it possible within Freedom UI to trigger a refresh of the Timeline/Feed/Next Steps components using JS? We seem to have an issue where the "Enable live data update" option does not seem to be working in Creatio CRM 8.1 for our Activities on certain pages, and while we've raised a support request for this, we were trying to find a workaround by manually updating the components from code for a specific use case, but we can't see what the data source is called for these types of components. Does anybody know what it would be? I presume refreshing the PDS would refresh them, but this seems heavy handed and might end up with data being lost on the main form page while the data actually being refreshed is just a child entity, so I would expect it to have its own data source.

Like 4

Like

3 comments

+1

Hello Harvey and Damien!

In Freedom UI Pages, the structure of the page is different and along with this a new way to refresh anything on the page. In this article you can find the way to achieve your goal:

https://customerfx.com/article/refreshing-reloading-page-or-list-data-on-a-creatio-freedom-ui-page/

Here's example of handler which you can use:

handlers: /**SCHEMA_HANDLERS*/[
 {
  request: "crt.HandleViewModelAttributeChangeRequest"/* The custom implementation of the system query handler. */
  handler: async (request, next) => {
   await next?.handle(request); 
   if (request.attributeName === 'Your Attribute Name' )
   {
    const handlerChain = sdk.HandlerChainService.instance;
    await handlerChain.process({
     type: 'crt.LoadDataRequest', $context: request.$context,
     config: { loadType: 'reload' },
    dataSourceName: 'Data Source Of Obj You Want To Refresh'
    });   
   }
  }
 },

You may also find this article useful:

https://customerfx.com/article/receiving-server-side-messages-in-a-creatio-freedom-ui-page/

 

Anhelina,

 

How can we find what the data source is for a component like a Timeline or Next Steps component though? The article suggests looking at the modelConfig elements in the page code, but none of these seem to relate to the timeline or timeline tiles. I expect there is some data source being created behind the scenes but finding out what it's called is the main problem for applying the theory of being able to reload anything on the page as is suggested.

 

Many thanks,

Harvey

Show all comments

Hi Creatio Community,

 

I've been trying to create custom Actions dropdown button (not FreedomUI) and I can't seem to be able to find working documentation for it or get something similar to it.  Would like your help for it.





 

Here are a couple of documentations I've tried out (First one is not working while the second one isn't exactly what we want):

 

1. https://community.creatio.com/questions/add-custom-buttons-actionbutton…



2. https://community.creatio.com/articles/how-create-and-popualte-drop-dow…

 

Thanks in advance.

 

Regards,

Abilash.S

Like 0

Like

3 comments
Best reply

Abilash,

 

Hi,

 

The task is to copy the logic of the existing "Actions" button and apply the same to the custom button. To do that (tested in the "Opportunity" section):

 

1) In the OpportunitySectionV2 section schema:

 

1.1) Add the CombinedModeCustomActionsButtonMenuItems attribute of the "Collection" dataValueType (Terrasoft.DataValueType.COLLECTION). The example is CombinedModeActionsButtonMenuItems from BaseDataView.

1.2) Create a PTP "GetCardActionsCustom" message with the SUBSCRIBE direction (as done on the BasePageV2)

1.3) In the subscribeSandboxEvents method subscribe to the "GetCardActionsCustom" message and trigger the initCustomActionButtonMenu method when the "GetCardActionsCustom" message is received (as done for the "GetCardActions" message on the BasePageV2)

1.4) Create an extension of the _initCollections method (as done for the basic "Actions" button)

1.5) Add an empty prepareCustomActionsButtonMenuItems function to methods (as done for prepareActionsButtonMenuItems method in BaseDataView)

1.6) Add the initCustomActionButtonMenu method which is a handler for the "GetCardActionsCustom" message (as done with the initActionButtonMenu method from BaseDataView).

1.7) Add the button itself to the diff array

 

The complete schema of OpportunitySectionV2:

define("OpportunitySectionV2", [], function() {
	return {
		entitySchemaName: "Opportunity",
		attributes: {
 
			"CombinedModeCustomActionsButtonMenuItems": {
				dataValueType: Terrasoft.DataValueType.COLLECTION
			}
		},
		messages: {
 
			"GetCardActionsCustom": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.SUBSCRIBE
			}
		},
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "CustomActionsButton",
				"parentName": "CombinedModeActionButtonsCardLeftContainer",
				"propertyName": "items",
				"values": {
					"itemType": Terrasoft.ViewItemType.BUTTON,
					"caption": {"bindTo": "Resources.Strings.CustomActionsButtonCaption"},
					"classes": {
						"textClass": ["actions-button-margin-right"],
						"wrapperClass": ["actions-button-margin-right"]
					},
					"prepareMenu": {"bindTo": "prepareCustomActionsButtonMenuItems"},
					"menu": {"items": {"bindTo": "CombinedModeCustomActionsButtonMenuItems"}}
				}
			},
		]/**SCHEMA_DIFF*/,
		methods: {
 
			subscribeSandboxEvents: function() {
				this.callParent(arguments);
				const cardModuleSandboxId = this.getCardModuleSandboxId();
				this.sandbox.subscribe("GetCardActionsCustom", function(actionMenuItems) {
					this.initCustomActionButtonMenu("Combined", actionMenuItems);
				}, this, [cardModuleSandboxId]);
			},
 
			prepareCustomActionsButtonMenuItems: Ext.emptyFn,
 
			_initCollections: function() {
				this.callParent(arguments);
				this.set("CombinedModeCustomActionsButtonMenuItems", this.Ext.create("Terrasoft.BaseViewModelCollection"));
			},
 
			initCustomActionButtonMenu: function(modeType, actionMenuItems) {
				const collectionName = modeType + "ModeCustomActionsButtonMenuItems";
				const collection = this.get(collectionName);
				if (actionMenuItems.getCount()) {
					this.set(modeType + "ModeActionsButtonVisible", true);
					const newCollection = this.Ext.create("Terrasoft.BaseViewModelCollection");
					actionMenuItems.each(function(item) {
						newCollection.addItem(item);
					}, this);
					if (collection) {
						collection.clear();
						collection.loadAll(newCollection);
					} else {
						this.set(collectionName, newCollection);
					}
				} else {
					this.set(modeType + "ModeActionsButtonVisible", false);
				}
			},
		}
	};
});

2) In OpportunityPageV2:

 

2.1) Create the "GetCardActionsCustom" message (as done for the "GetCardActions" existing message)

2.2) In the init method call the initCustomActionButtonMenu method

2.3) Create the initCustomActionButtonMenu method (as done for the initActionButtonMenu in BasePageV2)

2.4) Create the getCustomActions method (as done with the getActions method in the basic OpportunityPageV2 with only difference that you don't need to call parent method but create an instance of the Terrasoft.BaseViewModelCollection here)

2.5) Add the button itself to the diff array

 

The complete code is:

define("OpportunityPageV2", [], function() {
	return {
		entitySchemaName: "Opportunity",
		attributes: {},
		messages: {
			"GetCardActionsCustom": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.PUBLISH
			}
		},
		modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		details: /**SCHEMA_DETAILS*/{
			"UsrSchemaf6483d73Detaile560e0a4": {
				"schemaName": "UsrSchemaf6483d73Detail",
				"entitySchemaName": "UsrOppTestDet",
				"filter": {
					"detailColumn": "UsrOpportunity",
					"masterColumn": "Id"
				}
			}
		}/**SCHEMA_DETAILS*/,
		businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/,
		methods: {
 
			init: function() {
				this.callParent(arguments);
				this.initCustomActionButtonMenu();
			},
 
			initCustomActionButtonMenu: function() {
				this.publishPropertyValueToSection("IsCardInEditMode", this.isEditMode());
				var actionMenuItems = this.getCustomActions();
				var actionsButtonVisible = !actionMenuItems.isEmpty();
				this.set("CustomActionsButtonVisible", actionsButtonVisible);
				this.set("CustomActionsButtonMenuItems", actionMenuItems);
				this.sandbox.publish("GetCardActionsCustom", actionMenuItems, [this.sandbox.id]);
			},
 
			getCustomActions: function() {
				var actionMenuItems = this.Ext.create("Terrasoft.BaseViewModelCollection");
				actionMenuItems.addItem(this.getButtonMenuItem({
					"Caption": {"bindTo": "Resources.Strings.CustomButtonCaption"},
					"Tag": "clickCustomButton"
				}));
				return actionMenuItems;
			}
		},
		dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"parentName": "LeftContainer",
				"propertyName": "items",
				"name": "actions",
				"values": {
					"itemType": Terrasoft.ViewItemType.BUTTON,
					"caption": {"bindTo": "Resources.Strings.CustomButtonCaption"},
					"classes": {
						"textClass": ["actions-button-margin-right"],
						"wrapperClass": ["actions-button-margin-right"]
					},
					"menu": {
						"items": {"bindTo": "CustomActionsButtonMenuItems"}
					},
					"visible": {"bindTo": "CustomActionsButtonVisible"}
				}
			},
			{
				"operation": "merge",
				"name": "MetricsContainer",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityClient",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 1
					}
				}
			},
			{
				"operation": "remove",
				"name": "OpportunityClient",
				"properties": [
					"tip"
				]
			},
			{
				"operation": "merge",
				"name": "LablelMetricsContainer",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "BantProfileHeaderContainer",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "BantIcon",
				"values": {
					"layout": {
						"colSpan": 5,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "BantHeaderCaption",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 5,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityBudget",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 1
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityDecisionMaker",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityLeadType",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 3
					}
				}
			},
			{
				"operation": "move",
				"name": "OpportunityLeadType",
				"parentName": "BantProfile",
				"propertyName": "items",
				"index": 3
			},
			{
				"operation": "merge",
				"name": "OpportunityDueDate",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 4
					}
				}
			},
			{
				"operation": "merge",
				"name": "ESNTab",
				"values": {
					"order": 8
				}
			},
			{
				"operation": "merge",
				"name": "GeneralInfoTab",
				"values": {
					"order": 0
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityTitle",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "Amount",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 3
					}
				}
			},
			{
				"operation": "merge",
				"name": "ResponsibleDepartment",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 3
					}
				}
			},
			{
				"operation": "move",
				"name": "ResponsibleDepartment",
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 3
			},
			{
				"operation": "merge",
				"name": "Probability",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 4
					}
				}
			},
			{
				"operation": "merge",
				"name": "Owner",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 4
					}
				}
			},
			{
				"operation": "merge",
				"name": "Category",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 5
					}
				}
			},
			{
				"operation": "merge",
				"name": "Source",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 5
					}
				}
			},
			{
				"operation": "merge",
				"name": "Type",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 6
					}
				}
			},
			{
				"operation": "move",
				"name": "Type",
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 8
			},
			{
				"operation": "merge",
				"name": "CreatedOn",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 6
					}
				}
			},
			{
				"operation": "merge",
				"name": "Partner",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 7
					}
				}
			},
			{
				"operation": "merge",
				"name": "CloseReason",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 7
					}
				}
			},
			{
				"operation": "insert",
				"name": "DATETIME26d46360-17b4-45ee-acac-da084cf0aa67",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 8,
						"layoutName": "OpportunityPageGeneralBlock"
					},
					"bindTo": "UsrTestDateTime",
					"enabled": true
				},
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 12
			},
			{
				"operation": "merge",
				"name": "Description",
				"values": {
					"layout": {
						"colSpan": 23,
						"rowSpan": 1,
						"column": 1,
						"row": 0
					}
				}
			},
			{
				"operation": "insert",
				"name": "UsrSchemaf6483d73Detaile560e0a4",
				"values": {
					"itemType": 2,
					"markerValue": "added-detail"
				},
				"parentName": "GeneralInfoTab",
				"propertyName": "items",
				"index": 5
			},
			{
				"operation": "merge",
				"name": "LeadTab",
				"values": {
					"order": 4
				}
			},
			{
				"operation": "merge",
				"name": "TacticAndCompetitorTab",
				"values": {
					"order": 1
				}
			},
			{
				"operation": "merge",
				"name": "CheckDate",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "ProductsTab",
				"values": {
					"order": 2
				}
			},
			{
				"operation": "merge",
				"name": "HistoryTab",
				"values": {
					"order": 5
				}
			},
			{
				"operation": "merge",
				"name": "HistoryAccountTab",
				"values": {
					"order": 6
				}
			},
			{
				"operation": "merge",
				"name": "NotesTab",
				"values": {
					"order": 7
				}
			},
			{
				"operation": "move",
				"name": "IsPrimary",
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 0
			}
		]/**SCHEMA_DIFF*/
	};
});

As a result when opening the page you will get a custom button with items:

Also forgot to metion that you need to add localizable strings:

 

1) For OpportunityPageV2

 

CustomButtonCaption with "Custom action" value

 

2) For OpportunitySectionV2

 

CustomButtonCaption with "Custom button" value

 

Hope this example help!

 

 

Hello,



Could you please write in more detail, regarding the first option that suits you, what exactly are the difficulties you encountered? 

Malika,

Hello, 



Currently, I'm just getting a button with no dropdown like this







Here's the code for it:





//I've tried two different approaches for the method (both didn't work) based on the above two documentation

methods: {





//approach1



prepareMyActionsButtonMenuItems: function(filter, list) {

                if (list === null) {

                    return;

                }

                list.clear();

                var columns = {};

 

                var value1 = {

                    displayValue: "a123",

                    value: "1"

                };

                var value2 = {

                    displayValue: "b234",

                    value: "2"

                };

                var value3 = {

                    displayValue: "c345",

                    value: "3"

                };

 

                columns[1] = value1;

                columns[2] = value2;

                columns[3] = value3;

 

                list.loadAll(columns);

            },



//approach 2



prepareMyActionsButtonMenuItems: function(){

                this.set("MyActionsButtonMenuItems", ["Sample", "test", "Test5"]);

            }



}





attributes: {



              "MyActionsButtonMenuItems": {

                dataValueType: Terrasoft.DataValueType.COLLECTION,

              }

}



diff:[

{

                "operation": "insert",

                "name": "MyActionsButton",

                "parentName": "RightContainer",

                "propertyName": "items",

                "values": {

                      "itemType": Terrasoft.ViewItemType.BUTTON,

                      "caption": "MyActionsButton",

                      "classes": {

                        "textClass": ["actions-button-margin-right"],

                        "wrapperClass": ["actions-button-margin-right"]

                      },

                      "prepareMenu": {"bindTo": "prepareMyActionsButtonMenuItems"},

                      "menu": {"items": {"bindTo": "MyActionsButtonMenuItems"}},

                      "visible": true

                }

              }

]

Abilash,

 

Hi,

 

The task is to copy the logic of the existing "Actions" button and apply the same to the custom button. To do that (tested in the "Opportunity" section):

 

1) In the OpportunitySectionV2 section schema:

 

1.1) Add the CombinedModeCustomActionsButtonMenuItems attribute of the "Collection" dataValueType (Terrasoft.DataValueType.COLLECTION). The example is CombinedModeActionsButtonMenuItems from BaseDataView.

1.2) Create a PTP "GetCardActionsCustom" message with the SUBSCRIBE direction (as done on the BasePageV2)

1.3) In the subscribeSandboxEvents method subscribe to the "GetCardActionsCustom" message and trigger the initCustomActionButtonMenu method when the "GetCardActionsCustom" message is received (as done for the "GetCardActions" message on the BasePageV2)

1.4) Create an extension of the _initCollections method (as done for the basic "Actions" button)

1.5) Add an empty prepareCustomActionsButtonMenuItems function to methods (as done for prepareActionsButtonMenuItems method in BaseDataView)

1.6) Add the initCustomActionButtonMenu method which is a handler for the "GetCardActionsCustom" message (as done with the initActionButtonMenu method from BaseDataView).

1.7) Add the button itself to the diff array

 

The complete schema of OpportunitySectionV2:

define("OpportunitySectionV2", [], function() {
	return {
		entitySchemaName: "Opportunity",
		attributes: {
 
			"CombinedModeCustomActionsButtonMenuItems": {
				dataValueType: Terrasoft.DataValueType.COLLECTION
			}
		},
		messages: {
 
			"GetCardActionsCustom": {
				mode: Terrasoft.MessageMode.PTP,
				direction: Terrasoft.MessageDirectionType.SUBSCRIBE
			}
		},
		details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"name": "CustomActionsButton",
				"parentName": "CombinedModeActionButtonsCardLeftContainer",
				"propertyName": "items",
				"values": {
					"itemType": Terrasoft.ViewItemType.BUTTON,
					"caption": {"bindTo": "Resources.Strings.CustomActionsButtonCaption"},
					"classes": {
						"textClass": ["actions-button-margin-right"],
						"wrapperClass": ["actions-button-margin-right"]
					},
					"prepareMenu": {"bindTo": "prepareCustomActionsButtonMenuItems"},
					"menu": {"items": {"bindTo": "CombinedModeCustomActionsButtonMenuItems"}}
				}
			},
		]/**SCHEMA_DIFF*/,
		methods: {
 
			subscribeSandboxEvents: function() {
				this.callParent(arguments);
				const cardModuleSandboxId = this.getCardModuleSandboxId();
				this.sandbox.subscribe("GetCardActionsCustom", function(actionMenuItems) {
					this.initCustomActionButtonMenu("Combined", actionMenuItems);
				}, this, [cardModuleSandboxId]);
			},
 
			prepareCustomActionsButtonMenuItems: Ext.emptyFn,
 
			_initCollections: function() {
				this.callParent(arguments);
				this.set("CombinedModeCustomActionsButtonMenuItems", this.Ext.create("Terrasoft.BaseViewModelCollection"));
			},
 
			initCustomActionButtonMenu: function(modeType, actionMenuItems) {
				const collectionName = modeType + "ModeCustomActionsButtonMenuItems";
				const collection = this.get(collectionName);
				if (actionMenuItems.getCount()) {
					this.set(modeType + "ModeActionsButtonVisible", true);
					const newCollection = this.Ext.create("Terrasoft.BaseViewModelCollection");
					actionMenuItems.each(function(item) {
						newCollection.addItem(item);
					}, this);
					if (collection) {
						collection.clear();
						collection.loadAll(newCollection);
					} else {
						this.set(collectionName, newCollection);
					}
				} else {
					this.set(modeType + "ModeActionsButtonVisible", false);
				}
			},
		}
	};
});

2) In OpportunityPageV2:

 

2.1) Create the "GetCardActionsCustom" message (as done for the "GetCardActions" existing message)

2.2) In the init method call the initCustomActionButtonMenu method

2.3) Create the initCustomActionButtonMenu method (as done for the initActionButtonMenu in BasePageV2)

2.4) Create the getCustomActions method (as done with the getActions method in the basic OpportunityPageV2 with only difference that you don't need to call parent method but create an instance of the Terrasoft.BaseViewModelCollection here)

2.5) Add the button itself to the diff array

 

The complete code is:

define("OpportunityPageV2", [], function() {
	return {
		entitySchemaName: "Opportunity",
		attributes: {},
		messages: {
			"GetCardActionsCustom": {
				mode: this.Terrasoft.MessageMode.PTP,
				direction: this.Terrasoft.MessageDirectionType.PUBLISH
			}
		},
		modules: /**SCHEMA_MODULES*/{}/**SCHEMA_MODULES*/,
		details: /**SCHEMA_DETAILS*/{
			"UsrSchemaf6483d73Detaile560e0a4": {
				"schemaName": "UsrSchemaf6483d73Detail",
				"entitySchemaName": "UsrOppTestDet",
				"filter": {
					"detailColumn": "UsrOpportunity",
					"masterColumn": "Id"
				}
			}
		}/**SCHEMA_DETAILS*/,
		businessRules: /**SCHEMA_BUSINESS_RULES*/{}/**SCHEMA_BUSINESS_RULES*/,
		methods: {
 
			init: function() {
				this.callParent(arguments);
				this.initCustomActionButtonMenu();
			},
 
			initCustomActionButtonMenu: function() {
				this.publishPropertyValueToSection("IsCardInEditMode", this.isEditMode());
				var actionMenuItems = this.getCustomActions();
				var actionsButtonVisible = !actionMenuItems.isEmpty();
				this.set("CustomActionsButtonVisible", actionsButtonVisible);
				this.set("CustomActionsButtonMenuItems", actionMenuItems);
				this.sandbox.publish("GetCardActionsCustom", actionMenuItems, [this.sandbox.id]);
			},
 
			getCustomActions: function() {
				var actionMenuItems = this.Ext.create("Terrasoft.BaseViewModelCollection");
				actionMenuItems.addItem(this.getButtonMenuItem({
					"Caption": {"bindTo": "Resources.Strings.CustomButtonCaption"},
					"Tag": "clickCustomButton"
				}));
				return actionMenuItems;
			}
		},
		dataModels: /**SCHEMA_DATA_MODELS*/{}/**SCHEMA_DATA_MODELS*/,
		diff: /**SCHEMA_DIFF*/[
			{
				"operation": "insert",
				"parentName": "LeftContainer",
				"propertyName": "items",
				"name": "actions",
				"values": {
					"itemType": Terrasoft.ViewItemType.BUTTON,
					"caption": {"bindTo": "Resources.Strings.CustomButtonCaption"},
					"classes": {
						"textClass": ["actions-button-margin-right"],
						"wrapperClass": ["actions-button-margin-right"]
					},
					"menu": {
						"items": {"bindTo": "CustomActionsButtonMenuItems"}
					},
					"visible": {"bindTo": "CustomActionsButtonVisible"}
				}
			},
			{
				"operation": "merge",
				"name": "MetricsContainer",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityClient",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 1
					}
				}
			},
			{
				"operation": "remove",
				"name": "OpportunityClient",
				"properties": [
					"tip"
				]
			},
			{
				"operation": "merge",
				"name": "LablelMetricsContainer",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "BantProfileHeaderContainer",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "BantIcon",
				"values": {
					"layout": {
						"colSpan": 5,
						"rowSpan": 1,
						"column": 0,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "BantHeaderCaption",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 5,
						"row": 0
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityBudget",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 1
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityDecisionMaker",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityLeadType",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 3
					}
				}
			},
			{
				"operation": "move",
				"name": "OpportunityLeadType",
				"parentName": "BantProfile",
				"propertyName": "items",
				"index": 3
			},
			{
				"operation": "merge",
				"name": "OpportunityDueDate",
				"values": {
					"layout": {
						"colSpan": 19,
						"rowSpan": 1,
						"column": 5,
						"row": 4
					}
				}
			},
			{
				"operation": "merge",
				"name": "ESNTab",
				"values": {
					"order": 8
				}
			},
			{
				"operation": "merge",
				"name": "GeneralInfoTab",
				"values": {
					"order": 0
				}
			},
			{
				"operation": "merge",
				"name": "OpportunityTitle",
				"values": {
					"layout": {
						"colSpan": 24,
						"rowSpan": 1,
						"column": 0,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "Amount",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 3
					}
				}
			},
			{
				"operation": "merge",
				"name": "ResponsibleDepartment",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 3
					}
				}
			},
			{
				"operation": "move",
				"name": "ResponsibleDepartment",
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 3
			},
			{
				"operation": "merge",
				"name": "Probability",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 4
					}
				}
			},
			{
				"operation": "merge",
				"name": "Owner",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 4
					}
				}
			},
			{
				"operation": "merge",
				"name": "Category",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 5
					}
				}
			},
			{
				"operation": "merge",
				"name": "Source",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 5
					}
				}
			},
			{
				"operation": "merge",
				"name": "Type",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 6
					}
				}
			},
			{
				"operation": "move",
				"name": "Type",
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 8
			},
			{
				"operation": "merge",
				"name": "CreatedOn",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 6
					}
				}
			},
			{
				"operation": "merge",
				"name": "Partner",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 7
					}
				}
			},
			{
				"operation": "merge",
				"name": "CloseReason",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 7
					}
				}
			},
			{
				"operation": "insert",
				"name": "DATETIME26d46360-17b4-45ee-acac-da084cf0aa67",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 0,
						"row": 8,
						"layoutName": "OpportunityPageGeneralBlock"
					},
					"bindTo": "UsrTestDateTime",
					"enabled": true
				},
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 12
			},
			{
				"operation": "merge",
				"name": "Description",
				"values": {
					"layout": {
						"colSpan": 23,
						"rowSpan": 1,
						"column": 1,
						"row": 0
					}
				}
			},
			{
				"operation": "insert",
				"name": "UsrSchemaf6483d73Detaile560e0a4",
				"values": {
					"itemType": 2,
					"markerValue": "added-detail"
				},
				"parentName": "GeneralInfoTab",
				"propertyName": "items",
				"index": 5
			},
			{
				"operation": "merge",
				"name": "LeadTab",
				"values": {
					"order": 4
				}
			},
			{
				"operation": "merge",
				"name": "TacticAndCompetitorTab",
				"values": {
					"order": 1
				}
			},
			{
				"operation": "merge",
				"name": "CheckDate",
				"values": {
					"layout": {
						"colSpan": 12,
						"rowSpan": 1,
						"column": 12,
						"row": 2
					}
				}
			},
			{
				"operation": "merge",
				"name": "ProductsTab",
				"values": {
					"order": 2
				}
			},
			{
				"operation": "merge",
				"name": "HistoryTab",
				"values": {
					"order": 5
				}
			},
			{
				"operation": "merge",
				"name": "HistoryAccountTab",
				"values": {
					"order": 6
				}
			},
			{
				"operation": "merge",
				"name": "NotesTab",
				"values": {
					"order": 7
				}
			},
			{
				"operation": "move",
				"name": "IsPrimary",
				"parentName": "OpportunityPageGeneralBlock",
				"propertyName": "items",
				"index": 0
			}
		]/**SCHEMA_DIFF*/
	};
});

As a result when opening the page you will get a custom button with items:

Also forgot to metion that you need to add localizable strings:

 

1) For OpportunityPageV2

 

CustomButtonCaption with "Custom action" value

 

2) For OpportunitySectionV2

 

CustomButtonCaption with "Custom button" value

 

Hope this example help!

 

 

Show all comments

How can we apply custom filters on Lookups in Freedom UI? I can see that there is some existence of a filtersConfig potential property for the object passed as the first parameter to executeRequest, but cannot find any examples or information on how this should be configured in Academy or on other Community questions. We are trying to use this to associate records to a parent record using the + button on a Freedom UI "detail" list, but we don't want any records already associated with any parent by foreign key to be eligible for association using the lookup, and also have some other conditions to apply based on the child entity. Our environment is currently on 8.1 Quantum.

 

Here is the relevant excerpt from the handler on our form page, without any filters applied and with the non-relevant logic applied in the afterClosed area removed for brevity:

request.$context.executeRequest({
	type: "crt.OpenLookupPageRequest",
	$context: request.$context,
	entitySchemaName: "Order",
	caption: "Select Quotes to associate with the Lead",
	features: {
		select: {
			multiple: true,
			selectAll: false,
			resultType: 'lookupValues'
		},
		create: {
			enabled: false
		}
	},
	afterClosed: async function(selectedItems) {
		// logic here
		return next?.handle(request)
	}
});

 

Like 0

Like

5 comments
Best reply

Hello,

Here is an example of OpenLookupPageRequest with a filtersConfig.

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "usr.OpenLookupRequest",
				handler: async (request, next) => {
					devkit.HandlerChainService.instance.process({
						type: "crt.OpenLookupPageRequest",
						scopes: [...request.scopes],
						$context: request.$context,
						entitySchemaName: "Contact",
						// caption: 'Responsible',
						schemaName: 'CustomLookupPage',
						itemAttributeName: 'LookupAttribute_2mnilrq',
						// itemsAttributeName: 'Contact_List',
						afterClosed: (result) => {
							alert(result?.displayValue ?? '');
						},
						filtersConfig: {
							filterAttributes: [
								{
									name: 'MyFilter',
									loadOnChange: false
								}
							],
							attributesConfig: {
								MyFilter: {
									value: {
										"items": {
											"29e16d42-36f1-4e04-9029-4321cbb2494d": {
												"filterType": 1,
												"comparisonType": 11,
												"isEnabled": true,
												"trimDateTimeParameterToDate": false,
												"leftExpression": {
													"expressionType": 0,
													"columnPath": "Name"
												},
												"isAggregative": false,
												"dataValueType": 1,
												"rightExpression": {
													"expressionType": 2,
													"parameter": {
														"dataValueType": 1,
														"value": "Super"
													}
												}
											}
										},
										"logicalOperation": 0,
										"isEnabled": true,
										"filterType": 6,
										"rootSchemaName": "Contact"
									}
								}
							}
						}
					});
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

If you don't know how to build a proper filter here is a small tip. On a Freedom UI page add a list with the object you want to filter. In this list add a static filter with a condition you want to apply to a OpenLookupPageRequest and save it. As a result, in the code of this page, you can find the full filter code, all you need to do is to replace "MyFilter" with it.

Hello,

Here is an example of OpenLookupPageRequest with a filtersConfig.

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "usr.OpenLookupRequest",
				handler: async (request, next) => {
					devkit.HandlerChainService.instance.process({
						type: "crt.OpenLookupPageRequest",
						scopes: [...request.scopes],
						$context: request.$context,
						entitySchemaName: "Contact",
						// caption: 'Responsible',
						schemaName: 'CustomLookupPage',
						itemAttributeName: 'LookupAttribute_2mnilrq',
						// itemsAttributeName: 'Contact_List',
						afterClosed: (result) => {
							alert(result?.displayValue ?? '');
						},
						filtersConfig: {
							filterAttributes: [
								{
									name: 'MyFilter',
									loadOnChange: false
								}
							],
							attributesConfig: {
								MyFilter: {
									value: {
										"items": {
											"29e16d42-36f1-4e04-9029-4321cbb2494d": {
												"filterType": 1,
												"comparisonType": 11,
												"isEnabled": true,
												"trimDateTimeParameterToDate": false,
												"leftExpression": {
													"expressionType": 0,
													"columnPath": "Name"
												},
												"isAggregative": false,
												"dataValueType": 1,
												"rightExpression": {
													"expressionType": 2,
													"parameter": {
														"dataValueType": 1,
														"value": "Super"
													}
												}
											}
										},
										"logicalOperation": 0,
										"isEnabled": true,
										"filterType": 6,
										"rootSchemaName": "Contact"
									}
								}
							}
						}
					});
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

If you don't know how to build a proper filter here is a small tip. On a Freedom UI page add a list with the object you want to filter. In this list add a static filter with a condition you want to apply to a OpenLookupPageRequest and save it. As a result, in the code of this page, you can find the full filter code, all you need to do is to replace "MyFilter" with it.

Question on OpenLookupPageRequest. In an edit scenario, could you pass the already selected options so that they appear already selected in the lookup list?

You can use the option selectionState to predefine selected rows, which will be pre-selected

type: "crt.OpenLookupPageRequest",
	...
	selectionState: {
		type: 'specific',
		selected: [
			'9d06bf9f-eb7a-4849-b83d-cbba994f185d',
			'49ba9a9e-2e28-48cb-b1bc-81b7871acb9d',
		],
	},

 

Dmytro Vovchenko,

 

Those are really useful, are there any other parameters that can be passed to the newly opened lookup page? I'm currently looking for a way to automatically set the initial search value of the lookup window, but I'm sure there are many other undocumented useful parameters like the selectionState that can be passed to a lookup page when opening it. A generic way to pass data into the page would be great!

 

I looked into passing a defaultSearchValue parameter into the request, but it didn't seem to affect the modal lookup.

Harvey Adcock,

 

Hello,

 

Here is all the available documentation we have:

 

Lookup window example:

In order to open the lookup window, you have to use crt.OpenSelectionWindowRequest

/**
 * @publicApi
 */
@CrtRequest({
    type: 'crt.OpenSelectionWindowRequest',
})
export class OpenSelectionWindowRequest extends BaseRequest {
    public itemAttributeName?: string;
    public itemsAttributeName?: string;
    /**
     * @publicApi
     */
    public entitySchemaName?: string;
    /**
     * @publicApi
     */
    public schemaName?: string;
    /**
     * @publicApi
     */
    public filtersConfig?: FiltersConfig;
    /**
     * @publicApi
     */
    public features?: PageLookupFeatures;
    /**
     * @publicApi
     */
    public selectionState?: SelectionState;
    /**
     * @publicApi
     */
    public afterClosed?: (result: SelectionWindowResult) => void;
    /**
     * @publicApi
     */
    public caption?: LocalizableString;
}

Add the following code to your custom handler:

handlers: /**SCHEMA_HANDLERS*/[
			{
				request: "usr.OpenLookupRequest",
				handler: async (request, next) => {
					devkit.HandlerChainService.instance.process({
						type: "crt.OpenSelectionWindowRequest",
						scopes: [...request.scopes],
						$context: request.$context,
						entitySchemaName: "Contact",
						// caption: 'Responsible',
						schemaName: 'CustomLookupPage',
						itemAttributeName: 'LookupAttribute_2mnilrq',
						// itemsAttributeName: 'Contact_List',
						afterClosed: async (result) => {
							if (!result.canceled) {
								const lookupValues = await result.getLookupValues();
								const value = lookupValues[0];
								if (value) {
									alert(value?.displayValue ?? '');
								}
							}
						},
						filtersConfig: {
							filterAttributes: [
								{
									name: 'MyFilter',
									loadOnChange: false
								}
							],
							attributesConfig: {
								MyFilter: {
									value: {
										"items": {
											"29e16d42-36f1-4e04-9029-4321cbb2494d": {
												"filterType": 1,
												"comparisonType": 11,
												"isEnabled": true,
												"trimDateTimeParameterToDate": false,
												"leftExpression": {
													"expressionType": 0,
													"columnPath": "Name"
												},
												"isAggregative": false,
												"dataValueType": 1,
												"rightExpression": {
													"expressionType": 2,
													"parameter": {
														"dataValueType": 1,
														"value": "Super"
													}
												}
											}
										},
										"logicalOperation": 0,
										"isEnabled": true,
										"filterType": 6,
										"rootSchemaName": "Contact"
									}
								}
							}
						}
					});
					return next?.handle(request);
				}
			}
		]/**SCHEMA_HANDLERS*/,

where

 

entitySchemaName - the name of the entity schema whose data is displayed in the lookup window. Optional parameter. If not specified, the data source is taken from the attribute specified in itemAttributeName

 

caption - optional parameter, displayed in the window title. If caption is not specified, the caption is taken from the attribute specified in the itemAttributeName parameter. If itemAttributeName is not specified, then from the entity schema.

 

schemaName - the name of the schema that is displayed in the lookup window. Optional parameter. Default is BaseLookupPageTemplate

 

itemAttributeName - the name of the attribute from which the title is taken, the name of the entity schema and in which the result of the selection in the window will be written. Optional parameter. As a rule, this is the attribute with which the Combobox control is associated.

 

itemsAttributeName - the name of the attribute from which the data source name is taken. Optional parameter.

 

afterClosed - callback function returning the result of the selection in the window. Optional parameter.

 

filtersConfig-  describes the filter to be applied to the data. Optional parameter

 

PageLookupFeatures

 

Additionally, the user can specify additional features for the selection window.

export interface PageLookupFeatures {
    create?: {
        enabled: boolean;                         // false by default
    };
    select: {
        multiple: boolean;                        // false by default
        selectAll: boolean;                       // false by default
    };
    showDeactivatedRecords?: boolean;
}

 

The user should provide the Create option as enabled to display the New button in the selection window (only for the FreedomUI host).

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	"features": {
		"create": {
            "enabled": true;
        }
	}
});

 

The New button in this window works best only in the Freedom UI shell. In the Classic UI, new record will be created, but the selection window will close after saving it without passing the created record selected value. If you want to use this window in the Classic UI, please consider it, or don’t show this button there.

 

SelectionWindowResult  type

export class SelectionWindowResult {
    canceled: boolean; // indicates whether selection window was canceled by user
    filter: FilterMetadata; // Filter 
    async getLookupValues(options?: { pagingConfig: DataSourcePagingConfig }): Promise<LookupValue[]>; // method to get lookup values
}

where DataSourcePagingConfig is 

interface DataSourcePagingConfig {
    rowsOffset: number;
    rowCount: number;
}

example

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	"features": {
		"select": {
            "multiple": true;
        }
	},
	afterClosed: async (selectionWindowResult) => {
		const filter = selectionWindowResult.filter // getting filter
		// or 
		const lookupValues = await selectionWindowResult.getLookupValues(); // getting lookupValues
	}
});

 

Multiselection mode

 

To enable multiselection mode user should add next feature to OpenPageLookupRequest

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
            "multiple": true
        }
	}
});

So afterClosed will look like this 

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: async (selectionWindowResult) => {
		const lookupValues = await selectionWindowResult.getLookupValues();
		// do something with lookup values
	}
});

 

Select all


To enable the ability to select all records, you should add the next features to OpenPageLookupRequest.

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
            multiple: true,
            selectAll: true
        }
	}
});

 

Canceled
 

Handling cases when the user presses the cancels Selection window

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: (selectionWindowResult) => {
		const canceled = selectionWindowResult.canceled;
		if (canceled) {
			// do some logic when user canceled selection window
		}
	}
});

 

Selecting a special set of values


getLookupValues could be called with paging config where user can specify rowsOffset and rowCount to get a specific list of values

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: async (selectionWindowResult) => {
		const pagingConfig = {
			rowsOffset: 2,
			rowCount: 2
		}
		const lookupValues = await selectionWindowResult.getLookupValues({ pagingConfig });
		// do something with received lookup values
	}
});

Example of iterating through lookupValues. Getting pair of 2 lookupValues with step of 2

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	scopes: [...request.scopes],
	$context: request.$context,
	....
	features: {
		select: {
			multiple: true
		}
	},
	afterClosed: async (selectionWindowResult) => {
		let rowsOffset = 0;
        const rowCount = 2;
        const pagingConfig = { rowsOffset, rowCount };
        let lookupValues = await selectionWindowResult.getLookupValues({ pagingConfig });
        while (lookupValues.length) {
            /*
              fn(lookupValues); // do something with received lookupValues pair
            */
            rowsOffset += 2;
            lookupValues = await selectionWindowResult.getLookupValues({ pagingConfig: { rowsOffset, rowCount }});
        }
        if (!lookupValues.length) {
            /*
              Do some logic here on end of list - when there are no more lookupValues
            */
        }
	}
});

 

Selection state


and SelectionState is:

{
    type: 'specific';
    selected: unknown[]; // array of id's
}

 

So user can predefine selected rows, which will be pre-selected

devkit.HandlerChainService.instance.process({
	type: "crt.OpenSelectionWindowRequest",
	...
	selectionState: {
		type: 'specific',
		selected: [
			'9d06bf9f-eb7a-4849-b83d-cbba994f185d',
			'49ba9a9e-2e28-48cb-b1bc-81b7871acb9d',
		],
	},
});

 

showDeactivatedRecords


When set to true, deactivated entries of the object are shown.

 

This is all the information that we have on the lookup page handling cases, I hope it helps.

Show all comments

Hi,

I am able to create the feed entry, but what I would like to include is the @user function. Simply using the Formula in the message and constructing the text in the following way does not work.

"Hey @" + [#variable for contact] 

 

Does anyone know a way to make this active notification work in a business process to the Feed message?

Like 0

Like

3 comments

anyone?

 

I really want to be able to @someone in a feed message created in a business process and I am sure others would love to be able to do this too.

Mark Roberts,



Probably you have to add record to the SocialMention object as well, as there are stored all @'s

 

Kind regards,

Vladimir

Show all comments

Hi,

I have created a business process, which is simply notifying a user that a new record has been created within a Project. I can create the notification in the way I want, however when clicking on the link in the notification window, it simply takes the user to the Project list page and not the Project page itself i.e. the detail page.

I have used the Parent entity ID column and set this to the Project ID value, as you can see in the screenshot below. This I expected it to work. Performing a trace shows the correct Project ID value for the record in question, so I am not sure what is wrong.



Thanks

Like 0

Like

3 comments

Hello,

 

In order to create an activity, please add this value to the business process in the Add Data element:

To = responsible

Title

Time

Object

Source (for example Owner)

Unique caption Id = Record Id (from the signal)

Hi Anastasia

 

Many thanks for your reply.

 

I have the following data structure in place within the 'Notification' object for creating a new record:

 

To       -       Lookup to specific contact

Object     -      Lookup.Section Object(View).Project

Time     -    System - Current Date & Time

ParentEntityID    -    Project ID

Source     -     (I have tried a number of sources - Lookup > Owner, Lookup > Contact, Specific User via Process Parameter causes a foriegn key constraint error)

Unique Caption ID     -    RecordID from signal



Before I added Source and Unique Caption ID clicking the Notification link in the notification panel took me to the Project summary page. Adding these two as indicated in your reply above causes no action i.e. no page change occurs.



The notification is being created, although it is in the System Messages section, but the link is just not taking me to the Project.



Anything else you can guide me with would be very much appreciated.

 

thanks

 

Mark



 

I have got it working!



For those that come along after this, this is how:

 

  • Title    -     What you want to display in the notification subject

  • To       -       Lookup to specific contact

  • Object     -      Lookup.Section Object(View).Project

  • Time     -    System - Current Date & Time

  • Unique Caption ID     -    RecordID from signal

 

The issue was that I had ParentEntityID included, which once I removed that allowed the link to work. I read a previous Blog on this subject which had this value.

 

 

 

 

Show all comments

We're trying to create a chart to analyse Lead progression through the different Lead Stages, but the only sorting options are alphabetically by the grouping column or by the measure value. We want this to be sorted by an additional column on the Lead Stage that defines the order within the Lead progression rather than alphabetically or by the value to keep a consistent and logical order to the data, but cannot see an option for this unless there's a trick we're missing. Could someone please advise on how this might be done? We're mostly working with Freedom UI pages and therefore charts.

Like 2

Like

6 comments

Vladimir Sokolov,

it may be related, but that question is discussing combo boxes in pages, whereas I’m looking for chart sorting (e.g. in a bar graph) so I expect any solution would be fairly different.

Harvey Adcock,

 

Good day,

 

Could you please provide more details about your business task?



Perhaps you could take a screenshot with a description of your requirements so that we can better understand them and offer advice.

 

We are looking forward to your feedback.



Best regards,

Pavlo

Hi Pavlo,

 

Sure, what the business is asking for is to be able to sort a chart's columns by the lead stage through the process, rather than by the stage's name alphabetically or by the total number of leads in each stage as can be selected by default in the chart options. For example, see this chart available in the Home section of the Sales workplace in a clean CRM trial environment:

 

It is currently sorted by the stage name alphabetically, which doesn't align with the progression you actually get through the Opportunity stages. Looking at the sorting options, we can see that the only ones available are to sort by the grouping name alphabetically, or by the measure value:

 

So we are unable to sort by another field on the Lead Stage lookup that we've created - Stage Number - which would order it correctly. What we'd like is to be able to use that additional field for sorting without using it as the labels for the x axis.

 

If there are any workarounds for this besides numbering the stage names themselves, we'd love to hear about them!

 

Many thanks,

Harvey

Harvey Adcock,

Good day,

 

Unfortunately, it's not possible to implement this with the current basic functionality. However, we have registered the idea for our development team to consider implementing this feature.

Perhaps the "Full pipeline" dashboard type may work for you, where stages are grouped according to their placement in the DCM field?





 

Thank you for reaching out!

Hi Pavlo

 

Would you know if more advance sorting of dashboards has been enabled in any further Creatio releases? 

 

Thanks,

Jacek

Show all comments

Hi community,

We want to set the default currency in the Opportunity Mini Page (front end event), based on the Org Role of a user (oob functionality is based on the Base Currency system setting).

Is there any code implementation of a similar request ?

Sasori

Like 0

Like

2 comments
Best reply

Hello Sasori!

1) Add MultiCurrencyEditUtilities module as a dependency to your minipage schema. Example:

define("OpportunityMiniPage", ["MultiCurrencyEditUtilities"] ...

2) Add MultiCurrencyEditUtilities as a mixing to the minipage schema. Example:

...
mixins: {
  MultiCurrencyEditUtilities: "Terrasoft.MultiCurrencyEditUtilities",
  ...

3) Instead of using roles check you can use operation permission check. To use it you need to add RightUtilities module as a dependency to your minipage schema. Example:

define("OpportunityMiniPage", ["RightUtilities"], function(RightUtilities) { ...

4) Use the following methods in your minipage:

...
onEntityInitialized: function() {
  this.callParent(arguments);
  this.checkCurrencyForUser();
},
checkCurrencyForUser: function() {
  RightUtilities.checkCanExecuteOperation({
  operation: "NeedToUseEuro"
}, function(result) {
  if (result) {
    var euroId = "c0057119-53e6-df11-971b-001d60e938c6";
    this.onCurrencyMenuItemClick(euroId);
  }
 }, this);
}
...

The logic above will check if the user has access to the "NeedToUseEuro" operation (or this user role has access to the operation) and if so we will call the onCurrencyMenuItemClick method and pass euroId as an argument (see the onCurrencyMenuItemClick method signature in the MultiCurrencyEditUtilities module).

c0057119-53e6-df11-971b-001d60e938c6 is an Id of the "Euro" currency from the "Currency" table in the database. All you need to do is:

1. Correctly specify operation permissions (check if your user is not in several roles that are used in different operation permissions check)

2. Correctly setup a chain of operation permissions checks in the context of the checkCurrencyForUser method execution

P.S. Article about adding a multi-currency field: 

https://academy.creatio.com/docs/developer/interface_elements/record_page/field/overview#case-1915

Hi community,

Any update ?

Sasori

Hello Sasori!

1) Add MultiCurrencyEditUtilities module as a dependency to your minipage schema. Example:

define("OpportunityMiniPage", ["MultiCurrencyEditUtilities"] ...

2) Add MultiCurrencyEditUtilities as a mixing to the minipage schema. Example:

...
mixins: {
  MultiCurrencyEditUtilities: "Terrasoft.MultiCurrencyEditUtilities",
  ...

3) Instead of using roles check you can use operation permission check. To use it you need to add RightUtilities module as a dependency to your minipage schema. Example:

define("OpportunityMiniPage", ["RightUtilities"], function(RightUtilities) { ...

4) Use the following methods in your minipage:

...
onEntityInitialized: function() {
  this.callParent(arguments);
  this.checkCurrencyForUser();
},
checkCurrencyForUser: function() {
  RightUtilities.checkCanExecuteOperation({
  operation: "NeedToUseEuro"
}, function(result) {
  if (result) {
    var euroId = "c0057119-53e6-df11-971b-001d60e938c6";
    this.onCurrencyMenuItemClick(euroId);
  }
 }, this);
}
...

The logic above will check if the user has access to the "NeedToUseEuro" operation (or this user role has access to the operation) and if so we will call the onCurrencyMenuItemClick method and pass euroId as an argument (see the onCurrencyMenuItemClick method signature in the MultiCurrencyEditUtilities module).

c0057119-53e6-df11-971b-001d60e938c6 is an Id of the "Euro" currency from the "Currency" table in the database. All you need to do is:

1. Correctly specify operation permissions (check if your user is not in several roles that are used in different operation permissions check)

2. Correctly setup a chain of operation permissions checks in the context of the checkCurrencyForUser method execution

P.S. Article about adding a multi-currency field: 

https://academy.creatio.com/docs/developer/interface_elements/record_page/field/overview#case-1915

Show all comments

Hi dear community,

We have created a new Freedom UI section in the mobile. We want that a specific 'Field Group' is hidden permanently.

We dont want to delete this field group from the wizard because this would change the positioning of the elements in the layout.

Is there any specific code we have to insert in the Manifest or RecordPageSettings schemas.

Sasori 

Like 0

Like

3 comments

Hi Community,

Any update regarding this topic.

Sasori

Hello Community,

Any update?

Sasori

Hi,

The "Feild Group" doesn't have the property "visible" so it cannot be hidden. In your case, it would be better to delete it and then change the position of the needed elements manually in the RecordPageSettings schema.

Show all comments

Is it possible to set certain business requirements on Dynamic Case Management, for example to require that certain fields are populated or that a lookup field is one of a selection of values?

Like 0

Like

3 comments

To be clear, as I think I might not have been initially, is it possible to have manual transitions with transition requirements, as opposed to automatic transitions when certain conditions are met.

Hello,



"Manually" you can go both to the previous and subsequent stages from the current one, except when there is a mandatory task, in which case you can only go back (to the previous stages) without completing the task. More detailed information is provided at our academy in the block "Dynamic case setup (DCM)":

 https://academy.creatio.com/docs/user/bpm_tools/dynamic_case_setup

Hi Malika, thanks for your reply. I think the options for mandatory tasks is quite limited though right? As it doesn't enable transition requirements like I put in my original question - requiring that certain data requirements are met, such as certain fields being populated or lookup fields contain certain values etc. Unless I'm missing something in the academy documentation you linked to me?

Show all comments