Question

How can I set up a field of a drop-down list type out of a lookup field in an editable record list version 7.7.0.2293 SalesEnterprise + Marketing + CustomerCente? I created an editable record list of activities, the [Status] field on the activity page is a drop-down list. But in the editable record list the same field is a typical lookup with the corresponding lookup window.

P.S. The solution is useful, if there is no edit page or there are either a lot of them, or they are basic.

Answer

You can override the generateActiveRowControlsConfig() method in the detail schema and pass the necessary additional config when needed.

In our case, you can add:

if (columnName = "Status") {
 
   cellConfig.contentType = Terrasoft.ContentType.ENUM;
 
}

Right after you create cellConfig in it.

You can take the source code from the ConfigurationGridUtilities schema if it is different from the one used in the provided example.

An example of a detail schema, where everything was tested, including making the grid editable, with overriding generateActiveRowControlsConfig:

define("UsrSchema1Detail", ["terrasoft", "BusinessRulesApplierV2", "ConfigurationEnums", "BusinessRuleModule",
    "GridUtilitiesV2", "ConfigurationGrid", "ConfigurationGridGenerator", "ConfigurationGridUtilities"], function(
        Terrasoft, BusinessRulesApplier, ConfigurationEnums, BusinessRuleModule) {
    return {
        entitySchemaName: "Activity",
        attributes: {
         "IsEditable": {
            dataValueType: Terrasoft.DataValueType.BOOLEAN,
            type: Terrasoft.ViewModelColumnType.VIRTUAL_COLUMN,
            value: true
         }
        },
        mixins: {
         ConfigurationGridUtilites: "Terrasoft.ConfigurationGridUtilities"
        },
        details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[
            {
            "operation": "merge",
            "name": "DataGrid",
            "values": {
               "className": "Terrasoft.ConfigurationGrid",
               "generator": "ConfigurationGridGenerator.generatePartial",
               "generateControlsConfig": {"bindTo": "generatActiveRowControlsConfig"},
               "changeRow": {"bindTo": "changeRow"},
               "unSelectRow": {"bindTo": "unSelectRow"},
               "onGridClick": {"bindTo": "onGridClick"},
               "activeRowActions": [
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "save",
                     "markerValue": "save",
                     "imageConfig": {"bindTo": "Resources.Images.SaveIcon"}
                  },
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "cancel",
                     "markerValue": "cancel",
                     "imageConfig": {"bindTo": "Resources.Images.CancelIcon"}
                  },
                  {
                     "className": "Terrasoft.Button",
                     "style": this.Terrasoft.controls.ButtonEnums.style.TRANSPARENT,
                     "tag": "remove",
                     "markerValue": "remove",
                     "imageConfig": {"bindTo": "Resources.Images.RemoveIcon"}
                  }
               ],
               "initActiveRowKeyMap": {"bindTo": "initActiveRowKeyMap"},
               "activeRowAction": {"bindTo": "onActiveRowAction"},
               "multiSelect": false
            }
         }
        ]/**SCHEMA_DIFF*/,
        methods: {
            generateActiveRowControlsConfig: function(id, columnsConfig, rowConfig) {
                this.columnsConfig = columnsConfig;
                var gridLayoutItems = [];
                var currentColumnIndex = 0;
                this.Terrasoft.each(columnsConfig, function(columnConfig) {
                    var columnName = columnConfig.key[0].name.bindTo;
                    var column = this.getColumnByColumnName(columnName);
                    var cellConfig = this.getCellControlsConfig(column);
 
                    cellConfig = this.Ext.apply({
                        layout: {
                            colSpan: columnConfig.cols,
                            column: currentColumnIndex,
                            row: 0,
                            rowSpan: 1
                        }
                    }, cellConfig);
 
                    if (columnName = "Status") {
                        cellConfig.contentType = Terrasoft.ContentType.ENUM;
                    }
 
                    gridLayoutItems.push(cellConfig);
                    currentColumnIndex += columnConfig.cols;
                }, this);
                var gridData = this.getGridData();
                var activeRow = gridData.get(id);
                var rowClass = {prototype: activeRow};
                BusinessRulesApplier.applyRules(rowClass, gridLayoutItems);
                var viewGenerator = this.Ext.create("Terrasoft.ViewGenerator");
                viewGenerator.viewModelClass = {prototype: this};
                var gridLayoutConfig = viewGenerator.generateGridLayout({
                    name: this.name,
                    items: gridLayoutItems
                });
                rowConfig.push(gridLayoutConfig);
            },
        }
    };
});

 

Like 0

Like

Share

0 comments
Show all comments

Symptoms

Bpm'online mobile bug report

Type: Terrasoft.SourceCodeException

Message: TypeError: undefined is not an object (evaluating 'columnConfig.columnType')

Cause

The error occurs due to the fact that you have not configured the parameters of the embedded details correctly, e.g., in the "Leads" section.

Solution

You have to correctly configure all the details. For example, to set up the “Files and Attachments” detail in the “Leads” section:

- To display the details in the mobile application, you must select the “Lead attachments” detail

- Select "Lead" in the "Detail column" field

- In the “Object column” field specify “Id”

Like 0

Like

Share

0 comments
Show all comments

Question

I need to place a button under or next to one of the fields on the edit page, clicking on which will display the lookup list.

I need to open a lookup that is not related to the page, and I may need additional operations before that. This cannot be done by just adding a lookup field.

Is it possible to place a button somewhere in the middle of the page? The manual action will be quite inconvenient for the user.

Answer

In the config view, define the required control + a method to display it, and in the controller, assign a handler:

Ext.define("...view...", {
    config: {
       refreshButton: {
            id: 'usr_order_refresh_btn',
            cls: "x-button-primary-blue",
            text: 'Update'
        }
    },
    showRefreshButton: function (isShow) {
        var navigationPanel = this.getNavigationPanel(); /*a component in which the controll will be displayed*/
        var refreshButton = this.getRefreshButton();
        if (isShow) {
            this._refreshButton = navigationPanel.addButton(refreshButton);
        } else {
            navigationPanel.removeButton(refreshButton);
        }
        return this._refreshButton;
    }
});
Ext.define("...controller...", {
    initializeView: function (view) {
        this.callParent(arguments);
        var btn = view.showRefreshButton(true);
        btn.on("tap", this.onRefreshButtonTap, this);
    },
    onRefreshButtonTap: function() {
        /* subject */
    }
});

If you need to open a picker to select a value, then look in the MobileActivityGridPageControllerV2.  For example, there are pickers that enable you to select the "Responsible" employee (the "getEmployeePicker()" method) or select the schedule mode (the "getGridModePicker()" method).

Like 0

Like

Share

5 comments

Hi,

I am given with the requirement to create a button in Account Edit page section in Mobile application. The above code seems difficult to understand. Can you please explain How create/add a button in mobile application.

Please help/guide me to acheive this.

Sriraksha KS,

Hello, to add the button to the edit page you can follow the instructions from the article: 

https://community.bpmonline.com/articles/adding-custom-user-action-mobi…



Best regards,

Alex

Alex_Tim,

The link you gave displays

"You are not authorized to access this page."

 

Please help !!

Sriraksha KS,

It looks fine from my side. I recommend opening this link in another browser or incognito mode.

Seems like when you are logged into community, the link is not working; i was not logged in and it opened for me; but once i logged into my community profile, the link didn't open.

Show all comments

Question

At the moment, the synchronization does not complete successfully, due to the fact that the application (in the "Activities" section) contains a large number of files that the mobile application is trying to synchronize and as a result ends with a timeout error.

The analysis revealed that the main file type is mostly images used in email signatures (have the name "image").

Is it possible to set up the filtering mechanism in such a way that does not upload the extra files?

Answer

Add a filtering mechanism, which will ignore files related to the signature during synchronization. Add the following code to the mobile application manifest (MobileApplicationManifestDefaultWorkplace):

{
    "SyncOptions": {
        "SysSettingsImportConfig": [],
        "ModelDataImportConfig": [
            {
                "Name": "ActivityFile",
                "SyncFilter": {
                    "property": null,
                    "valueIsMacros": false,
                    "value": null,
                    "isNot": true,
                    "type": "Terrasoft.FilterTypes.Group",
                    "logicalOperation": "Terrasoft.FilterLogicalOperations.Or",
                    "subfilters": [
                        {
                            "property": "Name",
                            "funcType": "Terrasoft.FilterFunctions.SubStringOf",
                            "funcArgs": ["image"] //the word used to filter the images
                        },
                        {
                            "property": "Activity.Owner",
                            "isNot": true,
                            "valueIsMacros": true,
                            "value": "Terrasoft.ValueMacros.CurrentUserContact"
                        }
                    ]
                }
            }
        ]
    },
    "Modules": {},
    "Models": {}
}

If this is a FieldForce product, then you also need to add the same code to the "MobileApplicationManifestFieldForceWorkplace" manifest.

Like 0

Like

Share

0 comments
Show all comments

Symptoms

Terrasoft.ServerException

{Terrasoft.PerformanceCounterManager.startCounter(\"onReady\");Ext.BLANK_IMAGE_URL=\"/0/terrasoft.axd?rm=Terrasoft.UI.WebControls&r=s.gif\";\r\n\r\nthis.ErrorIcon=new Terrasoft.ImageBox({\r\n  id: \"ErrorIcon\",\r\n  cls: \"application-ico-error\",\r\n  renderTo: \"ErrorIcon_Container\"\r\n});\r\nthis.ErrorOccures=new Terrasoft.Label({\r\n  id: \"ErrorOccures\",\r\n  cls: \"x-label-black\",\r\n  renderTo: \"ErrorOccures_Container\",\r\n  caption: \"В работе приложения bpm'online возникла ошибка. Приносим извинения за неудобства.\"\r\n});\r\nthis.ErrorSupportInfo=new Terrasoft.Label({\r\n  id: \"ErrorSupportInfo\",\r\n  cls: \"x-label-black\",\r\n  renderTo: \"ErrorSupportInfo_Container\",\r\n  caption: \"Please contact bpm'online regarding this error.\"\r\n});Terrasoft.PerformanceCounterManager.stopCounter(\"onReady\");}});Terrasoft.ScriptManagerUniqueID=\"ScriptManager\";\n\t//]]>\n\t\n\r\n\r\n\t\r\n\r\n\r\n\r\nМы гарантируем полную конфиденциальность и анонимность.
\r\n\t\t\t
\r\n\t\t\t\r\n\t\t\t
\r\n\t\t\t
\r\n\t\t\tПоказать детальную информацию об ошибке

\r\n\t\t\tDate: 07.11.2015 8:12:22\r\nDate (UTC): 07.11.2015 6:12:22\r\n\r\nException Message: Memory gates checking failed because the free memory (107479040 bytes) is less than 1% of total memory.  As a result, the service will not be available for incoming requests.  To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.\r\nException Type: System.InsufficientMemoryException\r\nException Source: System.ServiceModel.Activation\r\n\r\nException Stack Trace:\r\n  at System.ServiceModel.Activation.ServiceMemoryGates.Check(Int32 minFreeMemoryPercentage, Boolean throwOnLowMemory, UInt64& availableMemoryBytes)\r\n  at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CheckMemoryCloseIdleServices(EventTraceActivity eventTraceActivity)\r\n  at System.ServiceModel.ServiceHostingEnvironment.HostingManager.EnsureServiceAvailable(String normalizedVirtualPath, EventTraceActivity eventTraceActivity)\r\n\r\nSessionID: w0l0muum2dgm2vmlxyszxo0j\r\nRequest URL: /0/ServiceModel/EntityDataService.svc/MobileDataCollection?$select=Id,CreatedById,CreatedOn,ModifiedById,ModifiedOn,Key&%24skip=0&%24top=-1\r\nRequest Path: /0/ServiceModel/EntityDataService.svc/MobileDataCollection\r\nRequest Type: GET\r\nUser Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13B143 (5048248176)\r\nUser Host Address: 37.147.161.229\r\nUser: Xxxxxxxxxxx\r\nIs Authenticated: True\r\nAuthentication Type: Forms\r\nIs Secure Connection: True\r\n\r\nApplication Version: 7.6.0.1148\r\nApplication Path: D:\\App\\peremenatrade\\Terrasoft.WebApp\\\r\nApplication Virtual Path: /0\r\nApplication Trust Level: Full\r\nMachine Name: RU2-C004-WEB01\r\nIs Local: False\r\n\r\nProcess ID: 9124\r\nProcess Name: w3wp.exe\r\nProcess Account Name: RU\\iis-peremenatrade\r\nThread Account Name: RU\\iis-peremenatrade\r\nOS Version: Microsoft Windows NT 6.3.9600.0\r\nNet Framework Version: 4.0.30319.34209\r\nDBExecutor Type: MSSqlExecutor\r\n\r\n\t\t\r\n\t\r\n\r\n\r\n"}

Cause

According to the mobile application error:

Exception Message: Memory gates checking failed because the free memory (107479040 bytes) is less than 1% of total memory.  As a result, the service will not be available for incoming requests.  To resolve this, either reduce the load on the machine or adjust the value of minFreeMemoryPercentageToActivateService on the serviceHostingEnvironment config element.\r\nException Type: System.InsufficientMemoryException\r\nException Source: System.ServiceModel.Activation\r\n\r\nException Stack Trace:\r\n  at System.ServiceModel.Activation.ServiceMemoryGates.Check(Int32 minFreeMemoryPercentage, Boolean throwOnLowMemory, UInt64& availableMemoryBytes)\r\n  at System.ServiceModel.ServiceHostingEnvironment.HostingManager.CheckMemoryCloseIdleServices(EventTraceActivity eventTraceActivity)\r\n  at 

Connected with a memory jump on the server where the application is deployed.

Solution

Restart the site in IIS.

Like 0

Like

Share

0 comments
Show all comments

Question

How do I make all elements of the [Addresses] detail on an account page uneditable? Version 7.2.0.

Answer

Below you can find an example of implementing the function for the AddressDetail schema:

1) You can add a new enableDetailControls method:

this.methods.enableDetailControls = function(viewConfig, enabled) {
    if (!viewConfig.items) {
        return;
    }
    viewConfig.items.forEach(function(item) {
        item.enabled = enabled;
    }, this);
};

2) Call this method within the "getCustomItemView" method after complete generation of the view configuration and add the necessary conditions. For example, in front of the "return viewConfig" string:

this.methods.getCustomItemView = function(viewModel, itemKey, action, types, itemViewModel) {
    var viewConfig = {};
    ...
    var enableControls = (action === "edit") && (/*любые другие условия*/);
    this.enableDetailControls(viewConfig, enableControls);
    return viewConfig;
};
It is recommended to receive the values of the necessary conditions before this, since after you execute getCustomItemView, the control function will be passed to the base detail module (DetailModule), where the model connection to the view and detail rendering are performed. 
Like 0

Like

Share

0 comments
Show all comments

Case description:

In agent desktop group queue item tabs by queue (see Figure 1).

 

Figure 1. Agent desktop

Algorithm of realization:

  1. Create replacing client schema of OperatorQueues (must be inherited from "Schema - Agent queues")
  2. Override loadQueues, queueTabChange and createQueuesTabs methods as following:

    define("OperatorQueues", ["terrasoft"],
        function (Terrasoft) {
            return {
                attributes: {},
                methods: {
                    loadQueues: function (callback) {
                        var esq = Ext.create("Terrasoft.EntitySchemaQuery", {
                            rootSchemaName: "Queue"
                        });
                        esq.isDistinct = true;
                        esq.addColumn("Id");
                        esq.addColumn("Name");
                        esq.addColumn("QueueEntitySchema");
                        esq.addColumn("[SysSchema:UId:QueueEntitySchema].Name", "EntitySchemaName");
                        esq.addColumn("[QueueObject:EntitySchemaUId:QueueEntitySchema].IsClosedQueue", "IsClosedQueue");
                        this.appendOperatorFilters(esq);
                        this.addQueueInProgressFilters(esq);
                        esq.getEntityCollection(function (result) {
                            if (!result.success) {
                                callback();
                            }
                            callback(result.collection);
                        });
                    },
                    queueTabChange: function (activeTab) {
                        var queueId = activeTab.get("Id");
                        var entitySchemaUId = activeTab.get("EntitySchemaUId");
                        var entitySchemaName = activeTab.get("EntitySchemaName");
                        var isClosedQueue = activeTab.get("IsClosedQueue");
                        var loadModuleCallback = function () {
                            this.sandbox.loadModule("QueueModule", {
                                renderTo: "operatorQueueEntityContainer",
                                parameters: {
                                    QueueId: queueId,
                                    EntitySchemaUId: entitySchemaUId,
                                    EntitySchemaName: entitySchemaName,
                                    IsClosedQueue: isClosedQueue
                                }
                            });
                        }.bind(this);
                        var profile = this.get("Profile");
                        if (profile.activeEntitySchemaUId !== entitySchemaUId) {
                            profile.activeEntitySchemaUId = entitySchemaUId;
                            this.saveProfileData(loadModuleCallback);
                        } else {
                            loadModuleCallback.call();
                        }
                    },
                    createQueuesTabs: function (collection) {
                        var activeQueueTabName = null;
                        if (!collection) {
                            return;
                        }
                        var profile = this.get("Profile");
                        var savedActiveEntitySchemaUId = profile.activeEntitySchemaUId;
                        var queues = this.get("Queues");
                        queues.clear();
                        collection.each(function (item) {
                            var queueId = item.get("Id");
                            var queueName = item.get("Name");
                            var queueEntitySchema = item.get("QueueEntitySchema");
                            var queueEntitySchemaName = item.get("EntitySchemaName");
                            var isClosedQueue = item.get("IsClosedQueue");
                            if (queueEntitySchema) {
                                var queueUId = queueEntitySchema.value;
                                var queueCaption = queueName;
                                var name = this.getQueueTabName(queueId);
                                queues.add(queueId, Ext.create("Terrasoft.BaseViewModel", {
                                    values: {
                                        Id: queueId,
                                        Caption: queueCaption,
                                        Name: name,
                                        EntitySchemaUId: queueUId,
                                        EntitySchemaName: queueEntitySchemaName,
                                        IsClosedQueue: isClosedQueue
                                    }
                                }));
                                if (queueId === savedActiveEntitySchemaUId) {
                                    activeQueueTabName = this.getQueueTabName(savedActiveEntitySchemaUId);
                                } else if (Ext.isEmpty(activeQueueTabName)) {
                                    activeQueueTabName = name;
                                }
                            }
                        }, this);
                        this.set("ActiveQueueTabName", activeQueueTabName);
                    }
                },
                diff: []
            };
        }
    );

     

Like 0

Like

Share

0 comments
Show all comments

Example override class SummaryModule

SummaryModuleV2.js

define("UsrSummaryModuleV2", ["SummaryModuleV2"],
    function() {
        Ext.define("Terrasoft.SummaryModuleOverrided", {
            override: "Terrasoft.SummaryModule",
 
           /*
            * @override
            */
            getESQ: function() {
                var esq = this.callParent(arguments);
                esq.queryKind = Terrasoft.QueryKind.LIMITED;
                return esq;
            }
        });
    }
);

On the page, which use base class you need to add dependency to overridden class:

BaseSectionV2

define("BaseSectionV2", ["UsrSummaryModuleV2"], function() {
    return {
        methods: {},
        details: /**SCHEMA_DETAILS*/{}/**SCHEMA_DETAILS*/,
        diff: /**SCHEMA_DIFF*/[]/**SCHEMA_DIFF*/
    };
});

 

Like 0

Like

Share

0 comments
Show all comments

Question

How can I set a value for an active record from section module in edit mode (vertical list)?

Answer

If the column, for which the value must be set, is among the active string columns, you can try saving the active string:

var activeRow = this.getActiveRow();
activeRow.set("YourColumnName", columnValue);
activeRow.saveEntity();

To make this code work, make sure the activeRow.columns collection contains a column with the YourColumnName name and the Terrasoft.ViewModelColumnType.ENTITY_COLUMN type (this constant equals 0).

You can also implement updating the value via a request, as follows:

var updateQuery = this.Ext.create("Terrasoft.UpdateQuery", {
        rootSchemaName: "EntitySchemaName"
});
var filters = updateQuery.filters;
filters.addItem(this.Terrasoft.createColumnFilterWithParameter(
        this.Terrasoft.ComparisonType.EQUAL, "Id", currentRecordId));
updateQuery.setParameterValue("YourColumnName", columnValue);
updateQuery.execute(callbackFunction, this);

 

Like 1

Like

Share

0 comments
Show all comments

Question

In the [Contacts] section, I created a [Driver's documents] detail, the UsrSchema6Detail schema. I need to display it, if the selected job title is [Driver]. If the job title is different or not selected at all, the detail is hidden.

 I added a business rule to the contact schema, but it does not work.

rules: {
   "UsrSchema6Detail": {
      BindParametrVisibilePlaceByType: {
         // Rule type: BINDPARAMETER.
         ruleType: BusinessRuleModule.enums.RuleType.BINDPARAMETER,
         // Rule is regulated by the VISIBLE field value.
         property: BusinessRuleModule.enums.Property.VISIBLE,
         conditions: [{
            // Expression of the left part of the condition.
            leftExpression: {
               //The ATTRIBUTE expression type indicates, that
               // the view model attribute (column)acts as the expression.
               type: BusinessRuleModule.enums.ValueType.ATTRIBUTE,
               // Name of the view model column, whose value was compared in the expression.
               attribute: "Job"
            },
            // Compare operation type.
            comparisonType: Terrasoft.ComparisonType.EQUAL,
            // Expression of the right part of the condition.
            rightExpression: {
               type: BusinessRuleModule.enums.ValueType.CONSTANT,
               value: "703e34d6-4113-43b5-84dc-2e1f8635c6d4"
            }
         }]
      }
   }
}

If I apply this rule to the [Department] column, it works OK.

Answer

Using business rules is not a good solution for your business case.

Below is an example of code for hiding the [Communication options] detail on the edit page of an [Account]. Create the AccountPagev2 replacing module, the following code is added in the diff property:

{
    "operation": "merge",
    "name": "Communications",
    "values": {
        "visible" : {
            "bindTo": "communicationsVisibility"
        }
    }
}

Declare the method responsible for detail visibility in the methods property:

communicationsVisibility: function(){
    var type = this.get("Type");
    return !!type && type.displayValue === "Our company";
}

As a result, the detail will be visible only in case the type is specified as "Our company". You can hide any detail similarly.

Like 0

Like

Share

0 comments
Show all comments